Exemplo n.º 1
0
def leafWetnessFromTemps(temp, dewpt, temp_units='F'):
    # use dewpoint depression as a prozy for leaf wetness
    if temp_units == 'F':
        tdd = temp - dewpt
    else: 
        tmp = convertUnits(temp, temp_units, 'F')
        dpt = convertUnits(dewpt, temp_units, 'F')
        tdd = tmp - dpt

    # need a wetness array filled with zeros for the entire time span
    wetness = N.zeros(tdd.shape, dtype='<i2')
    # array for track whether leaves were wet in a previous iteration
    last_wet = N.zeros(tdd.shape[1:], dtype='<i2')

    # need to process one time period per iteration
    for i in range(tdd.shape[0]):
        # leaves are wet at nodes with dew point depression less than 3 degrees
        where = N.where(tdd[i,:,:] < 3)
        wetness[i][where] = 1

        # add nodes where leaves were wet on previous day
        wetness[i][N.where(last_wet == 1)] = 1

        # track only where dewpoint criteria were met on this day
        last_wet.fill(0) # reset last_wet array to zeros first
        last_wet[where] = 1

    return wetness
Exemplo n.º 2
0
    def threatIndex(self, temp, rhum, precip, tmp_units='C', pcpn_units='in'):
        """
        Dollar Spot utilizes 3-day and 2-day averages and counts in
        order to calculate threat index. Therefore, hourly data arrays
        must begin 72 hours before the expected first day in results.

        NOTE: One day is 24 hours ending at 7AM.

        Arguments:
            temp: hourly temperatures
            rhum: hourly relative humidity
            precip: hourly precipitation
            tmp_units: units for temperature data. Default is 'C'.
                        Calculations require degrees 'C' (Celsius).
                        However, input data in degrees 'K' (Kelvin)
                        or 'F' (Fahrenheit) may be passed and will
                        be converted for use in the calculations. 
            pcpn_units: units for precipitation data. Default is 'in'.
                        Calculations require 'in' (inches of rainfall).
                        However, input data in kilograms per square
                        meter ('kg m**-2' or 'kg^m**-2') may be passed
                        and will be converted to 'in' for use in the
                        calculations. 

        Argument types:
            3D NumPy array : multiple days at multiple points
            2D NumPy array : same day at multiple points
            1D NumPy array : multiple days at single point

        NOTE: input arrays must :
              1) have the same dimensions
              2) be dtype=float
              3) have missing value == numpy.nan

        Returns: NumPy array containing threat index at each node.
        """
        if tmp_units == 'C': tmp = temp
        else: tmp = convertUnits(temp, tmp_units, 'C')
        if self.debug:
            print '\n\nDollarSpot.threatIndex ...'
            print '      hourly temp shape :', tmp.shape
            print '      hourly rhum shape :', rhum.shape
            print '    hourly precip shape :', precip.shape

        if pcpn_units == 'in': pcpn = precip
        else: pcpn = convertUnits(pcpn, pcpn_units, 'in')

        # calulate RH component of threat index
        rhum_component = self.rhumComponent(*self.rhumFactors(rhum, tmp, 'C'))

        # calculate component due to interaction of precip and avg temp
        precip_factors = self.precipFactors(pcpn, tmp, 'in', 'C')
        precip_component = self.precipComponent(*precip_factors[:-1])

        # calculate wet_count factor of threat index
        wetness_component = \
            self.wetnessComponent(*self.wetnessFactors(precip, tmp, 'in', 'C'))

        return self.componentsToThreatIndex(rhum_component, precip_component,
                                            wetness_component)
Exemplo n.º 3
0
def mixingRatio(pressure, dewpt, p_units='hPa', t_units='K'):
    """ calculate mixing ratio
    arguments:
        pressure in millibars (hectopascals)
        dew point in degrees Kelvin
    """
    dpt = convertUnits(dewpt, t_units, 'K')
    p = convertUnits(pressure, p_units, 'hPa')

    e = (0.0000000000253) * N.exp(-5420. / dpt)
    e_pressure = e / 100.
    return ((0.622 * e_pressure) / (p - e_pressure)) * 1000.
Exemplo n.º 4
0
def windChill(speed, temp, s_units='mph', t_units='F'):
    t_type, t = asArray(temp)
    t = convertUnits(t, t_units, 'K')
    s_type, spd = asArray(speed)
    spd = convertUnits(spd, s_units, 'mph')
    if isinstance(t, N.ndarray):
        spd_factor = N.power(spd * 35.75, 0.16)
        tspd_factor = N.power(t * spd * 0.4276, 0.16)
    else:
        spd_factor = math.pow(spd * 35.75, 0.16)
        tspd_factor = math.pow(t * spd * 0.4276, 0.16)

    t_factor = t * 0.6215
    return t_factor - spd_factor + tspd_factor + 35.74
Exemplo n.º 5
0
    def leafWetness(self, temp, dewpt, pcpn, temp_units, pcpn_units):

        # make sure that temperature and dew point units are correct
        tmp_units = self.config.units.tmp
        if temp_units == tmp_units:
            tmp = temp
            dpt = dewpt
        else:
            tmp = convertUnits(temp, temp_units, tmp_units)
            dpt = convertUnits(dewpt, temp_units, tmp_units)

        # dew point depression is one proxy for leaf wetness
        tdd = temp - dewpt

        # make sure that precip units are correct
        precip_units = self.config.units.pcpn
        if pcpn_units == precip_units: precip = pcpn
        else: precip = convertUnits(pcpn, pcpn_units, precip_units)
        # adjustment for minimum effective precipitation
        precip[N.where(precip < self.config.min_precip)] = 0

        # precipitation is the other proxy
        # need a wetness array filled with zeros for the entire time span
        wetness = N.zeros(pcpn.shape, dtype='<i2')
        # array to track whether leaves were wet in a previous iteration
        last_wet = N.zeros(pcpn.shape[1:], dtype='<i2')

        # need to process one time period per iteration
        for i in range(tdd.shape[0]):
            # leaves are wet wherever precip is greater than zero
            pcpn_where = N.where(pcpn[i,:,:] > 0)
            wetness[i][pcpn_where] = 1

            # also include nodes with dew point depression less than 3 degrees
            tdd_where = N.where(tdd[i,:,:] < 3)
            wetness[i][tdd_where] = 1
        
            # add nodes whereever leaves were wet on the previous day
            wetness[i][N.where(last_wet == 1)] = 1

            # track where only where wetness criteria wre met on this day
            last_wet.fill(0) # reset last_wet array to zeros first
            # track where precip criteria were met on this day
            last_wet[pcpn_where] = 1
            # track where dewpoint criteria were met on this day
            last_wet[tdd_where] = 1

        return wetness
