4 from netCDF4
import Dataset
5 from argparse
import ArgumentParser, ArgumentDefaultsHelpFormatter
6 from datetime
import datetime
as dt
11 from pathlib
import Path
13 IODA_CONV_PATH = Path(__file__).parent/
"@SCRIPT_LIB_PATH@"
14 if not IODA_CONV_PATH.is_dir():
15 IODA_CONV_PATH = Path(__file__).parent/
'..'/
'lib-python'
16 sys.path.append(
str(IODA_CONV_PATH.resolve()))
18 import bufr2ncCommon
as cm
19 from bufr2ncObsTypes
import ObsType
21 NCEP_CONFIG_PATH = (IODA_CONV_PATH/
'config').resolve()
30 bufr = ncepbufr.open(BufrFname)
32 Obs.start_msg_selector()
33 while (Obs.select_next_msg(bufr)):
44 bufr = ncepbufr.open(BufrFname)
49 Obs.start_msg_selector()
50 while (Obs.select_next_msg(bufr)):
51 NumObs += Obs.msg_obs_count(bufr)
54 return [NumObs, Obs.num_msg_selected, Obs.num_msg_mtype]
67 def __init__(self, bf_type, alt_type, tablefile, dictfile):
76 [
'datetime@MetaData',
'', cm.DTYPE_STRING, [
'nlocs',
'nstring'], [self.
nlocsnlocs, self.
nstringnstring]])
78 if (bf_type == cm.BFILE_BUFR):
81 if os.path.isfile(dictfile):
94 if not os.path.isfile(Lexicon):
95 for i
in spec_list[alt_type]:
98 full_table[i][
'name'].replace(
100 '_').replace(
'/',
'_'),
102 full_table[i][
'dtype'],
103 full_table[i][
'ddims']]
104 if intspecDum
not in intspec:
105 intspec.append([full_table[i][
'name'].replace(
106 ' ',
'_').replace(
'/',
'_'),
107 i, full_table[i][
'dtype'],
108 full_table[i][
'ddims']])
112 for j, dname
in enumerate(intspec):
113 if len(dname[3]) == 1:
114 intspec[j].append([self.
nlocsnlocs])
115 elif len(dname[3]) == 2:
116 intspec[j].append([self.
nlocsnlocs, self.
nstringnstring])
118 print(
'walked off the edge')
125 if '@ObsValue' in (
" ".join(map(str, k))):
134 for x
in range(0, len(intspec), 1)]
141 for i
in spec_list[alt_type]:
144 full_table[i][
'name'].replace(
145 ' ',
'_').replace(
'/',
'_'), i,
146 full_table[i][
'dtype'],
147 full_table[i][
'ddims']]
148 if repspecDum
not in repspec:
149 repspec.append([full_table[i][
'name'].replace(
150 ' ',
'_').replace(
'/',
'_'), i,
151 full_table[i][
'dtype'], full_table[i][
'ddims']])
152 for j, dname
in enumerate(repspec):
153 if len(dname[3]) == 1:
154 repspec[j].append([self.
nlocsnlocs])
155 elif len(dname[3]) == 2:
156 repspec[j].append([self.
nlocsnlocs, self.
nstringnstring])
158 print(
'walked off the edge')
162 for x
in range(0, len(repspec), 1)
if not repspec[x]
in intspec]
177 f = open(dictfileName,
'w')
178 yaml.dump(dictionary, f)
183 f = open(dictfileName,
'r')
184 dictionary = yaml.safe_load(f)
192 with open(filename)
as f:
194 if line[:11] !=
'|' +
'-' * 10 +
'|' \
195 and line[:11] !=
'|' +
' ' * 10 +
'|' \
196 and line.find(
'-' * 20) == -1:
201 for ndx, line
in enumerate(all[1:]):
202 if line.find(
'MNEMONIC') != -1:
205 part_a = all[2:stops[0]]
206 part_b = all[stops[0] + 3:stops[1]]
207 part_c = all[stops[1] + 3:]
222 tbl_a = {line.split(
'|')[1].strip(): line.split(
223 '|')[3].strip().lower()
for line
in part_a}
224 tbl_c = {line.split(
'|')[1].strip(): line.split(
225 '|')[5].strip().lower()
for line
in part_c}
227 full_table = {i: {
'name': tbl_a[i],
'units': tbl_c[i]}
228 for i
in tbl_c.keys()}
280 string_types = [
'CCITT IA5']
282 string_dims = [
'nlocs',
'nstring']
283 nums_dims = [
'nlocs']
285 for key, item
in full_table.items():
286 if item[
'units'].upper()
in integer_types:
287 full_table[key][
'dtype'] = cm.DTYPE_INTEGER
288 full_table[key][
'ddims'] = nums_dims
289 elif item[
'units'].upper()
in float_types:
290 full_table[key][
'dtype'] = cm.DTYPE_FLOAT
291 full_table[key][
'ddims'] = nums_dims
292 elif item[
'units'].upper()
in string_types:
293 full_table[key][
'dtype'] = cm.DTYPE_STRING
294 full_table[key][
'ddims'] = string_dims
296 full_table[key][
'dtype'] = cm.DTYPE_UNDEF
297 full_table[key][
'ddims'] = nums_dims
298 return full_table, part_b
325 if line.find(mnemonic) != -1:
326 if mnemonic
in bentries:
327 bentries[mnemonic] = bentries[mnemonic] + \
328 ''.join(line.split(
'|')[2:]).strip().split()
330 bentries[mnemonic] =
''.join(
331 line.split(
'|')[2:]).strip().split()
335 for b_monic
in bentries[mnemonic]:
350 if line.split(
'|')[1].find(b_monic) != -1:
351 bentries[mnemonic] = bentries[mnemonic] + \
352 ''.join(line.split(
'|')[2:]).strip().split()
381 if line.find(mnemonic) != -1:
382 if mnemonic
in bentries:
383 bentries[mnemonic] = bentries[mnemonic] + \
384 ''.join(line.split(
'|')[2:]).strip().split()
386 bentries[mnemonic] =
''.join(
387 line.split(
'|')[2:]).strip().split()
389 bentries[mnemonic] = [x[1:-1]
for x
in bentries[mnemonic]
if '(' in x]
391 for b_monic
in bentries[mnemonic]:
398 if line.split(
'|')[1].find(b_monic) != -1:
399 bentries[mnemonic] = bentries[mnemonic] + \
400 ''.join(line.split(
'|')[2:]).strip().split()
409 BufrFname = BufrPath + BufrFname
410 BufrTname = base_mnemo +
'.tbl'
411 NetcdfFname =
'xx' + base_mnemo[5:] +
'.nc'
413 return BufrFname, BufrTname, NetcdfFname
417 bufr = ncepbufr.open(BufrFname)
419 bufr.dump_table(ObsTable)
428 if __name__ ==
'__main__':
430 desc = (
'Read NCEP BUFR data and convert to IODA netCDF4 format'
431 'example: ./ncep_classes.py -p /path/to/obs/ -i obs_filename'
432 ' -ot observation type -l yamlfile -m number_of_messages')
434 parser = ArgumentParser(
436 formatter_class=ArgumentDefaultsHelpFormatter)
439 '-p',
'--obs_path', help=
'path with the observations',
440 type=str, required=
True)
443 '-i',
'--input_bufr', help=
'name of the input BUFR file',
444 type=str, required=
True)
447 '-ot',
'--obs_type', help=
'Submessage of the input BUFR file, e.g., NC001007',
448 type=str, required=
True)
451 '-o',
'--output_netcdf', help=
'name of the output NC file',
452 type=str, required=
False, default=
None)
455 '-m',
'--maxmsgs', help=
"maximum number of messages to keep",
456 type=int, required=
False, default=0, metavar=
"<max_num_msgs>")
459 '-Th',
'--thin', type=int, default=1,
460 help=
"select every nth message (thinning)", metavar=
"<thin_interval>")
463 '-d',
'--date', help=
'file date', metavar=
'YYYYMMDDHH',
464 type=str, required=
True)
467 '-l',
'--lexicon', help=
'yaml file with the dictionary', metavar=
"name_of_dict",
468 type=str, required=
True)
471 '-Pr',
'--bufr', action=
'store_true', default=1,
472 help=
'input BUFR file is in prepBUFR or BUFR format')
474 args = parser.parse_args()
476 BufrPath = args.obs_path
477 MaxNumMsg = args.maxmsgs
478 ThinInterval = args.thin
479 ObsType = args.obs_type
480 BufrFname = BufrPath + args.input_bufr
481 DateCentral = dt.strptime(args.date,
'%Y%m%d%H')
483 if Path(args.lexicon).is_absolute():
484 Lexicon = args.lexicon
486 Lexicon =
str((NCEP_CONFIG_PATH/args.lexicon).resolve())
489 BfileType = cm.BFILE_BUFR
491 BfileType = cm.BFILE_PREPBUFR
493 if (args.output_netcdf):
494 NetcdfFname = args.output_netcdf
496 NetcdfFname =
'ioda.' + ObsType +
'.' + \
497 DateCentral.strftime(
"%Y%m%d%H") +
'.nc'
499 date_time = DateCentral.strftime(
"%Y%m%d%H")
501 ObsTable = ObsType +
'.tbl'
502 DictObs = ObsType +
'.dict'
506 if os.path.isfile(BufrFname):
507 bufr = ncepbufr.open(BufrFname)
509 mnemonic = bufr.msg_type
511 print(
'Mnemonic name is ', mnemonic)
513 sys.exit(
'The ', BufrFname,
'does not exist.')
518 if os.path.isfile(ObsTable):
519 print(
'ObsTable exists: ', ObsTable)
521 print(
'ObsTable does not exist, the ', ObsTable,
'is created!')
529 Obs.max_num_msg = MaxNumMsg
531 Obs.max_num_msg = NumMessages[0]
532 print(
"NumMessages = ", NumMessages[0])
534 Obs.thin_interval = ThinInterval
535 Obs.date_central = DateCentral
538 Obs.set_nlocs(NumObs)
540 nc = Dataset(NetcdfFname,
'w', format=
'NETCDF4')
542 nc.date_time =
int(date_time[0:10])
544 bufr = ncepbufr.open(BufrFname)
545 pf_list = [
'NC001003',
'NC001103',
'NC031001',
'NC031002',
'NC031003',
546 'NC031004',
'NC031005',
'NC031006',
'NC031007']
547 if ObsType
in pf_list:
548 Obs.create_nc_datasets(nc,
True)
550 Obs.convert(bufr, nc,
True)
552 Obs.create_nc_datasets(nc,
False)
554 Obs.convert(bufr, nc,
False)
def init_dim_spec(self)
This method will set the dimension specs (data memeber self.dim_spec).
def __init__(self, bf_type, alt_type, tablefile, dictfile)
def BfilePreprocess(BufrFname, Obs)
def read_yaml(dictfileName)
def MessageCounter(BufrFname)
SUBROUTINES To be deleted (maybe).
def create_bufrtable(BufrFname, ObsTable)
def get_rep_spec(mnemonic, part_b)
get the rep_spec entries
def get_int_spec(mnemonic, part_b)
get the int_spec entries from satellite table
def write_yaml(dictionary, dictfileName)
def get_fname(base_mnemo, BufrPath)
function to create the full path of