for key,value in myParcelAnalysis.items(): if isinstance(value, float) : print("%s = %.1f"%(key,value)) else: print("%s = %s"%(key,str(value))) #Plot the parcel trajectory in the SkewT diagram # First we lift the parcel adiabatically initialLevel = myParcelAnalysis['initialLevel'] parcelTemperature = liftParcel(temperature[initialLevel], pressure, myParcelAnalysis['pressureAtLCL'], initialLevel=initialLevel, hPa=True, celsius=True) # Create a Figure Manager mySkewT_Figure = figure() # Add an Skew-T axes to the Figure mySkewT_Axes = mySkewT_Figure.add_subplot(111, projection='skewx') # Plot the parcel temperature mySkewT_Axes.plot(parcelTemperature, pressure, linewidth=3, color='r' ) # Add a marker for the LCL and the LFC mySkewT_Axes.plot(myParcelAnalysis['temperatureAtLCL'], myParcelAnalysis['pressureAtLCL'],
def addProfile(self, pressure, temperature, dewPointTemperature, hPa=True, celsius=True, method=0, initialLevel=0, parcel=True, label=None, diagnostics=False, markers=True, useVirtual=True, **kwargs): """ Add a profile to the Skew-T axis .. _`matplotlib.legend`: http://matplotlib.org/api/pyplot_api.html#matplotlib.pyplot.legend .. _ndarray: https://docs.scipy.org/doc/numpy/reference/generated/numpy.ndarray.html .. _MaskedArray: https://docs.scipy.org/doc/numpy/reference/maskedarray.html The input data can be ndarray_ or MaskedArray_. If MaskedArray_ are used, the pressure levels with masked or invalid entries in the pressure and temperature arrays are removed. Masked values in the dewPointTemperature are not plotted. Parameters ---------- pressure : ndarray_ or MaskedArray_ Pressure levels of the sounding temperature : ndarray_ or MaskedArray_ Temperature profile at pressure levels dewPointTemperature : : ndarray_ or MaskedArray_ Dew point temperature at pressure levels hPa: bool, optional If is True, the pressure levels are in hPa. Otherwise Pascals is assumed celsius : bool, optional If is True, the temperatures units correspond to celsius degrees. Otherwise Kelvin degrees units are assumed parcel : bool, optional If True, the parcel analysis is carried out. method : int, optional Parcel analysis method used. Supported: * Most Unstable : method=0 * Single Parcel: method=1 * Mixed Layer : method=2 (Not supported yet) initialLevel : int, optional Initial level (index) used to compute the parcel analysis. Levels below this value are ignored. For the Single Parcel analysis, this level correspond to the parcel used. By default, the initial level is 0 (surface). For the Most Unstable method, this value is ignored. label : str, optional Label assigned to the profile lines. If None, no label is used. When a line is labeled, the legend is added automatically to the plot. use keyword **loc** to control the position. diagnostics : bool, optional If True a text box is added to the upper right corner with some diagnostics from the parcel analysis. markers: bool, optional If True, the LCL, LFC and EL are marked in the plot with markers. useVirtual : bool, optional If True, in the parcel analysis, CAPE and CIN are computed used the virtual temperature. The temperatures plotted in the SkewT diagram will correspond to virtual temperature instead of temperature. If False, virtual temperatures corrections are neglected and the original temperature is plotted. Other Parameters ---------------- loc : str Legend location. See `matplotlib.legend`_ for more details. kwargs : extra The remaining extra keyword arguments are passed to the plot function when plotting the temperature profiles. """ mask = numpy.zeros_like(pressure, dtype=bool) if isinstance(pressure, masked_array): pressure[pressure.mask] = numpy.nan mask = logical_or(mask, getmaskarray(pressure)) if isinstance(temperature, masked_array): temperature[temperature.mask] = numpy.nan mask = logical_or(mask, getmaskarray(temperature)) if isinstance(dewPointTemperature, masked_array): dewPointMask = getmaskarray(dewPointTemperature) dewPointTemperature.data[dewPointMask] = numpy.nan dewPointTemperature = numpy.asarray(dewPointTemperature.data, dtype=numpy.float32) pressure = masked_invalid(pressure[~mask]) temperature = masked_invalid(temperature[~mask]) dewPointTemperature = masked_invalid(dewPointTemperature[~mask]) # Convert temperatures and pressure to hPa if not hPa: pressure /= 100 if not celsius: temperature -= degCtoK dewPointTemperature -= degCtoK if parcel: parcelAnalysisResult = parcelAnalysis(pressure, temperature, dewPointTemperature, hPa=True, celsius=True, useVirtual=1, initialLevel=initialLevel, method=method) initialLevel = parcelAnalysisResult['initialLevel'] initialTemperature = temperature[initialLevel] pressureAtLCL = parcelAnalysisResult['pressureAtLCL'] temperatureAtLCL = parcelAnalysisResult['temperatureAtLCL'] pressureAtLFC = parcelAnalysisResult['pressureAtLFC'] temperatureAtLFC = parcelAnalysisResult['temperatureAtLFC'] pressureAtEL = parcelAnalysisResult['pressureAtEL'] temperatureAtEL = parcelAnalysisResult['temperatureAtEL'] parcelTemperature = liftParcel(initialTemperature, pressure, pressureAtLCL, initialLevel=initialLevel, hPa=True, celsius=True) # Add LCL belowLCL = numpy.where(pressure > pressureAtLCL, True, False) newParcelTemperature = numpy.concatenate( (parcelTemperature[belowLCL], [temperatureAtLCL], parcelTemperature[~belowLCL])) newPressure = numpy.concatenate( (pressure[belowLCL], [pressureAtLCL], pressure[~belowLCL])) # Add EL belowEL = numpy.where(newPressure > pressureAtEL, True, False) newParcelTemperature = numpy.concatenate( (newParcelTemperature[belowEL], [temperatureAtEL], newParcelTemperature[~belowEL])) newPressure = numpy.concatenate( (newPressure[belowEL], [pressureAtEL], newPressure[~belowEL])) belowLFC = numpy.where(newPressure > pressureAtLFC, True, False) newParcelTemperature = numpy.concatenate( (newParcelTemperature[belowLFC], [temperatureAtLFC], newParcelTemperature[~belowLFC])) newPressure = numpy.concatenate( (newPressure[belowLFC], [pressureAtLFC], newPressure[~belowLFC])) newTemperature = numpy.interp(newPressure, pressure[::-1], temperature[::-1]) newParcelTemperature = masked_invalid(newParcelTemperature) if useVirtual: newDewPointTemperature = numpy.interp( newPressure, pressure[::-1], dewPointTemperature[::-1]) newTemperature = virtualTemp3(newTemperature, newDewPointTemperature, newPressure * 100) belowLCL = (newPressure >= pressureAtLCL) newParcelTemperature[belowLCL] = virtualTemp3( newParcelTemperature[belowLCL], dewPointTemperature[initialLevel], newPressure[belowLCL] * 100) aboveLCL = (newPressure < pressureAtLCL) newParcelTemperature[aboveLCL] = virtualTemp4( newParcelTemperature[aboveLCL], newPressure[aboveLCL] * 100) else: newTemperature = temperature newPressure = pressure kwargs['zorder'] = kwargs.pop('zorder', 5) kwargs['linewidth'] = kwargs.pop('linewidth', 2.0) kwargs['linestyle'] = kwargs.pop('linestyle', '-') loc = kwargs.pop('loc', 'best') temperatureLine, = self.plot(newTemperature, newPressure, 'r', **kwargs) self.plot(dewPointTemperature, pressure, 'b', **kwargs) if label is not None: self.linesHandlers.append(temperatureLine) self.linesLabels.append(label) self.legend(self.linesHandlers, self.linesLabels, loc=loc) if parcel: self.plot(newParcelTemperature, newPressure, 'k', **kwargs) if parcelAnalysisResult['CAPE'] > 0: # Positive Buoyancy cond1 = (newPressure <= pressureAtLFC) * (newPressure >= pressureAtEL) self.fill_betweenx(newPressure, newParcelTemperature, newTemperature, where=cond1, \ color="#ff0009", alpha=0.4, zorder=10) # Negative Buoyancy validMask = ~getmaskarray(masked_invalid(newParcelTemperature)) cond2 = ((newParcelTemperature[validMask] <= newTemperature[validMask]) * (newPressure[validMask] >= pressureAtLFC)) self.fill_betweenx(newPressure[validMask], newParcelTemperature[validMask], newTemperature[validMask], where=cond2, \ color="#045cff", alpha=0.4, zorder=10) if markers: if useVirtual: temperatureAtLCL = virtualTemp4(temperatureAtLCL, pressureAtLCL * 100) temperatureAtLFC = virtualTemp4(temperatureAtLFC, pressureAtLFC * 100) temperatureAtEL = virtualTemp4(temperatureAtEL, pressureAtEL * 100) self.plot(temperatureAtLCL, pressureAtLCL, ls='', marker='o', color='r') self.plot(temperatureAtLFC, pressureAtLFC, ls='', marker='o', color='g') self.plot(temperatureAtEL, pressureAtEL, ls='', marker='o', color='k') if diagnostics: # Add text to sounding dtext = "Diagnostics:\n" # dtext ="Parcel: %s\n"%ptype.upper() # dtext+="P :%6.1fhPa\n"%startp # dtext+="T : %4.1fC\n"%startt # dtext+="Td : %4.1fC\n"%startdp dtext += "-------------\n" dtext += "P_par:%6.1fhPa\n" % (pressure[initialLevel]) dtext += "P_LCL:%6.1fhPa\n" % ( parcelAnalysisResult['pressureAtLCL']) dtext += "T_LCL:%4.1fC\n" % ( parcelAnalysisResult['temperatureAtLCL']) dtext += "P_LFC:%6.1fhPa\n" % ( parcelAnalysisResult['pressureAtLFC']) dtext += "T_LFC:%4.1fC\n" % ( parcelAnalysisResult['temperatureAtLFC']) dtext += "P_EL:%6.1fhPa\n" % ( parcelAnalysisResult['pressureAtEL']) dtext += "T_EL:%4.1fC\n" % ( parcelAnalysisResult['temperatureAtEL']) dtext += "CAPE:%.1f\n" % parcelAnalysisResult['CAPE'] dtext += "CIN: %.1fJ" % parcelAnalysisResult['CIN'] axesBox = self.get_position().get_points() self.figure.text(axesBox[1, 0], axesBox[1, 1], dtext, fontname="monospace", backgroundcolor='white', zorder=10, verticalalignment='top', horizontalalignment='right', multialignment="left")