Exemplo n.º 6
0
    def mapDataExtremes(self, variable, start_time, end_time, region, debug,
                        **kwargs):
        lons, lats, data_units, data = \
            self.timeSlice(variable, start_time, end_time, lonlat=True)
        map_units = kwargs.get('units', data_units)
        if map_units != data_units:
            data = convertUnits(data, data_units, map_units)

        options = self.mapOptions(variable, start_time, end_time, region)
        title_template = options['title']

        arg_dict = {
            'summary': 'Min',
        }
        options['title'] = title_template % arg_dict
        options['outputfile'] = \
            self.mapFilepath(end_time, variable, region, **arg_dict)
        min_filepath = self.drawScatterMap(lons, lats, N.nanmin(data, axis=0),
                                           start_time, end_time, options,
                                           debug)

        arg_dict = {
            'summary': 'Max',
        }
        options['title'] = title_template % arg_dict
        options['outputfile'] = \
            self.mapFilepath(end_time, variable, region, **arg_dict)
        max_filepath = self.drawScatterMap(lons, lats, N.nanmax(data, axis=0),
                                           start_time, end_time, options,
                                           debug)

        return min_filepath, max_filepath
Exemplo n.º 7
0
    def mapDataTotals(self, variable, start_time, end_time, region, debug,
                      **kwargs):
        lons, lats, data_units, data = \
            self.timeSlice(variable, start_time, end_time, lonlat=True)
        map_units = kwargs.get('units', data_units)
        if map_units != data_units:
            data = convertUnits(data, data_units, map_units)

        options = self.mapOptions(variable, start_time, end_time, region)
        title_template = options['title']

        if variable in ('pcpn', 'PCPN'):
            arg_dict = {
                'summary': 'Accumulated',
            }
        else:
            arg_dict = {
                'summary': 'Total',
            }
        options['title'] = title_template % arg_dict
        options['outputfile'] = \
            self.mapFilepath(end_time, variable, region, **arg_dict)

        return self.drawScatterMap(lons, lats, N.nansum(data, axis=0),
                                   start_time, end_time, options, debug)
Exemplo n.º 8
0
def potentialTemp(temp, pressure, t_units='K', p_units='hPa'):
    """ calculate theta (potential temperature)
    arguments:
        pressure in millibars (hectopascals)
        temperature in degrees Kelvin
    """
    t_type, t = asArray(temp)
    t = convertUnits(t, t_units, 'K')
    if isinstance(t, N.ndarray):
        p_type, p = asArray(pressure)
        p = convertUnits(p, p_units, 'hPa')
        pt = t * N.power((1000. / p), 0.286)
    else:
        p = convertUnits(p, p_units, 'hPa')
        pt = t * math.pow((1000. / p), 0.286)
    return pt
Exemplo n.º 9
0
def dptDepression(temp, rhum, temp_units='K'):
    t_type, t = asArray(temp)
    t = convertUnits(t, t_units, 'K')
    if isinstance(t, N.ndarray):
        rh_type, rh = asArray(rhum)
        dpt = dptFromRhumAndTemp(rh, t, 'K')
    return temp - dewpoint
Exemplo n.º 10
0
 def _postUnpack(self, dataset_path, data, **kwargs):
     to_units = kwargs.get('units', None)
     if to_units is not None:
         from_units = self.getDatasetUnits(dataset_path)
         if from_units is not None:
             data = convertUnits(data, from_units, to_units)
     return data
Exemplo n.º 11
0
def tempToVaporPressure(temp, t_units='K'):
    # calcutate vapor pressure from temperature
    t_type, t = asArray(temp)
    t = convertUnits(t, t_units, 'K')
    if isinstance(t, N.ndarray):
        return E0 * N.exp(LRv * (T0inv - N.power(t, -1.0)))
    else:
        return E0 * N.exp(LRv * (T0inv - (1.0 / t)))
Exemplo n.º 12
0
def dptFromRhum(rhum, temp, t_units='K'):
    rh_type, rh = asArray(rhum)
    # saturation vapor pressure (sat_vp)
    sat_vp = tempToVaporPressure(temp, t_units)
    if isinstance(rh, N.ndarray):
        # actual vapor pressure (vp)
        rh = filterRhum(rh, True)
        vp = (rh * sat_vp) / 100.
        # convert to Rhum and match imcoming units
        return convertUnits(N.power((T0inv - (N.log(vp / E0) / LRv)), -1.0),
                            t_units)
    else:
        if rh <= 0: vp = N.nan
        else: vp = (rh * sat_vp) / 100.
        # convert to Rhum and match imcoming units
        return convertUnits(N.power((T0inv - (math.log(vp / E0) / LRv)), -1.0),
                            t_units)
Exemplo n.º 13
0
def vWind(speed, wdir, s_units='m/s'):
    """ calcualte v (Meridional Velocity) component of wind vector
    """
    s_type, spd = asArray(speed)
    spd = convertUnits(spd, s_units, 'm/s')
    if isinstance(spd, N.ndarray):
        d_type, wdir = asArray(directon)
        return spd * -N.cos(N.radians(wdir))
    else:
        return spd * -math.cos(math.radians(direction))
Exemplo n.º 14
0
def windComponents(speed, wdir, s_units='m/s'):
    s_type, spd = asArray(speed)
    spd = convertUnits(spd, s_units, 'm/s')
    if isinstance(spd, N.ndarray):
        d_type, wdir = asArray(directon)
        u = spd * -N.sin(N.radians(wdir))
        v = spd * -N.cos(N.radians(wdir))
    else:
        u = spd * -math.sin(math.radians(direction))
        v = spd * -math.cos(math.radians(direction))
    return u, v
