source: flex_extract.git/source/python/classes/GribUtil.py @ 79729d5

ctbtodev
Last change on this file since 79729d5 was 79729d5, checked in by Anne Philipp <anne.philipp@…>, 5 years ago

switched from python2 to python3

  • Property mode set to 100644
File size: 10.3 KB
Line 
1#!/usr/bin/env python3
2# -*- coding: utf-8 -*-
3#*******************************************************************************
4# @Author: Anne Fouilloux (University of Oslo)
5#
6# @Date: July 2014
7#
8# @Change History:
9#   February 2018 - Anne Philipp (University of Vienna):
10#        - applied PEP8 style guide
11#        - added documentation
12#        - changed some naming
13#
14# @License:
15#    (C) Copyright 2014-2018.
16#
17#    This software is licensed under the terms of the Apache Licence Version 2.0
18#    which can be obtained at http://www.apache.org/licenses/LICENSE-2.0.
19#
20# @Class Description:
21#    The GRIB API provides all necessary tools to work directly with the
22#    grib files. Nevertheless, the GRIB API tools are very basic and are in
23#    direct connection with the grib files. This class provides some higher
24#    functions which apply a set of GRIB API tools together in the respective
25#    context. So, the class initially contains a list of grib files (their
26#    names) and the using program then applies the methods directly on the
27#    class objects without having to think about how the actual GRIB API
28#    tools have to be arranged.
29#
30# @Class Content:
31#    - __init__
32#    - get_keys
33#    - set_keys
34#    - copy_dummy_msg
35#    - index
36#
37# @Class Attributes:
38#    - filenames
39#
40#*******************************************************************************
41
42# ------------------------------------------------------------------------------
43# MODULES
44# ------------------------------------------------------------------------------
45import os
46
47from eccodes import (codes_grib_new_from_file, codes_is_defined, codes_get,
48                     codes_release, codes_set, codes_write, codes_index_read,
49                     codes_index_new_from_file, codes_index_add_file,
50                     codes_index_write, codes_set_values)
51
52# ------------------------------------------------------------------------------
53# CLASS
54# ------------------------------------------------------------------------------
55class GribUtil(object):
56    '''
57    Class for GRIB utilities (new methods) based on GRIB API
58    '''
59    # --------------------------------------------------------------------------
60    # CLASS FUNCTIONS
61    # --------------------------------------------------------------------------
62    def __init__(self, filenames):
63        '''Initialise an object of GribUtil and assign a list of filenames.
64
65        Parameters
66        ----------
67        filenames : :obj:`list` of :obj:`strings`
68             A list of filenames.
69
70        Return
71        ------
72
73        '''
74
75        self.filenames = filenames
76
77        return
78
79
80    def get_keys(self, keynames, wherekeynames=[], wherekeyvalues=[]):
81        '''Get keyvalues for a given list of keynames a where statement
82        can be given (list of key and list of values)
83
84        Parameters
85        ----------
86        keynames : :obj:`list` of :obj:`string`
87            List of keynames.
88
89        wherekeynames : :obj:`list` of :obj:`string`, optional
90            Default value is an empty list.
91
92        wherekeyvalues : :obj:`list` of :obj:`string`, optional
93            Default value is an empty list.
94
95        Return
96        ------
97        return_list : :obj:`list` of :obj:`string`
98            List of keyvalues for given keynames.
99        '''
100
101        fileid = open(self.filenames, 'r')
102
103        return_list = []
104
105        while 1:
106            gid = codes_new_from_file(fileid)
107
108            if gid is None:
109                break
110
111            if len(wherekeynames) != len(wherekeyvalues):
112                raise Exception("Number of key values and key names must be \
113                                 the same. Give a value for each keyname!")
114
115            select = True
116            i = 0
117            for wherekey in wherekeynames:
118                if not codes_is_defined(gid, wherekey):
119                    raise Exception("where key was not defined")
120
121                select = (select and (str(wherekeyvalues[i]) ==
122                                      str(codes_get(gid, wherekey))))
123                i += 1
124
125            if select:
126                llist = []
127                for key in keynames:
128                    llist.extend([str(codes_get(gid, key))])
129                return_list.append(llist)
130
131            codes_release(gid)
132
133        fileid.close()
134
135        return return_list
136
137
138    def set_keys(self, fromfile, keynames, keyvalues, wherekeynames=[],
139                 wherekeyvalues=[], strict=False, filemode='w'):
140        '''Opens the file to read the grib messages and then write
141        the selected messages (with wherekeys) to a new output file.
142        Also, the keyvalues of the passed list of keynames are set.
143
144        Parameters
145        ----------
146        fromfile : :obj:`string`
147            Filename of the input file to read the grib messages from.
148
149        keynames : :obj:`list` of :obj:`string`
150            List of keynames to set in the selected messages.
151            Default is an empty list.
152
153        keyvalues : :obj:`list` of :obj:`string`
154            List of keyvalues to set in the selected messages.
155            Default is an empty list.
156
157        wherekeynames : :obj:`list` of :obj:`string`, optional
158            List of keynames to select correct message.
159            Default value is an empty list.
160
161        wherekeyvalues : :obj:`list` of :obj:`string`, optional
162            List of keyvalues for keynames to select correct message.
163            Default value is an empty list.
164
165        strict : :obj:`boolean`, optional
166            Decides if everything from keynames and keyvalues
167            is written out the grib file (False) or only those
168            meeting the where statement (True). Default is False.
169
170        filemode : :obj:`string`, optional
171            Sets the mode for the output file. Default is "w".
172
173        Return
174        ------
175
176        '''
177        if len(wherekeynames) != len(wherekeyvalues):
178            raise Exception("Give a value for each keyname!")
179
180        fout = open(self.filenames, filemode)
181        fin = open(fromfile)
182
183        while 1:
184            gid = codes_grib_new_from_file(fin)
185
186            if gid is None:
187                break
188
189            select = True
190            i = 0
191            for wherekey in wherekeynames:
192                if not codes_is_defined(gid, wherekey):
193                    raise Exception("wherekey was not defined")
194
195                select = (select and (str(wherekeyvalues[i]) ==
196                                      str(codes_get(gid, wherekey))))
197                i += 1
198
199            if select:
200                i = 0
201                for key in keynames:
202                    if key == 'values':
203                        codes_set_values(gid, keyvalues[i])
204                    else:
205                        codes_set(gid, key, keyvalues[i])
206                    i += 1
207
208                codes_write(gid, fout)
209
210            codes_release(gid)
211
212        fin.close()
213        fout.close()
214
215        return
216
217    def copy_dummy_msg(self, filename_in, selectWhere=True,
218                 keynames=[], keyvalues=[], filemode='w'):
219        '''Add the content of another input grib file to the objects file but
220        only messages corresponding to keys/values passed to the function.
221        The selectWhere switch decides if to copy the keys equal to (True) or
222        different to (False) the keynames/keyvalues list passed to the function.
223
224        Parameters
225        ----------
226        filename_in : :obj:`string`
227            Filename of the input file to read the grib messages from.
228
229        selectWhere : :obj:`boolean`, optional
230            Decides if to copy the keynames and values equal to (True) or
231            different to (False) the keynames/keyvalues list passed to the
232            function. Default is True.
233
234        keynames : :obj:`list` of :obj:`string`, optional
235            List of keynames. Default is an empty list.
236
237        keyvalues : :obj:`list` of :obj:`string`, optional
238            List of keyvalues. Default is an empty list.
239
240        filemode : :obj:`string`, optional
241            Sets the mode for the output file. Default is "w".
242
243        Return
244        ------
245
246        '''
247        if len(keynames) != len(keyvalues):
248            raise Exception("Give a value for each keyname!")
249
250        fin = open(filename_in)
251        fout = open(self.filenames, filemode)
252
253        fields = 0
254
255        while fields < 1:
256            gid = codes_grib_new_from_file(fin)
257
258            if gid is None:
259                break
260
261            select = True
262            i = 0
263            for key in keynames:
264                if not codes_is_defined(gid, key):
265                    raise Exception("Key was not defined")
266
267                if selectWhere:
268                    select = (select and (str(keyvalues[i]) ==
269                                          str(codes_get(gid, key))))
270                else:
271                    select = (select and (str(keyvalues[i]) !=
272                                          str(codes_get(gid, key))))
273                i += 1
274
275            if select:
276                fields = fields + 1
277                codes_write(gid, fout)
278
279            codes_release(gid)
280
281        fin.close()
282        fout.close()
283
284        return
285
286    def index(self, index_keys=["mars"], index_file="my.idx"):
287        '''Create index file from a list of files if it does not exist or
288        read an index file.
289
290        Parameters
291        ----------
292        index_keys: :obj:`list` of :obj:`string`, optional
293            Contains the list of key parameter names from
294            which the index is to be created.
295            Default is a list with a single entry string "mars".
296
297        index_file: :obj:`string`, optional
298            Filename where the indices are stored.
299            Default is "my.idx".
300
301        Return
302        ------
303        iid: :obj:`integer`
304            Grib index id.
305        '''
306        print("... index will be done")
307        iid = None
308
309        if os.path.exists(index_file):
310            iid = codes_index_read(index_file)
311            print("Use existing index file: %s " % (index_file))
312        else:
313            for filename in self.filenames:
314                print("Inputfile: %s " % (filename))
315                if iid is None:
316                    iid = codes_index_new_from_file(filename, index_keys)
317                else:
318                    codes_index_add_file(iid, filename)
319
320            if iid is not None:
321                codes_index_write(iid, index_file)
322
323        print('... index done')
324
325        return iid
Note: See TracBrowser for help on using the repository browser.
hosted by ZAMG