def do_thermodynamics(self):

        assert 'temp' in self.soundingdata, \
            "Temperature needed for thermodynamics! Add TEMP"
        assert 'pres' in self.soundingdata, \
            "Pressure needed for thermodynamics! Add PRES"
        assert 'dwpt' in self.soundingdata, \
            "Moisture needed for thermodynamics! Add DWPT"

        # primary variables
        prespa = self.soundingdata['pres'] * 100.
        tempc = self.soundingdata['temp']
        tempk = tempc + degCtoK
        dwptc = self.soundingdata['dwpt']

        # secondary variables
        e = VaporPressure(dwptc)
        esat = VaporPressure(tempc)

        # assign/extract other variables
        if 'thta' not in self.soundingdata:
            self.soundingdata['thta'] = Theta(tempk, prespa)

        if 'thte' not in self.soundingdata:
            self.soundingdata['thte'] = ThetaE(tempk, prespa, e)

        if 'thtv' not in self.soundingdata:
            self.soundingdata['thtv'] = ThetaV(tempk, prespa, e)

        if 'relh' not in self.soundingdata:
            self.soundingdata['relh'] = 100. * e / esat

        return
예제 #2
0
파일: SkewT.py 프로젝트: haipeng-one/SkewT
    def surface_parcel(self,mixdepth=125):
	"""Returns parameters for a parcel initialised by:
	1. Surface pressure (i.e. pressure of lowest level)
	2. Surface temperature determined from max(theta) of lowest <mixdepth> mbar
	3. Dew point temperature representative of lowest <mixdepth> mbar

	Inputs:
	mixdepth (mbar): depth to average mixing ratio over
	"""

	pres=self.data["pres"]
	temp=self.data["temp"]
	dwpt=self.data["dwpt"]

	# identify the layers for averaging
	layers=pres>pres[0]-mixdepth
	
	# parcel pressure is surface pressure
	pres_s=pres[0]

	# average theta over mixheight to give
	# parcel temperature
	thta_mix=Theta(temp[layers]+273.15,pres[layers]*100.).max()
	temp_s=TempK(thta_mix,pres_s*100)-273.15

	# average mixing ratio over mixheight
	vpres=SatVap(dwpt)
	mixr=MixRatio(vpres,pres*100)
	mixr_mix=mixr[layers].mean()
	vpres_s=MixR2VaporPress(mixr_mix,pres_s*100)

	# surface dew point temp
	dwpt_s=DewPoint(vpres_s)

	return pres_s,temp_s,dwpt_s
