Example #1
0
def verticalize(T, hyam, hybm, ps, level_src=plvlO):
    """
    For data T with CAM's hybrid level coordinates, interpolates to
    the more standard pressure level coordinates and returns the results.
    The input arguments hyam, hybm, ps are the usual CAM veriables by that
    name.  Order of dimensions must be (lev,lat,lon).
    The optional argument level_src is an array or list of the new level_src to which
    T should be interpolated.  Or it can be a cdms2 variable, in which case the
    levels will be obtained from its 'lev' or 'plev' axis, if any.
    """
    #pdb.set_trace()
    from metrics.computation.reductions import levAxis
    # constants as in functions_vertical.ncl, lines 5-10:
    p0 = 1000.  # mb
    interp = 2  # log interpolation
    extrap = False  # no extrapolation past psfc
    if levAxis(T) is None:
        return None
    if level_src is None:
        level_src = plvlO
    elif isinstance(level_src, cdms2.avariable.AbstractVariable):
        lev_axis = levAxis(level_src)
        if lev_axis == None:
            logger.warning("No level axis in %s", level_src.id)
            return None
        level_src = lev_axis[:]
    # Convert p0 to match ps.  Later, we'll convert back to mb.  This is faster than
    # converting ps to millibars.
    if ps.units == 'mb':
        ps.units = 'mbar'  # udunits uses mb for something else
    tmp = udunits(1.0, 'mbar')
    s, i = tmp.how(ps.units)
    p0 = s * p0 + i
    #psmb = cdms2.createVariable( pressures_in_mb( ps ), copy=True, units='mbar', id=ps.id )
    levels_orig = cdutil.vertical.reconstructPressureFromHybrid(
        ps, hyam, hybm, p0)
    # At this point levels_orig has the same units as ps.  Convert to to mbar
    tmp = udunits(1.0, ps.units)
    s, i = tmp.how('mbar')
    levels_orig = s * levels_orig + i
    levels_orig.units = 'mbar'
    newT = cdutil.vertical.logLinearInterpolation(T, levels_orig, level_src)
    # Ngl doesn't work yet onoceanonly:
    #newT = Ngl.vinth2p( T, hyam, hybm, plvlO, ps, interp, p0, 1 ,extrap )

    set_mean(newT)  # otherwise, mean may not be computed
    return newT
def convert_energyflux_precip(mv, preferred_units):

    # The latent heat of vaporization for water is 2260 kJ/kg
    lhvap = 2260.  # 'kJ/kg'
    secondsperday = 86400.
    kJperday = 86.4  # 'kJ/day'

    if hasattr(mv, 'id'):
        mvid = mv.id

    # syntax correction (just in case)
    mv.units = mv.units.replace(' m-2', '/m^2')
    mv.units = mv.units.replace(' s-1', '/s')
    if mv.units == 'W/m2':
        mv.units = 'W/m^2'
    if mv.units == 'mm/d':
        mv.units = 'mm/day'

    if mv.units == preferred_units:
        return mv

    # convert precip between kg/m2/s and mm/day
    if ( mv.units=="kg/m2/s" or mv.units=="kg/m^2/s" or mv.units=="kg/s/m2" or\
             mv.units=="kg/s/m^2") and preferred_units=="mm/day":
        mv = mv * secondsperday  # convert to kg/m2/s [= mm/s]
        mv.units = "mm/day"  # [if 1 kg = 10^6 mm^3 as for water]

    elif mv.units == 'mm/day' and preferred_units == "kg/m2/s":
        mv = mv / secondsperday  # convert to mm/sec [= kg/m2/s]
        mv.units = "kg/m2/s"  # [if 1 kg = 10^6 mm^3 as for water]

    # convert between energy flux (W/m2) and water flux (mm/day)
    elif mv.units == "kg/m2/s" and preferred_units == "W/m^2":
        mv = mv * kJperday * secondsperday * lhvap
        mv.units = 'W/m^2'

    elif mv.units == 'mm/day' and preferred_units == 'W/m^2':
        # 1 W = 86.4 kJ / day
        mv = mv * lhvap / kJperday
        mv.units = 'W/m^2'

    elif mv.units == 'W/m^2' and preferred_units == 'mm/day':
        mv = mv * kJperday / lhvap
        mv.units = 'mm/day'

    else:
        tmp = udunits(1.0, mv.units)
        try:
            s, i = tmp.how(preferred_units)
        except Exception as e:
            # conversion not possible.
            print "ERROR could not convert from", mv.units, "to", preferred_units
            raise e
        if not (numpy.allclose(s, 1.0) and numpy.allclose(i, 0.0)):
            mv = s * mv + i
        mv.units = preferred_units
    mv.id = mvid  # reset variable id

    return mv
def convert_energyflux_precip(mv, preferred_units):

    # The latent heat of vaporization for water is 2260 kJ/kg
    lhvap = 2260. # 'kJ/kg'
    secondsperday = 86400.
    kJperday = 86.4 # 'kJ/day'

    if hasattr(mv,'id'):
        mvid = mv.id

    # syntax correction (just in case)
    mv.units = mv.units.replace(' m-2','/m^2')
    mv.units = mv.units.replace(' s-1','/s')
    if  mv.units=='W/m2':
        mv.units='W/m^2'
    if mv.units=='mm/d':
        mv.units = 'mm/day'

    if mv.units==preferred_units:
        return mv

    # convert precip between kg/m2/s and mm/day
    if ( mv.units=="kg/m2/s" or mv.units=="kg/m^2/s" or mv.units=="kg/s/m2" or\
             mv.units=="kg/s/m^2") and preferred_units=="mm/day":
        mv = mv * secondsperday # convert to kg/m2/s [= mm/s]
        mv.units="mm/day"         # [if 1 kg = 10^6 mm^3 as for water]

    elif mv.units=='mm/day' and preferred_units=="kg/m2/s":
        mv = mv / secondsperday # convert to mm/sec [= kg/m2/s]
        mv.units="kg/m2/s"      # [if 1 kg = 10^6 mm^3 as for water]

    # convert between energy flux (W/m2) and water flux (mm/day)
    elif mv.units=="kg/m2/s" and preferred_units=="W/m^2":
        mv = mv * kJperday * secondsperday * lhvap
        mv.units = 'W/m^2'

    elif mv.units=='mm/day' and preferred_units=='W/m^2':
        # 1 W = 86.4 kJ / day
        mv = mv * lhvap / kJperday
        mv.units = 'W/m^2'

    elif mv.units=='W/m^2' and preferred_units=='mm/day':
        mv = mv * kJperday / lhvap
        mv.units = 'mm/day'

    else:
        tmp = udunits(1.0,mv.units)
        try:
            s,i = tmp.how(preferred_units)
        except Exception as e:
            # conversion not possible.
            print "ERROR could not convert from",mv.units,"to",preferred_units
            raise e
        if not ( numpy.allclose(s,1.0) and numpy.allclose(i,0.0) ):
            mv = s*mv + i
        mv.units = preferred_units
    mv.id = mvid # reset variable id

    return mv
Example #4
0
def verticalize( T, hyam, hybm, ps, level_src=plvlO ):
    """
    For data T with CAM's hybrid level coordinates, interpolates to
    the more standard pressure level coordinates and returns the results.
    The input arguments hyam, hybm, ps are the usual CAM veriables by that
    name.  Order of dimensions must be (lev,lat,lon).
    The optional argument level_src is an array or list of the new level_src to which
    T should be interpolated.  Or it can be a cdms2 variable, in which case the
    levels will be obtained from its 'lev' or 'plev' axis, if any.
    """
    #pdb.set_trace()
    from metrics.computation.reductions import levAxis
    # constants as in functions_vertical.ncl, lines 5-10:
    p0 = 1000.   # mb
    interp = 2   # log interpolation
    extrap = False     # no extrapolation past psfc
    if levAxis(T) is None:
        return None
    if level_src is None:
        level_src = plvlO
    elif isinstance(level_src,cdms2.avariable.AbstractVariable):
        lev_axis = levAxis(level_src)
        if lev_axis==None:
            logger.warning("No level axis in %s",level_src.id)
            return None
        level_src = lev_axis[:]
    # Convert p0 to match ps.  Later, we'll convert back to mb.  This is faster than
    # converting ps to millibars.
    if ps.units=='mb':
        ps.units = 'mbar' # udunits uses mb for something else
    tmp = udunits(1.0,'mbar')
    s,i = tmp.how(ps.units)
    p0 = s*p0 + i
    #psmb = cdms2.createVariable( pressures_in_mb( ps ), copy=True, units='mbar', id=ps.id )
    levels_orig = cdutil.vertical.reconstructPressureFromHybrid( ps, hyam, hybm, p0 )
    # At this point levels_orig has the same units as ps.  Convert to to mbar
    tmp = udunits(1.0,ps.units)
    s,i = tmp.how('mbar')
    levels_orig = s*levels_orig + i
    levels_orig.units = 'mbar'
    newT = cdutil.vertical.logLinearInterpolation( T, levels_orig, level_src )
    # Ngl doesn't work yet onoceanonly:
    #newT = Ngl.vinth2p( T, hyam, hybm, plvlO, ps, interp, p0, 1 ,extrap )

    set_mean(newT)  # otherwise, mean may not be computed
    return newT
