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
RevLine 
[8463d78]1#!/usr/bin/env python3
[64cf353]2# -*- coding: utf-8 -*-
[991df6a]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:
[44174de]15#    (C) Copyright 2014-2019.
16#    Anne Philipp, Leopold Haimberger
[991df6a]17#
[44174de]18#    SPDX-License-Identifier: CC-BY-4.0
[ff99eae]19#
[44174de]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.
[991df6a]24#*******************************************************************************
[64cf353]25
26# ------------------------------------------------------------------------------
27# MODULES
28# ------------------------------------------------------------------------------
[4ef5ba9]29from __future__ import print_function
[aa275fc]30
[4ef5ba9]31import os
[991df6a]32
[64cf353]33# ------------------------------------------------------------------------------
34# CLASS
35# ------------------------------------------------------------------------------
[268ee86]36class GribUtil(object):
[64cf353]37    '''
38    Class for GRIB utilities (new methods) based on GRIB API
[44174de]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.
[64cf353]48    '''
49    # --------------------------------------------------------------------------
[efdb01a]50    # CLASS FUNCTIONS
[64cf353]51    # --------------------------------------------------------------------------
52    def __init__(self, filenames):
[268ee86]53        '''Initialise an object of GribUtil and assign a list of filenames.
[274f9ef]54
55        Parameters
56        ----------
57        filenames : :obj:`list` of :obj:`strings`
58             A list of filenames.
[64cf353]59
[274f9ef]60        Return
61        ------
[64cf353]62
63        '''
64
[ff99eae]65        self.filenames = filenames
[64cf353]66
67        return
68
69
[ff99eae]70    def get_keys(self, keynames, wherekeynames=[], wherekeyvalues=[]):
[274f9ef]71        '''Get keyvalues for a given list of keynames a where statement
72        can be given (list of key and list of values)
[64cf353]73
[274f9ef]74        Parameters
75        ----------
76        keynames : :obj:`list` of :obj:`string`
77            List of keynames.
[64cf353]78
[274f9ef]79        wherekeynames : :obj:`list` of :obj:`string`, optional
80            Default value is an empty list.
[64cf353]81
[274f9ef]82        wherekeyvalues : :obj:`list` of :obj:`string`, optional
83            Default value is an empty list.
[64cf353]84
[274f9ef]85        Return
86        ------
87        return_list : :obj:`list` of :obj:`string`
88            List of keyvalues for given keynames.
[64cf353]89        '''
[4ef5ba9]90        from eccodes import (codes_new_from_file, codes_is_defined, codes_get,
91                             codes_release)
[64cf353]92
[ff99eae]93        fileid = open(self.filenames, 'r')
[64cf353]94
95        return_list = []
96
[d69b677]97        while 1:
[2e62398]98            gid = codes_new_from_file(fileid)
[d69b677]99
[aa275fc]100            if gid is None:
[64cf353]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
[d69b677]109            for wherekey in wherekeynames:
[2e62398]110                if not codes_is_defined(gid, wherekey):
[64cf353]111                    raise Exception("where key was not defined")
112
113                select = (select and (str(wherekeyvalues[i]) ==
[2e62398]114                                      str(codes_get(gid, wherekey))))
[64cf353]115                i += 1
116
[d69b677]117            if select:
118                llist = []
119                for key in keynames:
[2e62398]120                    llist.extend([str(codes_get(gid, key))])
[d69b677]121                return_list.append(llist)
[64cf353]122
[2e62398]123            codes_release(gid)
[64cf353]124
[d69b677]125        fileid.close()
[64cf353]126
[d69b677]127        return return_list
[64cf353]128
129
[ff99eae]130    def set_keys(self, fromfile, keynames, keyvalues, wherekeynames=[],
131                 wherekeyvalues=[], strict=False, filemode='w'):
[274f9ef]132        '''Opens the file to read the grib messages and then write
[268ee86]133        the selected messages (with wherekeys) to a new output file.
134        Also, the keyvalues of the passed list of keynames are set.
[64cf353]135
[274f9ef]136        Parameters
137        ----------
138        fromfile : :obj:`string`
139            Filename of the input file to read the grib messages from.
[64cf353]140
[274f9ef]141        keynames : :obj:`list` of :obj:`string`
[268ee86]142            List of keynames to set in the selected messages.
143            Default is an empty list.
[64cf353]144
[274f9ef]145        keyvalues : :obj:`list` of :obj:`string`
[268ee86]146            List of keyvalues to set in the selected messages.
147            Default is an empty list.
[64cf353]148
[274f9ef]149        wherekeynames : :obj:`list` of :obj:`string`, optional
[268ee86]150            List of keynames to select correct message.
[274f9ef]151            Default value is an empty list.
[64cf353]152
[274f9ef]153        wherekeyvalues : :obj:`list` of :obj:`string`, optional
[268ee86]154            List of keyvalues for keynames to select correct message.
[274f9ef]155            Default value is an empty list.
[64cf353]156
[274f9ef]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.
[64cf353]161
[274f9ef]162        filemode : :obj:`string`, optional
163            Sets the mode for the output file. Default is "w".
[64cf353]164
[274f9ef]165        Return
166        ------
[64cf353]167
168        '''
[4ef5ba9]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
[268ee86]173        if len(wherekeynames) != len(wherekeyvalues):
174            raise Exception("Give a value for each keyname!")
175
[ff99eae]176        fout = open(self.filenames, filemode)
[64cf353]177        fin = open(fromfile)
178
[d69b677]179        while 1:
[268ee86]180            gid = codes_grib_new_from_file(fin)
[64cf353]181
[aa275fc]182            if gid is None:
[64cf353]183                break
[d69b677]184
[64cf353]185            select = True
186            i = 0
[d69b677]187            for wherekey in wherekeynames:
[2e62398]188                if not codes_is_defined(gid, wherekey):
[268ee86]189                    raise Exception("wherekey was not defined")
[64cf353]190
191                select = (select and (str(wherekeyvalues[i]) ==
[2e62398]192                                      str(codes_get(gid, wherekey))))
[64cf353]193                i += 1
194
[d69b677]195            if select:
[64cf353]196                i = 0
[d69b677]197                for key in keynames:
[268ee86]198                    if key == 'values':
199                        codes_set_values(gid, keyvalues[i])
200                    else:
201                        codes_set(gid, key, keyvalues[i])
[64cf353]202                    i += 1
203
[268ee86]204                codes_write(gid, fout)
[ff99eae]205
[2e62398]206            codes_release(gid)
[64cf353]207
[d69b677]208        fin.close()
209        fout.close()
210
[64cf353]211        return
212
[268ee86]213    def copy_dummy_msg(self, filename_in, selectWhere=True,
214                 keynames=[], keyvalues=[], filemode='w'):
[274f9ef]215        '''Add the content of another input grib file to the objects file but
[64cf353]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
[274f9ef]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.
[64cf353]229
[274f9ef]230        keynames : :obj:`list` of :obj:`string`, optional
231            List of keynames. Default is an empty list.
[64cf353]232
[274f9ef]233        keyvalues : :obj:`list` of :obj:`string`, optional
[268ee86]234            List of keyvalues. Default is an empty list.
[64cf353]235
[274f9ef]236        filemode : :obj:`string`, optional
237            Sets the mode for the output file. Default is "w".
[64cf353]238
[274f9ef]239        Return
240        ------
[64cf353]241
242        '''
[4ef5ba9]243        from eccodes import (codes_grib_new_from_file, codes_is_defined,
244                             codes_get, codes_release, codes_write)
245
[268ee86]246        if len(keynames) != len(keyvalues):
247            raise Exception("Give a value for each keyname!")
[64cf353]248
[4ef5ba9]249        fin = open(filename_in, 'rb')
[ff99eae]250        fout = open(self.filenames, filemode)
[64cf353]251
[268ee86]252        fields = 0
253
254        while fields < 1:
255            gid = codes_grib_new_from_file(fin)
[d69b677]256
[aa275fc]257            if gid is None:
[64cf353]258                break
259
260            select = True
261            i = 0
[d69b677]262            for key in keynames:
[2e62398]263                if not codes_is_defined(gid, key):
[64cf353]264                    raise Exception("Key was not defined")
265
[d69b677]266                if selectWhere:
[64cf353]267                    select = (select and (str(keyvalues[i]) ==
[2e62398]268                                          str(codes_get(gid, key))))
[d69b677]269                else:
[64cf353]270                    select = (select and (str(keyvalues[i]) !=
[2e62398]271                                          str(codes_get(gid, key))))
[64cf353]272                i += 1
273
[d69b677]274            if select:
[268ee86]275                fields = fields + 1
[2e62398]276                codes_write(gid, fout)
[64cf353]277
[2e62398]278            codes_release(gid)
[64cf353]279
[d69b677]280        fin.close()
281        fout.close()
282
[64cf353]283        return
284
285    def index(self, index_keys=["mars"], index_file="my.idx"):
[274f9ef]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.
[64cf353]304        '''
[4ef5ba9]305        from eccodes import (codes_index_read, codes_index_new_from_file,
306                             codes_index_add_file, codes_index_write)
307
[2fb99de]308        print("... index will be done")
[ff99eae]309        iid = None
[64cf353]310
[ff99eae]311        if os.path.exists(index_file):
[2e62398]312            iid = codes_index_read(index_file)
[2fb99de]313            print("Use existing index file: %s " % (index_file))
[d69b677]314        else:
[ff99eae]315            for filename in self.filenames:
[2fb99de]316                print("Inputfile: %s " % (filename))
[ff99eae]317                if iid is None:
[2e62398]318                    iid = codes_index_new_from_file(filename, index_keys)
[d69b677]319                else:
[2e62398]320                    codes_index_add_file(iid, filename)
[d69b677]321
[ff99eae]322            if iid is not None:
[2e62398]323                codes_index_write(iid, index_file)
[d69b677]324
[2fb99de]325        print('... index done')
[d69b677]326
[ff99eae]327        return iid
Note: See TracBrowser for help on using the repository browser.
hosted by ZAMG