def setRttovProfiles(h5ProfileFileName, additionalItems=[]): nlevels = 101 nprofiles = 6 myProfiles = pyrttov.Profiles(nprofiles, nlevels) myProfiles.P, profileItems, myProfiles.GasUnits = readProfileItemsH5( h5ProfileFileName, additionalItems) for item in list(profileItems.keys()): exec("myProfiles.{} = profileItems['{}']".format(item, item)) # View/Solar angles # satzen, satazi, sunzen, sunazi #nprofiles, nvar (4) myProfiles.Angles = 0.0 * np.zeros([nprofiles, 4]) # set solar zenith angle below horizon +10 deg myProfiles.Angles[:, 2] = 100.0 #below horizon for solar # s2m surface 2m variables # surface : pressure, temperature, specific humidity, wind (u comp), wind (v comp), windfetch # nprofiles, nvar (6) s2m = [] for i in list(range(nprofiles)): Ps = myProfiles.P[:, -1] Ts = myProfiles.T[:, -1] Qs = myProfiles.Q[:, -1] s2m.append([Ps[i], Ts[i], Qs[i], 0, 0., 10000.]) myProfiles.S2m = np.asarray(s2m) #Skin variables #skin%t, skin%salinity, skin%snow_fraction, skin %foam_fraction, skin%fastem(1:5), skin%specularity #nprofiles, nvar (10) myProfiles.Skin = np.zeros([nprofiles, 10]) myProfiles.Skin[:, 0] = 270.0 myProfiles.Skin[:, 1] = 35.0 #Surface Type info # surftype (land = 0, sea = 1, seacice =2), watertype (fresh = 0, ocean = 1) #nprofiles, nvar (2) myProfiles.SurfType = np.ones([nprofiles, 2]) #Surface geometry # latitude, longitude, elevation (lat/lon used in refractivity and emis/BRDF atlases, elevation used for refractivity). #nprofiles, nvar (3) myProfiles.SurfGeom = np.zeros([nprofiles, 3]) #Date/times #nprofiles, nvar(6) datetimes = [] for i in list(range(nprofiles)): datetimes.append([2015, 8, 1, 0, 0, 0]) myProfiles.DateTimes = np.asarray(datetimes) return myProfiles
def make_profile(n_profiles, n_levels, ice_scheme, ice_paramer, pres, temp, spechum, ozone, sat_angs, s2m, skin, surf_type, surf_geom, datetimes): """Create a set of RTTOV profiles.""" my_profiles = pyrttov.Profiles(n_profiles, n_levels) # We want clouds in g/m3 my_profiles.MmrCldAer = 0 # Set ice cloud types icecloud = np.array([ice_scheme, ice_paramer], dtype=np.int32).transpose() # We want kg/kg for O3 and Q my_profiles.GasUnits = 1 # Set up the actual profiles, expanding for nprofs # This essentially copies the RTTOV example code my_profiles.P = expand2nprofiles(pres, n_profiles) my_profiles.T = expand2nprofiles(temp, n_profiles) my_profiles.Q = expand2nprofiles(spechum, n_profiles) my_profiles.O3 = expand2nprofiles(ozone, n_profiles) my_profiles.Angles = expand2nprofiles(sat_angs, n_profiles) my_profiles.S2m = expand2nprofiles(s2m, n_profiles) my_profiles.Skin = expand2nprofiles(skin, n_profiles) my_profiles.SurfType = expand2nprofiles(surf_type, n_profiles) my_profiles.SurfGeom = expand2nprofiles(surf_geom, n_profiles) my_profiles.DateTimes = expand2nprofiles(datetimes, n_profiles) my_profiles.IceCloud = expand2nprofiles(icecloud, n_profiles) my_profiles.Icede = expand2nprofiles(np.zeros(n_levels), n_profiles) my_profiles.Cirr = expand2nprofiles(np.zeros(n_levels), n_profiles) my_profiles.Cfrac = expand2nprofiles(np.zeros(n_levels), n_profiles) return my_profiles
def do_load(self, inp): """Load an atmospheric profile. Requires inputs for data and resolution.""" # Convert resolution into a number of profiles data, resolution, sun_zen, sun_az = inp.split() resolution = int(resolution) sun_zen = int(sun_zen) sun_az = int(sun_az) # Load the data data = h5py.File("{}/{}.h5".format(PROFILE_DIR, data), 'r') nlevels = len(np.array(data['P'])) # Set up the profiles nprofs = 4 * resolution * resolution self.Profiles = pyrttov.Profiles(nprofs, nlevels) # Set the profile data probs = ['GasUnits', 'Skin'] for key in [key for key in list(data.keys()) if key not in probs]: setattr(self.Profiles, key, np.tile(data[key], (nprofs, 1))) # print('{}\t{}'.format(key, getattr(self.Profiles, key).shape)) setattr(self.Profiles, 'GasUnits', int(np.squeeze(data['GasUnits']))) setattr(self.Profiles, 'Skin', np.tile(list(data['Skin']) + [0], (nprofs, 1))) # Set angles ang_arr = np.empty((resolution, 4 * resolution, 4)) # RTTOV can only handle up to 85 degrees for v9 predicators, otherwise 75 # zen_leg = 85/resolution if '9pred' in self.Rttov.FileCoef else 75/resolution zen_leg = 90 / resolution az_leg = 90 / resolution for zen in range(resolution): for az in range(4 * resolution): ang_arr[zen, az] = [zen_leg * zen, az_leg * az, sun_zen, sun_az] setattr(self.Profiles, 'Angles', ang_arr.reshape((nprofs, 4))) # print(self.Profiles.Angles) # Load the profiles self.Rttov.Profiles = self.Profiles return
def runRTTOV(profileDict): nlevels = profileDict['P'].shape[1] nprofiles = profileDict['P'].shape[0] myProfiles = pyrttov.Profiles(nprofiles, nlevels) myProfiles.GasUnits = 2 myProfiles.P = profileDict['P'] myProfiles.T = profileDict['T'] myProfiles.Q = profileDict['Q'] myProfiles.Angles = profileDict['Angles'] myProfiles.S2m = profileDict['S2m'] myProfiles.Skin = profileDict['Skin'] myProfiles.SurfType = profileDict['SurfType'] myProfiles.SurfGeom = profileDict['SurfGeom'] myProfiles.DateTimes = profileDict['Datetimes'] month = profileDict['Datetimes'][0, 1] # ------------------------------------------------------------------------ # Set up Rttov instance # ------------------------------------------------------------------------ # Create Rttov object for the TIRS instrument tirsRttov = pyrttov.Rttov() # nchan_tirs = 1 # Set the options for each Rttov instance: # - the path to the coefficient file must always be specified # - specify paths to the emissivity and BRDF atlas data in order to use # the atlases (the BRDF atlas is only used for VIS/NIR channels so here # it is unnecessary for HIRS or MHS) # - turn RTTOV interpolation on (because input pressure levels differ from # coefficient file levels) # - set the verbose_wrapper flag to true so the wrapper provides more # information # - enable solar simulations for SEVIRI # - enable CO2 simulations for HIRS (the CO2 profiles are ignored for # the SEVIRI and MHS simulations) # - enable the store_trans wrapper option for MHS to provide access to # RTTOV transmission structure s = pyrttov.__file__ envPath = os.sep.join(s.split(os.sep)[:-6]) rttovPath = os.path.join(envPath, 'share') rttovCoeffPath = os.path.join(rttovPath, 'rttov') rttovEmisPath = os.path.join(rttovCoeffPath, 'emis_data') rttovBRDFPath = os.path.join(rttovCoeffPath, 'brdf_data') if not os.path.exists(rttovBRDFPath): print("downloading atlases.....") ftp = ftplib.FTP("ftp.star.nesdis.noaa.gov") ftp.login("anonymous", "") ftp.cwd('/pub/smcd/emb/mschull/') # change directory to /pub/ getFile(ftp, 'rttov_atlas.tar') ftp.quit() untar('rttov_atlas.tar', rttovPath) subprocess.check_output("chmod 755 %s%s*.H5" % (rttovEmisPath, os.sep), shell=True) subprocess.check_output("chmod 755 %s%s*.H5" % (rttovBRDFPath, os.sep), shell=True) tirsRttov.FileCoef = '{}/{}'.format(rttovCoeffPath, "rtcoef_landsat_8_tirs.dat") tirsRttov.EmisAtlasPath = rttovEmisPath tirsRttov.BrdfAtlasPath = rttovBRDFPath tirsRttov.Options.AddInterp = True tirsRttov.Options.StoreTrans = True tirsRttov.Options.StoreRad2 = True tirsRttov.Options.VerboseWrapper = True # Load the instruments: try: tirsRttov.loadInst() except pyrttov.RttovError as e: sys.stderr.write("Error loading instrument(s): {!s}".format(e)) sys.exit(1) # Associate the profiles with each Rttov instance tirsRttov.Profiles = myProfiles # ------------------------------------------------------------------------ # Load the emissivity and BRDF atlases # ------------------------------------------------------------------------ # Load the emissivity and BRDF atlases: # - load data for August (month=8) # - note that we only need to load the IR emissivity once and it is # available for both SEVIRI and HIRS: we could use either the seviriRttov # or hirsRttov object to do this # - for the BRDF atlas, since SEVIRI is the only VIS/NIR instrument we can # use the single-instrument initialisation tirsRttov.irEmisAtlasSetup(month) # ------------------------------------------------------------------------ # Call RTTOV # ------------------------------------------------------------------------ # Since we want the emissivity/reflectance to be calculated, the # SurfEmisRefl attribute of the Rttov objects are left uninitialised: # That way they will be automatically initialise to -1 by the wrapper # Call the RTTOV direct model for each instrument: # no arguments are supplied to runDirect so all loaded channels are # simulated try: tirsRttov.runDirect() except pyrttov.RttovError as e: sys.stderr.write("Error running RTTOV direct model: {!s}".format(e)) sys.exit(1) return tirsRttov
def runRTTOV(profileDict): nlevels = profileDict['P'].shape[1] nprofiles = profileDict['P'].shape[0] myProfiles = pyrttov.Profiles(nprofiles, nlevels) myProfiles.GasUnits = 2 myProfiles.P = profileDict['P'] myProfiles.T = profileDict['T'] myProfiles.Q = profileDict['Q'] myProfiles.Angles = profileDict['Angles'] myProfiles.S2m = profileDict['S2m'] myProfiles.Skin = profileDict['Skin'] myProfiles.SurfType = profileDict['SurfType'] myProfiles.SurfGeom = profileDict['SurfGeom'] myProfiles.DateTimes = profileDict['Datetimes'] month = profileDict['Datetimes'][0, 1] # ------------------------------------------------------------------------ # Set up Rttov instance # ------------------------------------------------------------------------ # Create Rttov object for the TIRS instrument tirsRttov = pyrttov.Rttov() nchan_tirs = 1 # Set the options for each Rttov instance: # - the path to the coefficient file must always be specified # - specify paths to the emissivity and BRDF atlas data in order to use # the atlases (the BRDF atlas is only used for VIS/NIR channels so here # it is unnecessary for HIRS or MHS) # - turn RTTOV interpolation on (because input pressure levels differ from # coefficient file levels) # - set the verbose_wrapper flag to true so the wrapper provides more # information # - enable solar simulations for SEVIRI # - enable CO2 simulations for HIRS (the CO2 profiles are ignored for # the SEVIRI and MHS simulations) # - enable the store_trans wrapper option for MHS to provide access to # RTTOV transmission structure tirsRttov.FileCoef = '{}/{}'.format( rttov_installdir, "rtcoef_rttov11/rttov7pred54L/rtcoef_landsat_8_tirs.dat") #tirsRttov.EmisAtlasPath = os.path.join(base,'ALEXIdisALEXIfusion','rttov113','emis_data') tirsRttov.EmisAtlasPath = '{}/{}'.format(rttov_installdir, "emis_data") print "%s" % tirsRttov.EmisAtlasPath tirsRttov.BrdfAtlasPath = '{}/{}'.format(rttov_installdir, "brdf_data") #tirsRttov.BrdfAtlasPath = os.path.join(base,'ALEXIdisALEXIfusion','rttov113','brdf_data') tirsRttov.Options.AddInterp = True tirsRttov.Options.StoreTrans = True tirsRttov.Options.StoreRad2 = True tirsRttov.Options.VerboseWrapper = True # Load the instruments: try: tirsRttov.loadInst() except pyrttov.RttovError as e: sys.stderr.write("Error loading instrument(s): {!s}".format(e)) sys.exit(1) # Associate the profiles with each Rttov instance tirsRttov.Profiles = myProfiles # ------------------------------------------------------------------------ # Load the emissivity and BRDF atlases # ------------------------------------------------------------------------ # Load the emissivity and BRDF atlases: # - load data for August (month=8) # - note that we only need to load the IR emissivity once and it is # available for both SEVIRI and HIRS: we could use either the seviriRttov # or hirsRttov object to do this # - for the BRDF atlas, since SEVIRI is the only VIS/NIR instrument we can # use the single-instrument initialisation tirsRttov.irEmisAtlasSetup(month) # ------------------------------------------------------------------------ # Call RTTOV # ------------------------------------------------------------------------ # Since we want the emissivity/reflectance to be calculated, the # SurfEmisRefl attribute of the Rttov objects are left uninitialised: # That way they will be automatically initialise to -1 by the wrapper # Call the RTTOV direct model for each instrument: # no arguments are supplied to runDirect so all loaded channels are # simulated try: tirsRttov.runDirect() except pyrttov.RttovError as e: sys.stderr.write("Error running RTTOV direct model: {!s}".format(e)) sys.exit(1) return tirsRttov
def call_pyrttov(ds, config): """Run RTTOV, return xarray Dataset of reflectance or brightness temperature Args: ds (xr.Dataset): instance returned by xr.open_dataset, select one time config (object): see example below Example: config = setup_VIS() # or setup_IR() ds_xr_out = call_pyrttov(ds_xr_in, config) """ time_dt = get_wrfout_time(ds) print(time_dt) ########### input reading basetemp = 300. p = ds.PB / 100. # (ds.P + ds.PB)/100. # ignore perturbation pressure as this could break monotonicity in p, and RTTOV theta = ds.T + basetemp qv = ds.QVAPOR # Water vapor mixing ratio kg kg-1 qi = ds.QICE # Ice mixing ratio kg kg-1 qc = ds.QCLOUD cfrac = ds.CLDFRA tsk = ds.TSK u, v = ds.U10, ds.V10 psfc = ds.PSFC / 100. try: # in case that input is a wrfinput file (doesnt have these fields) albedo = ds.ALBEDO emissivity = ds.EMISS except AttributeError as e: warnings.warn(str(e) + ' -> using default values!') albedo = 0.17 + 0 * tsk emissivity = 0.985 + 0 * tsk nlevels = p.shape[0] def reformat_profile(arr): # reshape to out-dims: (nprofiles, nlevels); convention from TOA to ground return np.flip(arr.values.reshape((nlevels, -1)).transpose(), axis=1) p = reformat_profile(p) theta = reformat_profile(theta) qv = reformat_profile(qv) qi = reformat_profile(qi) qc = reformat_profile(qc) cfrac = reformat_profile(cfrac) nprofiles = p.shape[0] # reshape to (nprofiles, nlevels) u = u.values.reshape((-1, 1)) v = v.values.reshape((-1, 1)) tsk = tsk.values.reshape((-1, 1)) psfc = psfc.values.reshape((-1, 1)) albedo = albedo.values.reshape((-1, 1)) emissivity = emissivity.values.reshape((-1, 1)) ## conversion to Rttov kappa = 2 / 7 tmp = theta * ( p * 1e-3)**kappa # ignoring water vapor in conversion to dry temperature ####### actual rttov seviriRttov = config.seviriRttov irAtlas = config.irAtlas try: brdfAtlas = config.brdfAtlas brdfAtlas.loadBrdfAtlas( time_dt.month, seviriRttov ) # Supply Rttov object to enable single-instrument initialisation brdfAtlas.IncSea = False # Do not use BRDF atlas for sea surface types except AttributeError: pass nprofiles = p.shape[0] nlevels = p.shape[1] print('nlevels:', nlevels, 'nprofiles:', nprofiles) # solar angles lat = 45. lon = 0. sunzen = 90. - get_altitude(lat, lon, time_dt) sunazi = get_azimuth(lat, lon, time_dt) print('sunzen', sunzen, 'sunazi', sunazi) # surface data = lowest model half level data fetch = 100000. * np.ones(nprofiles) sfc_p_t_qv_u_v_fetch = np.stack( [psfc[:, 0], tmp[:, -1], qv[:, -1], u[:, 0], v[:, 0], fetch], axis=1).astype(np.float64) # sfc_u_v_fetch = np.array([[1., 1., 100000.]], dtype=np.float64) # sfc_u_v_fetch = expand(nprofiles, sfc_u_v_fetch) # sfc_p_t_qv_u_v_fetch = np.concatenate((arr[:,-1,:3], sfc_u_v_fetch), axis=-1) # quickfix qv # Q[:, :22] = 1e-6 # kg/kg until 120 hPa if True: # FIXME: is this necessary? qv[qv < 1e-9] = 1e-9 # print('surface p_t_qv_u_v_fetch:', sfc_p_t_qv_u_v_fetch[0,...]) # print('lowest level p tmp qv qc:', arr[0, -1, :]) # print('min sp', arr[:,-1,0].min()) # print('uppermost level p tmp qv qc:', arr[0, 0, :]) def expand2nprofiles(n, nprof): # Transform 1D array to a [nprof, nlevels] array outp = np.empty((nprof, len(n)), dtype=n.dtype) for i in range(nprof): outp[i, :] = n[:] return outp # Declare an instance of Profiles myProfiles = pyrttov.Profiles(nprofiles, nlevels) myProfiles.GasUnits = 1 # kg/kg for mixing ratios [ ppmv_dry=0, kg_per_kg=1, ppmv_wet=2 ] myProfiles.MmrCldAer = True # kg/kg for clouds and aerosoles myProfiles.P = p myProfiles.T = tmp myProfiles.Q = qv clw = qc # cloud liquid water ciw = qi # cloud ice water # input on layers; (nprofiles, nlevels) # myProfiles.CO2 = np.ones((nprofiles,nlevels))*3.743610E+02 # for MW channels # myProfiles.CLW = clw # quickfix debug = False if debug: print('cfrac', np.min(cfrac), np.max(cfrac)) myProfiles.Cfrac = cfrac # cloud fraction # WATER CLOUDS dummy = np.ones((nprofiles, 2)) dummy[:, 0] = 2 # clw_scheme : (1) OPAC or (2) Deff scheme dummy[:, 1] = 1 # clwde_param : currently only "1" possible myProfiles.ClwScheme = dummy myProfiles.Clwde = 20 * np.ones( (nprofiles, nlevels)) # microns effective diameter # Cloud types - concentrations in kg/kg myProfiles.Stco = clw # Stratus Continental STCO myProfiles.Stma = 0 * clw # Stratus Maritime STMA myProfiles.Cucc = 0 * clw # Cumulus Continental Clean CUCC myProfiles.Cucp = 0 * clw # Cumulus Continental Polluted CUCP myProfiles.Cuma = 0 * clw # Cumulus Maritime CUMA myProfiles.Cirr = ciw # all ice clouds CIRR # icecloud[2][nprofiles]: ice_scheme, idg icecloud = np.array([[1, 1]], dtype=np.int32) myProfiles.IceCloud = expand(nprofiles, icecloud) myProfiles.Icede = 60 * np.ones( (nprofiles, nlevels)) # microns effective diameter myProfiles.S2m = expand(nprofiles, sfc_p_t_qv_u_v_fetch) t_np = np.array([[ time_dt.year, time_dt.month, time_dt.day, time_dt.hour, time_dt.minute, 0 ]], dtype=np.int32) myProfiles.DateTimes = expand(nprofiles, t_np) # angles[4][nprofiles]: satzen, satazi, sunzen, sunazi angles = np.array([[45., 180., sunzen, sunazi]], dtype=np.float64) myProfiles.Angles = expand(nprofiles, angles) # surfgeom[3][nprofiles]: lat, lon, elev surfgeom = np.array([[lat, lon, 0.49]], dtype=np.float64) myProfiles.SurfGeom = expand(nprofiles, surfgeom) # surftype[2][nprofiles]: surftype, watertype surftype = np.array([[0, 0]], dtype=np.int32) myProfiles.SurfType = expand(nprofiles, surftype) # skin[10][nprofiles]: skin T, salinity, snow_frac, foam_frac, fastem_coefsx5, specularity skin = np.array([[270., 35., 0., 0., 3.0, 5.0, 15.0, 0.1, 0.3]], dtype=np.float64) myProfiles.Skin = expand(nprofiles, skin) myProfiles.Skin[:, 0] = tsk[:, 0] seviriRttov.Profiles = myProfiles irAtlas.loadIrEmisAtlas( time_dt.month, ang_corr=True ) # Include angular correction, but do not initialise for single-instrument ####################################### # Set up the surface emissivity/reflectance arrays and associate with the Rttov objects surfemisrefl_seviri = np.zeros((4, nprofiles, config.nchan), dtype=np.float64) surfemisrefl_seviri[0, :, :] = emissivity # emissivity surfemisrefl_seviri[1, :, :] = albedo / np.pi # reflectance surfemisrefl_seviri[2, :, :] = 0. # diffuse reflectance surfemisrefl_seviri[3, :, :] = 0. # specularity seviriRttov.SurfEmisRefl = surfemisrefl_seviri albedo_emiss_by_RTTOV = False if albedo_emiss_by_RTTOV: # Surface emissivity/reflectance arrays must be initialised *before every call to RTTOV* # Negative values will cause RTTOV to supply emissivity/BRDF values (i.e. equivalent to # calcemis/calcrefl TRUE - see RTTOV user guide) # Call emissivity and BRDF atlases try: # Do not supply a channel list for SEVIRI: this returns emissivity/BRDF values for all # *loaded* channels which is what is required surfemisrefl_seviri[:, :, 0] = irAtlas.getEmisBrdf(seviriRttov) surfemisrefl_seviri[:, :, 1] = brdfAtlas.getEmisBrdf(seviriRttov) except pyrttov.RttovError as e: # If there was an error the emissivities/BRDFs will not have been modified so it # is OK to continue and call RTTOV with calcemis/calcrefl set to TRUE everywhere sys.stderr.write("Error calling atlas: {!s}".format(e)) # Call the RTTOV direct model for each instrument: # no arguments are supplied to runDirect so all loaded channels are simulated try: t = time.time() seviriRttov.runDirect() t = time.time() - t print('took', int(t * 10) / 10., 's') except pyrttov.RttovError as e: sys.stderr.write("Error running RTTOV direct model: {!s}".format(e)) print('output shape:', (seviriRttov.BtRefl.shape)) if seviriRttov.RadQuality is not None: print('Quality (qualityflag>0, #issues):', np.sum(seviriRttov.RadQuality > 0)) dsout = ds.copy() delvars = [a for a in list(ds.variables) if not a in ['XLAT', 'XLONG']] # 'OLR', dsout = dsout.drop_vars(delvars) # save each channel to separate file if debug: mmin = data.ravel().min() mmax = data.ravel().max() print(name, 'min:', mmin, 'max:', mmax) nx, ny = len(ds.west_east), len(ds.south_north) #data = np.zeros((ny, nx), dtype=np.float32) for i, name in enumerate(config.chan_seviri_names): data = seviriRttov.BtRefl[:, i] dsout[name] = (("south_north", "west_east"), data.reshape(ny, nx).astype(np.float32)) dsout.coords['time'] = time_dt.replace( tzinfo=None) # .strftime('%Y-%m-%d_%H:%M') drop_lat_lon = True # switch to False to retain coordinates from input file. if drop_lat_lon: dsout = dsout.drop_vars(['XLAT', 'XLONG']) return dsout