Example #5
0
 def mean_lev( self, filetable, ffilt, domrange, gw ):
     """compute and return the mean of a reduced variable at a prescribed level.
     The returned mean is an mv (cdms2 TransientVariable) whose data is a scalar."""
     ulev = udunits(self.lev,'mbar')
     # We have to compute on a level surface.
     if self.var not in filetable.list_variables_with_levelaxis():
         return -999.000
     # The specified level is in millibars.  Do we have hybrid level coordinates?
     ft_hyam = filetable.find_files('hyam')
     hybrid = ft_hyam is not None and ft_hyam!=[]    # true iff filetable uses hybrid level coordinates
     if hybrid: # hybrid level coordinates
         reduced_variables = reduced_variables_hybrid_lev( filetable, self.var, self.seasonid,
                                                           filefilter=ffilt )
         vid1= dv.dict_id(self.var,'p',self.seasonid,filetable)
         vidl1=dv.dict_id(self.var,'lp',self.seasonid,filetable)
         vidm1=dv.dict_id(self.var,'mp',self.seasonid,filetable)
         derived_variables = { vid1: derived_var(
                 vid=vid1, inputs=[reduced_variable.dict_id(self.var,self.seasonid,filetable),
                                   reduced_variable.dict_id('hyam',self.seasonid,filetable),
                                   reduced_variable.dict_id('hybm',self.seasonid,filetable),
                                   reduced_variable.dict_id('PS',self.seasonid,filetable),
                                   reduced_variable.dict_id(self.var,self.seasonid,filetable) ],
                 func=verticalize ),
                               vidl1: derived_var(
                 vid=vidl1, inputs=[vid1], func=(lambda z: select_lev(z,ulev)) ),
                               vidm1: derived_var(
                 vid=vidm1, inputs=[vidl1], func=\
                     (lambda x,vid=None,season=self.season,dom0=domrange[0],dom1=domrange[1],gw=gw:
                          reduce2scalar_seasonal_zonal(
                         x,season,latmin=dom0,latmax=dom1,vid=vid,gw=gw) ) )
                               }
         variable_values = {}  # the following is similar to code in plot_plan._results()
         for v,rv1 in reduced_variables.iteritems():
             value = rv1.reduce(None)
             variable_values[v] = value  # could be None
         value = derived_variables[vid1].derive( variable_values )
         variable_values[vid1] = value
         value = derived_variables[vidl1].derive( variable_values )
         variable_values[vidl1] = value
         mean1 = derived_variables[vidm1].derive( variable_values )
     else: # pressure level coordinates in millibars, as "mbar"
         # There are other possibilities, but we aren't checking yet.
         reduced_variables = reduced_variables_press_lev(
             filetable, self.var, self.seasonid, filefilter=ffilt, rf=\
                 (lambda x,vid=None,season=self.season,dom0=domrange[0],dom1=domrange[1],gw=gw:
                          reduce2scalar_seasonal_zonal_level(
                     x,season,latmin=dom0,latmax=dom1,level=ulev,vid=vid,gw=gw) )
             )
         derived_variables = {}
         rv1 = reduced_variables[reduced_variables.keys()[0]]
         
         #save the reduce variable
         #VID = rv.dict_id(self.var, self.season, filetable, ffilt)
         #self.reduced_variables[VID] = rv1
         
         mean1 = rv1.reduce()
         #self.variable_values[VID] = mean1
     return mean1
Example #6
0
    def plot_windbarb(self, u, v, P=None, template=None, type="uv", bg=0):
        if type == "uv":
            n = numpy.ma.sqrt(u * u + v * v)
            d = numpy.ma.arccos(u / n)
            d = numpy.ma.where(numpy.ma.less(v, 0.0), -d, d)

        if P is None:
            P = u.getLevel()
            if P is None:
                P = u.getAxis(-1)
            P = P.clone()
            try:  # tries to convert to Pa
                for i in range(len(P)):
                    uni = unidata.udunits(P[i], P.units)
                    P[i] = uni.to("Pa").value
            except Exception:
                pass
            P = P[:]

        n1 = n / self.windbarbsscales[0]
        n1 = n1.astype("i")
        n2 = (n - n1 * self.windbarbsscales[0]) / self.windbarbsscales[1]
        n2 = n2.astype("i")
        n3 = (n - n1 * self.windbarbsscales[0] - n2 * self.windbarbsscales[1]) / self.windbarbsscales[2]
        n3 = n3.astype("i")

        # print 'n1:',n1
        # print 'n2:',n2
        # print 'n3:',n3

        nitems = len(P)
        for i in range(nitems):
            if not (MV2.isMA(n[i])):
                p = P[i]
                # Figure out the altitude to plot it (y coord) !
                dum, Y = self.TP2XY(273, p)
                lin = self.x.createline()
                lin.viewport = [template.data.x1, template.data.x2, template.data.y1, template.data.y2]
                lin.worldcoordinate = [-1, 1, -1, 1]
                lin.x = [0, 0]
                lin.y = [-1, 1]
                self.displays.append(self.x.plot(lin, bg=bg))
                lin = self.x.createline()
                lin.viewport = [template.data.x1, template.data.x2, template.data.y1, template.data.y2]
                lin.worldcoordinate = [-1, 1, self.ymin, self.ymax]
                # Set everything correctly y wise
                rw = 2 / (self.ymax - self.ymin)
                if self.x.islandscape():
                    r = 1.375
                else:
                    r = 0.72727272
                rv = (template.data.x2 - template.data.x1) / (template.data.y2 - template.data.y1)
                rw = 1.0 / rw
                x, y = self.make_barb(n[i], d[i], n1[i], n2[i], n3[i], rw * r * rv, Y)
                lin.x = x
                lin.y = y
                lin.linetype = ["solid"]
                self.displays.append(self.x.plot(lin, bg=bg))
Example #7
0
def pressures_in_mb(pressures):
    """From a variable or axis of pressures, this function
    converts to millibars, and returns the result as a numpy array."""
    if not hasattr(pressures, 'units'): return None
    if pressures.units == 'mb':
        pressures.units = 'mbar'  # udunits uses mb for something else
        return pressures[:]
    tmp = udunits(1.0, pressures.units)
    s, i = tmp.how('mbar')
    pressmb = s * pressures[:] + i
    return pressmb
Example #8
0
def qflx_precipunits2mmday(var):
    target_units_prect='mm/day'
    variableID=var.id
    if var.units=='kg m-2 s-1' or var.units=='kg/m2/s' or var.units=='kg/m^2/s' or var.units=='kg m^-2 s^-1' or var.units=='kg/s/m^2':
        var.units='mm/s'
    a_prect=udunits(1.,var.units)
    s_prect,i_prect=a_prect.how(target_units_prect)
    var=s_prect*var + i_prect
    var.units=target_units_prect
    var.id=variableID
    return var
Example #9
0
def pressures_in_mb( pressures ):
    """From a variable or axis of pressures, this function
    converts to millibars, and returns the result as a numpy array."""
    if not hasattr( pressures, 'units' ): return None
    if pressures.units=='mb':
        pressures.units = 'mbar' # udunits uses mb for something else
        return pressures[:]
    tmp = udunits(1.0,pressures.units)
    s,i = tmp.how('mbar')
    pressmb = s*pressures[:] + i
    return pressmb
Example #10
0
def qflx_precipunits2mmday(var):
    target_units_prect = 'mm/day'
    variableID = var.id
    if var.units == 'kg m-2 s-1' or var.units == 'kg/m2/s' or var.units == 'kg/m^2/s' or var.units == 'kg m^-2 s^-1' or var.units == 'kg/s/m^2':
        var.units = 'mm/s'
    a_prect = udunits(1., var.units)
    s_prect, i_prect = a_prect.how(target_units_prect)
    var = s_prect * var + i_prect
    var.units = target_units_prect
    var.id = variableID
    return var
Example #11
0
 def mean_lev( self, filetable, ffilt, domrange, gw ):
     """compute and return the mean of a reduced variable at a prescribed level.
     The returned mean is an mv (cdms2 TransientVariable) whose data is a scalar."""
     ulev = udunits(self.lev,'mbar')
     # We have to compute on a level surface.
     if self.var not in filetable.list_variables_with_levelaxis():
         return -999.000
     # The specified level is in millibars.  Do we have hybrid level coordinates?
     ft_hyam = filetable.find_files('hyam')
     hybrid = ft_hyam is not None and ft_hyam!=[]    # true iff filetable uses hybrid level coordinates
     if hybrid: # hybrid level coordinates
         reduced_variables = reduced_variables_hybrid_lev( filetable, self.var, self.seasonid,
                                                           filefilter=ffilt )
         vid1= dv.dict_id(self.var,'p',self.seasonid,filetable)
         vidl1=dv.dict_id(self.var,'lp',self.seasonid,filetable)
         vidm1=dv.dict_id(self.var,'mp',self.seasonid,filetable)
         derived_variables = { vid1: derived_var(
                 vid=vid1, inputs=[reduced_variable.dict_id(self.var,self.seasonid,filetable),
                                   reduced_variable.dict_id('hyam',self.seasonid,filetable),
                                   reduced_variable.dict_id('hybm',self.seasonid,filetable),
                                   reduced_variable.dict_id('PS',self.seasonid,filetable),
                                   reduced_variable.dict_id(self.var,self.seasonid,filetable) ],
                 func=verticalize ),
                               vidl1: derived_var(
                 vid=vidl1, inputs=[vid1], func=(lambda z: select_lev(z,ulev)) ),
                               vidm1: derived_var(
                 vid=vidm1, inputs=[vidl1], func=\
                     (lambda x,vid=None,season=self.season,dom0=domrange[0],dom1=domrange[1],gw=gw:
                          reduce2scalar_seasonal_zonal(
                         x,season,latmin=dom0,latmax=dom1,vid=vid,gw=gw) ) )
                               }
         variable_values = {}  # the following is similar to code in plot_spec._results()
         for v,rv1 in reduced_variables.iteritems():
             value = rv1.reduce(None)
             variable_values[v] = value  # could be None
         value = derived_variables[vid1].derive( variable_values )
         variable_values[vid1] = value
         value = derived_variables[vidl1].derive( variable_values )
         variable_values[vidl1] = value
         mean1 = derived_variables[vidm1].derive( variable_values )
     else: # pressure level coordinates in millibars, as "mbar"
         # There are other possibilities, but we aren't checking yet.
         reduced_variables = reduced_variables_press_lev(
             filetable, self.var, self.seasonid, filefilter=ffilt, rf=\
                 (lambda x,vid=None,season=self.season,dom0=domrange[0],dom1=domrange[1],gw=gw:
                          reduce2scalar_seasonal_zonal_level(
                     x,season,latmin=dom0,latmax=dom1,level=ulev,vid=vid,gw=gw) )
             )
         derived_variables = {}
         rv1 = reduced_variables[reduced_variables.keys()[0]]
         mean1 = rv1.reduce()
     return mean1
