13 from datetime
import datetime, timedelta
14 from pathlib
import Path
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()))
21 import ioda_conv_ncio
as iconv
22 from collections
import defaultdict, OrderedDict
23 from orddicts
import DefaultOrderedDict
26 (
"latitude",
"float"),
27 (
"longitude",
"float"),
28 (
"datetime",
"string")
32 'soil_moisture':
'soilMoistureVolumetric',
36 'converter': os.path.basename(__file__),
45 self.
varDictvarDict = defaultdict(
lambda: defaultdict(dict))
55 for iodavar
in [
'soilMoistureVolumetric']:
56 self.
varDictvarDict[iodavar][
'valKey'] = iodavar, self.
writerwriter.OvalName()
57 self.
varDictvarDict[iodavar][
'errKey'] = iodavar, self.
writerwriter.OerrName()
58 self.
varDictvarDict[iodavar][
'qcKey'] = iodavar, self.
writerwriter.OqcName()
59 self.
unitsunits[iodavar] =
'm3m-3'
61 ncd = nc.Dataset(self.
filenamefilename,
'r')
64 self.
sensorsensor =
"radar and radiometer"
65 AttrData[
"satellite"] = self.
satellitesatellite
66 AttrData[
"sensor"] = self.
sensorsensor
68 data = ncd.groups[
'Soil_Moisture_Retrieval_Data'].variables[
'soil_moisture'][:]
69 vals = data[:].ravel()
70 _FillValue = ncd.groups[
'Soil_Moisture_Retrieval_Data'].variables[
'soil_moisture'].getncattr(
'_FillValue')
71 valid_max = ncd.groups[
'Soil_Moisture_Retrieval_Data'].variables[
'soil_moisture'].getncattr(
'valid_max')
72 valid_min = ncd.groups[
'Soil_Moisture_Retrieval_Data'].variables[
'soil_moisture'].getncattr(
'valid_min')
74 lats = ncd.groups[
'Soil_Moisture_Retrieval_Data'].variables[
'latitude'][:].ravel()
75 lons = ncd.groups[
'Soil_Moisture_Retrieval_Data'].variables[
'longitude'][:].ravel()
76 errs = ncd.groups[
'Soil_Moisture_Retrieval_Data'].variables[
'soil_moisture_error'][:].ravel()
77 qflg = ncd.groups[
'Soil_Moisture_Retrieval_Data'].variables[
'retrieval_qual_flag'][:].ravel()
78 times = np.empty_like(vals, dtype=object)
80 if self.
maskmask ==
"maskout":
81 with np.errstate(invalid=
'ignore'):
82 mask = (vals > valid_min) & (vals < valid_max)
91 str_split = self.
filenamefilename.split(
"_")
92 str_datetime = str_split[7]
93 my_datetime = datetime.strptime(str_datetime,
"%Y%m%dT%H%M%S")
94 base_datetime = my_datetime.strftime(
'%Y-%m-%dT%H:%M:%SZ')
96 qflg = qflg.astype(
'int32')
97 AttrData[
'date_time_string'] = base_datetime
99 for i
in range(len(lons)):
103 errs[i] = 0.04*vals[i]
111 times[i] = base_datetime
112 self.
loc_mdataloc_mdata[
'datetime'] = self.
writerwriter.FillNcVector(times,
"datetime")
113 self.
loc_mdataloc_mdata[
'latitude'] = lats
114 self.
loc_mdataloc_mdata[
'longitude'] = lons
115 for iodavar
in [
'soilMoistureVolumetric']:
116 self.
outdataoutdata[self.
varDictvarDict[iodavar][
'valKey']] = vals
117 self.
outdataoutdata[self.
varDictvarDict[iodavar][
'errKey']] = errs
119 self.
writerwriter._nvars = len(obsvars)
125 parser = argparse.ArgumentParser(
126 description=(
'Read SMAP surface soil moisture file(s) and Converter'
127 ' of native h5 format for observations of surface'
128 ' soil moisture to IODA netCDF format.')
130 parser.add_argument(
'-i',
'--input',
131 help=
"name of smap surface soil moisture input file(s)",
132 type=str, required=
True)
133 parser.add_argument(
'-o',
'--output',
134 help=
"name of ioda output file",
135 type=str, required=
True)
136 optional = parser.add_argument_group(title=
'optional arguments')
137 optional.add_argument(
139 help=
"maskout missing values: maskout/default, default=none",
140 type=str, required=
True)
142 args = parser.parse_args()
144 writer = iconv.NcWriter(args.output, locationKeyList)
147 ssm =
smap(args.input, args.mask, writer)
149 writer.BuildNetcdf(ssm.outdata, ssm.loc_mdata, ssm.var_mdata, AttrData, ssm.units)
152 if __name__ ==
'__main__':
def __init__(self, filename, mask, writer)