source: flex_extract.git/Source/Python/Classes/GribUtil.py @ 2c3c135

ctbtodev
Last change on this file since 2c3c135 was 2c3c135, checked in by Anne Philipp <anne.philipp@…>, 4 years ago

eliminated bug with eccodes file opening for python3 for rrint feature

  • Property mode set to 100644
File size: 10.4 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:
[026b359]15#    (C) Copyright 2014-2020.
[44174de]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
[0f89116]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
[0f89116]79        wherekeynames : :obj:`list` of :obj:`string`
80            List of key names for indexing grib message parameter.
[64cf353]81
[0f89116]82        wherekeyvalues : :obj:`list` of :obj:`string`
83            List of key values corresponding the key names.
[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
93        return_list = []
94
[c77630a]95        with open(self.filenames, 'rb') as fileid:
[d69b677]96
[c77630a]97            gid = codes_new_from_file(fileid)
[64cf353]98
99            if len(wherekeynames) != len(wherekeyvalues):
100                raise Exception("Number of key values and key names must be \
101                                 the same. Give a value for each keyname!")
102
103            select = True
104            i = 0
[d69b677]105            for wherekey in wherekeynames:
[2e62398]106                if not codes_is_defined(gid, wherekey):
[64cf353]107                    raise Exception("where key was not defined")
108
109                select = (select and (str(wherekeyvalues[i]) ==
[2e62398]110                                      str(codes_get(gid, wherekey))))
[64cf353]111                i += 1
112
[d69b677]113            if select:
114                llist = []
115                for key in keynames:
[2e62398]116                    llist.extend([str(codes_get(gid, key))])
[d69b677]117                return_list.append(llist)
[64cf353]118
[2e62398]119            codes_release(gid)
[64cf353]120
[d69b677]121        return return_list
[64cf353]122
123
[2c3c135]124    def set_keys(self, fromfile, filemode='wb', keynames=[], keyvalues=[], 
125                 wherekeynames=[], wherekeyvalues=[]):
[274f9ef]126        '''Opens the file to read the grib messages and then write
[268ee86]127        the selected messages (with wherekeys) to a new output file.
128        Also, the keyvalues of the passed list of keynames are set.
[64cf353]129
[274f9ef]130        Parameters
131        ----------
132        fromfile : :obj:`string`
133            Filename of the input file to read the grib messages from.
[64cf353]134
[274f9ef]135        keynames : :obj:`list` of :obj:`string`
[268ee86]136            List of keynames to set in the selected messages.
137            Default is an empty list.
[64cf353]138
[274f9ef]139        keyvalues : :obj:`list` of :obj:`string`
[268ee86]140            List of keyvalues to set in the selected messages.
141            Default is an empty list.
[64cf353]142
[0f89116]143        wherekeynames : :obj:`list` of :obj:`string`
[268ee86]144            List of keynames to select correct message.
[64cf353]145
[0f89116]146        wherekeyvalues : :obj:`list` of :obj:`string`
[268ee86]147            List of keyvalues for keynames to select correct message.
[64cf353]148
[274f9ef]149        filemode : :obj:`string`, optional
[c77630a]150            Sets the mode for the output file. Default is "wb".
[64cf353]151
[274f9ef]152        Return
153        ------
[64cf353]154
155        '''
[4ef5ba9]156        from eccodes import (codes_grib_new_from_file, codes_is_defined,
157                             codes_get, codes_set, codes_write,
158                             codes_set_values, codes_release)
159
[268ee86]160        if len(wherekeynames) != len(wherekeyvalues):
161            raise Exception("Give a value for each keyname!")
162
[ff99eae]163        fout = open(self.filenames, filemode)
[2c3c135]164       # print(fout)
165        fin = open(fromfile, 'rb')
166       # print(fin)
167        while True:
[268ee86]168            gid = codes_grib_new_from_file(fin)
[2c3c135]169           # print('test')
170            if gid is None:
171                break           
172           
[64cf353]173            select = True
[2c3c135]174            #print(str(codes_get(gid,'paramId')))
175            for i, wherekey in enumerate(wherekeynames):
[2e62398]176                if not codes_is_defined(gid, wherekey):
[268ee86]177                    raise Exception("wherekey was not defined")
[64cf353]178
179                select = (select and (str(wherekeyvalues[i]) ==
[2e62398]180                                      str(codes_get(gid, wherekey))))
[64cf353]181
[d69b677]182            if select:
[2c3c135]183                for i, key in enumerate(keynames):
[268ee86]184                    if key == 'values':
185                        codes_set_values(gid, keyvalues[i])
186                    else:
187                        codes_set(gid, key, keyvalues[i])
[64cf353]188
[268ee86]189                codes_write(gid, fout)
[ff99eae]190
[2e62398]191            codes_release(gid)
[64cf353]192
[d69b677]193        fout.close()
[2c3c135]194        fin.close()
[d69b677]195
[64cf353]196        return
197
[0f89116]198    def copy_dummy_msg(self, filename_in, keynames, keyvalues,
199                       selectwhere=True, filemode='wb'):
[274f9ef]200        '''Add the content of another input grib file to the objects file but
[64cf353]201        only messages corresponding to keys/values passed to the function.
202        The selectWhere switch decides if to copy the keys equal to (True) or
203        different to (False) the keynames/keyvalues list passed to the function.
204
[274f9ef]205        Parameters
206        ----------
207        filename_in : :obj:`string`
208            Filename of the input file to read the grib messages from.
209
[0f89116]210        selectwhere : :obj:`boolean`, optional
[274f9ef]211            Decides if to copy the keynames and values equal to (True) or
212            different to (False) the keynames/keyvalues list passed to the
213            function. Default is True.
[64cf353]214
[0f89116]215        keynames : :obj:`list` of :obj:`string`
216            List of keynames.
[64cf353]217
[0f89116]218        keyvalues : :obj:`list` of :obj:`string`
219            List of keyvalues.
[64cf353]220
[274f9ef]221        filemode : :obj:`string`, optional
[c77630a]222            Sets the mode for the output file. Default is "wb".
[64cf353]223
[274f9ef]224        Return
225        ------
[64cf353]226
227        '''
[4ef5ba9]228        from eccodes import (codes_grib_new_from_file, codes_is_defined,
229                             codes_get, codes_release, codes_write)
230
[268ee86]231        if len(keynames) != len(keyvalues):
232            raise Exception("Give a value for each keyname!")
[64cf353]233
[ff99eae]234        fout = open(self.filenames, filemode)
[2c3c135]235        fin = open(filename_in, 'rb')
236       
[268ee86]237        fields = 0
[2c3c135]238        while True:
239            if fields >= len(keyvalues):
[c77630a]240                fout.close()
[2c3c135]241                fin.close()
[c77630a]242                return
[2c3c135]243               
[c77630a]244            gid = codes_grib_new_from_file(fin)
[2c3c135]245            if gid is None:
246                break           
[64cf353]247
[2c3c135]248            for i, key in enumerate(keynames):
249               
250                select = True
251               
[2e62398]252                if not codes_is_defined(gid, key):
[64cf353]253                    raise Exception("Key was not defined")
254
[0f89116]255                if selectwhere:
[64cf353]256                    select = (select and (str(keyvalues[i]) ==
[2e62398]257                                          str(codes_get(gid, key))))
[d69b677]258                else:
[64cf353]259                    select = (select and (str(keyvalues[i]) !=
[2e62398]260                                          str(codes_get(gid, key))))
[2c3c135]261               
262                if select:
263                    fields = fields + 1
264                    codes_write(gid, fout)
265                   
[2e62398]266            codes_release(gid)
[64cf353]267
[d69b677]268        fout.close()
[2c3c135]269        fin.close()
[d69b677]270
[64cf353]271        return
272
[0f89116]273    def index(self, index_keys, index_file="my.idx"):
[274f9ef]274        '''Create index file from a list of files if it does not exist or
275        read an index file.
276
277        Parameters
278        ----------
[0f89116]279        index_keys: :obj:`list` of :obj:`string`
[274f9ef]280            Contains the list of key parameter names from
281            which the index is to be created.
282
283        index_file: :obj:`string`, optional
284            Filename where the indices are stored.
285            Default is "my.idx".
286
287        Return
288        ------
289        iid: :obj:`integer`
290            Grib index id.
[64cf353]291        '''
[4ef5ba9]292        from eccodes import (codes_index_read, codes_index_new_from_file,
293                             codes_index_add_file, codes_index_write)
294
[2fb99de]295        print("... index will be done")
[ff99eae]296        iid = None
[64cf353]297
[ff99eae]298        if os.path.exists(index_file):
[2e62398]299            iid = codes_index_read(index_file)
[2fb99de]300            print("Use existing index file: %s " % (index_file))
[d69b677]301        else:
[ff99eae]302            for filename in self.filenames:
[2fb99de]303                print("Inputfile: %s " % (filename))
[ff99eae]304                if iid is None:
[2e62398]305                    iid = codes_index_new_from_file(filename, index_keys)
[d69b677]306                else:
[2e62398]307                    codes_index_add_file(iid, filename)
[d69b677]308
[ff99eae]309            if iid is not None:
[2e62398]310                codes_index_write(iid, index_file)
[d69b677]311
[2fb99de]312        print('... index done')
[d69b677]313
[ff99eae]314        return iid
Note: See TracBrowser for help on using the repository browser.
hosted by ZAMG