Example #12
0
def tometric(units, value=1.,  munits=['m',  'm/s']):
    """Try to convert units to metric system using :mod:`~unidata.udunits.udunits`

    :Return: a float or ``None`` if conversion failed.
    """
    import unidata
    u = unidata.udunits(value, units)
    if isinstance(munits, basestring):
        munits = [munits]
    for mu in munits:
        try:
            return u.to(mu).value
        except:
            pass
def convert(data,unitsout="Pa"):
    """ Convert data into unitsout if possible
    """
    if hasattr(data,'units'):
        units = data.units
        if units!=unitsout:
            u = unidata.udunits(1,units)
            try:
                sc,off = u.how(unitsout) # how to convert in Pa
                ps = ps*sc+off
            except:
                # well couldn't figure it out, assume it's ok but print a warning
                raise Warning, "Couldn't convert units %s to %s, assuming you know what you're doing" % (units, unitsout)
    return data
Example #14
0
def getPvalues(T):
    """computes pressure values from level axis,
    if not designated level then use last axis...
    """
    P = T.getLevel()
    if P is None:
        P=T.getAxis(-1)
    P = P.clone()
    try: # tries to convert to Pa
        for i in range(len(P)):
            u = unidata.udunits(P[i],P.units)
            P[i] = u.to("Pa").value
    except Exception,err:
        pass
Example #15
0
def getPvalues(T):
    """computes pressure values from level axis,
    if not designated level then use last axis...
    """
    P = T.getLevel()
    if P is None:
        P = T.getAxis(-1)
    P = P.clone()
    try:  # tries to convert to Pa
        for i in range(len(P)):
            u = unidata.udunits(P[i], P.units)
            P[i] = u.to("Pa").value
    except Exception, err:
        pass
Example #16
0
def calculate_reservoir_rate(var, surf_mask, surf_type=None):
    """Inputs are two maps (var and surf_mask). Whereas there may be scripts that 
    calculate the masked means, this calculates the volume flow rate (ie, not the 
    flux density, but the total flux. This is currently written to only apply to 
    water variables. """

    #If the units are not in mm/day, convert units
    target_units_prect = 'mm/day'
    if var.units == 'kg m-2 s-1' or var.units == 'kg/m2/s' or var.units == 'kg/m^2/s' or var.units == 'kg m^-2 s^-1' or var.units == 'kg/s/m^2':
        var.units = 'mm/s'
    a_prect = udunits(1., var.units)
    s_prect, i_prect = a_prect.how(target_units_prect)
    var = s_prect * var + i_prect
    var.units = target_units_prect

    #Mask the variable according to the surf_mask, using script in the same file
    var_masked = surface_maskvariable(var, surf_mask, surf_type=None)

    #Check to see if the variable has the time axis
    var_axislist = var_masked.getAxisList()
    if 'time' in var_axislist:
        scalar = genutil.averager(
            var_masked,
            axis='yxt')  #Calculate the spatial+temporal mean over the mask
        area_frac = genutil.averager(area_frac, axis='t')
        area_frac = 1. - genutil.averager(
            surf_mask, axis='yx'
        )  #Calculate the fractional area over which the numbers are calculated ie, where it's NOT masked
    else:
        scalar = genutil.averager(
            var_masked, axis='yx')  #Calculate the spatial mean over the mask
        area_frac = 1. - genutil.averager(
            surf_mask, axis='yx'
        )  #Calculate the fractional area over which the numbers are calculated ie, where it's NOT masked

    #Calculate the fraction of surface area that surf_mask covers

    #Here we hard-wire the coefficient necessary to move from mm/day * m^2 to km3/year
    coefficient = float(365. / 1000. /
                        1000000000.)  #to convert mm/day to km^3/yr

    r_earth = metrics.packages.amwg.derivations.atmconst.AtmConst.Rad_earth  #obtain radius of Earth
    A_earth = 4. * numpy.math.pi * r_earth**(
        2)  #Calulate the approximate surface area of Earth m^2
    reservoir_total = A_earth * scalar * coefficient * area_frac  #Calculate the volume rate
    #define the units of the reservoir total
    reservoir_total.units = 'km3/year'
    #reservoir_total.units=reservoir_total_units   #apply units to the output
    return reservoir_total
Example #17
0
def reconcile_units( mv1, mv2 ):
    if hasattr(mv1,'units') and hasattr(mv2,'units') and mv1.units!=mv2.units:
        if mv1.units=='mb':
            mv1.units = 'mbar' # udunits uses mb for something else
        if mv2.units=='mb':
            mv2.units = 'mbar' # udunits uses mb for something else
        if mv1.units=='mb/day':
            mv1.units = 'mbar/day' # udunits uses mb for something else
        if mv2.units=='mb/day':
            mv2.units = 'mbar/day' # udunits uses mb for something else
        tmp = udunits(1.0,mv2.units)
        s,i = tmp.how(mv1.units)  # will raise an exception if conversion not possible
        mv2 = s*mv2 + i
        mv2.units = mv1.units
    return mv1, mv2
Example #18
0
def aminusb_ax2( mv1, mv2 ):
    """returns a transient variable representing mv1-mv2, where mv1 and mv2 are variables with
    exactly two axes, with the first axis the same for each (but it's ok to differ only in units,
    which could be converted).
    To perform the subtraction, one of the variables is linearly interpolated in its second
    dimension to the second axis of the other.
    The axis used will be the coarsest (fewest points) of the two axes."""
    if hasattr(mv1,'units') and hasattr(mv2,'units') and mv1.units!=mv2.units:
        print "WARING: aminusb_ax2 is subtracting variables with different units!",mv1,mv1
    axes1 = allAxes(mv1)
    axes2 = allAxes(mv2)
    # TO DO: convert, interpolate, etc. as needed to accomodate differing first axes.
    # But for now, we'll just check a bit ...
    ax1=axes1[0]
    ax2=axes2[0]
    if ax1.shape!=ax2.shape:
        print "ERROR aminusb_ax2 requires same axes, but shape differs:",ax1.shape,ax2.shape
        print "ax1,ax2"
        return None
    if hasattr(ax1,'units') and hasattr(ax2,'units') and ax1.units!=ax2.units:
        if ax1.units=='mb':
            ax1.units = 'mbar' # udunits uses mb for something else
        if ax2.units=='mb':
            ax2.units = 'mbar' # udunits uses mb for something else
        tmp = udunits(1.0,ax2.units)
        s,i = tmp.how(ax1.units)  # will raise an exception if conversion not possible
        # crude substitute for a real units library:
        #if not (ax1.units=='mb' and ax2.units=='millibars') and\
        #   not (ax1.units=='millibars' and ax2.units=='mb'):
        #    print "ERROR aminusb_ax2 requires same axes, but units differ:",ax1.units,ax2,units
        #    print "ax1,ax2"
        #    return None
    ab_axes = [ax1]
    if len(axes1[1])<=len(axes2[1]):
        a = mv1
        b = interp2( axes1[1], mv2 )
        ab_axes.append(axes1[1])
    else:
        a = interp2( axes2[1], mv1 )
        b = mv2
        ab_axes.append(axes2[1])
    aminusb = a - b
    aminusb.id = mv1.id
    aminusb.initDomain( ab_axes )
    return aminusb
