#!/usr/bin/env python
from eccodes import *
import argparse
import pandas as pd
'''
# Copyright 2005- ECMWF.
# This software is licensed under the terms of the Apache Licence Version 2.0
# which can be obtained at http://www.apache.org/licenses/LICENSE-2.0.
# In applying this licence, ECMWF does not waive the privileges and immunities
# granted to it by virtue of its status as an intergovernmental organisation
# nor does it submit to any jurisdiction
This is a test program to encode Wigos Synop. Requires:
1) ecCodes version 2.8 or above (available at https://confluence.ecmwf.int/display/ECC/Releases)
2) python2.7
To run the program:
./wigosMultisubset.py -i synop_multi_subset.bufr -o out_synop_multisubset.bufr -w WIGOS_IDENTIFIERS.csv
Uses BUFR version 4 template and adds the WIGOS Identifier 301150
REQUIRES TablesVersionNumber above 28
'''
def read_cmdline():
'''
Reads the command line to get the input ascii filename and the output bufr file
Usage:
prog -i <input_bufr_file> -o <output_bufr_file> -w <wigos_csv_info>
'''
p = argparse.ArgumentParser()
p.add_argument('-i', '--input', help = 'input BUFR filename')
p.add_argument('-o', '--output', help = 'output BUFR filename')
p.add_argument("-w", "--wigoscodes",help="csv with the station codes")
args = p.parse_args()
return args
def read_wigosInfo(wigosCSVFile):
'''
dtype={"wigosLocalIdentifierCharacter":object} forces the column to be string compatible
with the wigosLocalIdentifierCharacter key in bufr. This column in the CSV must be created as a TEXT
'''
df=pd.read_csv(wigosCSVFile,sep=",",dtype={"wigosLocalIdentifierCharacter":object})
return df
def main():
'''
reads the arguments from the command line
-i input bufr file
-o output bufr file
-w wigos information ( csv containing the station Name and wigos information ( wigosLocalIdentifierCharacter etc)
'''
args=read_cmdline()
inputFileName=args.input
outputFilename=args.output
wigosFile=args.wigoscodes
'''
reads the wigos information into a pandas dataframe that is queried
for each station to retrieve the station's wigos information
'''
dfWigosInfo=read_wigosInfo(wigosFile)
fin=open(inputFileName,"rb")
ibid=codes_bufr_new_from_file(fin)
codes_set(ibid,"unpack",1)
inUE=codes_get_array(ibid,"unexpandedDescriptors")
nsubsets=codes_get(ibid,"numberOfSubsets")
masterTablesVN=codes_get(ibid,"masterTablesVersionNumber")
# change the masterTablesVersionNumber if is below 29 ( otherwise the WIGOS sequence is not present)
if masterTablesVN<28:
masterTablesVN=28
outUE=inUE.tolist()
# update the unexpandedDescriptors ( BUFR sequence) to add the WIGOS data
outUE.insert(0,301150)
fout=open(outputFilename,"wb")
obid=codes_bufr_new_from_samples("BUFR4")
### important, use master tables version number above 28 as they contain WIGOS keys
# otherwise it won't work
codes_set(obid, 'masterTablesVersionNumber', masterTablesVN)
# set the unexpandedDescriptors of the output file with the new sequence 301150 (WIGOS) + synop sequence
#from Input message
# IMPORTANT, read the number of subsets
codes_set(obid,"numberOfSubsets",nsubsets)
codes_set_array(obid,"unexpandedDescriptors",outUE)
# here wigos information is added, the stationName is used
# to query the dfWigosInfo dataframe and retrieve the station Wigos information (wigosLocalIdentifierCharacter etc)
for i in range(0,nsubsets):
stationKey="#{0}#stationOrSiteName".format(i+1)
stationName=codes_get(ibid,stationKey)
dfo=dfWigosInfo.query("station=='{0}'".format(stationName))
key="#{0}#wigosIdentifierSeries".format(i+1)
codes_set(obid, key,int(dfo["wigosIdentifierSeries"].values[0]) )
key="#{0}#wigosIssuerOfIdentifier".format(i+1)
codes_set(obid, key, int(dfo["wigosIssuerOfIdentifier"].values[0]))
key="#{0}#wigosIssueNumber".format(i+1)
value=dfo["wigosIssueNumber"].values[0]
codes_set(obid, key, value)
key="#{0}#wigosLocalIdentifierCharacter".format(i+1)
value=dfo["wigosLocalIdentifierCharacter"].values[0]
codes_set(obid,key,str(value))
# copies the data from the input message ( ibid) to the output message obid
codes_bufr_copy_data(ibid,obid)
# write to output file ( packing is not needed here as copy_data does it implicitly)
codes_write(obid,fout)
# release the obid and ibid bufr handles
codes_release(obid)
codes_release(ibid)
fout.close()
fin.close()
if __name__=="__main__":
main()