예제 #3
0
    def mixed_layer_parcel(self, depth=100):
        """Returns parameters for a parcel initialised by:
        1. Surface pressure (i.e. pressure of lowest level)
        2. Surface temperature determined from mean(theta) of lowest <depth> mb
        3. Dew point temperature representative of lowest <depth> mbar

        Inputs:
        depth (mbar): depth to average mixing ratio over
        """

        pres = self.soundingdata["pres"]
        temp = self.soundingdata["temp"]
        dwpt = self.soundingdata["dwpt"]

        pres0, temp0, dwpt0, null = self.surface_parcel()

        # identify the layers for averaging
        layers = pres > (pres0-depth)

        # average theta over mixheight to give
        # parcel temperature
        thta_mix = Theta(temp[layers]+degCtoK, pres[layers]*100.).mean()
        temp_s = TempK(thta_mix, pres0*100) - degCtoK

        # average mixing ratio over mixheight
        vpres = VaporPressure(dwpt)
        mixr = MixRatio(vpres, pres*100)
        mixr_mix = mixr[layers].mean()
        vpres_s = MixR2VaporPress(mixr_mix, pres0*100)

        # surface dew point temp
        dwpt_s = DewPoint(vpres_s)

        # print "----- Mixed Layer Parcel Characteristics -----"
        # print "Mixed layer depth                     : %5d mb "%depth
        # print "Mean mixed layer potential temperature: %5.1f K"%thta_mix
        # print "Mean mixed layer mixing ratio         : %5.2f g/kg"%
        # (mixr_mix*1e3)

        return pres0, temp_s, dwpt_s, 'ml'

        raise NotImplementedError
                        Qccoarse=np.copy(Pcoarse)
                        Qrcoarse=np.copy(Pcoarse)
                        for la in range(Pcoarse.shape[1]):
                            for lo in range(Pcoarse.shape[2]):
                                Pcoarse[:,la,lo]=np.mean(rgrP[:,la*iRatio:la*iRatio+iRatio,lo*iRatio:lo*iRatio+iRatio], axis=(1,2))
                                Tcoarse[:,la,lo]=np.mean(rgrT[:,la*iRatio:la*iRatio+iRatio,lo*iRatio:lo*iRatio+iRatio], axis=(1,2))
                                Qvcoarse[:,la,lo]=np.mean(rgrQv[:,la*iRatio:la*iRatio+iRatio,lo*iRatio:lo*iRatio+iRatio], axis=(1,2))
                                Qccoarse[:,la,lo]=np.mean(rgrQc[:,la*iRatio:la*iRatio+iRatio,lo*iRatio:lo*iRatio+iRatio], axis=(1,2))
                                Qrcoarse[:,la,lo]=np.mean(rgrQr[:,la*iRatio:la*iRatio+iRatio,lo*iRatio:lo*iRatio+iRatio], axis=(1,2))
                        rgrP=Pcoarse
                        rgrT=Tcoarse
                        rgrQv=Qvcoarse
                        rgrQc=Qccoarse
                        rgrQr=Qrcoarse
                # Calculate boyancy
                ThetaK=Theta(rgrT,rgrP)
                ThetaP=ThetaK*(1+0.608*rgrQv-rgrQc-rgrQr)
                AvArea=int(100000/rgrDX[dx])
                ThetaP_mean=scipy.ndimage.uniform_filter(ThetaP[:,:,:],[0,AvArea,AvArea])
                Boyancy=(9.81*(ThetaP-ThetaP_mean))/ThetaP_mean

                # Calculate cold pool intensity
                NAN=np.copy(Boyancy)
                for lev in range(Boyancy.shape[0]):
                    NAN[lev,:,:]=(Boyancy[lev,:,:] > -0.005)
                    NAN[lev,:,:][NAN[lev,:,:] == 1]=np.nan
                    if lev > 1:
                        NAN[lev,:,:]=NAN[lev,:,:]+NAN[lev-1,:,:]

                Boyancy_Low=np.copy(Boyancy)
                Boyancy_Low[np.isnan(NAN)]=np.nan