Example #19
0
File: amwg.py Project: imclab/uvis
    def plan_computation( self, filetable1, filetable2, varid, seasonid, aux ):
        # >>> Instead of reduce2latlon, I want to 
        # (1) Average var (Z3 for now) over time, thus reducing from Z3(time,hlev,lat,lon)
        # to Z3b(hlev,lat,lon) .  This is all that happens at the reduced_variables level.
        # (2) convert Z3b from hybrid (hlev) to pressure (plev) level coordinates- Z3c(plev,lat,lon)
        # This Z3c is a derived variable
        # (3) restrict Z3 to the 200 MB level, thus reducing it to Z3d(lat,lon)
        # This will have to be as the zfunc in the final plot definition.

        # In calling reduce_time_seasonal, I am assuming that no variable has axes other than (time,
        # lev,lat,lon).  If there were another axis, then we'd need a new function which reduces it.
        if isinstance(aux,Number):
            self.reduced_variables = {
                varid+'_1': reduced_variable(  # var=var(time,lev,lat,lon)
                    variableid=varid, filetable=filetable1, reduced_var_id=varid+'_1',
                    reduction_function=(lambda x,vid: reduce_time_seasonal( x, self.season, vid ) ) ),
                'hyam': reduced_variable(   # hyam=hyam(lev)
                    variableid='hyam', filetable=filetable1, reduced_var_id='hyam',
                    reduction_function=(lambda x,vid=None: x) ),
                'hybm': reduced_variable(   # hybm=hybm(lev)
                    variableid='hybm', filetable=filetable1, reduced_var_id='hybm',
                    reduction_function=(lambda x,vid=None: x) ),
                'ps': reduced_variable(     # ps=ps(time,lat,lon)
                    variableid='PS', filetable=filetable1, reduced_var_id='ps',
                    reduction_function=(lambda x,vid=None: reduce_time_seasonal( x, self.season, vid ) ) )
                }
        else:
            print "ERROR, for var=",varid," aux=",aux," is not supported yet!"
            self.plotall_id = None
            return None
        vid1 = varid+'_p'+'_1'
        self.derived_variables = {
            vid1: derived_var( vid=vid1, inputs=[ varid+'_1', 'hyam', 'hybm', 'ps' ], func=verticalize )
            }
        pselect = udunits(200,'mbar')
        self.single_plotspecs = {
            self.plot1_id: plotspec(
                vid = varid+'_1',
                zvars = [vid1],  zfunc = (lambda z: select_lev( z, pselect ) ),
                plottype = self.plottype )
            }
        self.composite_plotspecs = {
            self.plotall_id: [ self.plot1_id ]            
            }
        self.computation_planned = True
Example #20
0
    def plot_windbarb(self,u,v,P=None,template=None,type='uv',bg=0):
        if type=='uv':
            n=numpy.ma.sqrt(u*u+v*v)
            d=numpy.ma.arccos(u/n)
            d=numpy.ma.where(numpy.ma.less(v,0.),-d,d)

        if P is None:
            P=u.getLevel()
            if P is None:
                P=u.getAxis(-1)
            P = P.clone()
            try: # tries to convert to Pa
                for i in range(len(P)):
                    uni = unidata.udunits(P[i],P.units)
                    P[i] = uni.to("Pa").value
            except Exception,err:
                pass
            P=P[:]
Example #21
0
def scale_data(units, data):
    """This function is used to change scale to the units found in default_levels. """
    try:
        scale = udunits(1.0, data.units)
        scale = scale.to(units).value 
    except:
        if data.units == 'fraction':
            scale = 100.
        else:
            try:
                scale = float(units)
                units = 'scaled'
            except:
                logging.critical('Invalid display units: '+ units + ' for ' + data.units)
                sys.exit()
    data = scale*data 
    data.units = units
    return data                                              
Example #22
0
    def plot_windbarb(self, u, v, P=None, template=None, type='uv', bg=0):
        if type == 'uv':
            n = numpy.ma.sqrt(u * u + v * v)
            d = numpy.ma.arccos(u / n)
            d = numpy.ma.where(numpy.ma.less(v, 0.), -d, d)

        if P is None:
            P = u.getLevel()
            if P is None:
                P = u.getAxis(-1)
            P = P.clone()
            try:  # tries to convert to Pa
                for i in range(len(P)):
                    uni = unidata.udunits(P[i], P.units)
                    P[i] = uni.to("Pa").value
            except Exception, err:
                pass
            P = P[:]
Example #23
0
def calculate_reservoir_rate(var, surf_mask, surf_type=None):
    
    """Inputs are two maps (var and surf_mask). Whereas there may be scripts that 
    calculate the masked means, this calculates the volume flow rate (ie, not the 
    flux density, but the total flux. This is currently written to only apply to 
    water variables. """
    
    
    #If the units are not in mm/day, convert units
    target_units_prect='mm/day'
    if var.units=='kg m-2 s-1' or var.units=='kg/m2/s' or var.units=='kg/m^2/s' or var.units=='kg m^-2 s^-1' or var.units=='kg/s/m^2':
        var.units='mm/s'
    a_prect=udunits(1.,var.units)
    s_prect,i_prect=a_prect.how(target_units_prect)
    var=s_prect*var + i_prect
    var.units=target_units_prect
    
    #Mask the variable according to the surf_mask, using script in the same file
    var_masked=surface_maskvariable(var, surf_mask, surf_type=None)
    
    #Check to see if the variable has the time axis
    var_axislist=var_masked.getAxisList()
    if 'time' in var_axislist:
        scalar=genutil.averager(var_masked,axis='yxt') #Calculate the spatial+temporal mean over the mask
        area_frac=genutil.averager(area_frac,axis='t')
        area_frac=1.-genutil.averager(surf_mask,axis='yx') #Calculate the fractional area over which the numbers are calculated ie, where it's NOT masked
    else:
        scalar=genutil.averager(var_masked,axis='yx') #Calculate the spatial mean over the mask
        area_frac=1.-genutil.averager(surf_mask,axis='yx') #Calculate the fractional area over which the numbers are calculated ie, where it's NOT masked
    
    
    #Calculate the fraction of surface area that surf_mask covers
    
    
    #Here we hard-wire the coefficient necessary to move from mm/day * m^2 to km3/year
    coefficient=float(365./1000./1000000000.) #to convert mm/day to km^3/yr
    
    r_earth=metrics.packages.amwg.derivations.atmconst.AtmConst.Rad_earth #obtain radius of Earth
    A_earth=4. * numpy.math.pi * r_earth ** (2)    #Calulate the approximate surface area of Earth m^2
    reservoir_total=A_earth * scalar * coefficient * area_frac #Calculate the volume rate
    #define the units of the reservoir total
    reservoir_total.units='km3/year'
    #reservoir_total.units=reservoir_total_units   #apply units to the output
    return reservoir_total
Example #24
0
def scale_data(units, data):
    """This function is used to change scale to the units found in default_levels. """
    try:
        scale = udunits(1.0, data.units)
        scale = scale.to(units).value
    except:
        if data.units == 'fraction':
            scale = 100.
        else:
            try:
                scale = float(units)
                units = 'scaled'
            except:
                logging.critical('Invalid display units: ' + units + ' for ' +
                                 data.units)
                sys.exit()
    data = scale * data
    data.units = units
    return data
Example #25
0
def convert_variable( var, target_units ):
    """Converts a variable (cdms2 MV) to the target units (a string) if possible, and returns
    the variable modified to use the new units."""
    if not hasattr( var, 'units' ):
        return var
    if target_units==None or target_units=='':
        return var
    if var.units == target_units:
        return var
    if var.units in unit_synonyms.keys():
        var.units = unit_synonyms[var.units]
    if var.units in last_ditch_conversions.keys():
        u,s,o = last_ditch_conversions[var.units]
        var = s*var + o
        var.units = u
    try:
        s,o = udunits(1.0,var.units).how(target_units)
    except TypeError as e:
        logging.warning("Could not convert units from %s to %s",var.units,target_units)
        return var
    var = s*var + o
    var.units = target_units
    return var
Example #26
0
def convert_variable(var, target_units):
    """Converts a variable (cdms2 MV) to the target units (a string) if possible, and returns
    the variable modified to use the new units."""
    if not hasattr(var, 'units'):
        return var
    if target_units == None or target_units == '':
        return var
    if var.units == target_units:
        return var
    if var.units in unit_synonyms.keys():
        var.units = unit_synonyms[var.units]
    if var.units in last_ditch_conversions.keys():
        u, s, o = last_ditch_conversions[var.units]
        var = s * var + o
        var.units = u
    try:
        s, o = udunits(1.0, var.units).how(target_units)
    except TypeError as e:
        print "WARNING, could not convert units from", var.units, "to", target_units
        return var
    var = s * var + o
    var.units = target_units
    return var
Example #27
0
def wv_lifetime(prw,prect):
    """
    Calculates the life time of water vapor (wv_timescale) from the precipitable 
    water (prw) and the precipitation rate (prect). Expects the prw and prect 
    fields are climatological fields, so the length of time axis is 0.
    For comparison, the new prect and new prw maps, which have been regridded
    onto a coarse common grid and have been modified to fit units of mm/day and mm,
    are also output. The output, 'new_wv_timescale' has units of 'day'
    """
    
    logger.info("units before conversion \n %s \n %s \n ")

    
    #First part recognizes the different units and tries to make them all the same
    target_units_prw='mm'
    target_units_prect='mm/day'
    
    #common forms of precipitable water and precipitation rate that need to be converted
    if prw.units=='kg m-2' or prw.units=='kg/m2' or prw.units=='kg/m^2':
        prw.units='mm'
    if prect.units=='kg m-2 s-1' or prect.units=='kg/m2/s' or prect.units=='kg m^-2 s^-1':
        prect.units='mm/s'
    
    #calculate the unit conversions and convert variables into mm and mm/day
    a_prw=udunits(1.,prw.units)
    s_prw,i_prw=a_prw.how(target_units_prw)
    
    prw=s_prw*prw + i_prw
    prw.units=target_units_prw
    
    a_prect=udunits(1.,prect.units)
    s_prect,i_prect=a_prect.how(target_units_prect)
    prect=s_prect*prect + i_prect
    prect.units=target_units_prect
    
    #obtain the axes of prect and prw
    prect_axes=prect.getAxisList()
    prw_axes=prw.getAxisList()
    
    #obtain the grid of prect and prw
    prect_grid=prect.getGrid() # obtain the grid of prect
    prw_grid=prw.getGrid() # obtain the grid of the prw
    
    new_prect_axes=prect_axes
    new_prw_axes=prw_axes
    #remove time axis if the data has three axes
    if len(prect_axes)>=3 and len(prect_axes[0])==1:
        new_prect_axes=prect_axes[1:]
        logger.info("Shortened prect axes size")
    if len(prw_axes)>=3 and len(prw_axes[0])==1:
        new_prw_axes=prw_axes[1:]
        logger.info("Shortened prect axes size")
    
    #determine coarsest grid and regrid to that grid
    if prect_grid.shape == prw_grid.shape:
        new_prect=prect
        new_prw=prw
        logger.info("no need to regrid")
    else:
        if len(new_prect_axes[0])<=len(new_prw_axes[0]):
            new_prect=prect
            logger.info("PRW grid regridded")
            new_prw=prw.regrid(prect_grid,regridTool='esmf',regridMethod='conserve')
        else:
            new_prw=prw
            logger.info("PRECT grid regridded")
            new_prect=prect.regrid(prw_grid,regridTool='esmf',regridMethod='conserve')
    
    #divide prw with prect to obtain the timescale
    new_wv_timescale=new_prw/new_prect
    new_wv_timescale.units='day'
    #new_wv_timescale.id=vid
    new_wv_timescale.long_name='Column integrated bulk water vapor lifetime'
    return new_wv_timescale, new_prw, new_prect
