source: flex_extract.git/Source/Python/Classes/GribUtil.py @ 44174de

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

commented out the WRF parts since they are still under construction and added License SPDX tags

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