示例#1
0
    def get_sars(self):
        '''
        Function to get the SARS analogues from the hail and
        supercell databases. Requires calling get_kinematics()
        and get_parcels() first. Also calculates the significant
        hail parameter.
        
        Function returns nothing, but sets the following variables:

        self.matches - the matches from SARS HAIL
        self.ship - significant hail parameter
        self.supercell_matches - the matches from SARS SUPERCELL
        
        Parameters
        ----------
        None

        Returns
        -------
        None
        '''
        sfc_6km_shear = utils.KTS2MS(
            utils.mag(self.sfc_6km_shear[0], self.sfc_6km_shear[1]))
        sfc_3km_shear = utils.KTS2MS(
            utils.mag(self.sfc_3km_shear[0], self.sfc_3km_shear[1]))
        sfc_9km_shear = utils.KTS2MS(
            utils.mag(self.sfc_9km_shear[0], self.sfc_9km_shear[1]))
        h500t = interp.temp(self, 500.)
        lapse_rate = params.lapse_rate(self, 700., 500., pres=True)
        srh3km = self.srh3km[0]
        srh1km = self.srh1km[0]
        mucape = self.mupcl.bplus
        mlcape = self.mlpcl.bplus
        mllcl = self.mlpcl.lclhght
        mumr = thermo.mixratio(self.mupcl.pres, self.mupcl.dwpc)
        self.ship = params.ship(self)

        ## Cambios para el hemisferio sur JP JP
        if self.latitude < 0:
            srh1km = -srh1km
            srh3km = -srh3km

        self.hail_database = 'sars_hail.txt'
        self.supercell_database = 'sars_supercell.txt'
        try:
            self.matches = hail(self.hail_database, mumr, mucape, h500t,
                                lapse_rate, sfc_6km_shear, sfc_9km_shear,
                                sfc_3km_shear, srh3km)
        except:
            self.matches = ([], [], 0, 0, 0)
        try:
            self.supercell_matches = supercell(self.supercell_database, mlcape,
                                               mllcl, h500t, lapse_rate,
                                               utils.MS2KTS(sfc_6km_shear),
                                               srh1km,
                                               utils.MS2KTS(sfc_3km_shear),
                                               utils.MS2KTS(sfc_9km_shear),
                                               srh3km)
        except Exception as e:
            self.supercell_matches = ([], [], 0, 0, 0)
示例#2
0
def hodo_curve(prof, pbot=850, ptop=250, dp=-1, exact=True):
    '''
    Calculates the curvature of the hodograph length over a particular layer
    between (pbot) and (ptop), by dividing the total shear length by the
    bulk shear.  Values of exactly 1 indicate a perfectly straight hodograph
    length, while higher values indicate an increasingly more curved hodograph
    length.

    Parameters
    ----------
    prof: profile object
        Profile object
    pbot : number (optional; default 850 hPa)
        Pressure of the bottom level (hPa)
    ptop : number (optional; default 250 hPa)
        Pressure of the top level (hPa)
    dp : negative integer (optional; default -1)
        The pressure increment for the interpolated sounding
    exact : bool (optional; default = True)
        Switch to choose between using the exact data (slower) or using
        interpolated sounding at 'dp' pressure levels (faster)

    Returns
    -------
    hodo_curve : number
        Curvature ratio of the hodograph length
    '''

    tot_shr = total_shear(prof, pbot=pbot, ptop=ptop, dp=dp, exact=exact)[-1]
    bulk_shr = utils.mag(*wind_shear(prof, pbot=pbot, ptop=ptop))

    hodo_curve = tot_shr / bulk_shr

    return hodo_curve
示例#3
0
    def get_severe(self):
        '''
        Function to calculate special severe weather indices.
        Requires calling get_parcels() and get_kinematics().

        Returns nothing, but sets the following variables:

        self.stp_fixed - fixed layer significant tornado parameter
        self.stp_cin - effective layer significant tornado parameter
        self.right_scp - right moving supercell composite parameter
        self.left_scp - left moving supercell composite parameter

        Parameters
        ----------
        None
        
        Returns
        -------
        None
        '''
        wspd = utils.mag(self.sfc_6km_shear[0], self.sfc_6km_shear[1])
        self.stp_fixed = params.stp_fixed(self.sfcpcl.bplus, self.sfcpcl.lclhght, self.srh1km[0], utils.KTS2MS(wspd))
        if self.etop is np.ma.masked or self.ebottom is np.ma.masked:
            self.right_scp = 0.0; self.left_scp = 0.0
            self.stp_cin = 0.0
        else:
            self.right_scp = params.scp( self.mupcl.bplus, self.right_esrh[0], utils.KTS2MS(self.ebwspd))
            self.left_scp = params.scp( self.mupcl.bplus, self.left_esrh[0], utils.KTS2MS(self.ebwspd))
            self.stp_cin = params.stp_cin(self.mlpcl.bplus, self.right_esrh[0], utils.KTS2MS(self.ebwspd),
                self.mlpcl.lclhght, self.mlpcl.bminus)
示例#4
0
def test_mag_user_missing_single():
    missing = 50
    input_u = missing
    input_v = 10
    correct_answer = ma.masked
    returned_answer = utils.mag(input_u, input_v, missing)
    npt.assert_(type(returned_answer), type(correct_answer))
示例#5
0
def test_mag_user_missing_single():
    missing = 50
    input_u = missing
    input_v = 10
    correct_answer = ma.masked
    returned_answer = utils.mag(input_u, input_v, missing)
    npt.assert_equal(type(returned_answer), type(correct_answer))