Example #28
0
def convert_units(value, ufrom, uto):
    """Convert value from ufrom units to uto units using :mod:`~unidata.udunits.udunits`
    """
    import unidata
    return unidata.udunits(value, ufrom).to(uto).value
Example #29
0
def wv_lifetime(prw, prect):
    """
    Calculates the life time of water vapor (wv_timescale) from the precipitable 
    water (prw) and the precipitation rate (prect). Expects the prw and prect 
    fields are climatological fields, so the length of time axis is 0.
    For comparison, the new prect and new prw maps, which have been regridded
    onto a coarse common grid and have been modified to fit units of mm/day and mm,
    are also output. The output, 'new_wv_timescale' has units of 'day'
    """

    logger.info("units before conversion \n %s \n %s \n ")

    #First part recognizes the different units and tries to make them all the same
    target_units_prw = 'mm'
    target_units_prect = 'mm/day'

    #common forms of precipitable water and precipitation rate that need to be converted
    if prw.units == 'kg m-2' or prw.units == 'kg/m2' or prw.units == 'kg/m^2':
        prw.units = 'mm'
    if prect.units == 'kg m-2 s-1' or prect.units == 'kg/m2/s' or prect.units == 'kg m^-2 s^-1':
        prect.units = 'mm/s'

    #calculate the unit conversions and convert variables into mm and mm/day
    a_prw = udunits(1., prw.units)
    s_prw, i_prw = a_prw.how(target_units_prw)

    prw = s_prw * prw + i_prw
    prw.units = target_units_prw

    a_prect = udunits(1., prect.units)
    s_prect, i_prect = a_prect.how(target_units_prect)
    prect = s_prect * prect + i_prect
    prect.units = target_units_prect

    #obtain the axes of prect and prw
    prect_axes = prect.getAxisList()
    prw_axes = prw.getAxisList()

    #obtain the grid of prect and prw
    prect_grid = prect.getGrid()  # obtain the grid of prect
    prw_grid = prw.getGrid()  # obtain the grid of the prw

    new_prect_axes = prect_axes
    new_prw_axes = prw_axes
    #remove time axis if the data has three axes
    if len(prect_axes) >= 3 and len(prect_axes[0]) == 1:
        new_prect_axes = prect_axes[1:]
        logger.info("Shortened prect axes size")
    if len(prw_axes) >= 3 and len(prw_axes[0]) == 1:
        new_prw_axes = prw_axes[1:]
        logger.info("Shortened prect axes size")

    #determine coarsest grid and regrid to that grid
    if prect_grid.shape == prw_grid.shape:
        new_prect = prect
        new_prw = prw
        logger.info("no need to regrid")
    else:
        if len(new_prect_axes[0]) <= len(new_prw_axes[0]):
            new_prect = prect
            logger.info("PRW grid regridded")
            new_prw = prw.regrid(prect_grid,
                                 regridTool='esmf',
                                 regridMethod='conserve')
        else:
            new_prw = prw
            logger.info("PRECT grid regridded")
            new_prect = prect.regrid(prw_grid,
                                     regridTool='esmf',
                                     regridMethod='conserve')

    #divide prw with prect to obtain the timescale
    new_wv_timescale = new_prw / new_prect
    new_wv_timescale.units = 'day'
    #new_wv_timescale.id=vid
    new_wv_timescale.long_name = 'Column integrated bulk water vapor lifetime'
    return new_wv_timescale, new_prw, new_prect
Example #30
0
def kt2ms(nd):
    """Convert nds to m/s"""
    return udunits(nd, 'kt').to('m/s').value
Example #31
0
def ms2kt(ms):
    """Convert m/s to nds"""
    return udunits(ms, 'm/s').to('kt').value
def rhodz_from_plev( lev, nlev_want, mv ):
    """returns a variable rhodz which represents the air mass column density in each cell.
    The input variable is a level axis, units millibars.  nlev_want is 0 for a straightforward
    computation.  If nlev_want>0, then first lev should be changed to something with that
    number of levels, by some interpolation/extrapolation process."""
    # Thus rhodz will depend on lat,lon,level (and time).
    g = AtmConst.g     # 9.80665 m/s2.
    lat = mv.getLatitude()
    lon = mv.getLongitude()
    if nlev_want==0 or nlev_want==len(lev):
        levc = lev             # The "good" case.
    elif nlev_want==1+len(lev):  # Not so bad
        levc = interp_extrap_to_one_more_level( lev )
    else:                      # Terminally bad, don't know what to do
        raise DiagError( "ERROR, rhodz_from_plev does not have the right number of levels %, %" %\
                             (len(lev),nlev_want) )
    # I expect lev[0] to be the ground (highest value), lev[-1] to be high (lowest value)
    lev3ddat = numpy.zeros( (levc.shape[0], lat.shape[0], lon.shape[0] ))
    lev3d = cdms2.createVariable( lev3ddat, axes=[levc, lat, lon] )
    for k in range( levc.shape[0] ):
        lev3d[k,:,:] = levc[k]
    if hasattr( lev, '_filename' ):
        # We'll try to use other variables to do better than extrapolating.
        # This only works in CAM, CESM, ACME, etc.
        # For simplicity, if data is available at multiple times we will use just the first time.
        f = cdms2.open(lev._filename)
        fvars = f.variables.keys()
        if 'PS' in fvars:
            PS = f('PS')
            # I could relax all of the following assertions, but not without a test
            # problem, and I don't have one.  An assertion failure will provide a test
            # problem and make it clear what has to be done.
            assert (len(PS.shape)==3), "expected PS to be shaped (time,lat,lon)"
            assert (hasattr(lev,'units')), "levels should have units and don't"
            assert (hasattr(PS,'units')), "PS should have units and doesn't"
            assert (PS.shape[0]>=1), "expected PS first dimension to be time, with at least one time."

            # Make sure we can convert PS to the units of lev.  They come
            # from the same files so they should use the same units, but that's not always so!
            # Such an exception is ERAI obs files where lev.units=hPa and PS.units=mbar.
            # That's really the same, but we don't know that until going through udunits.
            # The first couple lines are because udunits doesn't understand 'mb' to be a pressure
            # unit, but some obs files do.
            levunits = 'mbar' if lev.units=='mb' else lev.units
            PSunits = 'mbar' if PS.units=='mb' else PS.units
            tmp = udunits(1.0,levunits)
            try:
                s,i = tmp.how(PSunits)
            except Exception as e:
                # conversion not possible.
                logging.exception("Could not convert from PS units %s to lev units %s",PS.units,lev.units)
                return None
            # Now, s*PS+i would be PS in the units of lev.  In all cases I've seen, s==1 and i==0

            nlat = PS.shape[1]  # normally lat, but doesn't have to be
            nlon = PS.shape[2]  # normally lon, but doesn't have to be
            for ilat in range(nlat):
                for ilon in range(nlon):
                    psl = s*PS[0,ilat,ilon] + i
                    if psl>lev[0]:
                        lev3d[0,ilat,ilon] = psl
                    # else some levels are underground.  Subterranean data should later get
                    # masked out, but even if it doesn't, doing nothing here does no harm.
        f.close()

    dp = lev3d[0:-1,:,:] - lev3d[1:,:,:]
    rhodz = dp/g   # (lev) shape
    return rhodz
