def from_era(ident, alt=0, lon=0, lat=0, savename='extract_ERA', verbose=0): """ Updated Version of profiles and surface # Can read ERA data from retrieved and converted MARS Requests ERADIR Parameters ---------- ident str/int/float Radiosonde ID alt int/float Radiosonde Station Altitude lon int/float Radiosonde Station Longitude lat int/float Radiosonde Station Latitude savename str Extract savename verbose int verboseness Returns ------- """ from raso.support import print_verbose, panel_to_database from raso.met.conversion import sh2ppmv, sh2vap, bolton_inverse, vap2sh from raso.met.esat_functions import foeewm from raso.config import rasodir # eradir from raso.qc import profile_limits # read new era file if isinstance(ident, (int, float)): ident = "%06d" % ident filename = rasodir + "/%s/%s.h5" % (ident, savename) cnames = ['t2m', 'q2m', 'msl', 'u10', 'v10', 'fetch', 'skt', 'FASTEM_1', 'FASTEM_2', 'FASTEM_3', 'FASTEM_4', 'FASTEM_5', 'surf_type', 'water_type', 'elev', 'lat', 'lon', 'sat_zen', 'sat_azi', 'sol_zen', 'sol_azi', 'cltp', 'clf'] surface = {} # pd.DataFrame(columns=cnames) era = {} if not os.path.isfile(filename): raise IOError('File not found: %s' % filename) with pd.HDFStore(filename, 'r') as store: for ikey in store.keys(): iname = ikey.replace('/', '') if ikey[1:] in ['t', 'q', 'o3']: # profile data tmp = store[ikey] tmp.index.name = 'date' tmp.columns.name = 'p' # tmp = tmp.reset_index().drop_duplicates('date').set_index('date') # remove duplicates era[iname] = tmp # DataFrame (time x p) else: # surface data if iname == 'sp': surface['msl'] = store[ikey][0] / 100. # [dates] / 100. # hPa elif iname == 'ci': # sea ice cover surface['surf_type'] = store[ikey][0] elif iname == 'u10': surface['u10'] = store[ikey][0] elif iname == 'v10': surface['v10'] = store[ikey][0] else: surface[iname] = store[ikey][0] era = pd.Panel(era) era = panel_to_database(era, remove=False) # ERA can have negative Q values !? qerror = era.query('q<=0').q.count() print_verbose("[%s] Found %d negative Q-values!" % (ident, qerror), verbose) # Interpolate limits rt = profile_limits(tohpa=True, simple_names=True) rt['qmin'] = vap2sh(rt.vpmin.values, rt.p.values) # both missing hPa factor qmins = np.interp(np.log(era.p.values), np.log(rt.p.values*100.), rt.qmin.values, left=rt.qmin.min(), right=rt.qmin.max()) # Interpolate Minimum Q era['q'] = np.where(era.q < qmins, qmins, era.q) # replace with RTTOV limit # Make a dataframe surface = pd.DataFrame(surface) surface['q2m'] = sh2ppmv(era.query('p==100000')['q'], 100000.) # ppmv surface['fetch'] = 100000. # m # FASTEM Surface model Parameters: surface['FASTEM_1'] = 3.0 surface['FASTEM_2'] = 5.0 surface['FASTEM_3'] = 15.0 surface['FASTEM_4'] = 0.1 surface['FASTEM_5'] = 0.3 # surface properties if 'surf_type' in surface.columns: if surface['surf_type'].isnull().any(0): if surface['surf_type'].count() > 0: surface['surf_type'].fillna(method='bfill') # backwards fill surface['surf_type'].fillna(method='ffill') # forward fill else: surface['surf_type'] = 0. # surface type (0=land, 1=sea, 2=sea-ice) else: surface['surf_type'] = 0. # surface type (0=land, 1=sea, 2=sea-ice) surface['water_type'] = 0. # water type (0=fresh, 1=ocean) surface['elev'] = alt / 1000. # ELEVATION km surface['lat'] = lat # LAT surface['lon'] = lon # LON surface['sat_azi'] = 0. # Satellite Azimuth Angle surface['sat_zen'] = 53.1 # OSCAR , SSMIS surface['sol_zen'] = 0. # Solar Zenith Angle surface['sol_azi'] = 0. # Solar Azimuth Angle surface['cltp'] = 500. # Cloud top pressure surface['clf'] = 0. # Cloud fraction # right order surface = surface[cnames].copy() # CONVERT TO WATER VAPOR PRESSURE in Pa era['vp'] = sh2vap(era['q'], era['p']) # formula era['td'] = bolton_inverse(era.vp.values) # default method from Murphy and Koop (iterative) logic = era['td'] > era['t'] # impossible era.loc[:, 'td'] = np.where(logic, era['t'].values, era['td'].values) era.loc[:, 'vp'] = np.where(logic, foeewm(era['t'].values), era['vp'].values) # ? fixes some problems ? return surface, era