Exemplo n.º 15
0
def heatIndex(temp, rhum, t_units='F'):
    """ calculate heat index using formulas laid out on NOAA web page
    http://www.hpc.ncep.noaa.gov/html/heatindex_equation.shtml

    arguments:
        temperature in degrees Fahrenheit
        humidity in (as a decimal number 0 to 100)
    """
    t_type, t = asArray(temp)
    t = convertUnits(t, t_units, 'F')
    # sequence was input
    if isinstance(t, N.ndarray):
        rh_type, rh = asArray(rhum)
        # only temps above 80 F may have an associated Heat Index
        indexes = N.where(t >= 80.)
        if len(indexes) > 0 and len(indexes[0]) > 0:
            heat = N.array(t)
            rh80 = rh[indexes]
            rh80_sq = rh80 * rh80
            t80 = t[indexes]
            t80_sq = t80 * t80
            heat[indexes] = (
                -42.379 + (2.04901523 * t80) + (10.14333127 * rh80) +
                (-0.22475541 * t80 * rh80) + (-6.83783e-03 * t80_sq) +
                (-5.481717e-02 * rh80_sq) + (1.22874e-03 * t80_sq * rh80) +
                (8.5282e-04 * t80 * rh80_sq) + (-1.99e-06 * t80_sq * rh80_sq))
            lh_indexes = N.where(rh < 13. & t >= 80. & t <= 112.)
            if len(lh_indexes) > 0 and len(lh_indexes[0]) > 0:
                heat[lh_indexes] -= (((13. - rh[lh_indexes]) / 4.) * N.sqrt(
                    (17. - N.absolute(t[lh_indexes] - 95.)) / 17.))
            hh_indexes = N.where(rh > 85. & t >= 80. & t <= 87.)
            if len(hh_indexes) > 0 and len(hh_indexes[0]) > 0:
                heat[hh_indexes] += (((rh[hh_indexes] - 85.) / 10.) *
                                     ((87. - t[hh_indexes]) / 5.))
            return heat
        # all temps are below 80 F
        else:
            return t

    # assume we got a single value
    if (t < 80): return t
    # only temps above 80 F may have an associated Heat Index
    rh80_sq = rhum * rhum
    t80_sq = t * t
    heat = (-42.379 + (2.04901523 * t) + (10.14333127 * rhum) +
            (-0.22475541 * t * rhum) + (-6.83783e-03 * t80_sq) +
            (-5.481717e-02 * rh80_sq) + (1.22874e-03 * t80_sq * rhum) +
            (8.5282e-04 * t * rh80_sq) + (-1.99e-06 * t80_sq * rh80_sq))
    if rhum < 13. and t >= 80. and t <= 112.:
        heat -= (((13. - rhum) / 4.) * math.sqrt((17. - abs(t - 95.)) / 17.))
    elif rhum > 85. and t >= 80. and t <= 87.:
        heat += (((rhum - 85.) / 10.) * ((87. - t) / 5.))
    return heat
Exemplo n.º 16
0
def leafWetness(precip, temp, dewpt, pcpn_units='in', temp_units='F'):
    if pcpn_units == 'in': pcpn = precip
    else: pcpn = convertUnits(precip, pcpn_units, 'in')

    # use dewpoint depression as a prozy for leaf wetness
    if temp_units == 'F':
        tdd = temp - dewpt
    else: 
        tmp = convertUnits(temp, temp_units, 'F')
        dpt = convertUnits(dewpt, temp_units, 'F')
        tdd = tmp - dpt

    # need a wetness array filled with zeros for the entire time span
    wetness = N.zeros(pcpn.shape, dtype='<i2')
    # array to track whether leaves were wet in a previous iteration
    last_wet = N.zeros(pcpn.shape[1:], dtype='<i2')

    # need to process one time period per iteration
    for i in range(tdd.shape[0]):
        # leaves are wet wherever precip is greater than zero
        pcpn_where = N.where(pcpn[i,:,:] > 0)
        wetness[i][pcpn_where] = 1

        # also include nodes with dew point depression less than 3 degrees
        tdd_where = N.where(tdd[i,:,:] < 3)
        wetness[i][tdd_where] = 1
        
        # add nodes whereever leaves were wet on the previous day
        wetness[i][N.where(last_wet == 1)] = 1

        # track where only where wetness criteria wre met on this day
        last_wet.fill(0) # reset last_wet array to zeros first
        # track where precip criteria were met on this day
        last_wet[pcpn_where] = 1
        # track where dewpoint criteria were met on this day
        last_wet[tdd_where] = 1

    return wetness
def updateDataGrids(factory, utc_time, filepath, debug):
    # get a reader for the grib file
    Class = factory.fileAccessorClass('grib', 'read')
    reader = Class(filepath, factory.grib_source)
    # update temp
    tmp_units, temp = extractData(factory, reader, 'TMP', debug)
    updateGridFile(factory, 'TMP', utc_time, temp, tmp_units, debug)
    # update dew point
    dpt_units, dewpt = extractData(factory, reader, 'DPT', debug)
    updateGridFile(factory, 'DPT', utc_time, dewpt, dpt_units, debug)
    # update humidity
    if dpt_units != tmp_units: dpt = convertUnits(dpt, dpt_units, tmp_units)
    rhum = N.around(rhumFromDpt(temp, dewpt, tmp_units), 2)
    updateGridFile(factory, 'RHUM', utc_time, rhum, '%', debug)
