source: flex_extract.git/Source/Python/Classes/GribUtil.py @ 8463d78

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

made python3 again, now working

  • Property mode set to 100644
File size: 10.6 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# ------------------------------------------------------------------------------
45from __future__ import print_function
46
47import os
48
49# ------------------------------------------------------------------------------
50# CLASS
51# ------------------------------------------------------------------------------
52class GribUtil(object):
53    '''
54    Class for GRIB utilities (new methods) based on GRIB API
55    '''
56    # --------------------------------------------------------------------------
57    # CLASS FUNCTIONS
58    # --------------------------------------------------------------------------
59    def __init__(self, filenames):
60        '''Initialise an object of GribUtil and assign a list of filenames.
61
62        Parameters
63        ----------
64        filenames : :obj:`list` of :obj:`strings`
65             A list of filenames.
66
67        Return
68        ------
69
70        '''
71
72        self.filenames = filenames
73
74        return
75
76
77    def get_keys(self, keynames, wherekeynames=[], wherekeyvalues=[]):
78        '''Get keyvalues for a given list of keynames a where statement
79        can be given (list of key and list of values)
80
81        Parameters
82        ----------
83        keynames : :obj:`list` of :obj:`string`
84            List of keynames.
85
86        wherekeynames : :obj:`list` of :obj:`string`, optional
87            Default value is an empty list.
88
89        wherekeyvalues : :obj:`list` of :obj:`string`, optional
90            Default value is an empty list.
91
92        Return
93        ------
94        return_list : :obj:`list` of :obj:`string`
95            List of keyvalues for given keynames.
96        '''
97        from eccodes import (codes_new_from_file, codes_is_defined, codes_get,
98                             codes_release)
99
100        fileid = open(self.filenames, 'r')
101
102        return_list = []
103
104        while 1:
105            gid = codes_new_from_file(fileid)
106
107            if gid is None:
108                break
109
110            if len(wherekeynames) != len(wherekeyvalues):
111                raise Exception("Number of key values and key names must be \
112                                 the same. Give a value for each keyname!")
113
114            select = True
115            i = 0
116            for wherekey in wherekeynames:
117                if not codes_is_defined(gid, wherekey):
118                    raise Exception("where key was not defined")
119
120                select = (select and (str(wherekeyvalues[i]) ==
121                                      str(codes_get(gid, wherekey))))
122                i += 1
123
124            if select:
125                llist = []
126                for key in keynames:
127                    llist.extend([str(codes_get(gid, key))])
128                return_list.append(llist)
129
130            codes_release(gid)
131
132        fileid.close()
133
134        return return_list
135
136
137    def set_keys(self, fromfile, keynames, keyvalues, wherekeynames=[],
138                 wherekeyvalues=[], strict=False, filemode='w'):
139        '''Opens the file to read the grib messages and then write
140        the selected messages (with wherekeys) to a new output file.
141        Also, the keyvalues of the passed list of keynames are set.
142
143        Parameters
144        ----------
145        fromfile : :obj:`string`
146            Filename of the input file to read the grib messages from.
147
148        keynames : :obj:`list` of :obj:`string`
149            List of keynames to set in the selected messages.
150            Default is an empty list.
151
152        keyvalues : :obj:`list` of :obj:`string`
153            List of keyvalues to set in the selected messages.
154            Default is an empty list.
155
156        wherekeynames : :obj:`list` of :obj:`string`, optional
157            List of keynames to select correct message.
158            Default value is an empty list.
159
160        wherekeyvalues : :obj:`list` of :obj:`string`, optional
161            List of keyvalues for keynames to select correct message.
162            Default value is an empty list.
163
164        strict : :obj:`boolean`, optional
165            Decides if everything from keynames and keyvalues
166            is written out the grib file (False) or only those
167            meeting the where statement (True). Default is False.
168
169        filemode : :obj:`string`, optional
170            Sets the mode for the output file. Default is "w".
171
172        Return
173        ------
174
175        '''
176        from eccodes import (codes_grib_new_from_file, codes_is_defined,
177                             codes_get, codes_set, codes_write,
178                             codes_set_values, codes_release)
179
180        if len(wherekeynames) != len(wherekeyvalues):
181            raise Exception("Give a value for each keyname!")
182
183        fout = open(self.filenames, filemode)
184        fin = open(fromfile)
185
186        while 1:
187            gid = codes_grib_new_from_file(fin)
188
189            if gid is None:
190                break
191
192            select = True
193            i = 0
194            for wherekey in wherekeynames:
195                if not codes_is_defined(gid, wherekey):
196                    raise Exception("wherekey was not defined")
197
198                select = (select and (str(wherekeyvalues[i]) ==
199                                      str(codes_get(gid, wherekey))))
200                i += 1
201
202            if select:
203                i = 0
204                for key in keynames:
205                    if key == 'values':
206                        codes_set_values(gid, keyvalues[i])
207                    else:
208                        codes_set(gid, key, keyvalues[i])
209                    i += 1
210
211                codes_write(gid, fout)
212
213            codes_release(gid)
214
215        fin.close()
216        fout.close()
217
218        return
219
220    def copy_dummy_msg(self, filename_in, selectWhere=True,
221                 keynames=[], keyvalues=[], filemode='w'):
222        '''Add the content of another input grib file to the objects file but
223        only messages corresponding to keys/values passed to the function.
224        The selectWhere switch decides if to copy the keys equal to (True) or
225        different to (False) the keynames/keyvalues list passed to the function.
226
227        Parameters
228        ----------
229        filename_in : :obj:`string`
230            Filename of the input file to read the grib messages from.
231
232        selectWhere : :obj:`boolean`, optional
233            Decides if to copy the keynames and values equal to (True) or
234            different to (False) the keynames/keyvalues list passed to the
235            function. Default is True.
236
237        keynames : :obj:`list` of :obj:`string`, optional
238            List of keynames. Default is an empty list.
239
240        keyvalues : :obj:`list` of :obj:`string`, optional
241            List of keyvalues. Default is an empty list.
242
243        filemode : :obj:`string`, optional
244            Sets the mode for the output file. Default is "w".
245
246        Return
247        ------
248
249        '''
250        from eccodes import (codes_grib_new_from_file, codes_is_defined,
251                             codes_get, codes_release, codes_write)
252
253        if len(keynames) != len(keyvalues):
254            raise Exception("Give a value for each keyname!")
255
256        fin = open(filename_in, 'rb')
257        fout = open(self.filenames, filemode)
258
259        fields = 0
260
261        while fields < 1:
262            gid = codes_grib_new_from_file(fin)
263
264            if gid is None:
265                break
266
267            select = True
268            i = 0
269            for key in keynames:
270                if not codes_is_defined(gid, key):
271                    raise Exception("Key was not defined")
272
273                if selectWhere:
274                    select = (select and (str(keyvalues[i]) ==
275                                          str(codes_get(gid, key))))
276                else:
277                    select = (select and (str(keyvalues[i]) !=
278                                          str(codes_get(gid, key))))
279                i += 1
280
281            if select:
282                fields = fields + 1
283                codes_write(gid, fout)
284
285            codes_release(gid)
286
287        fin.close()
288        fout.close()
289
290        return
291
292    def index(self, index_keys=["mars"], index_file="my.idx"):
293        '''Create index file from a list of files if it does not exist or
294        read an index file.
295
296        Parameters
297        ----------
298        index_keys: :obj:`list` of :obj:`string`, optional
299            Contains the list of key parameter names from
300            which the index is to be created.
301            Default is a list with a single entry string "mars".
302
303        index_file: :obj:`string`, optional
304            Filename where the indices are stored.
305            Default is "my.idx".
306
307        Return
308        ------
309        iid: :obj:`integer`
310            Grib index id.
311        '''
312        from eccodes import (codes_index_read, codes_index_new_from_file,
313                             codes_index_add_file, codes_index_write)
314
315        print("... index will be done")
316        iid = None
317
318        if os.path.exists(index_file):
319            iid = codes_index_read(index_file)
320            print("Use existing index file: %s " % (index_file))
321        else:
322            for filename in self.filenames:
323                print("Inputfile: %s " % (filename))
324                if iid is None:
325                    iid = codes_index_new_from_file(filename, index_keys)
326                else:
327                    codes_index_add_file(iid, filename)
328
329            if iid is not None:
330                codes_index_write(iid, index_file)
331
332        print('... index done')
333
334        return iid
Note: See TracBrowser for help on using the repository browser.
hosted by ZAMG