def test_helicity(): agl1 = 0. agl2 = 3000. input_ru = 10.5329157627 input_rv = -7.86385969675 correct = [284.9218078420389, 302.9305759626597, -18.008768120620786] returned = winds.helicity(prof, agl1, agl2, stu=input_ru, stv=input_rv, exact=True) npt.assert_almost_equal(returned, correct) correct = [285.00199936592099, 302.99422077416955, -17.992221408248568] returned = winds.helicity(prof, agl1, agl2, stu=input_ru, stv=input_rv, exact=False) npt.assert_almost_equal(returned, correct)
def test_helicity(): agl1 = 0. agl2 = 3000. input_ru = 10.5329157627 input_rv = -7.86385969675 correct = [284.9218078420389, 302.9305759626597, -18.008768120620786] returned = winds.helicity(prof, agl1, agl2, stu=input_ru, stv=input_rv, exact=True) npt.assert_almost_equal(returned, correct) correct = [285.00199936592099, 302.99422077416955, -17.992221408248568] returned = winds.helicity(prof, agl1, agl2, stu=input_ru, stv=input_rv, exact=False) npt.assert_almost_equal(returned, correct)
def get_kinematics(self): ''' Function to generate the numerous kinematic quantities used for display and calculations. It requires that the parcel calculations have already been called for the lcl to el shear and mean wind vectors, as well as indices that require an effective inflow layer. Parameters ---------- None Returns ------- None ''' sfc = self.pres[self.sfc] heights = np.array([1000., 3000., 4000., 5000., 6000., 8000., 9000.]) p1km, p3km, p4km, p5km, p6km, p8km, p9km = interp.pres( self, interp.to_msl(self, heights)) ## 1km and 6km winds self.wind1km = interp.vec(self, p1km) self.wind6km = interp.vec(self, p6km) ## calcluate wind shear self.sfc_1km_shear = winds.wind_shear(self, pbot=sfc, ptop=p1km) self.sfc_3km_shear = winds.wind_shear(self, pbot=sfc, ptop=p3km) self.sfc_6km_shear = winds.wind_shear(self, pbot=sfc, ptop=p6km) self.sfc_8km_shear = winds.wind_shear(self, pbot=sfc, ptop=p8km) self.sfc_9km_shear = winds.wind_shear(self, pbot=sfc, ptop=p9km) self.lcl_el_shear = winds.wind_shear(self, pbot=self.mupcl.lclpres, ptop=self.mupcl.elpres) ## calculate mean wind self.mean_1km = utils.comp2vec( *winds.mean_wind(self, pbot=sfc, ptop=p1km)) self.mean_3km = utils.comp2vec( *winds.mean_wind(self, pbot=sfc, ptop=p3km)) self.mean_6km = utils.comp2vec( *winds.mean_wind(self, pbot=sfc, ptop=p6km)) self.mean_8km = utils.comp2vec( *winds.mean_wind(self, pbot=sfc, ptop=p8km)) self.mean_lcl_el = utils.comp2vec(*winds.mean_wind( self, pbot=self.mupcl.lclpres, ptop=self.mupcl.elpres)) ## parameters that depend on the presence of an effective inflow layer if self.etop is ma.masked or self.ebottom is ma.masked: self.etopm = ma.masked self.ebotm = ma.masked self.srwind = winds.non_parcel_bunkers_motion(self) self.eff_shear = [MISSING, MISSING] self.ebwd = [MISSING, MISSING, MISSING] self.ebwspd = MISSING self.mean_eff = [MISSING, MISSING, MISSING] self.mean_ebw = [MISSING, MISSING, MISSING] self.srw_eff = [MISSING, MISSING, MISSING] self.srw_ebw = [MISSING, MISSING, MISSING] self.right_esrh = [ma.masked, ma.masked, ma.masked] self.left_esrh = [ma.masked, ma.masked, ma.masked] self.critical_angle = ma.masked else: self.srwind = params.bunkers_storm_motion(self, mupcl=self.mupcl, pbot=self.ebottom) depth = (self.mupcl.elhght - self.ebotm) / 2 elh = interp.pres(self, interp.to_msl(self, self.ebotm + depth)) ## calculate mean wind self.mean_eff = winds.mean_wind(self, self.ebottom, self.etop) self.mean_ebw = winds.mean_wind(self, pbot=self.ebottom, ptop=elh) ## calculate wind shear of the effective layer self.eff_shear = winds.wind_shear(self, pbot=self.ebottom, ptop=self.etop) self.ebwd = winds.wind_shear(self, pbot=self.ebottom, ptop=elh) self.ebwspd = utils.mag(self.ebwd[0], self.ebwd[1]) ## calculate the mean sr wind self.srw_eff = winds.sr_wind(self, pbot=self.ebottom, ptop=self.etop, stu=self.srwind[0], stv=self.srwind[1]) self.srw_ebw = winds.sr_wind(self, pbot=self.ebottom, ptop=elh, stu=self.srwind[0], stv=self.srwind[1]) self.right_esrh = winds.helicity(self, self.ebotm, self.etopm, stu=self.srwind[0], stv=self.srwind[1]) self.left_esrh = winds.helicity(self, self.ebotm, self.etopm, stu=self.srwind[2], stv=self.srwind[3]) self.critical_angle = winds.critical_angle(self, stu=self.srwind[0], stv=self.srwind[1]) ## calculate mean srw self.srw_1km = utils.comp2vec(*winds.sr_wind( self, pbot=sfc, ptop=p1km, stu=self.srwind[0], stv=self.srwind[1])) self.srw_3km = utils.comp2vec(*winds.sr_wind( self, pbot=sfc, ptop=p3km, stu=self.srwind[0], stv=self.srwind[1])) self.srw_6km = utils.comp2vec(*winds.sr_wind( self, pbot=sfc, ptop=p6km, stu=self.srwind[0], stv=self.srwind[1])) self.srw_8km = utils.comp2vec(*winds.sr_wind( self, pbot=sfc, ptop=p8km, stu=self.srwind[0], stv=self.srwind[1])) self.srw_4_5km = utils.comp2vec(*winds.sr_wind( self, pbot=p4km, ptop=p5km, stu=self.srwind[0], stv=self.srwind[1])) self.srw_lcl_el = utils.comp2vec( *winds.sr_wind(self, pbot=self.mupcl.lclpres, ptop=self.mupcl.elpres, stu=self.srwind[0], stv=self.srwind[1])) # This is for the red, blue, and purple bars that appear on the SR Winds vs. Height plot self.srw_0_2km = winds.sr_wind(self, pbot=sfc, ptop=interp.pres( self, interp.to_msl(self, 2000.)), stu=self.srwind[0], stv=self.srwind[1]) self.srw_4_6km = winds.sr_wind(self, pbot=interp.pres( self, interp.to_msl(self, 4000.)), ptop=p6km, stu=self.srwind[0], stv=self.srwind[1]) self.srw_9_11km = winds.sr_wind( self, pbot=interp.pres(self, interp.to_msl(self, 9000.)), ptop=interp.pres(self, interp.to_msl(self, 11000.)), stu=self.srwind[0], stv=self.srwind[1]) ## calculate upshear and downshear self.upshear_downshear = winds.mbe_vectors(self) self.srh1km = winds.helicity(self, 0, 1000., stu=self.srwind[0], stv=self.srwind[1]) self.srh3km = winds.helicity(self, 0, 3000., stu=self.srwind[0], stv=self.srwind[1])
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 plot_sounding(file, imgName): try: prof, time, location = decode(file) except Exception as e: print( "\n Oops! Couldn't decode the sounding data. No plot produced!\n") print(e) # return None # Open up the text file with the data in columns (e.g. the sample OAX file distributed with SHARPpy) locInfo = location.split('_') title = locInfo[0] + ' ' + locInfo[1] + ' ' + locInfo[ 2] + ' ' + time.strftime('%Y%m%d/%H%M') + ' (Observed)' # Set up the figure in matplotlib. fig = plt.figure(figsize=(14, 7.25)) gs = gridspec.GridSpec(4, 6, width_ratios=[1, 5, 1, 0.5, 3, 3]) ax = plt.subplot(gs[0:3, 0:2], projection='skewx') plt.title(title, fontsize=14, loc='left', color='w') ax.set_facecolor('k') ax.spines['left'].set_color('w') ax.spines['right'].set_color('w') ax.spines['bottom'].set_color('w') ax.spines['top'].set_color('w') # xticks = ax.xaxis.get_major_ticks() #mute a tick label outside plot # xticks[-4].label1.set_visible(False) ax.tick_params(axis='both', colors='w', grid_color='silver') ax.ticklabel_format(style='plain') # ax.xaxis.label.set_color('w') # ax.yaxis.label.set_color('w') ax.grid(True) plt.grid(True) # Ask user for default limits or custom limits pt_plot, t_lower, t_upper = ask_limits(prof.pres[~prof.dwpc.mask], prof.dwpc[~prof.dwpc.mask]) # Bounds of the pressure axis pb_plot = 1050 dp_plot = 10 plevs_plot = np.arange(pb_plot, pt_plot - 1, -dp_plot) # Plot the background variables # presvals = np.arange(1000, 0, -10) #draw mixing ratio lines draw_mixing_ratio_lines(ax) ax.semilogy(prof.tmpc[~prof.tmpc.mask], prof.pres[~prof.tmpc.mask], 'r', lw=2) ax.semilogy(prof.dwpc[~prof.dwpc.mask], prof.pres[~prof.dwpc.mask], 'lime', lw=2) ax.semilogy(prof.vtmp[~prof.dwpc.mask], prof.pres[~prof.dwpc.mask], 'r--', lw=1) ax.semilogy(prof.wetbulb[~prof.dwpc.mask], prof.pres[~prof.dwpc.mask], 'cyan', '-', lw=1) #write sfc temp and dewpoint in F sfcT = prof.tmpc[~prof.tmpc.mask][0] sfcTd = prof.dwpc[~prof.dwpc.mask][0] sfcW = prof.wetbulb[~prof.dwpc.mask][0] sfcP = prof.pres[~prof.tmpc.mask][0] ax.annotate(str(int(sfcW * (9 / 5) + 32)), (sfcW, sfcP), xytext=(-6, -9), textcoords='offset points', color='cyan', weight='black', size=8, path_effects=[pe.withStroke(linewidth=2, foreground="black")]) ax.annotate(str(int(sfcT * (9 / 5) + 32)), (sfcT, sfcP), xytext=(-2, -9), textcoords='offset points', color='r', weight='black', size=8, path_effects=[pe.withStroke(linewidth=2, foreground="black")]) ax.annotate(str(int(sfcTd * (9 / 5) + 32)), (sfcTd, sfcP), xytext=(-12, -9), textcoords='offset points', color='lime', weight='black', size=8, path_effects=[pe.withStroke(linewidth=2, foreground="black")]) #plot significant levels plot_sig_levels(ax, prof) # Plot the parcel trace, but this may fail. If it does so, inform the user. try: ax.semilogy(prof.mupcl.ttrace, prof.mupcl.ptrace, 'w--') except: print("Couldn't plot parcel traces...") # Highlight the 0 C and -20 C isotherms. l = ax.axvline(0, color='b', ls='--') l = ax.axvline(-20, color='b', ls='--') #plot dry adiabats skew.draw_dry_adiabats(ax, color='silver') #draw heights skew.draw_heights(ax, prof) # Disables the log-formatting that comes with semilogy ax.yaxis.set_major_formatter(ScalarFormatter()) pmin = prof.pres[~prof.dwpc.mask][-1] if pmin > 700.: ax.set_yticks(np.arange(100, 1000, 50)) else: ax.set_yticks(np.linspace(100, 1000, 10)) ax.set_ylim(pb_plot, pt_plot) # Plot the hodograph data. # inset_axes = draw_hodo_inset(ax, prof) hodoAx = plt.subplot(gs[0:3, 3:]) hodoAx.set_facecolor('k') hodoAx.axis('off') hodoAx = draw_hodo_inset(hodoAx, prof) # plotHodo(inset_axes, prof.hght, prof.u, prof.v, color='r') plotHodo(hodoAx, prof.hght, prof.u, prof.v, color='r') #plot bunkers motion unless the most unstable EL does not exist srwind = params.bunkers_storm_motion(prof) if isinstance(prof.mupcl.elpres, np.float64): hodoAx.text(srwind[0], srwind[1], 'RM', color='w', fontsize=8) hodoAx.text(srwind[2], srwind[3], 'LM', color='w', fontsize=8) else: print("couldn't plot Bunkers vectors") # inset_axes.text(srwind[0], srwind[1], 'RM', color='r', fontsize=8) # inset_axes.text(srwind[2], srwind[3], 'LM', color='b', fontsize=8) #mask out barbs above the top of the plot below_pmin = np.where(prof.pres >= pt_plot)[0] # Draw the wind barbs axis and everything that comes with it. if pmin > 700.: ax.xaxis.set_major_locator(MultipleLocator(5)) else: ax.xaxis.set_major_locator(MultipleLocator(10)) ax.set_xlim(t_lower, t_upper) ax2 = plt.subplot(gs[0:3, 2]) ax3 = plt.subplot(gs[3, 0:3]) plot_wind_axes(ax2, pb_plot, pt_plot, plevs_plot) #setting the stride for how many wind barbs plot # st = 15 # plot_wind_barbs(ax2, prof.pres[below_pmin][~prof.pres.mask[below_pmin]][::st], # prof.u[below_pmin][~prof.u.mask[below_pmin]][::st], # prof.v[below_pmin][~prof.v.mask[below_pmin]][::st], # pt_plot) plot_wind_barbs(ax2, prof.pres[below_pmin][~prof.pres.mask[below_pmin]], prof.u[below_pmin][~prof.u.mask[below_pmin]], prof.v[below_pmin][~prof.v.mask[below_pmin]], pt_plot) gs.update(left=0.05, bottom=0.05, top=0.95, right=1, wspace=0.025) # Calculate indices to be shown. More indices can be calculated here using the tutorial and reading the params module. p1km = interp.pres(prof, interp.to_msl(prof, 1000.)) p6km = interp.pres(prof, interp.to_msl(prof, 6000.)) sfc = prof.pres[prof.sfc] sfc_1km_shear = winds.wind_shear(prof, pbot=sfc, ptop=p1km) sfc_6km_shear = winds.wind_shear(prof, pbot=sfc, ptop=p6km) srh3km = winds.helicity(prof, 0, 3000., stu=srwind[0], stv=srwind[1]) srh1km = winds.helicity(prof, 0, 1000., stu=srwind[0], stv=srwind[1]) scp = params.scp(prof.mupcl.bplus, prof.right_esrh[0], prof.ebwspd) stp_cin = params.stp_cin(prof.mlpcl.bplus, prof.right_esrh[0], prof.ebwspd, prof.mlpcl.lclhght, prof.mlpcl.bminus) stp_fixed = params.stp_fixed( prof.sfcpcl.bplus, prof.sfcpcl.lclhght, srh1km[0], utils.comp2vec(prof.sfc_6km_shear[0], prof.sfc_6km_shear[1])[1]) ship = params.ship(prof) # A routine to perform the correct formatting when writing the indices out to the figure. def fmt(value, fmt='int'): if fmt == 'int': try: val = int(value) except: val = str("M") else: try: val = round(value, 1) except: val = "M" return val # Setting a dictionary that is a collection of all of the indices we'll be showing on the figure. # the dictionary includes the index name, the actual value, and the units. indices = {'SBCAPE': [fmt(prof.sfcpcl.bplus), 'J/kg'],\ 'SBCIN': [fmt(prof.sfcpcl.bminus), 'J/kg'],\ 'SBLCL': [fmt(prof.sfcpcl.lclhght), 'm AGL'],\ 'SBLFC': [fmt(prof.sfcpcl.lfchght), 'm AGL'],\ 'SBEL': [fmt(prof.sfcpcl.elhght), 'm AGL'],\ 'SBLI': [fmt(prof.sfcpcl.li5), 'C'],\ 'MLCAPE': [fmt(prof.mlpcl.bplus), 'J/kg'],\ 'MLCIN': [fmt(prof.mlpcl.bminus), 'J/kg'],\ 'MLLCL': [fmt(prof.mlpcl.lclhght), 'm AGL'],\ 'MLLFC': [fmt(prof.mlpcl.lfchght), 'm AGL'],\ 'MLEL': [fmt(prof.mlpcl.elhght), 'm AGL'],\ 'MLLI': [fmt(prof.mlpcl.li5), 'C'],\ 'MUCAPE': [fmt(prof.mupcl.bplus), 'J/kg'],\ 'MUCIN': [fmt(prof.mupcl.bminus), 'J/kg'],\ 'MULCL': [fmt(prof.mupcl.lclhght), 'm AGL'],\ 'MULFC': [fmt(prof.mupcl.lfchght), 'm AGL'],\ 'MUEL': [fmt(prof.mupcl.elhght), 'm AGL'],\ 'MULI': [fmt(prof.mupcl.li5), 'C'],\ '0-1 km SRH': [fmt(srh1km[0]), 'm2/s2'],\ '0-1 km Shear': [fmt(utils.comp2vec(sfc_1km_shear[0], sfc_1km_shear[1])[1]), 'kts'],\ '0-3 km SRH': [fmt(srh3km[0]), 'm2/s2'],\ '0-6 km Shear': [fmt(utils.comp2vec(sfc_6km_shear[0], sfc_6km_shear[1])[1]), 'kts'],\ 'Eff. SRH': [fmt(prof.right_esrh[0]), 'm2/s2'],\ 'EBWD': [fmt(prof.ebwspd), 'kts'],\ 'PWV': [round(prof.pwat, 2), 'inch'],\ 'K-index': [fmt(params.k_index(prof)), ''],\ 'STP(fix)': [fmt(stp_fixed, 'flt'), ''],\ 'SHIP': [fmt(ship, 'flt'), ''],\ 'SCP': [fmt(scp, 'flt'), ''],\ 'STP(cin)': [fmt(stp_cin, 'flt'), '']} # List the indices within the indices dictionary on the side of the plot. trans = transforms.blended_transform_factory(ax.transAxes, ax.transData) # Write out all of the indices to the figure. #print("##############") #print(" INDICES ") #print("##############") string = '' keys = np.sort(list(indices.keys())) x = 0 counter = 0 for key in keys: string = string + key + ': ' + str( indices[key][0]) + ' ' + indices[key][1] + '\n' # print((key + ": " + str(indices[key][0]) + ' ' + indices[key][1])) if counter < 7: counter += 1 continue else: counter = 0 ax3.text(x, 1, string, verticalalignment='top', transform=ax3.transAxes, fontsize=11, color='w') string = '' x += 0.3 ax3.text(x, 1, string, verticalalignment='top', transform=ax3.transAxes, fontsize=11, color='w') ax3.set_axis_off() # Show SARS matches (edited for Keith Sherburn) #try: # supercell_matches = prof.supercell_matches # hail_matches = prof.matches #except: # supercell_matches = prof.right_supercell_matches # hail_matches = prof.right_matches #print() #print("#############") #print(" SARS OUTPUT ") #print("#############") #for mtype, matches in zip(['Supercell', 'Hail'], [supercell_matches, hail_matches]): # print(mtype) # print('-----------') # if len(matches[0]) == 0: # print("NO QUALITY MATCHES") # for i in range(len(matches[0])): # print(matches[0][i] + ' ' + matches[1][i]) # print("Total Loose Matches:", matches[2]) # print("# of Loose Matches that met Criteria:", matches[3]) # print("SVR Probability:", matches[4]) # print() #plot logos im = plt.imread('logo.png') #left, bottom, width, height = [0.25, 0.6, 0.2, 0.2] #left, bottom, width, height = [0.1, 0.175, 0.4, 0.4] #bottom left left, bottom, width, height = [0.035, 0.65, 0.4, 0.4] # ax4 = fig.add_axes([left, bottom, width, height]) ax4 = plt.subplot(gs[3, 4]) implot = ax4.imshow(im, alpha=0.99) ax4.axis('off') ax4.set_facecolor('k') im2 = plt.imread('essc_logo.png') ax5 = plt.subplot(gs[3, 5]) implot = ax5.imshow(im2, alpha=0.99) ax5.axis('off') ax5.set_facecolor('k') #plot SHARPpy acknowledgement # plt.text(1, 1, 'Plotted with SHARPpy', horizontalalignment='right', # verticalalignment='top', transform=ax.transAxes, color='w') hodoAx.annotate( 'Plotted with SHARPpy - https://sharppy.github.io/SHARPpy/', (0.7, 0.96), xycoords='figure fraction', va='center', color='w') #filename for the plot # plotName = os.path.splitext(file)[0] + '.png' # Finalize the image formatting and alignments, and save the image to the file. #gs.tight_layout(fig) plt.style.use('dark_background') fn = time.strftime( '%Y%m%d.%H%M') + '_' + locInfo[0] + '_' + locInfo[1] + '.png' fn = fn.replace('/', '') print('SHARPpy quick-look image output at: ' + imgName) #plt.savefig(fn, bbox_inches='tight', dpi=180) plt.savefig(imgName, dpi=180)
#PARCEL CALCULATIONS with sharppy sfcpcl = params.parcelx(prof, flag=1) # Surface Parcel fcstpcl = params.parcelx(prof, flag=2) # Forecast Parcel mupcl = params.parcelx(prof, flag=3) # Most-Unstable Parcel mlpcl = params.parcelx(prof, flag=4) # 100 mb Mean Layer Parcel 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) 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]) 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) eff_inflow = params.effective_inflow_layer(prof) ebot_hght = interp.to_agl(prof, interp.hght(prof, eff_inflow[0])) etop_hght = interp.to_agl(prof, interp.hght(prof, eff_inflow[1])) effective_srh = winds.helicity(prof, ebot_hght, etop_hght, stu=srwind[0], stv=srwind[1]) ebwd = winds.wind_shear(prof, pbot=eff_inflow[0], ptop=eff_inflow[1])
def get_kinematics(self): ''' Function to generate the numerous kinematic quantities used for display and calculations. It requires that the parcel calculations have already been called for the lcl to el shear and mean wind vectors, as well as indices that require an effective inflow layer. Parameters ---------- None Returns ------- None ''' sfc = self.pres[self.sfc] heights = np.array([1000., 3000., 4000., 5000., 6000., 8000., 9000.]) p1km, p3km, p4km, p5km, p6km, p8km, p9km = interp.pres(self, interp.to_msl(self, heights)) ## 1km and 6km winds self.wind1km = interp.vec(self, p1km) self.wind6km = interp.vec(self, p6km) ## calcluate wind shear self.sfc_1km_shear = winds.wind_shear(self, pbot=sfc, ptop=p1km) self.sfc_3km_shear = winds.wind_shear(self, pbot=sfc, ptop=p3km) self.sfc_6km_shear = winds.wind_shear(self, pbot=sfc, ptop=p6km) self.sfc_8km_shear = winds.wind_shear(self, pbot=sfc, ptop=p8km) self.sfc_9km_shear = winds.wind_shear(self, pbot=sfc, ptop=p9km) self.lcl_el_shear = winds.wind_shear(self, pbot=self.mupcl.lclpres, ptop=self.mupcl.elpres) ## calculate mean wind self.mean_1km = utils.comp2vec(*winds.mean_wind(self, pbot=sfc, ptop=p1km)) self.mean_3km = utils.comp2vec(*winds.mean_wind(self, pbot=sfc, ptop=p3km)) self.mean_6km = utils.comp2vec(*winds.mean_wind(self, pbot=sfc, ptop=p6km)) self.mean_8km = utils.comp2vec(*winds.mean_wind(self, pbot=sfc, ptop=p8km)) self.mean_lcl_el = utils.comp2vec(*winds.mean_wind(self, pbot=self.mupcl.lclpres, ptop=self.mupcl.elpres)) ## parameters that depend on the presence of an effective inflow layer if self.etop is ma.masked or self.ebottom is ma.masked: self.etopm = ma.masked; self.ebotm = ma.masked self.srwind = winds.non_parcel_bunkers_motion( self ) self.eff_shear = [MISSING, MISSING] self.ebwd = [MISSING, MISSING, MISSING] self.ebwspd = MISSING self.mean_eff = [MISSING, MISSING, MISSING] self.mean_ebw = [MISSING, MISSING, MISSING] self.srw_eff = [MISSING, MISSING, MISSING] self.srw_ebw = [MISSING, MISSING, MISSING] self.right_esrh = [ma.masked, ma.masked, ma.masked] self.left_esrh = [ma.masked, ma.masked, ma.masked] self.critical_angle = ma.masked else: self.srwind = params.bunkers_storm_motion(self, mupcl=self.mupcl, pbot=self.ebottom) depth = ( self.mupcl.elhght - self.ebotm ) / 2 elh = interp.pres(self, interp.to_msl(self, self.ebotm + depth)) ## calculate mean wind self.mean_eff = winds.mean_wind(self, self.ebottom, self.etop ) self.mean_ebw = winds.mean_wind(self, pbot=self.ebottom, ptop=elh ) ## calculate wind shear of the effective layer self.eff_shear = winds.wind_shear(self, pbot=self.ebottom, ptop=self.etop) self.ebwd = winds.wind_shear(self, pbot=self.ebottom, ptop=elh) self.ebwspd = utils.mag( self.ebwd[0], self.ebwd[1] ) ## calculate the mean sr wind self.srw_eff = winds.sr_wind(self, pbot=self.ebottom, ptop=self.etop, stu=self.srwind[0], stv=self.srwind[1] ) self.srw_ebw = winds.sr_wind(self, pbot=self.ebottom, ptop=elh, stu=self.srwind[0], stv=self.srwind[1] ) self.right_esrh = winds.helicity(self, self.ebotm, self.etopm, stu=self.srwind[0], stv=self.srwind[1]) self.left_esrh = winds.helicity(self, self.ebotm, self.etopm, stu=self.srwind[2], stv=self.srwind[3]) self.critical_angle = winds.critical_angle(self, stu=self.srwind[0], stv=self.srwind[1]) ## calculate mean srw self.srw_1km = utils.comp2vec(*winds.sr_wind(self, pbot=sfc, ptop=p1km, stu=self.srwind[0], stv=self.srwind[1] )) self.srw_3km = utils.comp2vec(*winds.sr_wind(self, pbot=sfc, ptop=p3km, stu=self.srwind[0], stv=self.srwind[1] )) self.srw_6km = utils.comp2vec(*winds.sr_wind(self, pbot=sfc, ptop=p6km, stu=self.srwind[0], stv=self.srwind[1] )) self.srw_8km = utils.comp2vec(*winds.sr_wind(self, pbot=sfc, ptop=p8km, stu=self.srwind[0], stv=self.srwind[1] )) self.srw_4_5km = utils.comp2vec(*winds.sr_wind(self, pbot=p4km, ptop=p5km, stu=self.srwind[0], stv=self.srwind[1] )) self.srw_lcl_el = utils.comp2vec(*winds.sr_wind(self, pbot=self.mupcl.lclpres, ptop=self.mupcl.elpres, stu=self.srwind[0], stv=self.srwind[1] )) # This is for the red, blue, and purple bars that appear on the SR Winds vs. Height plot self.srw_0_2km = winds.sr_wind(self, pbot=sfc, ptop=interp.pres(self, interp.to_msl(self, 2000.)), stu=self.srwind[0], stv=self.srwind[1]) self.srw_4_6km = winds.sr_wind(self, pbot=interp.pres(self, interp.to_msl(self, 4000.)), ptop=p6km, stu=self.srwind[0], stv=self.srwind[1]) self.srw_9_11km = winds.sr_wind(self, pbot=interp.pres(self, interp.to_msl(self, 9000.)), ptop=interp.pres(self, interp.to_msl(self, 11000.)), stu=self.srwind[0], stv=self.srwind[1]) ## calculate upshear and downshear self.upshear_downshear = winds.mbe_vectors(self) self.srh1km = winds.helicity(self, 0, 1000., stu=self.srwind[0], stv=self.srwind[1]) self.srh3km = winds.helicity(self, 0, 3000., stu=self.srwind[0], stv=self.srwind[1])
######################### # Calculate indices to be shown. p1km = interp.pres(prof, interp.to_msl(prof, 1000.)) p3km = interp.pres(prof, interp.to_msl(prof, 3000.)) p6km = interp.pres(prof, interp.to_msl(prof, 6000.)) p8km = interp.pres(prof, interp.to_msl(prof, 8000.)) p9km = interp.pres(prof, interp.to_msl(prof, 9000.)) sfc = prof.pres[prof.sfc] sfc_1km_shear = winds.wind_shear(prof, pbot=sfc, ptop=p1km) sfc_3km_shear = winds.wind_shear(prof, pbot=sfc, ptop=p3km) sfc_6km_shear = winds.wind_shear(prof, pbot=sfc, ptop=p6km) sfc_8km_shear = winds.wind_shear(prof, pbot=sfc, ptop=p8km) sfc_9km_shear = winds.wind_shear(prof, pbot=sfc, ptop=p9km) srh3km = winds.helicity(prof, 0, 3000., stu=srwind[0], stv=srwind[1]) srh1km = winds.helicity(prof, 0, 1000., stu=srwind[0], stv=srwind[1]) scp = params.scp(prof.mupcl.bplus, prof.right_esrh[0], prof.ebwspd) stp_cin = params.stp_cin(prof.mlpcl.bplus, prof.right_esrh[0], prof.ebwspd, prof.mlpcl.lclhght, prof.mlpcl.bminus) stp_fixed = params.stp_fixed( prof.sfcpcl.bplus, prof.sfcpcl.lclhght, srh1km[0], utils.comp2vec(prof.sfc_6km_shear[0], prof.sfc_6km_shear[1])[1]) ship = params.ship(prof) ######################### # A routine to perform the correct formatting when writing the indices out to the figure. def fmt(value, fmt='int'): if fmt == 'int': try:
inflow_bot = skew.ax.axhline(eff_inflow[0], color='purple', xmin=0.38, xmax=0.45) inflow_top = skew.ax.axhline(eff_inflow[1], color='purple', xmin=0.38, xmax=0.45) srwind = params.bunkers_storm_motion(prof) # annotate effective inflow layer SRH if eff_inflow[0]: ebot_hght = interp.to_agl(prof, interp.hght(prof, eff_inflow[0])) etop_hght = interp.to_agl(prof, interp.hght(prof, eff_inflow[1])) effective_srh = winds.helicity(prof, ebot_hght, etop_hght, stu=srwind[0], stv=srwind[1]) # Set position of label # x position is mean of horizontal line bounds # For some reason this makes a big white space on the left side and for all subsequent plots. inflow_SRH = skew.ax.text(np.mean(inflow_top.get_xdata()), eff_inflow[1], '%.0f' % effective_srh[0] + ' ' + '$\mathregular{m^{2}s^{-2}}$', verticalalignment='bottom', horizontalalignment='center', size=6, transform=inflow_bot.get_transform(), color=inflow_top.get_color())
verticalalignment='top', horizontalalignment='center', size=7, color=dwpt_trace.get_color()) skew.plot(pcl.ptrace, pcl.ttrace, 'brown', linestyle="dashed" ) # parcel temperature trace skew.ax.set_ylim(1050,100) skew.ax.set_xlim(-50,45) # Plot the effective inflow layer using purple horizontal lines eff_inflow = params.effective_inflow_layer(prof) inflow_bot = skew.ax.axhline(eff_inflow[0], color='purple',xmin=0.38, xmax=0.45) inflow_top = skew.ax.axhline(eff_inflow[1], color='purple',xmin=0.38, xmax=0.45) srwind = params.bunkers_storm_motion(prof) # annotate effective inflow layer SRH if eff_inflow[0]: ebot_hght = interp.to_agl(prof, interp.hght(prof, eff_inflow[0])) etop_hght = interp.to_agl(prof, interp.hght(prof, eff_inflow[1])) effective_srh = winds.helicity(prof, ebot_hght, etop_hght, stu = srwind[0], stv = srwind[1]) # Set position of label # x position is mean of horizontal line bounds # For some reason this makes a big white space on the left side and for all subsequent plots. inflow_SRH = skew.ax.text( np.mean(inflow_top.get_xdata()), eff_inflow[1], '%.0f' % effective_srh[0] + ' ' + '$\mathregular{m^{2}s^{-2}}$', verticalalignment='bottom', horizontalalignment='center', size=6, transform=inflow_bot.get_transform(), color=inflow_top.get_color() ) # draw indices text string to the right of plot. indices_text = plt.text(1.08, 1.0, myskewt.indices(prof), verticalalignment='top', size=5.6, transform=plt.gca().transAxes) # globe with dot mapax = myskewt.add_globe(longitude, latitude)