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 orddicts
import DefaultOrderedDict
25 'A':
"aerosol_optical_depth_4",
29 (
"latitude",
"float"),
30 (
"longitude",
"float"),
31 (
"datetime",
"string")
39 def __init__(self, filename, method, mask, thin, writer):
49 ncd = nc.Dataset(self.
filenamefilename)
50 lons = ncd.variables[
'Longitude'][:].ravel()
51 lats = ncd.variables[
'Latitude'][:].ravel()
52 vals = ncd.variables[
'AOD550'][:].ravel()
53 errs = ncd.variables[
'Residual'][:].ravel()
54 qcpath = ncd.variables[
'QCPath'][:].ravel()
55 qcall = ncd.variables[
'QCAll'][:].ravel()
56 if self.
maskmask ==
"maskout":
57 mask = np.logical_not(vals.mask)
65 gatts = {attr: getattr(ncd, attr)
for attr
in ncd.ncattrs()}
66 base_datetime = gatts[
"time_coverage_end"]
68 self.
sensorsensor = gatts[
"instrument_name"]
71 valKey = vName[
'A'], self.
writerwriter.OvalName()
72 errKey = vName[
'A'], self.
writerwriter.OerrName()
73 qcKey = vName[
'A'], self.
writerwriter.OqcName()
76 if self.
thinthin > 0.0:
77 mask_thin = np.random.uniform(size=len(lons)) > self.
thinthin
78 lons = lons[mask_thin]
79 lats = lats[mask_thin]
80 vals = vals[mask_thin]
81 errs = errs[mask_thin]
82 qcpath = qcpath[mask_thin]
83 qcall = qcall[mask_thin]
86 sfcKey =
"surface_type",
"MetaData"
87 szaKey =
"sol_zenith_angle",
"MetaData"
88 saaKey =
"sol_azimuth_angle",
"MetaData"
89 mduKey =
"modis_deep_blue_flag",
"MetaData"
90 biaKey =
"aerosol_optical_depth_4",
"KnownObsBias"
94 uncertainty = 0.0*errs
95 uncertainty1 = 0.0*errs
96 uncertainty2 = 0.0*errs
101 if self.
methodmethod ==
"nesdis":
103 uncertainty = 0.00784394 + 0.219923*vals
104 bias = 0.0151799 + 0.0767385*vals
106 uncertainty1 = 0.0550472 + 0.299558*vals
107 bias1 = -0.0107621 + 0.150480*vals
109 uncertainty2 = 0.111431 + 0.128699*vals
110 bias2 = -0.0138969 + 0.157877*vals
112 for i
in range(len(lons)):
115 sfctyp[i] = int.from_bytes(qcpath[i], byteorder=
'big')
116 if self.
methodmethod ==
"nesdis":
119 uncertainty[i] = uncertainty1[i]
122 uncertainty[i] = uncertainty2[i]
123 errs[i] = uncertainty[i]
125 locKey = lats[i], lons[i], base_datetime
126 self.
datadata[0][locKey][valKey] = vals[i]
127 self.
datadata[0][locKey][errKey] = errs[i]
128 self.
datadata[0][locKey][qcKey] = qcall[i]
129 self.
datadata[0][locKey][biaKey] = bias[i]
134 self.
datadata[0][locKey][szaKey] = 0.0
135 self.
datadata[0][locKey][saaKey] = 0.0
136 self.
datadata[0][locKey][sfcKey] = sfctyp[i]
137 self.
datadata[0][locKey][mduKey] = 0
142 if self.
sensorsensor ==
'VIIRS':
143 self.
sensorsensor =
"v.viirs-m_npp"
145 AttrData[
"observation_type"] =
"AOD"
146 AttrData[
"satellite"] = self.
satellitesatellite
147 AttrData[
"sensor"] = self.
sensorsensor
148 AttrData[
'date_time_string'] = base_datetime
153 parser = argparse.ArgumentParser(
154 description=(
'Read VIIRS aerosol optical depth file(s) and Converter'
155 ' of native NetCDF format for observations of optical'
156 ' depth from VIIRS AOD550 to IODA netCDF format.')
158 parser.add_argument(
'-i',
'--input',
159 help=
"name of viirs aod input file(s)",
160 type=str, required=
True)
161 parser.add_argument(
'-o',
'--output',
162 help=
"name of ioda output file",
163 type=str, required=
True)
164 optional = parser.add_argument_group(title=
'optional arguments')
165 optional.add_argument(
167 help=
"calculation bias/error method: nesdis/default, default=none",
168 type=str, required=
True)
169 optional.add_argument(
171 help=
"maskout missing values: maskout/default, default=none",
172 type=str, required=
True)
173 optional.add_argument(
175 help=
"percentage of random thinning, from 0.0 to 1.0. Zero indicates"
176 " no thinning is performed. (default: %(default)s)",
177 type=float, default=0.0)
179 args = parser.parse_args()
181 writer = iconv.NcWriter(args.output, locationKeyList)
184 aod =
AOD(args.input, args.method, args.mask, args.thin, writer)
186 (ObsVars, LocMdata, VarMdata) = writer.ExtractObsData(aod.data)
189 VarMdata[
'frequency'] = np.full(1, 5.401666e+14, dtype=
'f4')
190 VarMdata[
'polarization'] = np.full(1, 1, dtype=
'i4')
191 VarMdata[
'wavenumber'] = np.full(1, 18161.61, dtype=
'f4')
192 VarMdata[
'sensor_channel'] = np.full(1, 4, dtype=
'i4')
194 writer.BuildNetcdf(ObsVars, LocMdata, VarMdata, AttrData)
197 if __name__ ==
'__main__':
def __init__(self, filename, method, mask, thin, writer)