def run_calcs(df, ctx): """Do our maths.""" # Convert sea level pressure to station pressure df['pressure'] = mcalc.add_height_to_pressure( df['slp'].values * units('millibars'), ctx['nt'].sts[ctx['station']]['elevation'] * units('m')).to( units('millibar')) # Compute the mixing ratio df['mixingratio'] = mcalc.mixing_ratio_from_relative_humidity( df['relh'].values * units('percent'), df['tmpf'].values * units('degF'), df['pressure'].values * units('millibars')) # Compute the saturation mixing ratio df['saturation_mixingratio'] = mcalc.saturation_mixing_ratio( df['pressure'].values * units('millibars'), df['tmpf'].values * units('degF')) df['vapor_pressure'] = mcalc.vapor_pressure( df['pressure'].values * units('millibars'), df['mixingratio'].values * units('kg/kg')).to(units('kPa')) df['saturation_vapor_pressure'] = mcalc.vapor_pressure( df['pressure'].values * units('millibars'), df['saturation_mixingratio'].values * units('kg/kg')).to(units('kPa')) df['vpd'] = df['saturation_vapor_pressure'] - df['vapor_pressure'] group = df.groupby('year') df = group.aggregate(np.average) df['dwpf'] = mcalc.dewpoint(df['vapor_pressure'].values * units('kPa')).to( units('degF')).m return df
def run_calcs(df, ctx): """Do our maths.""" # Convert sea level pressure to station pressure df["pressure"] = mcalc.add_height_to_pressure( df["slp"].values * units("millibars"), ctx["_nt"].sts[ctx["station"]]["elevation"] * units("m"), ).to(units("millibar")) # Compute the mixing ratio df["mixingratio"] = mcalc.mixing_ratio_from_relative_humidity( df["relh"].values * units("percent"), df["tmpf"].values * units("degF"), df["pressure"].values * units("millibars"), ) # Compute the saturation mixing ratio df["saturation_mixingratio"] = mcalc.saturation_mixing_ratio( df["pressure"].values * units("millibars"), df["tmpf"].values * units("degF"), ) df["vapor_pressure"] = mcalc.vapor_pressure( df["pressure"].values * units("millibars"), df["mixingratio"].values * units("kg/kg"), ).to(units("kPa")) df["saturation_vapor_pressure"] = mcalc.vapor_pressure( df["pressure"].values * units("millibars"), df["saturation_mixingratio"].values * units("kg/kg"), ).to(units("kPa")) df["vpd"] = df["saturation_vapor_pressure"] - df["vapor_pressure"] # remove any NaN rows df = df.dropna() group = df.groupby("year") df = group.aggregate(np.average) df["dwpf"] = (mcalc.dewpoint(df["vapor_pressure"].values * units("kPa")).to(units("degF")).m) return df
def equivalent_potential_temperature(pressure, temperature, dewpoint): r"""Calculate equivalent potential temperature. This calculation must be given an air parcel's pressure, temperature, and dewpoint. The implementation uses the formula outlined in [Bolton1980]_: First, the LCL temperature is calculated: .. math:: T_{L}=\frac{1}{\frac{1}{T_{D}-56}+\frac{ln(T_{K}/T_{D})}{800}}+56 Which is then used to calculate the potential temperature at the LCL: .. math:: \theta_{DL}=T_{K}\left(\frac{1000}{p-e}\right)^k \left(\frac{T_{K}}{T_{L}}\right)^{.28r} Both of these are used to calculate the final equivalent potential temperature: .. math:: \theta_{E}=\theta_{DL}\exp\left[\left(\frac{3036.}{T_{L}} -1.78\right)*r(1+.448r)\right] **Parameters** pressure: `pint.Quantity` Total atmospheric pressure temperature: `pint.Quantity` Temperature of parcel dewpoint: `pint.Quantity` Dewpoint of parcel **Returns** `pint.Quantity` The equivalent potential temperature of the parcel Notes ----- [Bolton1980]_ formula for Theta-e is used, since according to [DaviesJones2009]_ it is the most accurate non-iterative formulation available. """ t = temperature.to('kelvin').magnitude td = dewpoint.to('kelvin').magnitude p = pressure.to('hPa').magnitude e = mpcalc.saturation_vapor_pressure(dewpoint).to('hPa').magnitude r = mpcalc.saturation_mixing_ratio(pressure, dewpoint).magnitude kappa = 0.2854 t_l = 56 + 1. / (1. / (td - 56) + np.log(t / td) / 800.) th_l = t * (1000 / (p - e))**kappa * (t / t_l)**(0.28 * r) th_e = th_l * np.exp((3036. / t_l - 1.78) * r * (1 + 0.448 * r)) return th_e * units.kelvin
def mixing_ratio(pressure_arr, temperature_arr, rel_hum_arr): """ Compute the mixing ratio, using the metpy module to obtain the saturation mixing ratio. Mixing ratio is the product of saturation mixing ratio and the relative humidity times the number of grams in a kilogram. It's value is the mass of water vapor in grams in each 1000 grams (1 kg) of atmosphere. """ sat_mix_ratio = calc.saturation_mixing_ratio(pressure_arr, temperature_arr) mixing_ratio = sat_mix_ratio * rel_hum_arr return mixing_ratio
def moist_adiabat(z, SST): p = 1000 * np.exp(-9.81 * z / (287. * 270.)) * units.hPa Tp = mpcalc.moist_lapse(p, (SST - 1) * units.K) qp = 0.8 * mpcalc.saturation_mixing_ratio(p, Tp) ztrop1 = 17e3 ztrop2 = 19e3 idx1 = np.argmin((z - ztrop1)**2) idx2 = np.argmin((z - ztrop2)**2) Tp[idx1:idx2] = Tp[idx1] Tp[idx2:] = Tp[idx1] + 2e-3 * (z[idx2:] - ztrop2) * units.K thetap = mpcalc.potential_temperature(p, Tp) thicknesses = [ mpcalc.thickness_hydrostatic(p, Tp, bottom=p[i], depth=p[i] - p[i + 1]) / units.m for i in range(len(p) - 1) ] zp = np.concatenate([[0.], np.cumsum(thicknesses)]) thetaz = np.interp(z, zp, (thetap / units.K)) qz = np.interp(z, zp, qp) idxs = z < 35000 return z[idxs], np.array([float(x) for x in thetaz ])[idxs], np.array([float(x) for x in qz])[idxs]
def atmCalc(height, temp, humid): print("ATMCALC", height, temp, humid, file=sys.stderr) mtny = windh(MTNX, height, ratio=1, yoffset=0) windx = XVALUES windy = windh(windx, height) temp_ = temp * units.degC initp = mc.height_to_pressure_std(windy[0] * units.meters) dewpt = mc.dewpoint_from_relative_humidity(temp_, humid / 100.) lcl_ = mc.lcl(initp, temp_, dewpt, max_iters=50, eps=1e-5) LCL = mc.pressure_to_height_std(lcl_[0]) if (lcl_[0] > mc.height_to_pressure_std(max(windy) * units.meters) and LCL > windy[0] * units.meters * 1.000009): # add LCL to x xlcl = windh(LCL.to('meters').magnitude, height, inv=True) windx = np.sort(np.append(windx, xlcl)) windy = windh(windx, height) pressures = mc.height_to_pressure_std(windy * units.meters) wvmr0 = mc.mixing_ratio_from_relative_humidity(initp, temp_, humid / 100.) # now calculate the air parcel temperatures and RH at each position if (lcl_[0] <= min(pressures)): T = mc.dry_lapse(pressures, temp_) RH = [ mc.relative_humidity_from_mixing_ratio( wvmr0, t, p) for t, p in zip( T, pressures)] else: mini = np.argmin(pressures) p1 = pressures[:mini + 1] p2 = pressures[mini:] # with an overlap p11 = p1[p1 >= lcl_[0] * .9999999] # lower (with tol) with lcl p12 = p1[p1 < lcl_[0] * 1.000009] # upper (with tol) with lcl T11 = mc.dry_lapse(p11, temp_) T12 = mc.moist_lapse(p12, lcl_[1]) T1 = concatenate((T11[:-1], T12)) T2 = mc.dry_lapse(p2, T1[-1]) T = concatenate((T1, T2[1:])) wvmrtop = mc.saturation_mixing_ratio(pressures[mini], T[mini]) RH=[] for i in range(len(pressures)): if pressures[i] > lcl_[0] and i <= mini: v=mc.relative_humidity_from_mixing_ratio(pressures[i], T[i], wvmr0) else: if i < mini: v=1 else: v=mc.relative_humidity_from_mixing_ratio(pressures[i], T[i], wvmrtop) RH.append(v) #RH = [mc.relative_humidity_from_mixing_ratio(*tp, wvmr0) if tp[1] > lcl_[ #0] and i <= mini else 1.0 if i < mini else #mc.relative_humidity_from_mixing_ratio(*tp, wvmrtop) #for i, tp in enumerate(zip(pressures, T))] RH = concatenate(RH) return windx, mtny, windy, lcl_, LCL, T.to("degC"), RH
def plotter(fdict): """ Go """ pgconn = get_dbconn('asos') ctx = get_autoplot_context(fdict, get_description()) station = ctx['zstation'] network = ctx['network'] nt = NetworkTable(network) year = ctx['year'] varname = ctx['var'] df = read_sql(""" SELECT extract(year from valid) as year, coalesce(mslp, alti * 33.8639, 1013.25) as slp, extract(doy from valid) as doy, tmpf, dwpf from alldata where station = %s and dwpf > -50 and dwpf < 90 and tmpf > -50 and tmpf < 120 and valid > '1950-01-01' and report_type = 2 """, pgconn, params=(station, ), index_col=None) # compute RH df['relh'] = mcalc.relative_humidity_from_dewpoint( df['tmpf'].values * units('degF'), df['dwpf'].values * units('degF')) # saturation vapor pressure # Convert sea level pressure to station pressure df['pressure'] = mcalc.add_height_to_pressure( df['slp'].values * units('millibars'), nt.sts[station]['elevation'] * units('m')).to(units('millibar')) # Compute the relative humidity df['relh'] = mcalc.relative_humidity_from_dewpoint( df['tmpf'].values * units('degF'), df['dwpf'].values * units('degF')) # Compute the mixing ratio df['mixing_ratio'] = mcalc.mixing_ratio_from_relative_humidity( df['relh'].values, df['tmpf'].values * units('degF'), df['pressure'].values * units('millibars')) # Compute the saturation mixing ratio df['saturation_mixingratio'] = mcalc.saturation_mixing_ratio( df['pressure'].values * units('millibars'), df['tmpf'].values * units('degF')) df['vapor_pressure'] = mcalc.vapor_pressure( df['pressure'].values * units('millibars'), df['mixing_ratio'].values * units('kg/kg')).to(units('kPa')) df['saturation_vapor_pressure'] = mcalc.vapor_pressure( df['pressure'].values * units('millibars'), df['saturation_mixingratio'].values * units('kg/kg')).to(units('kPa')) df['vpd'] = df['saturation_vapor_pressure'] - df['vapor_pressure'] dailymeans = df[['year', 'doy', varname]].groupby(['year', 'doy']).mean() dailymeans = dailymeans.reset_index() df2 = dailymeans[['doy', varname]].groupby('doy').describe() dyear = df[df['year'] == year] df3 = dyear[['doy', varname]].groupby('doy').describe() df3[(varname, 'diff')] = df3[(varname, 'mean')] - df2[(varname, 'mean')] (fig, ax) = plt.subplots(2, 1, figsize=(8, 6)) multiplier = 1000. if varname == 'mixing_ratio' else 10. ax[0].fill_between(df2[(varname, 'min')].index.values, df2[(varname, 'min')].values * multiplier, df2[(varname, 'max')].values * multiplier, color='gray') ax[0].plot(df2[(varname, 'mean')].index.values, df2[(varname, 'mean')].values * multiplier, label="Climatology") ax[0].plot(df3[(varname, 'mean')].index.values, df3[(varname, 'mean')].values * multiplier, color='r', label="%s" % (year, )) ax[0].set_title(("%s [%s]\nDaily Mean Surface %s") % (station, nt.sts[station]['name'], PDICT[varname])) lbl = ("Mixing Ratio ($g/kg$)" if varname == 'mixing_ratio' else PDICT[varname]) ax[0].set_ylabel(lbl) ax[0].set_xlim(0, 366) ax[0].set_ylim(bottom=0) ax[0].set_xticks( (1, 32, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 365)) ax[0].set_xticklabels(calendar.month_abbr[1:]) ax[0].grid(True) ax[0].legend(loc=2, fontsize=10) cabove = 'b' if varname == 'mixing_ratio' else 'r' cbelow = 'r' if cabove == 'b' else 'b' rects = ax[1].bar(df3[(varname, 'diff')].index.values, df3[(varname, 'diff')].values * multiplier, facecolor=cabove, edgecolor=cabove) for rect in rects: if rect.get_height() < 0.: rect.set_facecolor(cbelow) rect.set_edgecolor(cbelow) plunits = '$g/kg$' if varname == 'mixing_ratio' else 'hPa' ax[1].set_ylabel("%.0f Departure (%s)" % (year, plunits)) ax[1].set_xlim(0, 366) ax[1].set_xticks( (1, 32, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 365)) ax[1].set_xticklabels(calendar.month_abbr[1:]) ax[1].grid(True) return fig, df3
def test_saturation_mixing_ratio(): """Test saturation mixing ratio calculation.""" p = 999. * units.mbar t = 288. * units.kelvin assert_almost_equal(saturation_mixing_ratio(p, t), .01068, 3)
def plotter(fdict): """ Go """ pgconn = get_dbconn("asos") ctx = get_autoplot_context(fdict, get_description()) station = ctx["zstation"] year = ctx["year"] varname = ctx["var"] df = read_sql( """ SELECT extract(year from valid) as year, coalesce(mslp, alti * 33.8639, 1013.25) as slp, extract(doy from valid) as doy, tmpf, dwpf, relh from alldata where station = %s and dwpf > -50 and dwpf < 90 and tmpf > -50 and tmpf < 120 and valid > '1950-01-01' and report_type = 2 """, pgconn, params=(station, ), index_col=None, ) if df.empty: raise NoDataFound("No Data was found.") # saturation vapor pressure # Convert sea level pressure to station pressure df["pressure"] = mcalc.add_height_to_pressure( df["slp"].values * units("millibars"), ctx["_nt"].sts[station]["elevation"] * units("m"), ).to(units("millibar")) # Compute the mixing ratio df["mixing_ratio"] = mcalc.mixing_ratio_from_relative_humidity( df["relh"].values * units("percent"), df["tmpf"].values * units("degF"), df["pressure"].values * units("millibars"), ) # Compute the saturation mixing ratio df["saturation_mixingratio"] = mcalc.saturation_mixing_ratio( df["pressure"].values * units("millibars"), df["tmpf"].values * units("degF"), ) df["vapor_pressure"] = mcalc.vapor_pressure( df["pressure"].values * units("millibars"), df["mixing_ratio"].values * units("kg/kg"), ).to(units("kPa")) df["saturation_vapor_pressure"] = mcalc.vapor_pressure( df["pressure"].values * units("millibars"), df["saturation_mixingratio"].values * units("kg/kg"), ).to(units("kPa")) df["vpd"] = df["saturation_vapor_pressure"] - df["vapor_pressure"] dailymeans = df[["year", "doy", varname]].groupby(["year", "doy"]).mean() dailymeans = dailymeans.reset_index() df2 = dailymeans[["doy", varname]].groupby("doy").describe() dyear = df[df["year"] == year] df3 = dyear[["doy", varname]].groupby("doy").describe() df3[(varname, "diff")] = df3[(varname, "mean")] - df2[(varname, "mean")] (fig, ax) = plt.subplots(2, 1, figsize=(8, 6)) multiplier = 1000.0 if varname == "mixing_ratio" else 10.0 ax[0].fill_between( df2[(varname, "min")].index.values, df2[(varname, "min")].values * multiplier, df2[(varname, "max")].values * multiplier, color="gray", ) ax[0].plot( df2[(varname, "mean")].index.values, df2[(varname, "mean")].values * multiplier, label="Climatology", ) ax[0].plot( df3[(varname, "mean")].index.values, df3[(varname, "mean")].values * multiplier, color="r", label="%s" % (year, ), ) ax[0].set_title(("%s [%s]\nDaily Mean Surface %s") % (station, ctx["_nt"].sts[station]["name"], PDICT[varname])) lbl = ("Mixing Ratio ($g/kg$)" if varname == "mixing_ratio" else PDICT[varname]) ax[0].set_ylabel(lbl) ax[0].set_xlim(0, 366) ax[0].set_ylim(bottom=0) ax[0].set_xticks((1, 32, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335)) ax[0].set_xticklabels(calendar.month_abbr[1:]) ax[0].grid(True) ax[0].legend(loc=2, fontsize=10) cabove = "b" if varname == "mixing_ratio" else "r" cbelow = "r" if cabove == "b" else "b" rects = ax[1].bar( df3[(varname, "diff")].index.values, df3[(varname, "diff")].values * multiplier, facecolor=cabove, edgecolor=cabove, ) for rect in rects: if rect.get_height() < 0.0: rect.set_facecolor(cbelow) rect.set_edgecolor(cbelow) plunits = "$g/kg$" if varname == "mixing_ratio" else "hPa" ax[1].set_ylabel("%.0f Departure (%s)" % (year, plunits)) ax[1].set_xlim(0, 366) ax[1].set_xticks((1, 32, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335)) ax[1].set_xticklabels(calendar.month_abbr[1:]) ax[1].grid(True) return fig, df3
def test_saturation_mixing_ratio_dimensions(): """Verify saturation mixing ratio returns a dimensionless number.""" p = 998. * units.mbar temp = 20 * units.celsius assert str(saturation_mixing_ratio(p, temp).units) == 'dimensionless'
def test_saturation_mixing_ratio(): """Test saturation mixing ratio calculation.""" p = 999. * units.mbar t = 288. * units.kelvin assert_almost_equal(saturation_mixing_ratio(p, t), .01068, 3)
def equation_of_state(p, t): mixing = mpcalc.saturation_mixing_ratio(p * units.hPa, t * units.kelvin).to('dimensionless') #mpcalc.virtual_temperature(t,r, molecular_weight_ratio=0.6219800858985514) density = mpcalc.density(p * units.hPa, t * units.kelvin, mixing) return density
def get_csf_cape(): a = 'lkdfhisoe78347834 (())&/&745 ' months_short = [4, 6, 9, 11] years_leap = [2004, 2008, 2012, 2016, 2020] for year in range(2000, 2020): for month in range(1, 13): cape_day_list = [] cape_list = [] csf_list = [] time_list = [] day_list = [] month_list = [] year_list = [] if month == 2: if year in years_leap: date_end = 29 else: date_end = 28 elif month in months_short: date_end = 30 else: date_end = 31 for date in range(0, date_end): for time in range(0, 2): year = 2014 month = 8 date = 29 time = time * 12 time = str(time).zfill(2) date = str(date).zfill(2) # Jakarta #url = "http://weather.uwyo.edu/cgi-bin/sounding?region=seasia&TYPE=TEXT%3ALIST&YEAR={}&MONTH={}&FROM={}{}&TO={}{}&STNM=96749".format(year,month,date,time,date,time) # Guam url = "http://weather.uwyo.edu/cgi-bin/sounding?region=se&TYPE=TEXT%3ALIST&YEAR={}&MONTH={}&FROM={}{}&TO={}{}&STNM=91212".format( year, month, date, time, date, time) page = requests.get(url) print(page) print(page.status_code) print('Month: {}'.format(month)) print('Year: {}'.format(year)) #while page.status_code != 200: # page = requests.get(url) print(page) print(page.status_code) print('Month: {}'.format(month)) print('Year: {}'.format(year)) soup = BeautifulSoup(page.content, 'html.parser') ## For the Date and Time ## date = soup.find_all('h2') #date = date[6].text #print(date) #wordlist = re.sub("[^\w]", " ", date).split() #print(wordlist[-4:]) #print(wordlist[-4:][0]) ## For the CAPE ## midnight_data_exists = 0 noon_data_exists = 0 for i in tqdm(range(0, len(soup.find_all('pre')))): p = soup.find_all('pre')[i] if i % 2 == 1: p = p.text.strip() p = p.splitlines() l1 = [ k for k in p if 'Convective' in k and 'Potential' in k ] for i in range(0, len(l1)): cape = float(re.sub("[^\d\.]", '', l1[i])) cape_day_list.append(cape) if int(time) == 12: noon_data_exists = 1 if int(time) == 0: midnight_data_exists = 1 #try: # cape #except NameError: # print("CAPE UNDEFINED") else: date_current = date[int(i / 2)].text date_split = re.sub("[^\w]", " ", date_current).split()[-4:] time_list.append(date_split[0]) day_list.append(date_split[1]) month_list.append(date_split[2]) year_list.append(date_split[3]) p_array = np.array( p.text.strip().splitlines()[4].split()) p_array = p_array.astype(np.float) p_list = [] for i in range(4, len(p.text.strip().splitlines())): p_array = np.array( p.text.strip().splitlines()[i].split()) p_array = p_array.astype(np.float) if len(p_array) == 11: p_list.append(p_array) p_stack = np.stack(p_list) p_stack = p_stack[p_stack[:, 0] > 100] pressure = p_stack[:, 0] * 100 * units.pascal temperature = p_stack[:, 2] + 273.15 temperature = temperature * units.kelvin q = p_stack[:, 5] / 1000 pressure_diff = np.diff(pressure, axis=0) ## Calculate CSF ## sat = mpcalc.saturation_mixing_ratio( pressure, temperature) sat_weighted = sat.data[:-1] * pressure_diff sat_sum = np.sum(sat_weighted) q_weighted = q.data[:-1] * pressure_diff q_sum = np.sum(q_weighted) csf = (q_sum / sat_sum).magnitude csf_list.append(csf) #print(csf) if noon_data_exists == 1 and midnight_data_exists == 0: cape_list.extend(cape_day_list) csf_list.extend(csf_day_list) time_list.extend(time_day_list) month_list.extend(month_day_list) year_list.extend(year_day_list) cape_list = np.array(cape_list) csf_list = np.array(csf_list) time_list = np.array(time_list) day_list = np.array(day_list) month_list = np.array(month_list) year_list = np.array(year_list) if np.shape(cape_list) != np.shape(csf_list): print('WARNING!!!!') print('Month: {}'.format(month)) print('Year: {}'.format(year)) sys.exit() print(np.nanmean(cape_list)) print(np.nanmean(csf_list)) print(time_list[1]) print(day_list[1]) print(month_list[1]) print(year_list[1]) print(np.shape(cape_list)) print(np.shape(csf_list)) print(np.shape(time_list)) print(np.shape(day_list)) print(np.shape(month_list)) print(np.shape(year_list)) np.save("jakarta/jakarta_cape_{}_{}".format(month, year), cape_list) np.save("jakarta/jakarta_csf_{}_{}".format(month, year), csf_list) np.save("jakarta/jakarta_time_{}_{}".format(month, year), time_list) np.save("jakarta/jakarta_day_{}_{}".format(month, year), day_list) np.save("jakarta/jakarta_month_{}_{}".format(month, year), month_list) np.save("jakarta/jakarta_year_{}_{}".format(month, year), year_list) return
RHmean = np.nanmean(RHArr, 0) if np.isnan(RHmean).all(): isRH = 0 else: isRH = 1 ###################################################### ## Calculate thermodymanic and convective variables ## ###################################################### theta = np.array( mcalc.potential_temperature(pres * units.mbar, (Tmean + 273.15) * units.kelvin)) Td = np.array(mcalc.dewpoint_rh(Tmean * units.degC, RHmean / 100.)) ws = np.array( mcalc.saturation_mixing_ratio(pres * units.mbar, (Tmean + 273.15) * units.kelvin)) w = np.multiply(RHmean / 100., ws * 1000.) # check for RH if isRH: lclpres, lcltemp = mcalc.lcl(pres[0] * units.mbar, Tmean[0] * units.degC, Td[0] * units.degC) print 'LCL Pressure: {}'.format(lclpres) print 'LCL Temperature: {}'.format(lcltemp) # parcel profile # determine if there are points sampled above lcl ilcl = np.squeeze(np.where((pres * units.mbar) <= lclpres)) # if not, entire profile dry adiabatic if ilcl.size == 0: prof = mcalc.dry_lapse(pres * units.mbar,
def cape(filelist,storm,track,show): #Sort filelist. filelist=np.sort(filelist) # Get sampling periods (this will be a dictionary). See the toolbox print('Retrieving sampling periods') sampleperiods=getsamplingperiods(filelist,3.) # Iterate over all sampling periods. for sampindex,periodskey in enumerate(sampleperiods): #Allocate starting (stdt) and ending date (endt). Remeber dt is the convetional short-name for date. stdt=periodskey endt=sampleperiods[periodskey] # Define sampling period string period=str(stdt.hour)+'_'+str(stdt.day)+'-'+str(endt.hour)+'_'+str(endt.day) # Create new-empty lists. lats=[] lons=[] xs=[] ys=[] capes=[] cins=[] distfig = plt.figure(figsize=(13, 9)) ax=distfig.add_subplot(111) print('start filelist loop') # Iterate over all files. for filename in filelist: # Select end-name of file by inspecting filename string. Notice how filename can change how file is read. if 'radazm' in filename.split('/')[-1] or 'eol' in filename.split('/')[-1]: end='radazm' else: end='avp' # Obtain properties of file, i.e., launch time and location into a dictionary (dicc). dicc=findproperties(filename,end) # Condition to see if current file is in sampling period. # Notice how if structure is constructed, condition finds times outside of sampling period and # if found outside the sampling period, continue to next file. if dicc['Launch Time']<stdt or dicc['Launch Time'] > endt: continue nump=np.genfromtxt(filename,skip_header=16,skip_footer=0) temperature=clean1(nump[:,5]) pressure=clean1(nump[:,4]) Height=clean1(nump[:,13]) if np.nanmax(Height)<3500: continue #Clean for cape RelH=clean1(nump[:,7]) lon=clean1(nump[:,14]) lat=clean1(nump[:,15]) lon=clean1(lon) lat=clean1(lat) mlon=np.nanmean(lon) mlat=np.nanmean(lat) RH=RelH/100 T,P,rh,dz=cleanforcape(temperature,pressure,RH,Height) #Metpy set-up T=np.flip(T,0) rh=np.flip(rh,0) p=np.flip(P,0) dz=np.flip(dz,0) p=p*units.hPa T=T*units.celsius mixing=rh*mpcalc.saturation_mixing_ratio(p,T) epsilon=0.6219800858985514 Tv=mpcalc.virtual_temperature(T, mixing, molecular_weight_ratio=epsilon) dwpoint=mpcalc.dewpoint_rh(T, rh) blh_indx=np.where(dz<500) try: parcelprofile=mpcalc.parcel_profile(p,np.nanmean(T[blh_indx])*units.celsius,mpcalc.dewpoint_rh(np.nanmean(T[blh_indx])*units.celsius, np.nanmean(rh[blh_indx]))).to('degC') Tv_parcelprofile=mpcalc.virtual_temperature(parcelprofile, mixing, molecular_weight_ratio=epsilon) cape,cin=cape_cin(p,Tv,dwpoint,Tv_parcelprofile,dz,T) except: continue plotskewT=True if plotskewT==True: os.system('mkdir figs/skewt') fig = plt.figure(figsize=(9, 9)) skew = SkewT(fig, rotation=45) skew.ax.set_ylim(1000, 100) skew.ax.set_xlim(-40, 60) skew.plot(p, dwpoint, 'g',label=r'$T_{dp}$') skew.plot(p, Tv, 'r',label=r'$T_v$') plt.text(-120,120,str(np.around(cape,2)),fontsize=14,fontweight='bold') # Plot the data using normal plotting functions, in this case using # log scaling in Y, as dictated by the typical meteorological plot skew.plot(p,Tv_parcelprofile,'k',label=r'$T_{v env}$') skew.shade_cin(p, T, parcelprofile,label='CIN') skew.shade_cape(p, Tv, Tv_parcelprofile,label='CAPE') skew.plot_dry_adiabats() skew.plot_moist_adiabats() plt.legend() plt.title(storm + ' on' + period,fontsize=14) plt.savefig('figs/skewt/'+storm+str(dicc['Launch Time'].time())+'.png') #plt.show() plt.close() r,theta=cart_to_cylindr(mlon,mlat,track,dicc['Launch Time']) if not(np.isnan(r)) and not(np.isnan(theta)) and not(np.isnan(cape.magnitude)): xs.append(r*np.cos(theta)) ys.append(r*np.sin(theta)) capes.append(cape.magnitude) cins.append(cin) cs=ax.scatter(xs,ys,c=np.asarray(capes),cmap='jet') for i,xi in enumerate(xs): ax.text(xi,ys[i]+10,str(np.around(capes[i],1))) plt.colorbar(cs) ax.scatter(0,0,marker='v',s=100,color='black') ax.grid() ax.set_xlabel('X distance [km]') ax.set_ylabel('Y distance [km]') ax.set_title('CAPE distribution for '+storm+' on '+period,fontsize=14) distfig.savefig('figs/cape'+storm+period+'.png') if show: plt.show()
k, 0] # thetav = theta(1+eps*q) but q =0 q_bl[k, 0] = 0. w_e = -r_ft / gam # w_e = -w_FT in dry case q_ft = 0. """ print("dry equilibrium: h = "+ str(round(h[k,0],2)) +" m, \ th = "+ str(round(th_bl[k,0],2)) +" K, \ qbl = "+ str(round(q_bl[k,0] *1.e3,2))+", \ dthv = "+ str(round(d_thv[k,0],2)) +" K, \ entrainment velocity = "+ str(round(w_e*100,2)) +"cm/s") """ # calculate water vapor saturation mixing ratio as a function of pressure and temperature # In Naumann et al, 2019, the surface is assumed to be saturated with surface water # vapor mixing ratio, qsfc = qsat(theta_surf, z=0). q_sat = mpcalc.saturation_mixing_ratio(p_sfc * units.Pa, th_sfc * units.K) # g/g #print("saturation water vapor mixing ratio: q_sat = "+ str(round(q_sat,3)) +" (in g/g)") # time loop to find adjustment to circulation # f_theta in dry case * 1000 ~ 5 for i in range(1, nt): f_th[k, i] = C_d * v * (th_sfc - th_bl[k, i - 1] ) # kinematic surface sensible heat flux # surface assumed to be saturated, q_sfc = q_sat f_q[k, i] = C_d * v * (q_sat - q_bl[k, i - 1] ) # the kinematic surface moisture flux f_thv[k, i] = f_th[k, i] + eps * th_bl[k, i - 1] * f_q[ k, i] # the kinematic buoyancy flux w_e = A * f_thv[k, i] / d_thv[
def test_saturation_mixing_ratio_dimensions(): """Verify saturation mixing ratio returns a dimensionless number.""" p = 998. * units.mbar temp = 20 * units.celsius assert str(saturation_mixing_ratio(p, temp).units) == 'dimensionless'