示例#6
0
 def get_severe(self):
     '''
     Function to calculate special severe weather indices.
     Requires calling get_parcels() and get_kinematics().
     Returns nothing, but sets the following variables:
     self.stp_fixed - fixed layer significant tornado parameter
     self.stp_cin - effective layer significant tornado parameter
     self.right_scp - right moving supercell composite parameter
     self.left_scp - left moving supercell composite parameter
     Parameters
     ----------
     None
     
     Returns
     -------
     None
     '''
     wspd = utils.mag(self.sfc_6km_shear[0], self.sfc_6km_shear[1])
     self.stp_fixed = params.stp_fixed(self.sfcpcl.bplus, self.sfcpcl.lclhght, self.srh1km[0], utils.KTS2MS(wspd))
     if self.etop is np.ma.masked or self.ebottom is np.ma.masked:
         self.right_scp = 0.0; self.left_scp = 0.0
         self.stp_cin = 0.0
     else:
         self.right_scp = params.scp( self.mupcl.bplus, self.right_esrh[0], utils.KTS2MS(self.ebwspd))
         self.left_scp = params.scp( self.mupcl.bplus, self.left_esrh[0], utils.KTS2MS(self.ebwspd))
         self.stp_cin = params.stp_cin(self.mlpcl.bplus, self.right_esrh[0], utils.KTS2MS(self.ebwspd),
             self.mlpcl.lclhght, self.mlpcl.bminus)
示例#7
0
def norm_wind_shear(prof, pbot=850, ptop=250):
    '''
    Calculates the bulk shear between the wind at (pbot) and (ptop), normalized
    by dividing by the thickness of the layer.

    Parameters
    ----------
    prof: profile object
        Profile object
    pbot : number (optional; default 850 hPa)
        Pressure of the bottom level (hPa)
    ptop : number (optional; default 250 hPa)
        Pressure of the top level (hPa)

    Returns
    -------
    nws : number
        Normalized wind shear (Thousandths of units per second)
    '''
    shr = utils.KTS2MS(utils.mag(*wind_shear(prof, pbot=pbot, ptop=ptop)))
    hbot = interp.hght(prof, pbot)
    htop = interp.hght(prof, ptop)
    thickness = htop - hbot
    nws = shr / thickness
    return nws
示例#8
0
def test_mag_array():
    rt2 = np.sqrt(2)
    input_u = [5, 10, 15]
    input_v = [5, 10, 15]
    correct_answer = [5*rt2, 10*rt2, 15*rt2]
    correct_answer = ma.asanyarray(correct_answer)
    returned_answer = utils.mag(input_u, input_v)
    npt.assert_almost_equal(returned_answer, correct_answer)
示例#9
0
def test_mag_array():
    rt2 = np.sqrt(2)
    input_u = [5, 10, 15]
    input_v = [5, 10, 15]
    correct_answer = [5 * rt2, 10 * rt2, 15 * rt2]
    correct_answer = ma.asanyarray(correct_answer)
    returned_answer = utils.mag(input_u, input_v)
    npt.assert_almost_equal(returned_answer, correct_answer)
示例#10
0
    def get_sars(self):
        '''
        Function to get the SARS analogues from the hail and
        supercell databases. Requires calling get_kinematics()
        and get_parcels() first. Also calculates the significant
        hail parameter.
        
        Function returns nothing, but sets the following variables:

        self.matches - the matches from SARS HAIL
        self.ship - significant hail parameter
        self.supercell_matches - the matches from SARS SUPERCELL
        
        Parameters
        ----------
        None

        Returns
        -------
        None
        '''
        sfc_6km_shear = utils.KTS2MS( utils.mag( self.sfc_6km_shear[0], self.sfc_6km_shear[1]) )
        sfc_3km_shear = utils.KTS2MS( utils.mag( self.sfc_3km_shear[0], self.sfc_3km_shear[1]) )
        sfc_9km_shear = utils.KTS2MS( utils.mag( self.sfc_9km_shear[0], self.sfc_9km_shear[1]) )
        h500t = interp.temp(self, 500.)
        lapse_rate = params.lapse_rate( self, 700., 500., pres=True )
        srh3km = self.srh3km[0]
        srh1km = self.srh1km[0]
        mucape = self.mupcl.bplus
        mlcape = self.mlpcl.bplus
        mllcl = self.mlpcl.lclhght
        mumr = thermo.mixratio(self.mupcl.pres, self.mupcl.dwpc)
        self.ship = params.ship(self)

        self.hail_database = 'sars_hail.txt'
        self.supercell_database = 'sars_supercell.txt'
        try:
            self.matches = hail(self.hail_database, mumr, mucape, h500t, lapse_rate, sfc_6km_shear,
                sfc_9km_shear, sfc_3km_shear, srh3km)
        except:
            self.matches = ([], [], 0, 0, 0)
        try:
            self.supercell_matches = supercell(self.supercell_database, mlcape, mllcl, h500t, lapse_rate, utils.MS2KTS(sfc_6km_shear), srh1km, utils.MS2KTS(sfc_3km_shear), utils.MS2KTS(sfc_9km_shear), srh3km)
        except Exception as e:
            self.supercell_matches = ([], [], 0, 0, 0)
示例#11
0
def test_mag_default_missing_array():
    rt2 = np.sqrt(2)
    input_u = [MISSING, 10, 20, 30, 40]
    input_v = [0, 10, 20, 30, MISSING]
    correct_answer = [MISSING, 10*rt2, 20*rt2, 30*rt2, MISSING]
    correct_answer = ma.asanyarray(correct_answer).astype(np.float64)
    correct_answer[correct_answer == MISSING] = ma.masked
    returned_answer = utils.mag(input_u, input_v)
    npt.assert_almost_equal(returned_answer, correct_answer)
示例#12
0
def test_mag_default_missing_array():
    rt2 = np.sqrt(2)
    input_u = [MISSING, 10, 20, 30, 40]
    input_v = [0, 10, 20, 30, MISSING]
    correct_answer = [MISSING, 10 * rt2, 20 * rt2, 30 * rt2, MISSING]
    correct_answer = ma.asanyarray(correct_answer).astype(np.float64)
    correct_answer[correct_answer == MISSING] = ma.masked
    returned_answer = utils.mag(input_u, input_v)
    npt.assert_almost_equal(returned_answer, correct_answer)