Exemplo n.º 18
0
def equivPotentialTemp(temp, dewpt, pressure, t_units='K', p_units='hpa'):
    """ calculate theta e (equivalent potential temperature)
    arguments:
        pressure in millibars (hectopascals)
        temperature in degrees Kelvin
        dew point in degrees Kelvin
    """
    t_type, t = asArray(temp)
    t = convertUnits(t, t_units, 'K')
    if isinstance(t, N.ndarray):
        dpt_type, dpt = asArray(dewpt)
        dpt = convertUnits(dpt, t_units, 'K')
        p_type, p = asArray(pressure)
        p = convertUnits(p, p_units, 'hPa')
        pt = t * N.power((1000. / p), 0.286)
        mix_ratio = mixingRatio(p, t, dpt) / 1000.
        ept = pt * N.exp((0.00000250 * mix_ratio) / (1005. * t))
    else:
        dpt = convertUnits(dewpt, t_units, 'K')
        p = convertUnits(pressure, p_units, 'hPa')
        pt = t * math.pow((1000. / p), 0.286)
        mix_ratio = mixingRatio(p, t, d) / 1000.
        ept = pt * math.exp((0.00000250 * mix_ratio) / (1005. * t))
    return ept
Exemplo n.º 19
0
    def threatIndex(self, temp, rhum, temp_units='F'):
        """
        Pithium Blight utilizes 2-day averages and counts in order to
        calculate threat index. Therefore, hourly data arrays must
        begin at least 48 hours before the first day in results.

        NOTE: One day is 24 hours ending at 7AM.

        Arguments:
          temp: hourly temperatures
          rhum: hourly relative humidity
          temp_units: units for temperature array. Default is 'F'.
                      Calculations require degrees 'F' (Fahrenheit).
                      However, input data in degrees 'C' (Celsius)
                      or 'K' (Kelvin) may be passed and will be
                      converted to'F' for use in calculations. 

        Supported types for temp and rhum data:
            3D NumPy array : multiple days at multiple points
            2D NumPy array : snme day at multiple points
            1D NumPy array : multiple days at single point

        NOTE: temp and rhum arrays must :
              1) have the same dimensions
              2) be dtype=float
              3) have mssing value == N.nan

        Returns: NumPy array containing daily threat index at each node.
        """
        span = self.config.timespan  # number of hours to evaluate per iteration
        step = self.config.timestep  # number of hours to increment b/w interations

        if temp_units == 'F': tmp = temp
        else: tmp = convertUnits(temp, temp_units, 'F')

        maxt = funcs.calcTimespanMax(tmp, step, span)
        mint = funcs.calcTimespanMin(tmp, step, span)
        rh89 = funcs.countTimespanGT(rhum, 89, step, span)

        index = (maxt - 86) + (mint - 68) + (0.5 * (rh89 - 6))

        # average threat index over consecutive days
        span = self.period.num_days  # should be 3 or 7 days
        # get average threat over last 'span' days
        return funcs.calcTimespanAvg(index, 1, span, 0)
Exemplo n.º 20
0
    def rhumFactors(self, rhum, temp, tmp_units='C'):
        """
        Calculate the threat factors contributed by the interaction
        of relative humidity and temperature.

        NOTE: input arrays must be dtype=float with missing value=NaN

        Arguments:
            rhum: hourly relative humidity
            temp: hourly temperature 
            tmp_units: units for temperature data. Default is 'C'.
                        Calculations require degrees 'C' (Celsius).
                        However, input data in degrees 'K' (Kelvin)
                        or 'F' (Fahrenheit) may be passed and will
                        be converted for use in the calculations. 

        Argument types:
            3D NumPy array : multiple hours for multiple grid nodes
            2D NumPy array : multiple hours at multple points
            1D NumPy array : multiple hours at single point

        Returns : tuple
            tuple[0] 
            tupke[1]
        """
        if self.debug: print '\n  in rhumFactors ...'

        # offset for humidity factors
        offset = self.offsets.rh_factors  # should be 0
        span = self.timespans.rh_factors  # should be 24 hours
        step = self.timesteps.rh_factors  # should be 24 hours

        # calculate daily avg temp for use in max_rh factor
        if tmp_units == 'C': tmp = temp
        else: tmp = convertUnits(temp, tmp_units, 'C')
        avgt = funcs.calcTimespanAvg(tmp, step, span, offset)
        if self.debug:
            print '         avg temp shape :', avgt.shape

        max_rh = funcs.calcTimespanMax(rhum, step, span, offset)
        if self.debug:
            print '           max rh shape :', max_rh.shape

        return max_rh, avgt, 'C'  # avgt units
Exemplo n.º 21
0
def leafWetnessFromPrecip(precip, pcpn_units='in'):
    if pcpn_units == 'in': pcpn = precip
    else: pcpn = convertUnits(precip, pcpn_units, 'in')

    # need empty wetness array for entire time span
    wetness = N.zeros(pcpn.shape, dtype='<i2')
    # track whether leaves were wet in an iteration
    last_wet = N.zeros(pcpn.shape[1:], dtype='<i2')

    # need to process one time period per iteration
    for i in range(pcpn.shape[0]):
        # leaves are wet wherever precip greater than zero
        where = N.where(pcpn[i,:,:] > 0)
        wetness[i][where] = 1

        # add nodes whereever leaves were wet on the previous day
        wetness[i][N.where(last_wet == 1)] = 1

        # track only where precip criteria were met on this day
        last_wet.fill(0)  # reset last_wet array to zeros first
        last_wet[where] = 1

    return wetness
