9 Convert GMAO ocean data to IODA netCDF4 format
12 from __future__
import print_function
14 from argparse
import ArgumentParser, ArgumentDefaultsHelpFormatter
17 from datetime
import datetime
18 from pathlib
import Path
20 IODA_CONV_PATH = Path(__file__).parent/
"@SCRIPT_LIB_PATH@"
21 if not IODA_CONV_PATH.is_dir():
22 IODA_CONV_PATH = Path(__file__).parent/
'..'/
'lib-python'
23 sys.path.append(
str(IODA_CONV_PATH.resolve()))
25 import ioda_conv_ncio
as iconv
26 from orddicts
import DefaultOrderedDict
31 5521:
'sea_water_salinity',
32 3073:
'sea_water_temperature',
33 5525:
'sea_surface_temperature',
34 5526:
'obs_absolute_dynamic_topography',
35 5351:
'obs_absolute_dynamic_topography',
36 6000:
'sea_ice_area_fraction',
37 6001:
'sea_ice_thickness'
42 'sea_water_salinity':
'sal',
43 'sea_water_temperature':
'temp',
44 'sea_surface_temperature':
'sst',
45 'obs_absolute_dynamic_topography':
'adt',
46 'sea_ice_area_fraction':
'frac',
47 'sea_ice_thickness':
'thick'
55 for key, value
in dictIn.items():
56 if value
not in dictOut:
57 dictOut[value] = [key]
59 dictOut[value].append(key)
80 nc = nc4.Dataset(self.
filenamefilename)
82 data[
'nobs'] = len(nc.dimensions[
'nobs'])
84 data[
'typ'] = nc.variables[
'typ'][:].data
85 data[
'lon'] = nc.variables[
'lon'][:].data
86 data[
'lat'] = nc.variables[
'lat'][:].data
87 data[
'depth'] = nc.variables[
'depth'][:].data
88 data[
'value'] = nc.variables[
'value'][:].data
89 data[
'oerr'] = nc.variables[
'oerr'][:].data
111 def __init__(self, filename, date, varName, obsList):
113 Initialize IODA writer class,
114 transform to IODA data structure and,
115 write out to IODA file.
122 (
"latitude",
"float"),
123 (
"longitude",
"float"),
125 (
"datetime",
"string")
130 'date_time_string': self.
datedate.strftime(
"%Y-%m-%dT%H:%M:%SZ")
136 if obs.data[
'nobs'] <= 0:
138 totalObs += obs.data[
'nobs']
140 print(
'No %s observations for IODA!' % varName)
147 self.
keyDictkeyDict[varName][
'valKey'] = varName, self.
writerwriter.OvalName()
148 self.
keyDictkeyDict[varName][
'errKey'] = varName, self.
writerwriter.OerrName()
149 self.
keyDictkeyDict[varName][
'qcKey'] = varName, self.
writerwriter.OqcName()
158 if obs.data[
'nobs'] <= 0:
161 for n
in range(obs.data[
'nobs']):
163 oval = obs.data[
'value'][n]
164 oerr = obs.data[
'oerr'][n]
169 lat = obs.data[
'lat'][n]
170 lon = obs.data[
'lon'][n]
171 lvl = obs.data[
'depth'][n]
173 locKey = lat, lon, lvl, obs.date.strftime(
"%Y-%m-%dT%H:%M:%SZ")
175 valKey = self.
keyDictkeyDict[varName][
'valKey']
176 errKey = self.
keyDictkeyDict[varName][
'errKey']
177 qcKey = self.
keyDictkeyDict[varName][
'qcKey']
179 self.
datadata[recKey][locKey][valKey] = oval
180 self.
datadata[recKey][locKey][errKey] = oerr
181 self.
datadata[recKey][locKey][qcKey] = 0
183 (ObsVars, LocMdata, VarMdata) = self.
writerwriter.ExtractObsData(self.
datadata)
184 self.
writerwriter.BuildNetcdf(ObsVars, LocMdata, VarMdata, self.
AttrDataAttrData)
192 for key
in obsIdDict.keys():
199 filename = obs.filename
201 ind = np.where(obs.data[
'typ'] == key)
204 data[
'nobs'] = len(ind[0])
205 data[
'typ'] = obs.data[
'typ'][ind]
206 data[
'lon'] = obs.data[
'lon'][ind]
207 data[
'lat'] = obs.data[
'lat'][ind]
208 data[
'depth'] = obs.data[
'depth'][ind]
209 data[
'value'] = obs.data[
'value'][ind]
210 data[
'oerr'] = obs.data[
'oerr'][ind]
212 obsListKey.append(
refGMAOobs(filename, date, data))
214 obsDict[key] = obsListKey
222 obsIdDictFlipped =
flipDict(obsIdDict)
227 for key, values
in obsIdDictFlipped.items():
231 obsList.append(obsDictIn[value])
234 obsDictOut[key] = [item
for sublist
in obsList
for item
in sublist]
243 if varName
in [
"sea_water_salinity"]:
244 if 0. <= obsValue <= 50.:
246 elif varName
in [
"sea_water_temperature",
"sea_surface_temperature"]:
247 if -2. <= obsValue <= 100.:
249 elif varName
in [
"obs_absolute_dynamic_topography"]:
250 if -5. <= obsValue <= 5.:
252 elif varName
in [
"sea_ice_area_fraction"]:
253 if 0. <= obsValue <= 1.:
255 elif varName
in [
"sea_ice_thickness"]:
258 raise SystemExit(
"Unknown observation variable %s" % varName)
265 parser = ArgumentParser(
267 formatter_class=ArgumentDefaultsHelpFormatter)
269 '-i',
'--input', help=
'name of the input GMAO ocean obs file(s)',
270 type=str, nargs=
'+', required=
True)
272 '-o',
'--output', help=
'template name of the output IODA file (one per type)',
273 type=str, required=
True)
275 '-d',
'--date', help=
'datetime at the middle of the window', metavar=
'YYYYMMDDHH',
276 type=str, required=
True)
278 '--inputdates', help=
'dates of the input GMAO ocean obs file(s)',
279 type=str, nargs=
'+', required=
False, metavar=
'YYYYMMDDHH')
281 args = parser.parse_args()
284 dList = args.inputdates
285 foutput = args.output
286 fdate = datetime.strptime(args.date,
'%Y%m%d%H')
289 assert len(dList) == len(fList)
290 dList = [datetime.strptime(d,
'%Y%m%d%H')
for d
in dList]
292 dList = [fdate] * len(fList)
295 for fname, idate
in zip(fList, dList):
296 obsList.append(
GMAOobs(fname, idate))
302 for key, value
in varDict.items():
303 fout =
'%s_%s.nc' % (foutput, value)
304 IODA(fout, fdate, key, obsDictSorted[key])
307 if __name__ ==
'__main__':
def __init__(self, filename, date)
def __init__(self, filename, date, varName, obsList)
def __init__(self, filename, date, data)
def discardOb(varName, obsValue)