示例#13
0
def non_parcel_bunkers_motion_experimental(prof):
    '''
        Compute the Bunkers Storm Motion for a Right Moving Supercell
        
        Parameters
        ----------
        prof : profile object
            Profile Object
        
        Returns
        -------
        rstu : number
            Right Storm Motion U-component (kts)
        rstv : number
            Right Storm Motion V-component (kts)
        lstu : number
            Left Storm Motion U-component (kts)
        lstv : number
            Left Storm Motion V-component (kts)
        
        '''
    if prof.wdir.count() == 0:
        return ma.masked, ma.masked, ma.masked, ma.masked

    d = utils.MS2KTS(7.5)  # Deviation value emperically derived as 7.5 m/s
    ## get the msl height of 500m, 5.5km, and 6.0km above the surface
    msl500m = interp.to_msl(prof, 500.)
    msl5500m = interp.to_msl(prof, 5500.)
    msl6000m = interp.to_msl(prof, 6000.)

    ## get the pressure of the surface, 500m, 5.5km, and 6.0km levels
    psfc = prof.pres[prof.sfc]
    p500m = interp.pres(prof, msl500m)
    p5500m = interp.pres(prof, msl5500m)
    p6000m = interp.pres(prof, msl6000m)

    ## sfc-500m Mean Wind
    mnu500m, mnv500m = mean_wind(prof, psfc, p500m)

    ## 5.5km-6.0km Mean Wind
    mnu5500m_6000m, mnv5500m_6000m = mean_wind(prof, p5500m, p6000m)

    # shear vector of the two mean winds
    shru = mnu5500m_6000m - mnu500m
    shrv = mnv5500m_6000m - mnv500m

    # SFC-6km Mean Wind
    mnu6, mnv6 = mean_wind(prof, psfc, p6000m)

    # Bunkers Right Motion
    tmp = d / utils.mag(shru, shrv)
    rstu = mnu6 + (tmp * shrv)
    rstv = mnv6 - (tmp * shru)
    lstu = mnu6 - (tmp * shrv)
    lstv = mnv6 + (tmp * shru)

    return rstu, rstv, lstu, lstv
示例#14
0
def test_mag_user_missing_array():
    missing = 50
    rt2 = np.sqrt(2)
    input_u = [missing, 10, 20, 30, 40]
    input_v = [0, 10, 20, 30, missing]
    correct_answer = [missing, 10 * rt2, 20 * rt2, 30 * rt2, missing]
    correct_answer = ma.asanyarray(correct_answer).astype(np.float64)
    correct_answer[correct_answer == missing] = ma.masked
    returned_answer = utils.mag(input_u, input_v, missing)
    npt.assert_almost_equal(returned_answer, correct_answer)
示例#15
0
def test_mag_user_missing_array():
    missing = 50
    rt2 = np.sqrt(2)
    input_u = [missing, 10, 20, 30, 40]
    input_v = [0, 10, 20, 30, missing]
    correct_answer = [missing, 10*rt2, 20*rt2, 30*rt2, missing]
    correct_answer = ma.asanyarray(correct_answer).astype(np.float64)
    correct_answer[correct_answer == missing] = ma.masked
    returned_answer = utils.mag(input_u, input_v, missing)
    npt.assert_almost_equal(returned_answer, correct_answer)
示例#16
0
文件: winds.py 项目: nguy/SHARPpy
def non_parcel_bunkers_motion_experimental(prof):
    '''
        Compute the Bunkers Storm Motion for a Right Moving Supercell
        
        Inputs
        ------
        prof : profile object
        Profile Object
        
        Returns
        -------
        rstu : number
        Right Storm Motion U-component
        rstv : number
        Right Storm Motion V-component
        lstu : number
        Left Storm Motion U-component
        lstv : number
        Left Storm Motion V-component
        
        '''
    d = utils.MS2KTS(7.5)     # Deviation value emperically derived as 7.5 m/s
    ## get the msl height of 500m, 5.5km, and 6.0km above the surface
    msl500m = interp.to_msl(prof, 500.)
    msl5500m = interp.to_msl(prof, 5500.)
    msl6000m = interp.to_msl(prof, 6000.)
    
    ## get the pressure of the surface, 500m, 5.5km, and 6.0km levels
    psfc = prof.pres[prof.sfc]
    p500m = interp.pres(prof, msl500m)
    p5500m = interp.pres(prof, msl5500m)
    p6000m = interp.pres(prof, msl6000m)
    
    ## sfc-500m Mean Wind
    mnu500m, mnv500m = mean_wind(prof, psfc, p500m)
    
    ## 5.5km-6.0km Mean Wind
    mnu5500m_6000m, mnv5500m_6000m = mean_wind(prof, p5500m, p6000m)
    
    # shear vector of the two mean winds
    shru = mnu5500m_6000m - mnu500m
    shrv = mnv5500m_6000m - mnv500m
    
    # SFC-6km Mean Wind
    mnu6, mnv6 = mean_wind(prof, psfc, p6000m)
    
    # Bunkers Right Motion
    tmp = d / utils.mag(shru, shrv)
    rstu = mnu6 + (tmp * shrv)
    rstv = mnv6 - (tmp * shru)
    lstu = mnu6 - (tmp * shrv)
    lstv = mnv6 + (tmp * shru)
    
    return rstu, rstv, lstu, lstv