Exemplo n.º 22
0
    def stressHours(self, temp, rhum, temp_units='F'):
        """
        Heat Stress utilizes 12 hour data summaries to calculate
        daily stress hours. A "day" is 12 hours ending at 7AM.

        NOTE: Hourly data arrays must contain full 24 hour sequences
        beginning 12 hours before the expected first day in results.

        Arguments:
            temp: hourly temperatures for 24 hours
            rhum: hourly relative humidity 24 hours
            temp_units: units for temperature data. Default is 'F'.
                        Calculations require degrees 'F' (Fahrenheit)
                        However, input data in degrees 'C' (Celsius).
                        or 'K' (Kelvin) may be passed and will
                        be converted for use in the calculations. 

        Argument types:
            3D NumPy array : multiple days at multiple points
            2D NumPy array : same day at multiple points
            1D NumPy array : multiple days at single point

        NOTE: all arguments must be the same type and have the same dimensions

        Returns: NumPy array containing daily stress hours at each node.
        """
        # number of hours to skip before starting iteration
        offset = self.config.offset
        # number of hours to evaluate per iteration
        span = self.config.timespan
        # number of hours to increment b/w interations
        step = self.config.timestep

        if temp_units == 'F': tmp = temp
        else: tmp = convertUnits(temp, temp_units, 'F')

        # need sum of temp and rhum for 2nd part of index
        trh = tmp + rhum

        # need to know the number of hours where tmp >= 70 & trh > 150
        # so create a count array that is the same size as tmp & trh
        stress_hours = N.zeros(tmp.shape, dtype='<i2')

        # Need to create separate tmp stress and trh stress conditions
        # because NumPy cannot handle N.where(tmp >= 70 & trh > 150).
        # It often throws TypeError with message "truth value of an
        # array with more than one element is ambiguous"
        thresholds = self.config.stress_thresholds

        # filter annoying NumPy/SciPy warnings
        warnings.filterwarnings('ignore', "All-NaN axis encountered")
        warnings.filterwarnings('ignore', "All-NaN slice encountered")
        warnings.filterwarnings('ignore',
                                "invalid value encountered in greater")
        warnings.filterwarnings('ignore',
                                "invalid value encountered in greater_equal")

        # set nodes where temp threshold is met
        stress_hours[N.where(tmp >= thresholds.temp)] = 1
        # now add nodes where trh threshold is met so that
        stress_hours[N.where(trh > thresholds.rhum)] += 1

        # turn annoying NumPy/SciPy warnings back on
        warnings.resetwarnings()

        # stress_hours == 2 when N.where(tmp >= 70 & trh > 150)
        return countTimespanEQ(stress_hours, 2, step, span, offset)
Exemplo n.º 23
0
        print 'Repaired data for %s with data from grib file %s' % info
        # turn annoying numpy warnings back on before exiting
        warnings.resetwarnings()
        exit()
    reasons.append('    grib file for missing hour contains no valid data')
else:
    reasons.append('    no grib file found for missing hour')
    prev_time = repair_time - ONE_HOUR
    success, info = factory.dataFromGrib(file_variable,
                                         prev_time,
                                         return_units=True)
    if success:
        units, data = info
        if len(N.where(N.isfinite(data))[0]) > 0:
            if units != grid_units:
                prev_data = convertUnits(data, units, grid_units)
            else:
                prev_data = data
        else:
            reasons.append(
                '    grib file for previous hour contains no valid data')
    else:
        reasons.append('    no grib file found for previous hour')

    next_time = repair_time + ONE_HOUR
    success, info = factory.dataFromGrib(file_variable,
                                         next_time,
                                         return_units=True)
    if success:
        units, data = info
        if len(N.where(N.isfinite(data))[0]) > 0:
Exemplo n.º 24
0
    def rhumComponent(self, max_rh, avg_temp, tmp_units='C'):
        """
        Calculate a the threat factor contributed by the interaction
        of relative humidity and temperature.

        Arguments:
            rhum: daily maximum relative humidity
            avg_temp: daily average temprature for each day in max_rh.
            tmp_units: units for average temperature data. Default is
                       'C'.  Calculations require degrees 'C' (Celsius).
                       However, input data in degrees 'K' (Kelvin)
                       or 'F' (Fahrenheit) may be passed and will
                       be converted for use in the calculations. 

        Argument types:
            3D NumPy array : multiple hours for multiple grid nodes
            2D NumPy array : multiple hours at multple points
            1D NumPy array : multiple hours at single point

        NOTE: input arrays must :
              1) be dtype=float
              2) have missing value == NaN

        Returns :
            int NumPy array containing rh/temp component
                    at each node.
                
            else: returns tuple = (rh_factor, avg_temp) 
                [0] int NumPy array containing rh/temp factor at each node.
                [1] float NumPy array average temperature array used to
                    calculate the rh factor (in degress C).
        """
        if self.debug:
            print '\n  in rhumComponent ...'
            print '           max_rh shape :', max_rh.shape
            print '             avgt shape :', avg_temp.shape

        if tmp_units == 'C': avgt = avg_temp
        else: avgt = convertUnits(avg_temp, tmp_units, 'C')

        # Need to create separate avg temp and max_rh components because
        # NumPy cannot handle N.where(max_rh > 90 & avg_temp > 25). It often
        # throws TypeError with message "ufunc 'bitwise_and' not supported
        # for the input types, and the inputs could not be safely coerced
        # to any supported types according to the casting rule ''safe''"
        #
        # daily average temp factor - 1 means condition was met
        avgt_factor = N.zeros(avgt.shape, '<i2')
        avgt_factor[N.where(avgt > 25)] = 1
        # daily max_rh factor - 1 means condition was met
        maxrh_factor = N.zeros(max_rh.shape, '<i2')
        maxrh_factor[N.where(max_rh > 90)] = 1

        # daily composite of max_rh and avg_temp factors
        # maxrh_avgt == 2 is where here max_rh > 90 & avg_temp > 25
        maxrh_avgt = avgt_factor + maxrh_factor
        if self.debug:
            print '     maxrh & avgt shape :', maxrh_avgt.shape

        # RH componet is number of days that maxrh_avgt has value of 2
        offset = self.offsets.maxrh_avgt_count  # should be 0
        span = self.timespans.maxrh_avgt_count  # should be 7 days
        step = self.timesteps.maxrh_avgt_count  # should be 1
        # maxrh_avgt == 2 is where here max_rh > 90 & avg_temp > 25
        maxrh_avgt_count = funcs.countTimespanEQ(maxrh_avgt, 2, step, span,
                                                 offset, '<i2')
        if self.debug:
            print ' maxrh avgt count shape :', maxrh_avgt_count.shape
            num_nans = len(N.where(N.isnan(avgt))[0])
            print '    maxrh_avgt_count NaN :', num_nans
            num_nodes = len(N.where(maxrh_avgt_count == 0)[0]) - num_nans
            print '    maxrh_avgt_count = 0 :', num_nodes
            for n in range(1, N.max(maxrh_avgt_count) + 1):
                num_nodes = len(N.where(maxrh_avgt_count == n)[0])
                print '    maxrh_avgt_count = %d : %d' % (n, num_nodes)

        # RH componet is 1 where maxrh_avgt_count >= threshold
        threshold = self.count_thresholds.rh_component
        rh_component = N.zeros(maxrh_avgt_count.shape, dtype=float)
        # account for NaN in the original data
        # assumes all days have NaN at the same nodes
        nans = N.where(N.isnan(avgt[0, :, :]))
        for day in range(rh_component.shape[0]):
            rh_component[day][nans] = N.nan

        rh_component[N.where(maxrh_avgt_count >= threshold)] = 1
        if self.debug:
            print '     rh_component shape :', maxrh_avgt_count.shape

        return rh_component