Example #33
0
    def plan_computation_level_surface( self, model, obs, varnom, seasonid, aux=None, names={}, plotparms=None ):
        filetable1, filetable2 = self.getfts(model, obs)
        """Set up for a lat-lon contour plot, averaged in other directions - except that if the
        variable to be plotted depend on level, it is not averaged over level.  Instead, the value
        at a single specified pressure level, aux, is used. The units of aux are millbars."""
        # In calling reduce_time_seasonal, I am assuming that no variable has axes other than
        # (time, lev,lat,lon).
        # If there were another axis, then we'd need a new function which reduces it as well.
        if not isinstance(aux,Number): return None
        pselect = udunits(aux,'mbar')
        pselect.value=int(pselect.value)
        PSELECT = str(pselect)

        reduced_varlis = [
            reduced_variable(  # var=var(time,lev,lat,lon)
                variableid=varnom, filetable=filetable1, season=self.season,
                reduction_function=(lambda x,vid: reduce_time_seasonal( x, self.season, self.region, vid ) ) ),
            reduced_variable(   # hyam=hyam(lev)
                variableid='hyam', filetable=filetable1, season=self.season,
                reduction_function=(lambda x,vid=None: select_region( x, self.region)) ),
            reduced_variable(   # hybm=hybm(lev)
                variableid='hybm', filetable=filetable1, season=self.season,
                reduction_function=(lambda x,vid=None: select_region( x, self.region)) ),
            reduced_variable(     # ps=ps(time,lat,lon)
                variableid='PS', filetable=filetable1, season=self.season,
                reduction_function=(lambda x,vid: reduce_time_seasonal( x, self.season, self.region, vid ) ) ) ]
        # vid1 = varnom+'_p_1'
        # vidl1 = varnom+'_lp_1'
        vid1 = dv.dict_id(  varnom, 'p', seasonid, filetable1)
        vidl1 = dv.dict_id(varnom, 'lp', seasonid, filetable1)
        self.derived_variables = {
            vid1: derived_var( vid=vid1, inputs =
                               [rv.dict_id(varnom,seasonid,filetable1), rv.dict_id('hyam',seasonid,filetable1),
                                rv.dict_id('hybm',seasonid,filetable1), rv.dict_id('PS',seasonid,filetable1) ],
            #was  vid1: derived_var( vid=vid1, inputs=[ varnom+'_1', 'hyam_1', 'hybm_1', 'PS_1' ],
                               func=verticalize ),
            vidl1: derived_var( vid=vidl1, inputs=[vid1],
                                func=(lambda z,psl=pselect: select_lev(z,psl))) }

        ft1src = filetable1.source()
        #note: the title in the following is parced in customizeTemplate. This is a garbage kludge! Mea culpa. 
        varstr = varnom + '(' + PSELECT + ')'
        self.single_plotspecs = {
            self.plot1_id: plotspec(
                # was vid = varnom+'_1',
                # was zvars = [vid1],  zfunc = (lambda z: select_lev( z, pselect ) ),
                vid = ps.dict_idid(vidl1),
                zvars = [vidl1],  zfunc = (lambda z: z),
                plottype = self.plottype,
                title = ' '.join([varstr, seasonid, 'model', names['model']]),
                title1 = ' '.join([varstr, seasonid, 'model', names['model']]),
                title2 = 'model',
                file_descr = 'model',
                source = names['model'],
                plotparms = plotparms[src2modobs(ft1src)] ) }
           
        if filetable2 is None:
            self.reduced_variables = { v.id():v for v in reduced_varlis }
            self.composite_plotspecs = {
                self.plotall_id: [ self.plot1_id ]
                }
            self.computation_planned = True
            return

        if 'hyam' in filetable2.list_variables() and 'hybm' in filetable2.list_variables():
            # hybrid levels in use, convert to pressure levels
            reduced_varlis += [
                reduced_variable(  # var=var(time,lev,lat,lon)
                    variableid=varnom, filetable=filetable2, season=self.season,
                    reduction_function=(lambda x,vid: reduce_time_seasonal( x, self.season, self.region, vid ) ) ),
                reduced_variable(   # hyam=hyam(lev)
                    variableid='hyam', filetable=filetable2, season=self.season,
                    reduction_function=(lambda x,vid=None: select_region( x, self.region)) ),
                reduced_variable(   # hybm=hybm(lev)
                    variableid='hybm', filetable=filetable2, season=self.season,
                    reduction_function=(lambda x,vid=None: select_region( x, self.region)) ),
                reduced_variable(     # ps=ps(time,lat,lon)
                    variableid='PS', filetable=filetable2, season=self.season,
                    reduction_function=(lambda x,vid: reduce_time_seasonal( x, self.season, self.region, vid ) ) )
                ]
            #vid2 = varnom+'_p_2'
            #vidl2 = varnom+'_lp_2'
            vid2 = dv.dict_id( varnom, 'p', seasonid, filetable2 )
            vid2 = dv.dict_id( vards, 'lp', seasonid, filetable2 )
            self.derived_variables[vid2] = derived_var( vid=vid2, inputs=[
                    rv.dict_id(varnom,seasonid,filetable2), rv.dict_id('hyam',seasonid,filetable2),
                    rv.dict_id('hybm',seasonid,filetable2), rv.dict_id('PS',seasonid,filetable2) ],
                                                        func=verticalize )
            self.derived_variables[vidl2] = derived_var(
                vid=vidl2, inputs=[vid2], func=(lambda z,psl=pselect: select_lev(z,psl) ) )
        else:
            # no hybrid levels, assume pressure levels.
            #vid2 = varnom+'_2'
            #vidl2 = varnom+'_lp_2'
            vid2 = rv.dict_id(varnom,seasonid,filetable2)
            vidl2 = dv.dict_id( varnom, 'lp', seasonid, filetable2 )
            reduced_varlis += [
                reduced_variable(  # var=var(time,lev,lat,lon)
                    variableid=varnom, filetable=filetable2, season=self.season,
                    reduction_function=(lambda x,vid: reduce_time_seasonal( x, self.season, self.region, vid ) ) )
                ]
            self.derived_variables[vidl2] = derived_var(
                vid=vidl2, inputs=[vid2], func=(lambda z,psl=pselect: select_lev(z,psl) ) )
        self.reduced_variables = { v.id():v for v in reduced_varlis }

        try:
            ft2src = filetable2.source()
        except:
            ft2src = ''
        filterid = ft2src.split('_')[-1] #recover the filter id: kludge
        self.single_plotspecs[self.plot2_id] = plotspec(
                #was vid = varnom+'_2',
                vid = ps.dict_idid(vidl2),
                zvars = [vidl2],  zfunc = (lambda z: z),
                plottype = self.plottype,
                title = ' '.join([varstr,seasonid,'observation',names['obs']]),
                title1 = ' '.join([varstr, seasonid, 'observation',names['obs']]),
                title2 = 'observation',
                file_descr = 'obs',
                source = names['obs'],
                plotparms = plotparms[src2obsmod(ft2src)] )
        self.single_plotspecs[self.plot3_id] = plotspec(
                #was vid = varnom+'_diff',
                vid = ps.dict_id(varnom,'diff',seasonid,filetable1,filetable2),
                zvars = [vidl1,vidl2],  zfunc = aminusb_2ax,
                plottype = self.plottype,
                title = ' '.join([varstr,seasonid,'difference']),
                title1 = ' '.join([varstr, seasonid, 'difference']),
                title2 = 'difference',
                file_descr = 'diff',
                plotparms = plotparms['diff'] )
#                zerocontour=-1 )
        self.composite_plotspecs = {
            self.plotall_id: [ self.plot1_id, self.plot2_id, self.plot3_id ]
            }
        self.computation_planned = True
Example #34
0
    def plot_windbarb(self, u, v, P=None, template=None, type='uv', bg=0):
        if type == 'uv':
            n = numpy.ma.sqrt(u * u + v * v)
            d = numpy.ma.arccos(u / n)
            d = numpy.ma.where(numpy.ma.less(v, 0.), -d, d)

        if P is None:
            P = u.getLevel()
            if P is None:
                P = u.getAxis(-1)
            P = P.clone()
            try:  # tries to convert to Pa
                for i in range(len(P)):
                    uni = unidata.udunits(P[i], P.units)
                    P[i] = uni.to("Pa").value
            except Exception:
                pass
            P = P[:]

        n1 = n / self.windbarbsscales[0]
        n1 = n1.astype('i')
        n2 = (n - n1 * self.windbarbsscales[0]) / self.windbarbsscales[1]
        n2 = n2.astype('i')
        n3 = (n - n1 * self.windbarbsscales[0] -
              n2 * self.windbarbsscales[1]) / self.windbarbsscales[2]
        n3 = n3.astype('i')

        # print 'n1:',n1
        # print 'n2:',n2
        # print 'n3:',n3

        nitems = len(P)
        for i in range(nitems):
            if not (MV2.isMA(n[i])):
                p = P[i]
                # Figure out the altitude to plot it (y coord) !
                dum, Y = self.TP2XY(273, p)
                lin = self.x.createline()
                lin.viewport = [
                    template.data.x1, template.data.x2, template.data.y1,
                    template.data.y2
                ]
                lin.worldcoordinate = [-1, 1, -1, 1]
                lin.x = [0, 0]
                lin.y = [-1, 1]
                self.displays.append(self.x.plot(lin, bg=bg))
                lin = self.x.createline()
                lin.viewport = [
                    template.data.x1, template.data.x2, template.data.y1,
                    template.data.y2
                ]
                lin.worldcoordinate = [-1, 1, self.ymin, self.ymax]
                # Set everything correctly y wise
                rw = 2 / (self.ymax - self.ymin)
                if self.x.islandscape():
                    r = 1.375
                else:
                    r = .72727272
                rv = (template.data.x2 -
                      template.data.x1) / (template.data.y2 - template.data.y1)
                rw = 1. / rw
                x, y = self.make_barb(n[i], d[i], n1[i], n2[i], n3[i],
                                      rw * r * rv, Y)
                lin.x = x
                lin.y = y
                lin.type = ['solid']
                self.displays.append(self.x.plot(lin, bg=bg))