示例#17
0
def non_parcel_bunkers_motion(prof):
    '''
    Compute the Bunkers Storm Motion for a Right Moving Supercell

    Inputs
    ------
    prof : profile object
        Profile Object

    Returns
    -------
    rstu : number
        Right Storm Motion U-component
    rstv : number
        Right Storm Motion V-component
    lstu : number
        Left Storm Motion U-component
    lstv : number
        Left Storm Motion V-component

    '''
    d = utils.MS2KTS(7.5)  # Deviation value emperically derived as 7.5 m/s
    msl6km = interp.to_msl(prof, 6000.)
    p6km = interp.pres(prof, msl6km)

    # SFC-6km Mean Wind
    mnu6, mnv6 = mean_wind_npw(prof, prof.pres[prof.sfc], p6km)
    # SFC-6km Shear Vector
    shru, shrv = wind_shear(prof, prof.pres[prof.sfc], p6km)

    # Bunkers Right Motion
    tmp = d / utils.mag(shru, shrv)

    # Cambios para el hemisferio sur JP JP
    if prof.latitude < 0:
        lstu = mnu6 + (tmp * shrv)
        lstv = mnv6 - (tmp * shru)
        rstu = mnu6 - (tmp * shrv)
        rstv = mnv6 + (tmp * shru)
    else:
        rstu = mnu6 + (tmp * shrv)
        rstv = mnv6 - (tmp * shru)
        lstu = mnu6 - (tmp * shrv)
        lstv = mnv6 + (tmp * shru)

    return rstu, rstv, lstu, lstv
示例#18
0
def non_parcel_bunkers_motion(prof):
    '''
    Compute the Bunkers Storm Motion for a Right Moving Supercell

    Parameters
    ----------
    prof : profile object
        Profile Object

    Returns
    -------
    rstu : number
        Right Storm Motion U-component (kts)
    rstv : number
        Right Storm Motion V-component (kts)
    lstu : number
        Left Storm Motion U-component (kts)
    lstv : number
        Left Storm Motion V-component (kts)

    '''
    if prof.wdir.count() == 0:
        return ma.masked, ma.masked, ma.masked, ma.masked

    d = utils.MS2KTS(7.5)  # Deviation value emperically derived as 7.5 m/s
    msl6km = interp.to_msl(prof, 6000.)
    p6km = interp.pres(prof, msl6km)
    # SFC-6km Mean Wind
    mnu6, mnv6 = mean_wind_npw(prof, prof.pres[prof.sfc], p6km)
    # SFC-6km Shear Vector
    shru, shrv = wind_shear(prof, prof.pres[prof.sfc], p6km)

    # Bunkers Right Motion
    tmp = d / utils.mag(shru, shrv)
    rstu = mnu6 + (tmp * shrv)
    rstv = mnv6 - (tmp * shru)
    lstu = mnu6 - (tmp * shrv)
    lstv = mnv6 + (tmp * shru)

    return rstu, rstv, lstu, lstv
示例#19
0
文件: winds.py 项目: neo9091/SHARPpy
def non_parcel_bunkers_motion(prof):
    '''
    Compute the Bunkers Storm Motion for a Right Moving Supercell

    Inputs
    ------
    prof : profile object
        Profile Object

    Returns
    -------
    rstu : number
        Right Storm Motion U-component
    rstv : number
        Right Storm Motion V-component
    lstu : number
        Left Storm Motion U-component
    lstv : number
        Left Storm Motion V-component

    '''
    d = utils.MS2KTS(7.5)     # Deviation value emperically derived as 7.5 m/s
    msl6km = interp.to_msl(prof, 6000.)
    p6km = interp.pres(prof, msl6km)
            
    # SFC-6km Mean Wind
    mnu6, mnv6 = mean_wind_npw(prof, prof.pres[prof.sfc], p6km)
    # SFC-6km Shear Vector
    shru, shrv = wind_shear(prof, prof.pres[prof.sfc], p6km)

    # Bunkers Right Motion
    tmp = d / utils.mag(shru, shrv)
    rstu = mnu6 + (tmp * shrv)
    rstv = mnv6 - (tmp * shru)
    lstu = mnu6 - (tmp * shrv)
    lstv = mnv6 + (tmp * shru)

    return rstu, rstv, lstu, lstv
示例#20
0
def test_mag_single():
    input_u = 5
    input_v = 5
    correct_answer = np.sqrt(input_u**2 + input_v**2)
    returned_answer = utils.mag(input_u, input_v)
    npt.assert_almost_equal(returned_answer, correct_answer)
示例#21
0
def test_mag_zero():
    input_u = 0
    input_v = 0
    correct_answer = 0
    returned_answer = utils.mag(input_u, input_v)
    npt.assert_almost_equal(returned_answer, correct_answer)
示例#22
0
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])
ebwspd = utils.mag(ebwd[0], ebwd[1])
scp = params.scp(mupcl.bplus, effective_srh[0], ebwspd)
stp_cin = params.stp_cin(mlpcl.bplus, effective_srh[0], ebwspd, mlpcl.lclhght,
                         mlpcl.bminus)

indices = {'SBCAPE': [int(sfcpcl.bplus), 'J/kg'],\
           'SBCIN': [int(sfcpcl.bminus), 'J/kg'],\
           'SBLCL': [int(sfcpcl.lclhght), 'm AGL'],\
           'SBLFC': [int(sfcpcl.lfchght), 'm AGL'],\
           'SBEL': [int(sfcpcl.elhght), 'm AGL'],\
           'SBLI': [int(sfcpcl.li5), 'C'],\
           'MLCAPE': [int(mlpcl.bplus), 'J/kg'],\
           'MLCIN': [int(mlpcl.bminus), 'J/kg'],\
           'MLLCL': [int(mlpcl.lclhght), 'm AGL'],\
           'MLLFC': [int(mlpcl.lfchght), 'm AGL'],\
           'MLEL': [int(mlpcl.elhght), 'm AGL'],\
示例#23
0
def test_mag_default_missing_single():
    input_u = MISSING
    input_v = 10
    correct_answer = ma.masked
    returned_answer = utils.mag(input_u, input_v)
    npt.assert_(type(returned_answer), type(correct_answer))
示例#24
0
 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])