Exemplo n.º 25
0
    def consecPcpnAvgt(self, rain_count, avg_temp, tmp_units='C'):
        """
        Utilizes daily rain counts to determine the number of
        consecutive days with precipitation. Input data must contain
        hourly precipitation for a minimum of 5 days before data 
        reduction can begin. For example, 120 hours of data will
        return number of consectuive days with precip for 1 day,
        144 hours will return results for 2 days, etc.

        Arguments:
            rain_count: daily count of hours with precipitation
            avg_temp: daily average temprature for same days as 
                      rain_count
            tmp_units: units for temperature data. Default is 'C'.
                       Calculations require degrees 'C' (Celsius).
                       However, input data in degrees 'K' (Kelvin)
                       or 'F' (Fahrenheit) may be passed and will
                       be converted for use in the calculations.

        Data argument types:
            3D NumPy array : multiple days at multiple points
            2D NumPy array : same day at multiple points
            1D NumPy array : multiple days at single point

        NOTE: input arrays must :
              1) have the same dimensions
              2) be dtype=float
              3) have missing value == N.nan

        Returns: 
              1) NumPy array containing counts of consecutive days of
                 precipitation for each day at each node.
              2) NumPy array containing average temperatures on days
                 with precipitaton
        """
        # capture avg_tmp for each consecutive day of rain
        if tmp_units == 'C': avgt = avg_temp
        else: avgt = convertUnits(avg_temp, tmp_units, 'C')
        if self.debug:
            print '\n  in consecPcpnAvgt ...'
            print '             avgt shape :', avgt.shape

        # determine number of consecutive previous days with rain
        offset = self.offsets.consec_rain
        span = self.timespans.consec_rain
        step = self.timesteps.consec_rain
        threshold = self.count_thresholds.wet_count
        consec_rain = funcs.countTimespanGE(rain_count, threshold, step, span,
                                            offset, '<i2')
        if self.debug:
            print '\n  in consecPcpnAvgt ...'
            print '      consec rain shape :', consec_rain.shape
            for day in range(consec_rain.shape[0]):
                print '    day :', day
                for n in range(threshold, span + 1):
                    num_nodes = len(N.where(consec_rain[day, :, :] == n)[0])
                    print '      %d consec days rain : %d' % (n, num_nodes)

        # because consecutive rain is for the 5 previous days,
        # the result in consec_rain is 1 day too long
        consec_rain = consec_rain[1:, :, :]
        consec_avgt = N.zeros(consec_rain.shape, dtype=float)
        consec_avgt[N.where(N.isnan(consec_rain))] = N.nan
        avg_tmp_sum = N.zeros(consec_rain.shape[1:], dtype=float)

        for rain_day in range(offset, consec_rain.shape[0]):
            consec_days = 0
            avg_tmp_sum.fill(0)
            avg_tmp_sum[N.where(N.isnan(consec_rain[rain_day, :, :]))] = N.nan

            # loop thru max previous days with rain
            for day_num in range(span):
                day = rain_day - day_num
                if day < 0: break
                count = day_num + 1
                # look for nodes with rain
                where = N.where(consec_rain[day, :, :] >= count)
                if len(where[0]) > 0:  # rain_found
                    consec_days += 1
                    avg_tmp_sum[where] += avgt[day][where]
                    # must have a least 2 consecutive days of rain
                    if consec_days > 1:
                        consec_avgt[rain_day][where] = \
                                    avg_tmp_sum[where] / consec_days

        return consec_rain, consec_avgt
