7 from collections
import defaultdict, OrderedDict
10 import ioda_conv_ncio
as iconv
13 from orddicts
import DefaultOrderedDict
20 wrfda_miss_float = -888888.
21 wrfda_miss_int = -888888
24 'date': [(
'datetime',
'string')],
25 'lat': [(
'latitude',
'float')],
26 'lon': [(
'longitude',
'float')],
27 'elv': [(
'height_above_mean_sea_level',
'float')],
28 'scanpos': [(
'scan_position',
'float')],
29 'satzen': [(
'sensor_zenith_angle',
'float'),
30 (
'sensor_view_angle',
'float')],
31 'satazi': [(
'sensor_azimuth_angle',
'float')],
32 'solzen': [(
'solar_zenith_angle',
'float')],
33 'solazi': [(
'solar_azimuth_angle',
'float')],
34 'cloud_frac': [(
'cloud_area_fraction',
'float')],
41 'tb_err':
'WrfdaFinalObsError',
46 rad_platform_sensor_combos = [
78 wrfda2crtm_satellite_map = {
86 'himawari-8':
'himawari8',
100 sensor_chanlist_dict = {
101 'abi': list(range(7, 17)),
102 'ahi': list(range(7, 17)),
105 rad_platform_sensor_ObsError = {
106 'goes-16-abi': [2.720, 1.790, 1.920, 1.740, 5.000, wrfda_miss_float, 3.080, 3.060, 2.820, 1.740],
107 'goes-17-abi': [wrfda_miss_float]*10,
108 'himawari-8-ahi': [1.052, 1.700, 1.700, 1.350, 0.814, wrfda_miss_float, 0.871, 0.926, 0.933, 0.787],
116 'virtual_temperature':
'K',
117 'atmosphere_ln_pressure_coordinate':
'1',
118 'specific_humidity':
'1',
119 'northward_wind':
'm s-1',
120 'eastward_wind':
'm s-1',
121 'geopotential_height':
'm',
122 'height_above_mean_sea_level':
'm',
123 'surface_pressure':
'Pa',
124 'surface_temperature':
'K',
125 'surface_roughness_length':
'm',
126 'surface_geopotential_height':
'm',
127 'land_area_fraction':
'1',
128 'air_temperature':
'K',
129 'air_pressure':
'Pa',
130 'air_pressure_levels':
'Pa',
131 'humidity_mixing_ratio':
'1',
132 'mole_fraction_of_carbon_dioxide_in_air':
'1',
133 'mole_fraction_of_ozone_in_air':
'1',
134 'atmosphere_mass_content_of_cloud_liquid_water':
'kg m-2',
135 'effective_radius_of_cloud_liquid_water_particle':
'm',
136 'atmosphere_mass_content_of_cloud_ice':
'kg m-2',
137 'effective_radius_of_cloud_ice_particle':
'm',
138 'water_area_fraction':
'1',
139 'land_area_fraction':
'1',
140 'ice_area_fraction':
'1',
141 'surface_snow_area_fraction':
'1',
142 'vegetation_area_fraction':
'1',
143 'surface_temperature_where_sea':
'K',
144 'surface_temperature_where_land':
'K',
145 'surface_temperature_where_ice':
'K',
146 'surface_temperature_where_snow':
'K',
147 'surface_wind_speed':
'm s-1',
148 'surface_wind_from_direction':
'degree',
149 'leaf_area_index':
'1',
150 'volume_fraction_of_condensed_water_in_soil':
'1',
151 'soil_temperature':
'K',
152 'land_type_index':
'1',
153 'vegetation_type_index':
'1',
155 'surface_snow_thickness':
'm',
156 'humidity_mixing_ratio':
'1',
157 'wind_reduction_factor_at_10m':
'1',
172 'latitude':
'degrees_north',
173 'longitude':
'degrees_east',
174 'station_elevation':
'm',
176 'height_above_mean_sea_level':
'm',
177 'cloud_area_fraction':
'1',
178 'scan_position':
'1',
179 'sensor_azimuth_angle':
'degree',
180 'sensor_zenith_angle':
'degree',
181 'sensor_view_angle':
'degree',
182 'solar_zenith_angle':
'degree',
183 'solar_azimuth_angle':
'degree',
184 'modis_deep_blue_flag':
'1',
185 'row_anomaly_index':
'1',
186 'top_level_pressure':
'Pa',
187 'bottom_level_pressure':
'Pa',
188 'tropopause_pressure':
'Pa',
189 'brightness_temperature_jacobian_surface_temperature':
'1',
190 'brightness_temperature_jacobian_surface_emissivity':
'K',
191 'brightness_temperature_jacobian_air_temperature':
'1',
192 'brightness_temperature_jacobian_humidity_mixing_ratio':
'K/g/Kg ',
193 'optical_thickness_of_atmosphere_layer':
'1',
207 """ class Radiances - satellite radiance observations
209 Use this class to read in satellite radiance observations
210 from WRFDA netCDF diag files
215 filename - string path to file
216 validtime - datetime object of valid observation time
217 nobs - number of observations
224 splitfname = self.
filenamefilename.split(
'/')[-1].split(
'_')
226 for s
in rad_platform_sensor_combos:
229 i = splitfname.index(s)
231 raise ValueError(
"Observation is not a radiance type...")
235 df = nc.Dataset(self.
filenamefilename)
236 tstr = self.
filenamefilename.split(
'/')[-1].split(
'_')[-1].split(
'.')[0]
237 self.
validtimevalidtime = dt.datetime.strptime(tstr,
"%Y%m%d%H")
240 satellite =
"-".join(self.
platform_sensorplatform_sensor.split(
'-')[0:-1])
241 if satellite
in wrfda2crtm_satellite_map:
242 self.
satellitesatellite = wrfda2crtm_satellite_map[satellite]
244 print(
"ERROR: Satellite not found in wrfda2crtm_satellite_map:")
249 self.
nlocsnlocs = len(df.dimensions[
'npixel'])
250 self.
nchansnchans = len(df.dimensions[
'nchan'])
257 def toIODAobs(self, OutDir, clobber=True, dateSubDirs=False):
258 """ toIODAobs(OutDir,clobber=True)
259 output observations from the specified WRFDA diag file
260 to the JEDI/IODA observation format
265 fullOutDir = fullOutDir +
'/' + self.
validtimevalidtime.strftime(
"%Y%m%d%H")
268 os.makedirs(fullOutDir)
269 except OSError
as exc:
270 if exc.errno == errno.EEXIST
and os.path.isdir(fullOutDir):
274 outname = fullOutDir +
'/' + self.
sensorsensor +
'_' + self.
satellitesatellite + \
275 '_obs_' + self.
validtimevalidtime.strftime(
"%Y%m%d%H") +
'.nc4'
277 if (os.path.exists(outname)):
278 print(
"File exists. Skipping and not overwriting:")
286 varDict = defaultdict(
lambda: defaultdict(dict))
292 for ncv
in self.
dfdf.variables:
293 if ncv
in all_LocKeyList:
294 for val
in all_LocKeyList[ncv]:
295 LocKeyList.append(val)
299 for ncv
in self.
dfdf.variables:
300 if ncv
in test_fields:
301 TestKeyList.append(test_fields[ncv])
306 writer = iconv.NcWriter(outname, LocKeyList, TestKeyList=TestKeyList)
308 if self.
sensorsensor
in sensor_chanlist_dict:
309 chanlist = sensor_chanlist_dict[self.
sensorsensor]
311 chanlist = list(range(1, self.nchan+1))
312 nchans = len(chanlist)
314 for chan
in chanlist:
315 value =
"brightness_temperature_{:d}".format(chan)
316 varDict[value][
'valKey'] = value, writer.OvalName()
317 varDict[value][
'errKey'] = value, writer.OerrName()
318 varDict[value][
'qcKey'] = value, writer.OqcName()
319 units_values[value] =
'K'
321 for ivar, lvar
in enumerate(LocVars):
322 loc_mdata_name = LocKeyList[ivar][0]
323 loc_mdata_type = LocKeyList[ivar][1]
325 tmp = self.
dfdf[lvar][:]
326 obstimes = [dt.datetime.strptime(
"".join(a.astype(str)),
"%Y-%m-%d_%H:%M:%S")
for a
in tmp]
327 obstimes = [a.strftime(
"%Y-%m-%dT%H:%M:%SZ")
for a
in obstimes]
328 loc_mdata[loc_mdata_name] = writer.FillNcVector(obstimes,
"datetime")
330 if loc_mdata_type ==
'float':
331 tmp = self.
dfdf[lvar][:].astype(float)
332 tmp[tmp <= wrfda_miss_float] = nc.default_fillvals[
'f4']
334 tmp = self.
dfdf[lvar][:]
335 loc_mdata[loc_mdata_name] = tmp
338 for tvar
in TestVars:
339 test_mdata_name = test_fields[tvar][0]
340 tmp = self.
dfdf[tvar][:]
341 tmp[tmp <= wrfda_miss_float] = nc.default_fillvals[
'f4']
342 test_mdata[test_mdata_name] = tmp
345 for wrfdavar, iodavar
in wrfda_add_vars.items():
346 if wrfdavar
in self.
dfdf.variables:
347 tmp = np.transpose(np.asarray(self.
dfdf[wrfdavar]))
349 tmp[tmp <= wrfda_miss_float] = nc.default_fillvals[
'f4']
350 for c, chan
in enumerate(chanlist):
351 varname =
"brightness_temperature_{:d}".format(chan)
352 gvname = varname, iodavar
354 outdata[gvname] = outvals
358 obsdata = np.transpose(np.asarray(self.
dfdf[
'tb_obs']))
359 obserr = rad_platform_sensor_ObsError[self.
platform_sensorplatform_sensor]
361 obsqc = np.transpose(np.asarray(self.
dfdf[
'tb_qc']))
365 for c, chan
in enumerate(chanlist):
366 value =
"brightness_temperature_{:d}".format(chan)
367 var_names.append(value)
369 obsdatasub = obsdata[c]
370 obsdatasub[obsdatasub <= wrfda_miss_float] = nc.default_fillvals[
'f4']
372 obserrsub = np.full(self.
nlocsnlocs, obserr[c])
373 obserrsub[obserrsub <= wrfda_miss_float] = nc.default_fillvals[
'f4']
376 obsqcsub[obsqcsub <= wrfda_miss_int] = nc.default_fillvals[
'i4']
379 outdata[varDict[value][
'valKey']] = obsdatasub
380 outdata[varDict[value][
'errKey']] = obserrsub
381 outdata[varDict[value][
'qcKey']] = obsqcsub.astype(int)
384 var_mdata[
'variable_names'] = writer.FillNcVector(var_names,
"string")
385 var_mdata[
'sensor_channel'] = np.asarray(chanlist)
389 AttrData[
"date_time_string"] = self.
validtimevalidtime.strftime(
"%Y-%m-%dT%H:%M:%SZ")
390 AttrData[
"satellite"] = self.
satellitesatellite
391 AttrData[
"sensor"] = self.
sensorsensor
395 writer._nvars = nchans
396 writer._nlocs = self.
nlocsnlocs
398 writer.BuildNetcdf(outdata, loc_mdata, var_mdata,
399 AttrData, units_values, test_mdata)
400 print(
"Satellite radiance obs processed, wrote to:")
def __init__(self, filename)
def toIODAobs(self, OutDir, clobber=True, dateSubDirs=False)