def get_thermo(self): ''' Function to generate thermodynamic indices. Function returns nothing, but sets the following variables: self.k_idx - K Index, a severe weather index self.pwat - Precipitable Water Vapor (inches) self.lapserate_3km - 0 to 3km AGL lapse rate (C/km) self.lapserate_3_6km - 3 to 6km AGL lapse rate (C/km) self.lapserate_850_500 - 850 to 500mb lapse rate (C/km) self.lapserate_700_500 - 700 to 500mb lapse rate (C/km) self.convT - The Convective Temperature (F) self.maxT - The Maximum Forecast Surface Temp (F) self.mean_mixr - Mean Mixing Ratio self.low_rh - low level mean relative humidity self.mid_rh - mid level mean relative humidity self.totals_totals - Totals Totals index, a severe weather index Parameters ---------- None Returns ------- None ''' ## either get or calculate the indices, round to the nearest int, and ## convert them to strings. ## K Index self.k_idx = params.k_index( self ) ## precipitable water self.pwat = params.precip_water( self ) ## 0-3km agl lapse rate self.lapserate_3km = params.lapse_rate( self, 0., 3000., pres=False ) ## 3-6km agl lapse rate self.lapserate_3_6km = params.lapse_rate( self, 3000., 6000., pres=False ) ## 850-500mb lapse rate self.lapserate_850_500 = params.lapse_rate( self, 850., 500., pres=True ) ## 700-500mb lapse rate self.lapserate_700_500 = params.lapse_rate( self, 700., 500., pres=True ) ## 2-6 km max lapse rate self.max_lapse_rate_2_6 = params.max_lapse_rate( self ) ## convective temperature self.convT = thermo.ctof( params.convective_temp( self ) ) ## sounding forecast surface temperature self.maxT = thermo.ctof( params.max_temp( self ) ) #fzl = str(int(self.sfcparcel.hght0c)) ## 100mb mean mixing ratio self.mean_mixr = params.mean_mixratio( self ) ## 150mb mean rh self.low_rh = params.mean_relh( self ) self.mid_rh = params.mean_relh( self, pbot=(self.pres[self.sfc] - 150), ptop=(self.pres[self.sfc] - 350) ) ## calculate the totals totals index self.totals_totals = params.t_totals( self ) ## calculate the inferred temperature advection self.inf_temp_adv = params.inferred_temp_adv(self, lat=self.latitude)
def get_thermo(self): ''' Function to generate thermodynamic indices. Function returns nothing, but sets the following variables: self.k_idx - K Index, a severe weather index self.pwat - Precipitable Water Vapor (inches) self.lapserate_3km - 0 to 3km AGL lapse rate (C/km) self.lapserate_3_6km - 3 to 6km AGL lapse rate (C/km) self.lapserate_850_500 - 850 to 500mb lapse rate (C/km) self.lapserate_700_500 - 700 to 500mb lapse rate (C/km) self.convT - The Convective Temperature (F) self.maxT - The Maximum Forecast Surface Temp (F) self.mean_mixr - Mean Mixing Ratio self.low_rh - low level mean relative humidity self.mid_rh - mid level mean relative humidity self.totals_totals - Totals Totals index, a severe weather index Parameters ---------- None Returns ------- None ''' ## either get or calculate the indices, round to the nearest int, and ## convert them to strings. ## K Index self.k_idx = params.k_index( self ) ## precipitable water self.pwat = params.precip_water( self ) ## 0-3km agl lapse rate self.lapserate_3km = params.lapse_rate( self, 0., 3000., pres=False ) ## 3-6km agl lapse rate self.lapserate_3_6km = params.lapse_rate( self, 3000., 6000., pres=False ) ## 850-500mb lapse rate self.lapserate_850_500 = params.lapse_rate( self, 850., 500., pres=True ) ## 700-500mb lapse rate self.lapserate_700_500 = params.lapse_rate( self, 700., 500., pres=True ) ## convective temperature self.convT = thermo.ctof( params.convective_temp( self ) ) ## sounding forecast surface temperature self.maxT = thermo.ctof( params.max_temp( self ) ) #fzl = str(int(self.sfcparcel.hght0c)) ## 100mb mean mixing ratio self.mean_mixr = params.mean_mixratio( self ) ## 150mb mean rh self.low_rh = params.mean_relh( self ) self.mid_rh = params.mean_relh( self, pbot=(self.pres[self.sfc] - 150), ptop=(self.pres[self.sfc] - 350) ) ## calculate the totals totals index self.totals_totals = params.t_totals( self ) ## calculate the inferred temperature advection self.inf_temp_adv = params.inferred_temp_adv(self)
def get_precip(self): ''' Function to generate different indices and information regarding any precipitation in the sounding. This helps fill the data shown in the WINTER inset. Returns nothing, but sets the following variables: self.dgz_pbot, self.dgz_ptop : the dendretic growth zone (DGZ) top and bottom (mb) self.dgz_meanrh : DGZ mean relative humidity (%) self.dgz_pw : the preciptable water vapor in the DGZ (inches) self.dgz_meanq : the mean water vapor mixing ratio in the DGZ (g/kg) self.dgz_meanomeg : the mean omega in the DGZ (microbars/second) self.oprh : the OPRH variable (units don't mean anything) self.plevel, self.phase, self.tmp, self.st : the initial phase, level, temperature, and state of any precip in the sounding self.tpos, self.tneg, self.ttop, self.tbot : positive and negative temperature layers in the sounding self.wpos, self.wneg, self.wtop, self.wbot : positive and negative wetbulb layers in the soundings self.precip_type : the best guess precipitation type Parameters ---------- None Returns ------- None ''' self.dgz_pbot, self.dgz_ptop = params.dgz(self) self.dgz_meanrh = params.mean_relh(self, pbot=self.dgz_pbot, ptop=self.dgz_ptop) self.dgz_pw = params.precip_water(self, pbot=self.dgz_pbot, ptop=self.dgz_ptop) self.dgz_meanq = params.mean_mixratio(self, pbot=self.dgz_pbot, ptop=self.dgz_ptop) self.dgz_meanomeg = params.mean_omega( self, pbot=self.dgz_pbot, ptop=self.dgz_ptop) * 10 # to microbars/sec self.oprh = self.dgz_meanomeg * self.dgz_pw * (self.dgz_meanrh / 100.) self.plevel, self.phase, self.tmp, self.st = watch_type.init_phase( self) self.tpos, self.tneg, self.ttop, self.tbot = watch_type.posneg_temperature( self, start=self.plevel) self.wpos, self.wneg, self.wtop, self.wbot = watch_type.posneg_wetbulb( self, start=self.plevel) self.precip_type = watch_type.best_guess_precip( self, self.phase, self.plevel, self.tmp, self.tpos, self.tneg)
def get_precip(self): ''' Function to generate different indices and information regarding any precipitation in the sounding. This helps fill the data shown in the WINTER inset. Returns nothing, but sets the following variables: self.dgz_pbot, self.dgz_ptop : the dendretic growth zone (DGZ) top and bottom (mb) self.dgz_meanrh : DGZ mean relative humidity (%) self.dgz_pw : the preciptable water vapor in the DGZ (inches) self.dgz_meanq : the mean water vapor mixing ratio in the DGZ (g/kg) self.dgz_meanomeg : the mean omega in the DGZ (microbars/second) self.oprh : the OPRH variable (units don't mean anything) self.plevel, self.phase, self.tmp, self.st : the initial phase, level, temperature, and state of any precip in the sounding self.tpos, self.tneg, self.ttop, self.tbot : positive and negative temperature layers in the sounding self.wpos, self.wneg, self.wtop, self.wbot : positive and negative wetbulb layers in the soundings self.precip_type : the best guess precipitation type Parameters ---------- None Returns ------- None ''' self.dgz_pbot, self.dgz_ptop = params.dgz(self) self.dgz_meanrh = params.mean_relh(self, pbot=self.dgz_pbot, ptop=self.dgz_ptop) self.dgz_pw = params.precip_water(self, pbot=self.dgz_pbot, ptop=self.dgz_ptop) self.dgz_meanq = params.mean_mixratio(self, pbot=self.dgz_pbot, ptop=self.dgz_ptop) self.dgz_meanomeg = params.mean_omega(self, pbot=self.dgz_pbot, ptop=self.dgz_ptop) * 10 # to microbars/sec self.oprh = self.dgz_meanomeg * self.dgz_pw * (self.dgz_meanrh/100.) self.plevel, self.phase, self.tmp, self.st = watch_type.init_phase(self) self.tpos, self.tneg, self.ttop, self.tbot = watch_type.posneg_temperature(self, start=self.plevel) self.wpos, self.wneg, self.wtop, self.wbot = watch_type.posneg_wetbulb(self, start=self.plevel) self.precip_type = watch_type.best_guess_precip(self, self.phase, self.plevel, self.tmp, self.tpos, self.tneg)
def indices(prof, debug=False): # return a formatted-string list of stability and kinematic indices sfcpcl = params.parcelx(prof, flag=1) mupcl = params.parcelx(prof, flag=3) # most unstable mlpcl = params.parcelx(prof, flag=4) # 100 mb mean layer parcel pcl = mupcl sfc = prof.pres[prof.sfc] p3km = interp.pres(prof, interp.to_msl(prof, 3000.)) p6km = interp.pres(prof, interp.to_msl(prof, 6000.)) p1km = interp.pres(prof, interp.to_msl(prof, 1000.)) mean_3km = winds.mean_wind(prof, pbot=sfc, ptop=p3km) sfc_6km_shear = winds.wind_shear(prof, pbot=sfc, ptop=p6km) sfc_3km_shear = winds.wind_shear(prof, pbot=sfc, ptop=p3km) sfc_1km_shear = winds.wind_shear(prof, pbot=sfc, ptop=p1km) #print "0-3 km Pressure-Weighted Mean Wind (kt):", utils.comp2vec(mean_3km[0], mean_3km[1])[1] #print "0-6 km Shear (kt):", utils.comp2vec(sfc_6km_shear[0], sfc_6km_shear[1])[1] srwind = params.bunkers_storm_motion(prof) srh3km = winds.helicity(prof, 0, 3000., stu=srwind[0], stv=srwind[1]) srh1km = winds.helicity(prof, 0, 1000., stu=srwind[0], stv=srwind[1]) #print "0-3 km Storm Relative Helicity [m2/s2]:",srh3km[0] #### Calculating variables based off of the effective inflow layer: # The effective inflow layer concept is used to obtain the layer of buoyant parcels that feed a storm's inflow. # Here are a few examples of how to compute variables that require the effective inflow layer in order to calculate them: stp_fixed = params.stp_fixed( sfcpcl.bplus, sfcpcl.lclhght, srh1km[0], utils.comp2vec(sfc_6km_shear[0], sfc_6km_shear[1])[1]) ship = params.ship(prof) # If you get an error about not converting masked constant to python int # use the round() function instead of int() - Ahijevych May 11 2016 # 2nd element of list is the # of decimal places indices = { 'SBCAPE': [sfcpcl.bplus, 0, 'J $\mathregular{kg^{-1}}$'], 'SBCIN': [sfcpcl.bminus, 0, 'J $\mathregular{kg^{-1}}$'], 'SBLCL': [sfcpcl.lclhght, 0, 'm AGL'], 'SBLFC': [sfcpcl.lfchght, 0, 'm AGL'], 'SBEL': [sfcpcl.elhght, 0, 'm AGL'], 'SBLI': [sfcpcl.li5, 0, 'C'], 'MLCAPE': [mlpcl.bplus, 0, 'J $\mathregular{kg^{-1}}$'], 'MLCIN': [mlpcl.bminus, 0, 'J $\mathregular{kg^{-1}}$'], 'MLLCL': [mlpcl.lclhght, 0, 'm AGL'], 'MLLFC': [mlpcl.lfchght, 0, 'm AGL'], 'MLEL': [mlpcl.elhght, 0, 'm AGL'], 'MLLI': [mlpcl.li5, 0, 'C'], 'MUCAPE': [mupcl.bplus, 0, 'J $\mathregular{kg^{-1}}$'], 'MUCIN': [mupcl.bminus, 0, 'J $\mathregular{kg^{-1}}$'], 'MULCL': [mupcl.lclhght, 0, 'm AGL'], 'MULFC': [mupcl.lfchght, 0, 'm AGL'], 'MUEL': [mupcl.elhght, 0, 'm AGL'], 'MULI': [mupcl.li5, 0, 'C'], '0-1 km SRH': [srh1km[0], 0, '$\mathregular{m^{2}s^{-2}}$'], '0-1 km Shear': [utils.comp2vec(sfc_1km_shear[0], sfc_1km_shear[1])[1], 0, 'kt'], '0-3 km SRH': [srh3km[0], 0, '$\mathregular{m^{2}s^{-2}}$'], '0-6 km Shear': [utils.comp2vec(sfc_6km_shear[0], sfc_6km_shear[1])[1], 0, 'kt'], 'PWV': [params.precip_water(prof), 2, 'inch'], 'K-index': [params.k_index(prof), 0, ''], 'STP(fix)': [stp_fixed, 1, ''], 'SHIP': [ship, 1, ''] } eff_inflow = params.effective_inflow_layer(prof) if any(eff_inflow): ebot_hght = interp.to_agl(prof, interp.hght(prof, eff_inflow[0])) etop_hght = interp.to_agl(prof, interp.hght(prof, eff_inflow[1])) #print "Effective Inflow Layer Bottom Height (m AGL):", ebot_hght #print "Effective Inflow Layer Top Height (m AGL):", etop_hght effective_srh = winds.helicity(prof, ebot_hght, etop_hght, stu=srwind[0], stv=srwind[1]) indices['Eff. SRH'] = [ effective_srh[0], 0, '$\mathregular{m^{2}s^{-2}}$' ] #print "Effective Inflow Layer SRH (m2/s2):", effective_srh[0] ebwd = winds.wind_shear(prof, pbot=eff_inflow[0], ptop=eff_inflow[1]) ebwspd = utils.mag(*ebwd) indices['EBWD'] = [ebwspd, 0, 'kt'] #print "Effective Bulk Wind Difference:", ebwspd scp = params.scp(mupcl.bplus, effective_srh[0], ebwspd) indices['SCP'] = [scp, 1, ''] stp_cin = params.stp_cin(mlpcl.bplus, effective_srh[0], ebwspd, mlpcl.lclhght, mlpcl.bminus) indices['STP(cin)'] = [stp_cin, 1, ''] #print "Supercell Composite Parameter:", scp #print "Significant Tornado Parameter (w/CIN):", stp_cin #print "Significant Tornado Parameter (fixed):", stp_fixed # Update the indices within the indices dictionary on the side of the plot. string = '' for index, value in sorted(indices.items()): if np.ma.is_masked(value[0]): if debug: print("skipping masked value for index=", index) continue if debug: print("index=", index) print("value=", value) format = '%.' + str(value[1]) + 'f' string += index + ": " + format % value[0] + " " + value[2] + '\n' return string
''' Create the Sounding (Profile) Object '''
def pwv_climo(prof, station, month=None): ''' month is an integer from 1-12 station_id_3 is the station ID (lower case) prof is the profile object This function uses the PWV climatology databases provided by Matt Bunkers (NWS/UNR) and accepts a SHARPPY profile object, the station name, and the month and returns to the user a number indicating where in the distribution the profile's PWV value lies. This function is used in SHARPPY to help provide the user climatological context of the PWV index they are viewing. x can equal 0, 1, 2, or 3 If the returned value is x, the PWV lies outside +x standard deviations of the mean If the returned value is -x, the PWV lies outside -x standard deviations of the mean If the returned value is 0, the PWV lies within 1 standard deviation of the mean Written by Greg Blumberg and Kelton Halbert. ''' if not month: month = datetime.now().month # Calculate the PWV up to 300 mb so it's consistent with the PWV Climo pwv_300 = params.precip_water(prof, pbot=None, ptop=300) # pwv_300 needs to be in inches (if it isn't already) # Load in the PWV mean and standard deviations pwv_means = get_mean_pwv(station) pwv_stds = get_stdev_pwv(station) if pwv_means is np.ma.masked: return 0 month_mean = float(pwv_means[month-1]) month_std = float(pwv_stds[month-1]) sigma_1 = (month_mean - month_std, month_mean + month_std) sigma_2 = (month_mean - (2.*month_std), month_mean + (2.*month_std)) sigma_3 = (month_mean - (3.*month_std), month_mean + (3.*month_std)) if len(np.where(pwv_300 > sigma_3[1])[0]) > 0: # Means the PWV value is outside +3 sigma of the distribution flag = 3 elif len(np.where(pwv_300 < sigma_3[0])[0]) > 0: # Means the PWV value is outside -3 sigma of the distribution flag = -3 elif len(np.where(pwv_300 > sigma_2[1])[0]) > 0: # Means the PWV value is outside +2 sigma of the distribution flag = 2 elif len(np.where(pwv_300 < sigma_2[0])[0]) > 0: # Means the PWV value is outside -2 sigma of the distribution flag = -2 elif len(np.where(pwv_300 > sigma_1[1])[0]) > 0: # Means the PWV value is outside +1 sigma of the distribution flag = 1 elif len(np.where(pwv_300 < sigma_1[0])[0]) > 0: # Means the PWV value is outside -1 sigma of the distribution flag = -1 else: # Means that the PWV value is within 1 sigma of the distribution flag = 0 return flag
'MLLCL': [int(mlpcl.lclhght), 'm AGL'],\ 'MLLFC': [int(mlpcl.lfchght), 'm AGL'],\ 'MLEL': [int(mlpcl.elhght), 'm AGL'],\ 'MLLI': [int(mlpcl.li5), 'C'],\ 'MUCAPE': [int(mupcl.bplus), 'J/kg'],\ 'MUCIN': [int(mupcl.bminus), 'J/kg'],\ 'MULCL': [int(mupcl.lclhght), 'm AGL'],\ 'MULFC': [int(mupcl.lfchght), 'm AGL'],\ 'MUEL': [int(mupcl.elhght), 'm AGL'],\ 'MULI': [int(mupcl.li5), 'C'],\ '0-1 km SRH': [int(srh1km[0]), 'm2/s2'],\ '0-1 km Shear': [int(utils.comp2vec(sfc_1km_shear[0], sfc_1km_shear[1])[1]), 'kts'],\ '0-3 km SRH': [int(srh3km[0]), 'm2/s2'],\ 'Eff. SRH': [int(effective_srh[0]), 'm2/s2'],\ 'EBWD': [int(ebwspd), 'kts'],\ 'PWV': [round(params.precip_water(prof), 2), 'inch'],\ 'K-index': [int(params.k_index(prof)), ''],\ 'STP(fix)': [round(stp_fixed, 1), ''],\ 'SHIP': [round(ship, 1), ''],\ 'SCP': [round(scp, 1), ''],\ 'STP(cin)': [round(stp_cin, 1), '']} # Set the parcel trace to be plotted as the Most-Unstable parcel. pcl = mupcl # Create a new figure. The dimensions here give a good aspect ratio fig = plt.figure(figsize=(10, 10)) ax = fig.add_subplot(111, projection='skewx') ax.grid(True) pmax = 1000
def pwv_climo(prof, station, month=None): ''' month is an integer from 1-12 station_id_3 is the station ID (lower case) prof is the profile object This function uses the PWV climatology databases provided by Matt Bunkers (NWS/UNR) and accepts a SHARPPY profile object, the station name, and the month and returns to the user a number indicating where in the distribution the profile's PWV value lies. This function is used in SHARPPY to help provide the user climatological context of the PWV index they are viewing. x can equal 0, 1, 2, or 3 If the returned value is x, the PWV lies outside +x standard deviations of the mean If the returned value is -x, the PWV lies outside -x standard deviations of the mean If the returned value is 0, the PWV lies within 1 standard deviation of the mean Written by Greg Blumberg and Kelton Halbert. ''' if not month: month = datetime.now().month # Calculate the PWV up to 300 mb so it's consistent with the PWV Climo pwv_300 = params.precip_water(prof, pbot=None, ptop=300) # pwv_300 needs to be in inches (if it isn't already) # Load in the PWV mean and standard deviations pwv_means = get_mean_pwv(station) pwv_stds = get_stdev_pwv(station) if pwv_means is np.ma.masked: return 0 elif pwv_means is None: return 0 month_mean = float(pwv_means[month-1]) month_std = float(pwv_stds[month-1]) sigma_1 = (month_mean - month_std, month_mean + month_std) sigma_2 = (month_mean - (2.*month_std), month_mean + (2.*month_std)) sigma_3 = (month_mean - (3.*month_std), month_mean + (3.*month_std)) if len(np.where(pwv_300 > sigma_3[1])[0]) > 0: # Means the PWV value is outside +3 sigma of the distribution flag = 3 elif len(np.where(pwv_300 < sigma_3[0])[0]) > 0: # Means the PWV value is outside -3 sigma of the distribution flag = -3 elif len(np.where(pwv_300 > sigma_2[1])[0]) > 0: # Means the PWV value is outside +2 sigma of the distribution flag = 2 elif len(np.where(pwv_300 < sigma_2[0])[0]) > 0: # Means the PWV value is outside -2 sigma of the distribution flag = -2 elif len(np.where(pwv_300 > sigma_1[1])[0]) > 0: # Means the PWV value is outside +1 sigma of the distribution flag = 1 elif len(np.where(pwv_300 < sigma_1[0])[0]) > 0: # Means the PWV value is outside -1 sigma of the distribution flag = -1 else: # Means that the PWV value is within 1 sigma of the distribution flag = 0 return flag