예제 #5
0
    def make_skewt_axes(self, pmax=1100., pmin=50.):

        self.fig = figure(figsize=(9, 8))
        self.fig.clf()

        rcParams.update({\
        'font.size':10,})

        P = linspace(pmax, pmin, 37)
        pres_levels = np.arange(1000, 0, -100)

        self.skewxaxis = self.fig.add_axes([.085, .1, .73, .8],
                                           projection='skewx')
        self.skewxaxis.set_yscale('log')

        xticklocs = arange(-80, 45, 10)
        T0 = xticklocs

        w = array([
            0.0001, 0.0004, 0.001, 0.002, 0.004, 0.007, 0.01, 0.016, 0.024,
            0.032
        ])
        self.skewxaxis.add_mixratio_isopleths(w,
                                              P[P >= 550],
                                              color='purple',
                                              ls='--',
                                              alpha=1.,
                                              lw=0.5)
        self.skewxaxis.add_dry_adiabats(linspace(250, 440, 20) - 273.15,
                                        P,
                                        color='red',
                                        ls='--',
                                        alpha=1.,
                                        lw=0.5)
        self.skewxaxis.add_moist_adiabats(linspace(8, 32, 7),
                                          P[P >= 200],
                                          color='g',
                                          ls='--',
                                          alpha=1.,
                                          lw=0.5)
        self.skewxaxis.other_housekeeping()

        self.wbax = self.fig.add_axes([0.75, 0.1, 0.1, 0.8],
                                      sharey=self.skewxaxis,
                                      frameon=False)  # wind barb axis
        self.wbax.xaxis.set_ticks([], [])
        self.wbax.yaxis.grid(True, ls='-', color='y', lw=0.5)
        for tick in self.wbax.yaxis.get_major_ticks():
            # tick.label1On = False
            pass
        self.wbax.get_yaxis().set_tick_params(size=0, color='y')
        self.wbax.set_xlim(-1.5, 1.5)
        self.wbax.get_yaxis().set_visible(False)

        # Set up standard atmosphere height scale on
        # LHS of plot. It's jus
        majorLocatorKM = MultipleLocator(2)
        majorLocatorKFT = MultipleLocator(5)
        minorLocator = MultipleLocator(1)

        self.htax = self.fig.add_axes([0.1, 0.1, 1e-6, 0.8],
                                      sharey=self.skewxaxis,
                                      frameon=False)
        self.htax.xaxis.set_ticks([], [])
        self.htax.spines['left'].set_color('k')
        self.htax.spines['right'].set_visible(False)
        self.htax.get_yaxis().set_tick_params(size=0, color='y')
        self.htax.get_yaxis().set_visible(False)
        pres_heights = np.array([
            self.data['hght'][np.argmin(np.abs(_ - self.data['pres']))]
            for _ in pres_levels
        ])
        for ph in range(pres_levels.shape[0]):
            self.htax.text(0,
                           pres_levels[ph],
                           '%d m' % pres_heights[ph],
                           fontsize=8)
        #print pres_heights

        self.fig.text(0.83, 0.9, 'Sounding Params')
        #$\underline{Sounding Params}$')
        #h0 = interp(0, self.data['temp'], self.data['hght'])
        h0 = self.data['hght'][np.argmin(abs(self.data['temp'] - 0))]
        h20 = self.data['hght'][np.argmin(abs(self.data['temp'] + 20))]
        h40 = self.data['hght'][np.argmin(abs(self.data['temp'] + 40))]
        lcl_height = 216 * (self.data['temp'][0] - self.data['dwpt'][0])
        mr = MixRatio(SatVap(self.data['dwpt']), self.data['pres'] * 100)
        pdiff = -1.0 * np.diff(self.data['pres'])
        #print mr.shape, pdiff.shape
        # precipitable water
        pw = np.sum(
            np.array([
                mr[_] * 100.0 * pdiff[_] / 9.8 for _ in range(pdiff.shape[0])
            ]))
        # crude estimate of wet bulb temp
        tw = self.data['temp'][0] - (self.data['temp'][0] -
                                     self.data['dwpt'][0]) / 3.
        # now some shear calculations
        wspd6km = self.data['sknt'][np.argmin(abs(self.data['hght'] - 6000))]
        wdir6km = self.data['drct'][np.argmin(abs(self.data['hght'] - 6000))]

        udiff = wspd6km * np.cos(
            np.radians(270 - wdir6km)) - self.data['sknt'][3] * np.cos(
                np.radians(270 - self.data['drct'][3]))
        vdiff = wspd6km * np.sin(
            np.radians(270 - wdir6km)) - self.data['sknt'][3] * np.sin(
                np.radians(270 - self.data['drct'][3]))
        #print udiff, vdiff
        shear6km = np.sqrt(udiff**2 + vdiff**2)

        #trop_index = tropopause_index(self.data['temp'])
        #if trop_index == -999: tropopause_pressure = -999.
        #else: tropopause_pressure = self.data['pres'][trop_index]
        # New way to do tropopause pressure

        # first calculate the parameters that go in
        smooth_temp = running_mean(self.data['temp'], 3, ntimes=30)

        dp = np.gradient(self.data['pres'])

        #lapse = 1000.0*np.diff(smooth)/np.diff(S.data['hght'])

        deriv = np.gradient(smooth_temp, dp)
        deriv_smooth = running_mean(deriv, 3, ntimes=30)

        theta = running_mean(Theta(273.15 + self.data['temp'],
                                   self.data['pres'] * 100.0),
                             3,
                             ntimes=50)

        dtheta = -1.0 * running_mean(np.gradient(theta, dp), 3, ntimes=10)

        rh = running_mean(RH(self.data['temp'], self.data['dwpt']),
                          3,
                          ntimes=30)
        drh = -1.0 * np.gradient(rh, dp)
        weights = {
            'theta': 1.0,
            'dtdp': 1.0,
            'T': 1.0,
            'dthetadp': 1.0,
            'drhdp': 0.6,
            'pres': 1.0
        }
        input_data = {
            'theta': theta,
            'dtdp': deriv_smooth,
            'T': smooth_temp,
            'dthetadp': dtheta,
            'drhdp': drh,
            'pres': self.data['pres']
        }
        tropopause_pressure = fuzzy_tropopause(input_data, weights)

        self.fig.text(0.83, 0.88, '0%s: %d m' % (degC, h0))
        self.fig.text(0.83, 0.86, '-20%s: %d m' % (degC, h20))
        self.fig.text(0.83, 0.84, '-40%s: %d m' % (degC, h40))
        self.fig.text(0.83, 0.82, 'LCL: %d m' % lcl_height)
        self.fig.text(0.83, 0.80, 'PW: %.1f mm' % pw)
        self.fig.text(0.83, 0.78, '6 km shear: %d kts' % shear6km)
        self.fig.text(0.83, 0.76, 'Trop: %d hPa' % (tropopause_pressure))

        self.fig.text(0.83, 0.70, 'Surface')
        self.fig.text(0.83, 0.68, 'P: %.1f hPa' % self.data['pres'][0])
        self.fig.text(0.83, 0.66, 'Ht: %d m' % (self.data['hght'][0]))

        self.fig.text(0.83, 0.64, 'T: %.1f %s' % (self.data['temp'][0], degC))
        self.fig.text(0.83, 0.62,
                      'T$_D$: %.1f %s' % (self.data['dwpt'][0], degC))
        self.fig.text(0.83, 0.60, 'T$_W$: %.1f %s' % (tw, degC))

        # now do the hodograph?
        self.hodoax = self.fig.add_axes([0.08, 0.69, 0.20, 0.20],
                                        frameon=True,
                                        polar=True)
        self.hodoax.xaxis.set_ticks([], [])
        self.hodoax.yaxis.set_ticks([], [])
        speed_mask = np.ma.masked_where(self.data['sknt'] > 999,
                                        self.data['sknt'])
        angle = 270 - self.data['drct']
        rad_angle = np.radians(angle)
        pres_mask = np.bitwise_and(
            self.data['pres'] > 200.,
            self.data['drct'] < 361.)  # only look at valid winds below 200 mb

        if self.fmt == 'EDT' or self.fmt == 'EC':
            self.hodoax.scatter(rad_angle[pres_mask], self.data['sknt'][pres_mask], c = self.data['hght'][pres_mask], \
            edgecolors = 'none', s = 5, cmap = plt.cm.jet_r)
        elif self.fmt == 'UWYO':
            self.hodoax.plot(rad_angle,
                             self.data['sknt'],
                             c='red',
                             linewidth=3)

        #self.hodoax.plot(rad_angle, speed_mask, c = 'red', linewidth = 3)
        #self.hodoax.set_rmax(100)

        self.hodoax.set_yticks(np.arange(0, 150, 30))
        self.hodoax.tick_params(labelsize=5)
        self.hodoax.set_rlabel_position(180)
        self.hodoax.set_xticks(np.arange(0, 2 * np.pi, np.pi / 2))
        self.hodoax.set_xticklabels([])
        self.hodoax.grid(True)