示例#25
0
def possible_watch(prof):
    '''
        Possible Weather/Hazard/Watch Type
        
        This function generates a list of possible significant weather types
        one can expect given a Profile object. (Currently works only for ConvectiveProfile.)

        These possible weather types are computed via fuzzy logic through set thresholds that
        have been found through a.) analyzing ingredients within the profile and b.) combining those ingredients
        with forecasting experience to produce a suggestion of what hazards may exist.  Some of the logic is 
        based on experience, some of it is based on actual National Weather Service criteria.

        This function has not been formally verified and is not meant to be comprehensive nor
        a source of strict guidance for weather forecasters.  As always, the raw data is to be 
        consulted.

        This code base is currently under development.

        Wx Categories (ranked in terms of severity):
        - PDS TOR
        - TOR
        - MRGL TOR
        - SVR
        - MRGL SVR
        - FLASH FLOOD
        - BLIZZARD
        - WINTER STORM
        - WIND CHILL
        - FIRE WEATHER
        - EXCESSIVE HEAT
        - FREEZE
    
        Suggestions for severe/tornado thresholds were contributed by Rich Thompson - NOAA Storm Prediction Center

        Parameters
        ----------
        prof : ConvectiveProfile object

        Returns
        -------
        watch_types :  a list of strings containing the weather types in code
        colors : a list of the HEX colors corresponding to each weather type
    '''
        
    watch_types = []
    colors = []
    
    lr1 = params.lapse_rate( prof, 0, 1000, pres=False )
    stp_eff = prof.stp_cin
    stp_fixed = prof.stp_fixed
    srw_4_6km = utils.mag(prof.srw_4_6km[0],prof.srw_4_6km[1])
    sfc_8km_shear = utils.mag(prof.sfc_8km_shear[0],prof.sfc_8km_shear[1])
    right_esrh = prof.right_esrh[0]
    srh1km = prof.srh1km[0]
    if stp_eff >= 3 and stp_fixed >= 3 and srh1km >= 200 and right_esrh >= 200 and srw_4_6km >= 15.0 and \
        sfc_8km_shear > 45.0 and prof.sfcpcl.lclhght < 1000. and prof.mlpcl.lclhght < 1200 and lr1 >= 5.0 and \
        prof.mlpcl.bminus > -50 and prof.ebotm == 0:
        watch_types.append("PDS TOR")
        colors.append(constants.MAGENTA)
    elif (stp_eff >= 3 or stp_fixed >= 4) and prof.mlpcl.bminus > -125. and prof.ebotm == 0:
        watch_types.append("TOR")
        colors.append("#FF0000")
    elif (stp_eff >= 1 or stp_fixed >= 1) and (srw_4_6km >= 15.0 or sfc_8km_shear >= 40) and \
        prof.mlpcl.bminus > -50 and prof.ebotm == 0:
        watch_types.append("TOR")
        colors.append("#FF0000")
    elif (stp_eff >= 1 or stp_fixed >= 1) and ((prof.low_rh + prof.mid_rh)/2. >= 60) and lr1 >= 5.0 and \
        prof.mlpcl.bminus > -50 and prof.ebotm == 0:
        watch_types.append("TOR")
        colors.append("#FF0000")
    elif (stp_eff >= 1 or stp_fixed >= 1) and prof.mlpcl.bminus > -150 and prof.ebotm == 0.:
        watch_types.append("MRGL TOR")
        colors.append("#FF0000")
    elif (stp_eff >= 0.5 and prof.right_esrh >= 150) or (stp_fixed >= 0.5 and srh1km >= 150) and \
        prof.mlpcl.bminus > -50 and prof.ebotm == 0.:
        watch_types.append("MRGL TOR")
        colors.append("#FF0000")

    #SVR LOGIC
    if (stp_fixed >= 1.0 or prof.right_scp >= 4.0 or stp_eff >= 1.0) and prof.mupcl.bminus >= -50:
        colors.append("#FFFF00")
        watch_types.append("SVR")
    elif prof.right_scp >= 2.0 and (prof.ship >= 1.0 or prof.dcape >= 750) and prof.mupcl.bminus >= -50:
        colors.append("#FFFF00")
        watch_types.append("SVR")
    elif prof.sig_severe >= 30000 and prof.mmp >= 0.6 and prof.mupcl.bminus >= -50:
        colors.append("#FFFF00")
        watch_types.append("SVR")
    elif prof.mupcl.bminus >= -75.0 and (prof.wndg >= 0.5 or prof.ship >= 0.5 or prof.right_scp >= 0.5):
        colors.append("#0099CC")
        watch_types.append("MRGL SVR")
    
    # Flash Flood Watch PWV is larger than normal and cloud layer mean wind speeds are slow
    # This is trying to capture the ingredients of moisture and advection speed, but cannot
    # handle precipitation efficiency or vertical motion
    pw_climo_flag = prof.pwv_flag
    pwat = prof.pwat
    upshear = utils.comp2vec(prof.upshear_downshear[0],prof.upshear_downshear[1])
    if pw_climo_flag >= 2 and upshear[1] < 25:
        watch_types.append("FLASH FLOOD")
        colors.append("#5FFB17")
    #elif pwat > 1.3 and upshear[1] < 25:
    #    watch_types.append("FLASH FLOOD")
    #    colors.append("#5FFB17")
    
    # Blizzard if sfc winds > 35 mph and precip type detects snow 
    # Still needs to be tied into the 
    sfc_wspd = utils.KTS2MPH(prof.wspd[prof.get_sfc()])
    if sfc_wspd > 35. and prof.tmpc[prof.get_sfc()] <= 0:
        watch_types.append("BLIZZARD")
        colors.append("#3366FF")
    
    # Wind Chill (if wind chill gets below -20 F)
    if wind_chill(prof) < -20.:
        watch_types.append("WIND CHILL")
        colors.append("#3366FF")
    
    # Fire WX (sfc RH < 30% and sfc_wind speed > 15 mph) (needs to be updated to include SPC Fire Wx Indices)
    if sfc_wspd > 15. and thermo.relh(prof.pres[prof.get_sfc()], prof.tmpc[prof.get_sfc()], prof.dwpc[prof.get_sfc()]) < 30. :
        watch_types.append("FIRE WEATHER")
        colors.append("#FF9900")
    
    # Excessive Heat (if Max_temp > 105 F and sfc dewpoint > 75 F)
    if thermo.ctof(prof.dwpc[prof.get_sfc()]) > 75. and thermo.ctof(params.max_temp(prof)) >= 105.:
        watch_types.append("EXCESSIVE HEAT")
        colors.append("#CC33CC")
    
    # Freeze (checks to see if wetbulb is below freezing and temperature isn't and wind speeds are low)
    # Still in testing.
    if thermo.ctof(prof.dwpc[prof.get_sfc()]) <= 32. and thermo.ctof(prof.wetbulb[prof.get_sfc()]) <= 32 and prof.wspd[prof.get_sfc()] < 5.:
        watch_types.append("FREEZE")
        colors.append("#3366FF")
    
    watch_types.append("NONE")
    colors.append("#FFCC33")
    
    return np.asarray(watch_types), np.asarray(colors)