Example #35
0
def rhodz_from_plev( lev, nlev_want, mv ):
    """returns a variable rhodz which represents the air mass column density in each cell.
    The input variable is a level axis, units millibars.  nlev_want is 0 for a straightforward
    computation.  If nlev_want>0, then first lev should be changed to something with that
    number of levels, by some interpolation/extrapolation process."""
    # Thus rhodz will depend on lat,lon,level (and time).
    if lev[0]>lev[-1]:
        ibottom = 0  # lev is ordered bottom-up , assuming it is pressure levels
    else:
        ibottom = -1 # lev is ordered top-down, assuming it is pressure levels
    g = AtmConst.g     # 9.80665 m/s2.
    lat = mv.getLatitude()
    lon = mv.getLongitude()
    if nlev_want==0 or nlev_want==len(lev):
        levc = lev             # The "good" case.
    elif nlev_want==1+len(lev):  # Not so bad
        levc = interp_extrap_to_one_more_level( lev )
    else:                      # Terminally bad, don't know what to do
        raise DiagError( "ERROR, rhodz_from_plev does not have the right number of levels %, %" %\
                             (len(lev),nlev_want) )
    # I expect lev[0] to be the ground (highest value), lev[-1] to be high (lowest value)
    lev3ddat = numpy.zeros( (levc.shape[0], lat.shape[0], lon.shape[0] ))
    lev3d = cdms2.createVariable( lev3ddat, axes=[levc, lat, lon] )
    for k in range( levc.shape[0] ):
        lev3d[k,:,:] = levc[k]
    if hasattr( lev, 'filename' ):
        # We'll try to use other variables to do better than extrapolating.
        # This only works in CAM, CESM, ACME, etc.
        # For simplicity, if data is available at multiple times we will use just the first time.
        f = cdms2.open(lev.filename)
        fvars = f.variables.keys()
        if 'PS' in fvars:
            latm1,latm2 = axis_minmax( lat, f )
            lonm1,lonm2 = axis_minmax( lon, f )
            PS = f('PS')(latitude=(latm1,latm2),longitude=(lonm1,lonm2))
            # I could relax all of the following assertions, but not without a test
            # problem, and I don't have one.  An assertion failure will provide a test
            # problem and make it clear what has to be done.
            assert (len(PS.shape)==3), "expected PS to be shaped (time,lat,lon)"
            assert (hasattr(lev,'units')), "levels should have units and don't"
            assert (hasattr(PS,'units')), "PS should have units and doesn't"
            assert (PS.shape[0]>=1), "expected PS first dimension to be time, with at least one time."

            # Make sure we can convert PS to the units of lev.  They come
            # from the same files so they should use the same units, but that's not always so!
            # Such an exception is ERAI obs files where lev.units=hPa and PS.units=mbar.
            # That's really the same, but we don't know that until going through udunits.
            # The first couple lines are because udunits doesn't understand 'mb' to be a pressure
            # unit, but some obs files do.
            levunits = 'mbar' if lev.units=='mb' else lev.units
            PSunits = 'mbar' if PS.units=='mb' else PS.units
            tmp = udunits(1.0,PSunits)
            try:
                s,i = tmp.how(levunits)
            except Exception as e:
                # conversion not possible.
                logging.exception("Could not convert from PS units %s to lev units %s",PS.units,lev.units)
                return None
            # Now, s*PS+i would be PS in the units of lev.  In all cases I've seen, i==0

            nlat = PS.shape[1]  # normally lat, but doesn't have to be
            nlon = PS.shape[2]  # normally lon, but doesn't have to be
            # Adjust the lowest level of lev3d, if above the surface, to be the surface pressure.
            for ilat in range(nlat):
                for ilon in range(nlon):
                    psl = s*PS[0,ilat,ilon] + i
                    if psl>lev[ibottom]:
                        lev3d[ibottom,ilat,ilon] = psl
                    # else some levels are underground.  Subterranean data should later get
                    # masked out, but even if it doesn't, doing nothing here does no harm.
        f.close()

    if ibottom==0:
        dp = lev3d[0:-1,:,:] - lev3d[1:,:,:]  # for bottom-up, i.e. level 0 is near the surface
    else:
        dp = lev3d[1:,:,:] - lev3d[0:-1:,:,:]   # for top-down
    rhodz = dp/g   # (lev) shape

    # Fix level axis attributes:
    lev3dlev = lev3d.getLevel()
    levunits = getattr(lev3dlev,'units',None)
    levaxis = getattr(lev3dlev,'axis',None)
    levrho = rhodz.getAxisList()[0]
    if not levrho.isLatitude() and not levrho.isLongitude():
        if levunits is not None:  setattr(levrho,'units',levunits)
        if levaxis is not None: setattr(levrho,'axis',levaxis)

    return rhodz
Example #36
0
import unidata

m=unidata.udunits(5,'m')

cm=unidata.udunits(7,'cm')

i=unidata.udunits(3,'in')

f=unidata.udunits(5,'feet')

print m
print cm
print i
print f

dC=unidata.udunits(33,'degC')
dF=unidata.udunits(83,'degF')
dK=unidata.udunits(300,'K')

print m,'+',cm,'=',m+cm

print cm,'+',i,'=',cm+i
print i,'+',cm,'=',i+cm

m.units='km'
print m

try:
    m2=m+dK
except:
    print 'Ok could not add',m,'and',dK
Example #37
0
## Create an offsetted units for dimless
unidata.addOffsettedUnit("fakeCelsius",273.15,"dimless")

## Create mutliplied units
unidata.addMultipliedUnits("efC","eq","fakeCelsius")
unidata.addMultipliedUnits("efP","eq","pourcent")

## Create divded units
unidata.addDividedUnits("defC","eq","fakeCelsius")
unidata.addDividedUnits("defP","eq","pourcent")

## Create inverted unit
unidata.addInvertedUnit("iefC","defC")

## Test scaled
p = unidata.udunits(1,"pourcent")
## Test new base unit
eq = unidata.udunits(1,"eq")

o=p.to("dimless")
print o
assert(o.units=="dimless")
assert(o.value == 0.01)

fC = unidata.udunits(2,"fakeCelsius")
o=fC.to("dimless")
print o
assert(o.units=="dimless")
assert(numpy.allclose(o.value,275.15))
o=fC.to("pourcent")
print o
Example #38
0
File: amwg.py Project: imclab/uvis
 def plan_computation_level_surface( self, filetable1, filetable2, varid, seasonid, aux ):
     """Set up for a lat-lon contour plot, averaged in other directions - except that if the
     variable to be plotted depend on level, it is not averaged over level.  Instead, the value
     at a single specified pressure level, aux, is used. The units of aux are millbars."""
     # In calling reduce_time_seasonal, I am assuming that no variable has axes other than
     # (time, lev,lat,lon).
     # If there were another axis, then we'd need a new function which reduces it as well.
     if not isinstance(aux,Number): return None
     self.reduced_variables = {
         varid+'_1': reduced_variable(  # var=var(time,lev,lat,lon)
             variableid=varid, filetable=filetable1, reduced_var_id=varid+'_1',
             reduction_function=(lambda x,vid: reduce_time_seasonal( x, self.season, vid ) ) ),
         'hyam_1': reduced_variable(   # hyam=hyam(lev)
             variableid='hyam', filetable=filetable1, reduced_var_id='hyam_1',
             reduction_function=(lambda x,vid=None: x) ),
         'hybm_1': reduced_variable(   # hybm=hybm(lev)
             variableid='hybm', filetable=filetable1, reduced_var_id='hybm_1',
             reduction_function=(lambda x,vid=None: x) ),
         'PS_1': reduced_variable(     # ps=ps(time,lat,lon)
             variableid='PS', filetable=filetable1, reduced_var_id='PS_1',
             reduction_function=(lambda x,vid=None: reduce_time_seasonal( x, self.season, vid ) ) ),
         varid+'_2': reduced_variable(  # var=var(time,lev,lat,lon)
             variableid=varid, filetable=filetable2, reduced_var_id=varid+'_2',
             reduction_function=(lambda x,vid: reduce_time_seasonal( x, self.season, vid ) ) ),
         'hyam_2': reduced_variable(   # hyam=hyam(lev)
             variableid='hyam', filetable=filetable2, reduced_var_id='hyam_2',
             reduction_function=(lambda x,vid=None: x) ),
         'hybm_2': reduced_variable(   # hybm=hybm(lev)
             variableid='hybm', filetable=filetable2, reduced_var_id='hybm_2',
             reduction_function=(lambda x,vid=None: x) ),
         'PS_2': reduced_variable(     # ps=ps(time,lat,lon)
             variableid='PS', filetable=filetable2, reduced_var_id='PS_2',
             reduction_function=(lambda x,vid=None: reduce_time_seasonal( x, self.season, vid ) ) )
         }
     pselect = udunits(aux,'mbar')
     vid1 = varid+'_p_1'
     vidl1 = varid+'_lp_1'
     vid2 = varid+'_p_2'
     vidl2 = varid+'_lp_2'
     self.derived_variables = {
         vid1: derived_var( vid=vid1, inputs=[ varid+'_1', 'hyam_1', 'hybm_1', 'PS_1' ],
                            func=verticalize ),
         vidl1: derived_var( vid=vidl1, inputs=[vid1], func=(lambda z: select_lev(z,pselect) ) ),
         vid2: derived_var( vid=vid2, inputs=[ varid+'_2', 'hyam_2', 'hybm_2', 'PS_2' ],
                            func=verticalize ),
         vidl2: derived_var( vid=vidl2, inputs=[vid2], func=(lambda z: select_lev(z,pselect) ) )
         }
     self.single_plotspecs = {
         self.plot1_id: plotspec(
             vid = varid+'_1',
             # was zvars = [vid1],  zfunc = (lambda z: select_lev( z, pselect ) ),
             zvars = [vidl1],  zfunc = (lambda z: z),
             plottype = self.plottype ),
         self.plot2_id: plotspec(
             vid = varid+'_2',
             zvars = [vidl2],  zfunc = (lambda z: z),
             plottype = self.plottype ),
         self.plot3_id: plotspec(
             vid = varid+'_diff',
             zvars = [vidl1,vidl2],  zfunc = aminusb_2ax,
             plottype = self.plottype ),
         }
     self.composite_plotspecs = {
         self.plotall_id: [ self.plot1_id, self.plot2_id, self.plot3_id ]            
         }
     self.computation_planned = True