def repairOneHour(factory, manager, repair_time, variable, grib_region):
    success, info = factory.dataFromGrib(file_variable, repair_time, return_units=True)
    if success:
        units, data = info
        if len(N.where(N.isfinite(data))[0]) > 0:
            manager.open('a')
            manager.updateReanalysisData(reanalysis, file_variable, repair_time, data, units=units)
            manager.close()
            grib_filename = factory.gribFilename(repair_time, file_variable, grib_region)
            info = (repair_time.strftime('%Y-%m-%d:%H'), grib_filename)
            return 'Repaired data for %s with data from grib file %s' % info
        else: reasons.append('    grib file for missing hour contains no valid data')
    else:
        reasons.append('    no grib file found for missing hour')
        prev_time = repair_time - ONE_HOUR
        manager.open('r')
        grid_units = manager.datasetAttribute(file_variable, 'units')
        manager.close()
        success, info = factory.dataFromGrib(file_variable, prev_time, return_units=True)
        if success:
            units, data = info
            if len(N.where(N.isfinite(data))[0]) > 0:
                if units != grid_units: prev_data = convertUnits(data, units, grid_units)
                else: prev_data = data
            else: reasons.append('    grib file for previous hour contains no valid data')
        else: reasons.append('    no grib file found for previous hour')
    
        next_time = repair_time + ONE_HOUR
        success, info = factory.dataFromGrib(file_variable, next_time, return_units=True)
        if success:
            units, data = info
            if len(N.where(N.isfinite(data))[0]) > 0:
                if units != grid_units: next_data = convertUnits(data, units, grid_units)
                else: next_data = data
            else: reasons.append('    grib file for next hour contains no valid data')
        else: reasons.append('    no grib file found for next hour')

    if prev_data is None:
        prev_time = repair_time - ONE_HOUR
        manager.open('r')
        data = manager.dataForHour(file_variable, prev_time)
        manager.close()
        if len(N.where(N.isfinite(data))[0]) > 0: prev_data = data
        else: reasons.append('    grid file contains missing data for previous hour')

    if next_data is None:
        next_time = repair_time - ONE_HOUR
        manager.open('r')
        next_data = manager.dataForHour(file_variable, next_time)
        manager.close()
        if len(N.where(N.isfinite(data))[0]) > 0: next_data = data
        else: reasons.append('    grid file contains missing data for next hour')

    if prev_data is not None and next_data is not None:
        fudge = (prev_data + next_data) / 2.
        manager.open('a')
        manager.insertFudgedData(file_variable, repair_time, fudge)
        manager.close()
        msg = 'Data for %s @ %s was interpolated using data from previous and next hours'
        return msg % (file_variable, repair_time.strftime('%Y-%m-%d:%H'))

    return reasons
                print 'ERROR : time in TMP file and DPT file are out of sync for'
                interval = (slice_start.strftime('%Y-%m-%d:%H'), slice_end.strftime('%Y-%m-%d:%H'))
                print '        interval %s to %s' % interval
                print 'Further processing is not possible'
                continue

            tmp_reader.open()
            tmp = tmp_reader.timeSlice('TMP', slice_start, slice_end)
            tmp_units = tmp_reader.datasetAttribute('TMP','units')
            tmp_reader.close()

            dpt_reader.open()
            dpt = dpt_reader.timeSlice('DPT', slice_start, slice_end)
            dpt_units = dpt_reader.datasetAttribute('DPT','units')
            dpt_reader.close()
            if dpt_units != tmp_units: dpt = convertUnits(dpt, dpt_units, tmp_units)
 
            rhum = N.around(rhumFromDpt(tmp, dpt, tmp_units), 2)
            num_hours = rhum.shape[0]

            manager.open('a')
            manager.updateReanalysisData(analysis, 'RHUM', slice_start, rhum)
            manager.close()

            if verbose:
                skip = ('end_time', 'start_time', 'timezone', 'tzinfo')
                print '\nUpdated time attributes for RHUM dataset :'
                manager.open('r')
                for time_key, hour in manager.timeAttributes('RHUM').items():
                    if not time_key in skip:
                        print '    %s = %s' % (time_key, hour.strftime('%Y-%m-%d:%H'))
Exemplo n.º 28
0
    def precipFactors(self,
                      pcpn,
                      temp,
                      pcpn_units='in',
                      tmp_units='C',
                      return_count=False):
        """
        Calculate the individual threat factors contributed by the
        interaction of consecutive days of precipitation and the
        corresponding average temperature on those days.

        NOTE: input arrays must :
              1) have the same dimensions
              2) be dtype=float
              3) have missing value = numpy.nan

        Arguments:
            pcpn: hourly precipitation
            temp: houry temprature 
            pcpn_units: units for precipitation data. Default is 'in'.
                        Calculations require 'in' (inches of rainfall).
                        However, input data in kilograms per square
                        meter ('kg m**-2' or 'kg^m**-2') may be passed
                        and will be converted to 'in' for use in the
                        calculations. 
            tmp_units: units for temperature data. Default is 'C'.
                        Calculations require degrees 'C' (Celsius).
                        However, input data in degrees 'K' (Kelvin)
                        or 'F' (Fahrenheit) may be passed and will
                        be converted for use in the calculations.
            return_count: boolean, whete to include daily counts
                           of hours with rain in results

        Argument types:
            3D NumPy array : multiple hours for multiple grid nodes
            2D NumPy array : multiple hours at multple points
            1D NumPy array : multiple hours at single point

        Returns : tuple containing the following items
            tuple[0] = int NumPy array containing number of consecutive
                       days of rain for each day at each node.
            tuple[1] float NumPy array containing the average temperature
                     over the consecutive days of rain for each day at
                     each node.
            tiple[2] units for average temperature data

            if return_count == Ture, tuple also includes:
               tuple[3] = int NumPy array containing the number of hours
                          of rain for each day at each node. This array
                          will contain 6 more days than the other arrays
        """
        if pcpn_units == 'in': precip = pcpn
        else: precip = convertUnits(pcpn, pcpn_units, 'in')
        # adjustment for minimum effective precipitation
        precip[N.where(precip < self.config.min_precip)] = 0

        if tmp_units == 'C': tmp = temp
        else: tmp = convertUnits(temp, tmp_units, 'C')
        if self.debug:
            print '\n  in precipFactors ...'
            print '           precip shape :', pcpn.shape
            print '             temp shape :', tmp.shape

        # offset, time span and time step for avg temp and rain counts
        offset = self.offsets.rain_count
        span = self.timespans.rain_count
        step = self.timesteps.rain_count
        threshold = self.count_thresholds.rain_count
        # calculate the daily average temps for the days needed
        avg_temp = funcs.calcTimespanAvg(tmp, step, span, offset)
        # rain_count = number of hours with rain on each day
        rain_count = \
            funcs.countTimespanGT(precip, threshold, step, span, offset)

        if self.debug:
            print '     average temp shape :', avg_temp.shape
            print '       rain count shape :', rain_count.shape

        # get a solver for consecutive days of rain and the average temp
        ndims = len(avg_temp.shape)
        if ndims == 3:
            solver = DollarSpot3D(self.period, self.debug)
        else:
            raise TypeError, '%dD arrays are not currently supported' % ndims

        # get counts of consecutive days of rain and the average temp
        # over those days
        consec_rain, consec_avgt = \
            solver.consecPcpnAvgt(rain_count, avg_temp, 'C')
        if self.debug:
            print '\n    solver results ...'
            print '      consec rain shape :', consec_rain.shape
            print '      consec avgt shape :', consec_avgt.shape

        results = [consec_rain, consec_avgt, 'C']
        if return_count: result.append(rain_count)
        return tuple(results)