示例#26
0
''' Create the Sounding (Profile) Object '''
示例#27
0
def possible_watch(prof):
    '''
        Possible Weather/Hazard/Watch Type
        
        This function generates a list of possible significant weather types
        one can expect given a Profile object. (Currently works only for ConvectiveProfile.)

        These possible weather types are computed via fuzzy logic through set thresholds that
        have been found through a.) analyzing ingredients within the profile and b.) combining those ingredients
        with forecasting experience to produce a suggestion of what hazards may exist.  Some of the logic is 
        based on experience, some of it is based on actual National Weather Service criteria.

        This function has not been formally verified and is not meant to be comprehensive nor
        a source of strict guidance for weather forecasters.  As always, the raw data is to be 
        consulted.

        This code base is currently under development.

        Wx Categories (ranked in terms of severity):
        - PDS TOR
        - TOR
        - MRGL TOR
        - SVR
        - MRGL SVR
        - FLASH FLOOD
        - BLIZZARD
        - WINTER STORM
        - WIND CHILL
        - FIRE WEATHER
        - EXCESSIVE HEAT
        - FREEZE
    
        Suggestions for severe/tornado thresholds were contributed by Rich Thompson - NOAA Storm Prediction Center

        Parameters
        ----------
        prof : ConvectiveProfile object

        Returns
        -------
        watch_types :  a list of strings containing the weather types in code
        colors : a list of the HEX colors corresponding to each weather type
    '''

    watch_types = []
    colors = []

    lr1 = params.lapse_rate(prof, 0, 1000, pres=False)
    stp_eff = prof.stp_cin
    stp_fixed = prof.stp_fixed
    srw_4_6km = utils.mag(prof.srw_4_6km[0], prof.srw_4_6km[1])
    sfc_8km_shear = utils.mag(prof.sfc_8km_shear[0], prof.sfc_8km_shear[1])
    right_esrh = prof.right_esrh[0]
    srh1km = prof.srh1km[0]
    right_scp = prof.right_scp
    ## Cambios para el hemisferio sur JP JP
    if prof.latitude < 0:
        srh1km = -srh1km
        stp_eff = -stp_eff
        stp_fixed = -stp_fixed
        right_scp = -prof.left_scp
        right_esrh = -prof.left_esrh[0]
    if stp_eff >= 3 and stp_fixed >= 3 and srh1km >= 200 and right_esrh >= 200 and srw_4_6km >= 15.0 and \
        sfc_8km_shear > 45.0 and prof.sfcpcl.lclhght < 1000. and prof.mlpcl.lclhght < 1200 and lr1 >= 5.0 and \
        prof.mlpcl.bminus >= -50 and prof.ebotm == 0:
        watch_types.append("SPP TOR")
        colors.append(constants.MAGENTA)
    elif (stp_eff >= 3 or
          stp_fixed >= 4) and prof.mlpcl.bminus >= -125. and prof.ebotm == 0:
        watch_types.append("TOR")
        colors.append("#FF0000")
    elif (stp_eff >= 1 or stp_fixed >= 1) and (srw_4_6km >= 15.0 or sfc_8km_shear >= 40) and \
        prof.mlpcl.bminus >= -50 and prof.ebotm == 0:
        watch_types.append("TOR")
        colors.append("#FF0000")
    elif (stp_eff >= 1 or stp_fixed >= 1) and ((prof.low_rh + prof.mid_rh)/2. >= 60) and lr1 >= 5.0 and \
        prof.mlpcl.bminus >= -50 and prof.ebotm == 0:
        watch_types.append("TOR")
        colors.append("#FF0000")
    elif (stp_eff >= 1 or
          stp_fixed >= 1) and prof.mlpcl.bminus >= -150 and prof.ebotm == 0.:
        watch_types.append("MRGL TOR")
        colors.append("#FF0000")
    elif (stp_eff >= 0.5 and prof.right_esrh >= 150) or (stp_fixed >= 0.5 and srh1km >= 150) and \
        prof.mlpcl.bminus >= -50 and prof.ebotm == 0.:
        watch_types.append("MRGL TOR")
        colors.append("#FF0000")
    #t1 = tab.utils.FLOAT2STR(stp_eff, 1)
    #t2 = tab.utils.FLOAT2STR(stp_fixed, 1)
    #t3 = tab.utils.FLOAT2STR(srw_4_6km, 1)
    #t4 = tab.utils.INT2STR(sfc_8km_shear)
    #t5 = tab.utils.INT2STR(prof.mlpcl.bminus)
    #t6 = tab.utils.INT2STR(prof.ebotm)
    #with open('C:\\temp.txt', 'a') as f:
    #    f.write(t1 + ',' + t2 + ',' + t3 + ',' + t4 + ',' + t5 + ',' + t6 + '\n')

    #SVR LOGIC
    if (stp_fixed >= 1.0 or right_scp >= 4.0
            or stp_eff >= 1.0) and prof.mupcl.bminus >= -50:
        colors.append("#FFFF00")
        watch_types.append("SVR")
    elif right_scp >= 2.0 and (prof.ship >= 1.0 or
                               prof.dcape >= 750) and prof.mupcl.bminus >= -50:
        colors.append("#FFFF00")
        watch_types.append("SVR")
    elif prof.sig_severe >= 30000 and prof.mmp >= 0.6 and prof.mupcl.bminus >= -50:
        colors.append("#FFFF00")
        watch_types.append("SVR")
    elif prof.mupcl.bminus >= -75.0 and (prof.wndg >= 0.5 or prof.ship >= 0.5
                                         or right_scp >= 0.5):
        colors.append("#0099CC")
        watch_types.append("MRGL SVR")

    # Flash Flood Watch PWV is larger than normal and cloud layer mean wind speeds are slow
    # This is trying to capture the ingredients of moisture and advection speed, but cannot
    # handle precipitation efficiency or vertical motion
    pw_climo_flag = prof.pwv_flag
    pwat = prof.pwat
    upshear = utils.comp2vec(prof.upshear_downshear[0],
                             prof.upshear_downshear[1])
    if pw_climo_flag >= 2 and upshear[1] < 25:
        watch_types.append("INUND REPENT")
        colors.append("#5FFB17")
    #elif pwat > 1.3 and upshear[1] < 25:
    #    watch_types.append("FLASH FLOOD")
    #    colors.append("#5FFB17")

    # Blizzard if sfc winds > 35 mph and precip type detects snow
    # Still needs to be tied into the
    sfc_wspd = utils.KTS2MPH(prof.wspd[prof.get_sfc()])
    if sfc_wspd > 35. and prof.tmpc[
            prof.get_sfc()] <= 0 and "Snow" in prof.precip_type:
        watch_types.append("TORM NIEVE")
        colors.append("#3366FF")

    # Wind Chill (if wind chill gets below -20 F)
    if wind_chill(prof) < -20.:
        watch_types.append("ST VIENTO")
        colors.append("#3366FF")

    # Fire WX (sfc RH < 30% and sfc_wind speed > 15 mph) (needs to be updated to include SPC Fire Wx Indices)
    if sfc_wspd > 15. and thermo.relh(prof.pres[prof.get_sfc()],
                                      prof.tmpc[prof.get_sfc()],
                                      prof.tmpc[prof.get_sfc()]) < 30.:
        watch_types.append("INCENDIOS")
        colors.append("#FF9900")

    # Excessive Heat (if Max_temp > 105 F and sfc dewpoint > 75 F)
    if thermo.ctof(prof.dwpc[prof.get_sfc()]) > 75. and thermo.ctof(
            params.max_temp(prof)) >= 105.:
        watch_types.append("CALOR INTENSO")
        colors.append("#CC33CC")

    # Freeze (checks to see if wetbulb is below freezing and temperature isn't and wind speeds are low)
    # Still in testing.
    if thermo.ctof(prof.dwpc[prof.get_sfc()]) <= 32. and thermo.ctof(
            prof.wetbulb[prof.get_sfc()]) <= 32 and prof.wspd[
                prof.get_sfc()] < 5.:
        watch_types.append("HELADAS")
        colors.append("#3366FF")

    watch_types.append("NINGUNA")
    colors.append("#FFCC33")

    return np.asarray(watch_types), np.asarray(colors)
