IODA Bundle
ims_scf2ioda.py
Go to the documentation of this file.
1 #!/usr/bin/env python3
2 #
3 # (C) Copyright 2020 NOAA/NWS/NCEP/EMC
4 #
5 # This software is licensed under the terms of the Apache Licence Version 2.0
6 # which can be obtained at http://www.apache.org/licenses/LICENSE-2.0.
7 #
8 import pygrib
9 import time, os, sys
10 import argparse
11 import netCDF4 as nc
12 import numpy as np
13 from datetime import datetime, timedelta
14 from pathlib import Path
15 
16 IODA_CONV_PATH = Path(__file__).parent/"@SCRIPT_LIB_PATH@"
17 if not IODA_CONV_PATH.is_dir():
18  IODA_CONV_PATH = Path(__file__).parent/'..'/'lib-python'
19 sys.path.append(str(IODA_CONV_PATH.resolve()))
20 
21 import ioda_conv_ncio as iconv
22 from collections import defaultdict, OrderedDict
23 from orddicts import DefaultOrderedDict
24 
25 locationKeyList = [
26  ("latitude", "float"),
27  ("longitude", "float"),
28  ("datetime", "string")
29 ]
30 
31 obsvars = {
32  'snow_cover_fraction': 'snowCover',
33 }
34 
35 AttrData = {
36  'converter': os.path.basename(__file__),
37 }
38 
39 
40 class imsscf(object):
41 
42  def __init__(self, filename, mask, writer):
43  self.filenamefilename = filename
44  self.maskmask = mask
45  self.writerwriter = writer
46  self.varDictvarDict = defaultdict(lambda: defaultdict(dict))
47  self.outdataoutdata = defaultdict(lambda: DefaultOrderedDict(OrderedDict))
48  self.loc_mdataloc_mdata = defaultdict(lambda: DefaultOrderedDict(OrderedDict))
49  self.var_mdatavar_mdata = defaultdict(lambda: DefaultOrderedDict(OrderedDict))
50  self.unitsunits = {}
51  self._read_read()
52 
53  def _read(self):
54 
55  # set up variable names for IODA
56  for iodavar in ['snowCover']:
57  self.varDictvarDict[iodavar]['valKey'] = iodavar, self.writerwriter.OvalName()
58  self.varDictvarDict[iodavar]['errKey'] = iodavar, self.writerwriter.OerrName()
59  self.varDictvarDict[iodavar]['qcKey'] = iodavar, self.writerwriter.OqcName()
60  self.unitsunits[iodavar] = '%'
61  # read self.filename to get data
62  data = pygrib.open(self.filenamefilename)
63  lat, lon = data[1].latlons()
64  lons = lon[:].ravel()
65  lats = lat[:].ravel()
66  vals = data.select(name='Snow cover')[0].values[:].ravel()
67  # defined errors and qc
68  errs = 0.08*vals
69  qflg = 0*vals.astype('int32')
70  times = np.empty_like(vals, dtype=object)
71 
72  if self.maskmask == "maskout":
73  mask = np.logical_not(vals.mask)
74  vals = vals[mask]
75  errs = errs[mask]
76  qflg = qflg[mask]
77  lons = lons[mask]
78  lats = lats[mask]
79  times = times[mask]
80  # get global attributes
81  start_datetime = data[1].analDate
82  base_datetime = start_datetime.isoformat() + "Z"
83  # grbs.close()
84 
85  # write global attributes out
86  self.satellitesatellite = "POES/GOES"
87  self.sensorsensor = "IMS.Multisensor"
88  AttrData["observation_type"] = "Snow Cover Fraction"
89  AttrData["satellite"] = self.satellitesatellite
90  AttrData["sensor"] = self.sensorsensor
91  AttrData['date_time_string'] = base_datetime
92 
93  for i in range(len(lons)):
94  times[i] = base_datetime
95  self.loc_mdataloc_mdata['datetime'] = self.writerwriter.FillNcVector(times, "datetime")
96  self.loc_mdataloc_mdata['latitude'] = lats
97  self.loc_mdataloc_mdata['longitude'] = lons
98  for iodavar in ['snowCover']:
99  self.outdataoutdata[self.varDictvarDict[iodavar]['valKey']] = vals
100  self.outdataoutdata[self.varDictvarDict[iodavar]['errKey']] = errs
101  self.outdataoutdata[self.varDictvarDict[iodavar]['qcKey']] = qflg
102  self.writerwriter._nvars = len(obsvars)
103  self.writerwriter._nlocs = len(self.loc_mdataloc_mdata['datetime'])
104 
105 
106 def main():
107 
108  parser = argparse.ArgumentParser(
109  description=('Read IMS snow cover fraction file(s) and Converter'
110  ' of native grib2 format for observations of snow'
111  ' cover fraction to IODA netCDF format.')
112  )
113  parser.add_argument('-i', '--input',
114  help="name of ims snow cover input file(s)",
115  type=str, required=True)
116  parser.add_argument('-o', '--output',
117  help="name of ioda output file",
118  type=str, required=True)
119  optional = parser.add_argument_group(title='optional arguments')
120  optional.add_argument(
121  '-m', '--mask',
122  help="maskout missing values: maskout/default, default=none",
123  type=str, required=True)
124 
125  args = parser.parse_args()
126 
127  writer = iconv.NcWriter(args.output, locationKeyList)
128 
129  # Read in the profiles
130  scf = imsscf(args.input, args.mask, writer)
131 
132  # write the data out
133  writer.BuildNetcdf(scf.outdata, scf.loc_mdata, scf.var_mdata, AttrData, scf.units)
134 
135 
136 if __name__ == '__main__':
137  main()
def __init__(self, filename, mask, writer)
Definition: ims_scf2ioda.py:42