Exemplo n.º 29
0
    def dailyReductions(self, temp, dewpt, rhum, pcpn, temp_units, pcpn_units):
        """
        Brown Patch utilizes 24 hour data reductions to calculate 
        threat index. Therefore, hourly data arrays must begin 48
        hours before the expected first day in results.
        
        NOTE: One day is 24 hours ending at 7AM.

        Arguments:
            temp: hourly temperatures.
            dewpt: hourly dewpoint temperatures.
            rhum: hourly relative humidity
            pcpn: hourly precipitation.
            temp_units: units for temperature and dew point arrays.
                        Calculations require degrees 'C' (Celsius),
                        however, input data in degrees 'K' (Kelvin)
                        or 'F' (Fahrenheit) may be passed and will be
                        converted to 'C' for use in the calculations. 
            pcpn_units: units for precipitation data.
                        Calculations require 'in' (inches of rainfall).
                        Data in other units may be passed and will be 
                        converted to 'in' for use in the calculations. 

        Argument types:ple days at multiple points
            2D NumPy array : snme day at multiple points
            1D NumPy array : multiple days at single point

        NOTE: input arrays must :
              1) have the same dimensions
              2) be dtype=float
              3) have mssing value == N.nan

        Returns: NumPy arrays for the following daily reductions:
                 1) minimum temp
                 2) average rhum
                 3) num hours of leaf wetness 
        """
        # number of hours to skip before starting iteration
        offset = self.config.offset
        # number of hours to evaluate per iteration
        span = self.config.timespan
        # number of hours to increment b/w interations
        step = self.config.timestep

        # make sure that temperature and dew point units are correct
        tmp_units = self.config.units.tmp
        if temp_units == tmp_units:
            tmp = temp
            dpt = dewpt
        else:
            tmp = convertUnits(temp, temp_units, tmp_units)
            dpt = convertUnits(dewpt, temp_units, tmp_units)

        # calculate minimum daily temp
        mint = funcs.calcTimespanMin(tmp, step, span, offset, N.nan)
        if self.debug:
            print '\n  in dailyReductions ...'
            print '             temp shape :', tmp.shape
            print '         min temp shape :', mint.shape

        # calculate average daily humidity
        avgrh = funcs.calcTimespanAvg(rhum, step, span, offset, N.nan)
        if self.debug:
            print '     avg humidity shape :', avgrh.shape

        # count daily rhum > threshold
        threshold = self.config.rh_threshold
        rh_count = funcs.countTimespanGT(rhum, threshold, step, span, offset)
        if self.debug:
            print '           rh threshold :', threshold
            print '         rh count shape :', rh_count.shape

        # get hourly leaf wetness
        leaf_wet = self.leafWetness(tmp, dpt, pcpn, tmp_units, pcpn_units)
        if self.debug:
            stats = (N.nanmin(leaf_wet), N.nanmean(leaf_wet),
                     N.nanmedian(leaf_wet), N.nanmax(leaf_wet))
            print '         leaf wet stats :', stats
        # count number of hours with leaf wetness
        wet_count = funcs.countTimespanGT(leaf_wet, 0, step, span, offset)
        if self.debug:
            print '              wet count :', wet_count.shape

        return mint, avgrh, rh_count, wet_count
Exemplo n.º 30
0
    def wetnessFactors(self, precip, temp, pcpn_units='in', tmp_units='C'):
        """
        Calculate a the threat factor contributed by the interaction
        of leaf wetness and temperature.

        NOTE: inputs must be NumPy float arrays with the same dimensions
              and missing value = nan

        Arguments:
            precip: hourly precipitation
            temp: hourly temprature for same hours as precip
            tmp_units: units for temperature data. Default is 'C'.
                       Calculations require degrees 'C' (Celsius).
                       However, input data in degrees 'K' (Kelvin)
                       or 'F' (Fahrenheit) may be passed and will
                       be converted for use in the calculations. 
            pcpn_units: units for precipitation data. Default is 'in'.
                        Calculations require 'in' (inches of rainfall).
                        However, input data in kilograms per square
                        meter ('kg m**-2' or 'kg^m**-2') may be passed
                        and will be converted to 'in' for use in the
                        calculations. 

        Argument types:
            3D NumPy array : multiple hours for multiple grid nodes
            2D NumPy array : multiple hours at multple points
            1D NumPy array : multiple hours at single point

        Returns : tuple of arrays
            tuple[0] = int NumPy array 
                       daily count of hours with leaf wetness at each node.
            tuple[1] = float NumPy array
                       average daily temp for each day in leaf wetnes array
        """
        if self.debug: print '\n  in wetnessFactors ...'
        # make sure that input precip is in the correct units
        if pcpn_units == 'in': pcpn = precip
        else: pcpn = convertUnits(precip, pcpn_units, 'C')
        if self.debug: print '             pcpn shape :', pcpn.shape

        # make sure that input temps are in the correct units
        if tmp_units == 'C': tmp = temp
        else: tmp = convertUnits(temp, tmp_units, 'C')
        if self.debug: print '             temp shape :', tmp.shape

        # get mask-like array with 1 in each hour with wetness
        leaf_wetness = leafWetnessFromPrecip(pcpn, 'in')
        if self.debug: print '     leaf wetness shape :', leaf_wetness.shape

        # offset, span, step for wet_count
        offset = self.offsets.wet_count  # should skip first 4 days (96 hours)
        span = self.timespans.wet_count  # should 3 days (72 hours)
        step = self.timesteps.wet_count  # 24 hours
        threshold = self.count_thresholds.wet_count
        # count number of hours of leaf wetness per day
        wet_count = funcs.countTimespanEQ(leaf_wetness, threshold, step, span,
                                          offset, '<i2')
        if self.debug: print '    wetness count shape :', wet_count.shape

        span = 24
        step = 24

        wet_avgt = funcs.calcTimespanAvg(tmp, step, span, offset)
        if self.debug: print '     wetness avgt shape :', wet_avgt.shape

        if wet_count.shape[0] < wet_avgt.shape[0]:
            diff = wet_avgt.shape[0] - wet_count.shape[0]
            wet_avgt = wet_avgt[diff:, :, :]
            if self.debug:
                print '\n wetness avgt adjust to match wetness count'
                print '     new wetness avgt shape :', wet_avgt.shape

        return wet_count, wet_avgt