示例#28
0
def test_mag_single():
    input_u = 5
    input_v = 5
    correct_answer = np.sqrt(input_u**2 + input_v**2)
    returned_answer = utils.mag(input_u, input_v)
    npt.assert_almost_equal(returned_answer, correct_answer)
示例#29
0
def test_mag_default_missing_single():
    input_u = MISSING
    input_v = 10
    correct_answer = ma.masked
    returned_answer = utils.mag(input_u, input_v)
    npt.assert_equal(type(returned_answer), type(correct_answer))
示例#30
0
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
示例#31
0
def test_mag_zero():
    input_u = 0
    input_v = 0
    correct_answer = 0
    returned_answer = utils.mag(input_u, input_v)
    npt.assert_almost_equal(returned_answer, correct_answer)
示例#32
0
    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])
示例#33
0
def possible_watch(prof, use_left=False):
    '''
        Possible Weather/Hazard/Watch Type
        
        This function generates a list of possible significant weather types
        one can expect given a Profile object. (Currently works only for ConvectiveProfile.)

        These possible weather types are computed via fuzzy logic through set thresholds that
        have been found through a.) analyzing ingredients within the profile and b.) combining those ingredients
        with forecasting experience to produce a suggestion of what hazards may exist.  Some of the logic is 
        based on experience, some of it is based on actual National Weather Service criteria.

        This function has not been formally verified and is not meant to be comprehensive nor
        a source of strict guidance for weather forecasters.  As always, the raw data is to be 
        consulted.

        Wx Categories (ranked in terms of severity):
        * PDS TOR
        * TOR
        * MRGL TOR
        * SVR
        * MRGL SVR
        * FLASH FLOOD
        * BLIZZARD
        * EXCESSIVE HEAT
    
        Suggestions for severe/tornado thresholds were contributed by Rich Thompson - NOAA Storm Prediction Center

        Parameters
        ----------
        prof : profile object
            ConvectiveProfile object
        use_left : bool
            If True, uses the parameters computed from the left-mover bunkers vector to decide the watch type. If False,
            uses parameters from the right-mover vector. The default is False.

        Returns
        -------
        watch_types : numpy array
            strings containing the weather types in code
    '''

    watch_types = []

    lr1 = params.lapse_rate(prof, 0, 1000, pres=False)
    if use_left:
        stp_eff = prof.left_stp_cin
        stp_fixed = prof.left_stp_fixed
        srw_4_6km = utils.mag(prof.left_srw_4_6km[0], prof.left_srw_4_6km[1])
        esrh = prof.left_esrh[0]
        srh1km = prof.left_srh1km[0]
    else:
        stp_eff = prof.right_stp_cin
        stp_fixed = prof.right_stp_fixed
        srw_4_6km = utils.mag(prof.right_srw_4_6km[0], prof.right_srw_4_6km[1])
        esrh = prof.right_esrh[0]
        srh1km = prof.right_srh1km[0]

    if prof.latitude < 0:
        stp_eff = -stp_eff
        stp_fixed = -stp_fixed
        esrh = -esrh
        srh1km = -srh1km

    sfc_8km_shear = utils.mag(prof.sfc_8km_shear[0], prof.sfc_8km_shear[1])

    if stp_eff >= 3 and stp_fixed >= 3 and srh1km >= 200 and esrh >= 200 and srw_4_6km >= 15.0 and \
        sfc_8km_shear > 45.0 and prof.sfcpcl.lclhght < 1000. and prof.mlpcl.lclhght < 1200 and lr1 >= 5.0 and \
        prof.mlpcl.bminus > -50 and prof.ebotm == 0:
        watch_types.append("PDS TOR")
    elif (stp_eff >= 3
          or stp_fixed >= 4) and prof.mlpcl.bminus > -125. and prof.ebotm == 0:
        watch_types.append("TOR")
    elif (stp_eff >= 1 or stp_fixed >= 1) and (srw_4_6km >= 15.0 or sfc_8km_shear >= 40) and \
        prof.mlpcl.bminus > -50 and prof.ebotm == 0:
        watch_types.append("TOR")
    elif (stp_eff >= 1 or stp_fixed >= 1) and ((prof.low_rh + prof.mid_rh)/2. >= 60) and lr1 >= 5.0 and \
        prof.mlpcl.bminus > -50 and prof.ebotm == 0:
        watch_types.append("TOR")
    elif (stp_eff >= 1
          or stp_fixed >= 1) and prof.mlpcl.bminus > -150 and prof.ebotm == 0.:
        watch_types.append("MRGL TOR")
    elif (stp_eff >= 0.5 and esrh >= 150) or (stp_fixed >= 0.5 and srh1km >= 150) and \
        prof.mlpcl.bminus > -50 and prof.ebotm == 0.:
        watch_types.append("MRGL TOR")

    #SVR LOGIC
    if use_left:
        scp = prof.left_scp
    else:
        scp = prof.right_scp

    if (stp_fixed >= 1.0 or scp >= 4.0
            or stp_eff >= 1.0) and prof.mupcl.bminus >= -50:
        watch_types.append("SVR")
    elif scp >= 2.0 and (prof.ship >= 1.0
                         or prof.dcape >= 750) and prof.mupcl.bminus >= -50:
        watch_types.append("SVR")
    elif prof.sig_severe >= 30000 and prof.mmp >= 0.6 and prof.mupcl.bminus >= -50:
        watch_types.append("SVR")
    elif prof.mupcl.bminus >= -75.0 and (prof.wndg >= 0.5 or prof.ship >= 0.5
                                         or scp >= 0.5):
        watch_types.append("MRGL SVR")

    # Flash Flood Watch PWV is larger than normal and cloud layer mean wind speeds are slow
    # This is trying to capture the ingredients of moisture and advection speed, but cannot
    # handle precipitation efficiency or vertical motion

    # Likely is good for handling slow moving MCSes.
    pw_climo_flag = prof.pwv_flag
    pwat = prof.pwat
    upshear = utils.comp2vec(prof.upshear_downshear[0],
                             prof.upshear_downshear[1])
    if pw_climo_flag >= 2 and upshear[1] < 25:
        watch_types.append("FLASH FLOOD")
    #elif pwat > 1.3 and upshear[1] < 25:
    #    watch_types.append("FLASH FLOOD")

    # Blizzard if sfc winds > 35 mph and precip type detects snow
    # Still needs to be tied into the
    sfc_wspd = utils.KTS2MPH(prof.wspd[prof.get_sfc()])
    if sfc_wspd > 35. and prof.tmpc[
            prof.get_sfc()] <= 0 and "Snow" in prof.precip_type:
        watch_types.append("BLIZZARD")

    # Wind Chill (if wind chill gets below -20 F)
    # TODO: Be reinstated in future releases if the logic becomes a little more solid.
    #if wind_chill(prof) < -20.:
    #    watch_types.append("WIND CHILL")

    # Fire WX (sfc RH < 30% and sfc_wind speed > 15 mph) (needs to be updated to include SPC Fire Wx Indices)
    # TODO: Be reinstated in future releases once the logic becomes a little more solid
    #if sfc_wspd > 15. and thermo.relh(prof.pres[prof.get_sfc()], prof.tmpc[prof.get_sfc()], prof.dwpc[prof.get_sfc()]) < 30. :
    #watch_types.append("FIRE WEATHER")

    # Excessive Heat (use the heat index calculation (and the max temperature algorithm))
    temp = thermo.ctof(prof.tmpc[prof.get_sfc()])
    rh = thermo.relh(prof.pres[prof.get_sfc()], temp,
                     prof.dwpc[prof.get_sfc()])
    hi = heat_index(temp, rh)
    if hi > 105.:
        watch_types.append("EXCESSIVE HEAT")

    # Freeze (checks to see if wetbulb is below freezing and temperature isn't and wind speeds are low)
    # Still in testing.  To be reinstated in future releases.
    #if thermo.ctof(prof.dwpc[prof.get_sfc()]) <= 32. and thermo.ctof(prof.wetbulb[prof.get_sfc()]) <= 32 and prof.wspd[prof.get_sfc()] < 5.:
    #    watch_types.append("FREEZE")

    watch_types.append("NONE")

    return np.asarray(watch_types)