Example #39
0
    def plan_computation_level_surface(self,
                                       model,
                                       obs,
                                       varnom,
                                       seasonid,
                                       aux=None,
                                       names={},
                                       plotparms=None):
        filetable1, filetable2 = self.getfts(model, obs)
        """Set up for a lat-lon contour plot, averaged in other directions - except that if the
        variable to be plotted depend on level, it is not averaged over level.  Instead, the value
        at a single specified pressure level, aux, is used. The units of aux are millbars."""
        # In calling reduce_time_seasonal, I am assuming that no variable has axes other than
        # (time, lev,lat,lon).
        # If there were another axis, then we'd need a new function which reduces it as well.
        if not isinstance(aux, Number): return None
        pselect = udunits(aux, 'mbar')
        pselect.value = int(pselect.value)
        PSELECT = str(pselect)

        reduced_varlis = [
            reduced_variable(  # var=var(time,lev,lat,lon)
                variableid=varnom,
                filetable=filetable1,
                season=self.season,
                reduction_function=(lambda x, vid: reduce_time_seasonal(
                    x, self.season, self.region, vid))),
            reduced_variable(  # hyam=hyam(lev)
                variableid='hyam',
                filetable=filetable1,
                season=self.season,
                reduction_function=(
                    lambda x, vid=None: select_region(x, self.region))),
            reduced_variable(  # hybm=hybm(lev)
                variableid='hybm',
                filetable=filetable1,
                season=self.season,
                reduction_function=(
                    lambda x, vid=None: select_region(x, self.region))),
            reduced_variable(  # ps=ps(time,lat,lon)
                variableid='PS',
                filetable=filetable1,
                season=self.season,
                reduction_function=(lambda x, vid: reduce_time_seasonal(
                    x, self.season, self.region, vid)))
        ]
        # vid1 = varnom+'_p_1'
        # vidl1 = varnom+'_lp_1'
        vid1 = dv.dict_id(varnom, 'p', seasonid, filetable1)
        vidl1 = dv.dict_id(varnom, 'lp', seasonid, filetable1)
        self.derived_variables = {
            vid1:
            derived_var(
                vid=vid1,
                inputs=[
                    rv.dict_id(varnom, seasonid, filetable1),
                    rv.dict_id('hyam', seasonid, filetable1),
                    rv.dict_id('hybm', seasonid, filetable1),
                    rv.dict_id('PS', seasonid, filetable1)
                ],
                #was  vid1: derived_var( vid=vid1, inputs=[ varnom+'_1', 'hyam_1', 'hybm_1', 'PS_1' ],
                func=verticalize),
            vidl1:
            derived_var(vid=vidl1,
                        inputs=[vid1],
                        func=(lambda z, psl=pselect: select_lev(z, psl)))
        }

        ft1src = filetable1.source()
        #note: the title in the following is parced in customizeTemplate. This is a garbage kludge! Mea culpa.
        varstr = varnom + '(' + PSELECT + ')'
        self.single_plotspecs = {
            self.plot1_id:
            plotspec(
                # was vid = varnom+'_1',
                # was zvars = [vid1],  zfunc = (lambda z: select_lev( z, pselect ) ),
                vid=ps.dict_idid(vidl1),
                zvars=[vidl1],
                zfunc=(lambda z: z),
                plottype=self.plottype,
                title=' '.join([varstr, seasonid, 'model', names['model']]),
                title1=' '.join([varstr, seasonid, 'model', names['model']]),
                title2='model',
                file_descr='model',
                source=names['model'],
                plotparms=plotparms[src2modobs(ft1src)])
        }

        if filetable2 is None:
            self.reduced_variables = {v.id(): v for v in reduced_varlis}
            self.composite_plotspecs = {self.plotall_id: [self.plot1_id]}
            self.computation_planned = True
            return

        if 'hyam' in filetable2.list_variables(
        ) and 'hybm' in filetable2.list_variables():
            # hybrid levels in use, convert to pressure levels
            reduced_varlis += [
                reduced_variable(  # var=var(time,lev,lat,lon)
                    variableid=varnom,
                    filetable=filetable2,
                    season=self.season,
                    reduction_function=(lambda x, vid: reduce_time_seasonal(
                        x, self.season, self.region, vid))),
                reduced_variable(  # hyam=hyam(lev)
                    variableid='hyam',
                    filetable=filetable2,
                    season=self.season,
                    reduction_function=(
                        lambda x, vid=None: select_region(x, self.region))),
                reduced_variable(  # hybm=hybm(lev)
                    variableid='hybm',
                    filetable=filetable2,
                    season=self.season,
                    reduction_function=(
                        lambda x, vid=None: select_region(x, self.region))),
                reduced_variable(  # ps=ps(time,lat,lon)
                    variableid='PS',
                    filetable=filetable2,
                    season=self.season,
                    reduction_function=(lambda x, vid: reduce_time_seasonal(
                        x, self.season, self.region, vid)))
            ]
            #vid2 = varnom+'_p_2'
            #vidl2 = varnom+'_lp_2'
            vid2 = dv.dict_id(varnom, 'p', seasonid, filetable2)
            vid2 = dv.dict_id(vards, 'lp', seasonid, filetable2)
            self.derived_variables[vid2] = derived_var(
                vid=vid2,
                inputs=[
                    rv.dict_id(varnom, seasonid, filetable2),
                    rv.dict_id('hyam', seasonid, filetable2),
                    rv.dict_id('hybm', seasonid, filetable2),
                    rv.dict_id('PS', seasonid, filetable2)
                ],
                func=verticalize)
            self.derived_variables[vidl2] = derived_var(
                vid=vidl2,
                inputs=[vid2],
                func=(lambda z, psl=pselect: select_lev(z, psl)))
        else:
            # no hybrid levels, assume pressure levels.
            #vid2 = varnom+'_2'
            #vidl2 = varnom+'_lp_2'
            vid2 = rv.dict_id(varnom, seasonid, filetable2)
            vidl2 = dv.dict_id(varnom, 'lp', seasonid, filetable2)
            reduced_varlis += [
                reduced_variable(  # var=var(time,lev,lat,lon)
                    variableid=varnom,
                    filetable=filetable2,
                    season=self.season,
                    reduction_function=(lambda x, vid: reduce_time_seasonal(
                        x, self.season, self.region, vid)))
            ]
            self.derived_variables[vidl2] = derived_var(
                vid=vidl2,
                inputs=[vid2],
                func=(lambda z, psl=pselect: select_lev(z, psl)))
        self.reduced_variables = {v.id(): v for v in reduced_varlis}

        try:
            ft2src = filetable2.source()
        except:
            ft2src = ''
        filterid = ft2src.split('_')[-1]  #recover the filter id: kludge
        self.single_plotspecs[self.plot2_id] = plotspec(
            #was vid = varnom+'_2',
            vid=ps.dict_idid(vidl2),
            zvars=[vidl2],
            zfunc=(lambda z: z),
            plottype=self.plottype,
            title=' '.join([varstr, seasonid, 'observation', names['obs']]),
            title1=' '.join([varstr, seasonid, 'observation', names['obs']]),
            title2='observation',
            file_descr='obs',
            source=names['obs'],
            plotparms=plotparms[src2obsmod(ft2src)])
        self.single_plotspecs[self.plot3_id] = plotspec(
            #was vid = varnom+'_diff',
            vid=ps.dict_id(varnom, 'diff', seasonid, filetable1, filetable2),
            zvars=[vidl1, vidl2],
            zfunc=aminusb_2ax,
            plottype=self.plottype,
            title=' '.join([varstr, seasonid, 'difference']),
            title1=' '.join([varstr, seasonid, 'difference']),
            title2='difference',
            file_descr='diff',
            plotparms=plotparms['diff'])
        #                zerocontour=-1 )
        self.composite_plotspecs = {
            self.plotall_id: [self.plot1_id, self.plot2_id, self.plot3_id]
        }
        self.computation_planned = True
Example #40
0
import unidata,numpy

m=unidata.udunits(5,'m')

cm=unidata.udunits(7,'cm')

i=unidata.udunits(3,'in')

f=unidata.udunits(5,'feet')

print m
print cm
print i
print f

dC=unidata.udunits(33,'degC')
dF=unidata.udunits(83,'degF')
dK=unidata.udunits(300,'K')

o = m+cm
print m,'+',cm,'=',o
assert(o.units==m.units)
assert(numpy.allclose(o.value,5.07))


o=cm+i
print cm,'+',i,'=',cm+i
assert(o.units==cm.units)
assert(numpy.allclose(o.value,14.62))
o=i+cm
print i,'+',cm,'=',i+cm