Example #1
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)
Example #2
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
Example #3
0
    def componentsToThreatIndex(self, rh_component, pcpn_component,
                                leaf_wetness_component):
        """
        Dollar Spot utilizes 3-day averages. Therefore, hourly data arrays
        must begin 72 hours before the expected first day in results.

        NOTE: input arrays must be in  the same dimensions

        Arguments:
            rh_component: daily humidity component of threat index
                          calculated using rhumComponent function
            pcpn_component: daily precipition component of threat index
                            calculated using precipComponent function
            leaf_wetness_component: daily leaf wetness compnent
                            calculated using wetnessComponent function

        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: NumPy array containing threat index at each node.
        """
        if self.debug:
            print '\ncalculating average threat index ...'
            print '   rhum component shape :', rh_component.shape
            print ' precip component shape :', pcpn_component.shape
            print 'wetness component shape :', leaf_wetness_component.shape
        # threat index = sum of RH, wetness and consecutive precip factors
        threat_index = rh_component + pcpn_component + leaf_wetness_component

        # average threat index over consecutive days
        offset = self.offsets.threat  # should be 0
        span = self.period.num_days  # should be 3 or 7 days
        step = self.timesteps.threat  # should be 1 day
        # get average threat over last 'span' days
        return funcs.calcTimespanAvg(threat_index, step, span, offset)
Example #4
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
Example #5
0
    def threatIndex(self, first_hour, temp, dewpt, rhum, pcpn, temp_units,
                    pcpn_units):
        """
        Brown Patch utilizes 24 hour averages and counts in order to
        calculate threat index. Therefore, your hourly data arrays
        must begin 24 hours before the expected first day in results.
        
        NOTE: One day is 24 hours ending at 7AM.

        Arguments:
            first_hour: first hour in data arrays (datetime.datetime)
            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:
            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: input arrays must :
              1) have the same dimensions
              2) be dtype=float
              3) have mssing value == N.nan

        Returns: NumPy array with threat index for each node on each day
        """
        mint, avgrh, rh95, wet_count = \
        self.dailyReductions(temp, dewpt, rhum, pcpn, temp_units, pcpn_units)

        # convert avg daily rhum to an index (0,1)
        avgrh_factor = N.zeros(avgrh.shape, '<i2')
        avgrh_factor[N.where(avgrh >= 80)] = 1

        # convert rhum > 95 count to index (0,1,2)
        rh95_factor = N.zeros(rh95.shape, '<i2')
        rh95_factor[N.where(rh95 > 4)] = 1
        rh95_factor[N.where(rh95 >= 8)] = 2

        # convert leaf wetness counts to an index (0,1)
        lwet_factor = N.zeros(wet_count.shape, '<i2')
        lwet_factor[N.where(wet_count >= 10)] = 1

        # convert min temperature to an index (-4, -2, 1)
        mint_factor = N.empty(mint.shape, '<i2')
        mint_factor.fill(-2)  # covers effect of low min temps in season
        # mint_factor = N.zeros(mint.shape, '<i2')
        # always count temps above 16 degrees C whether in season or not
        mint_factor[N.where(mint >= 16)] = 1

        # adjust mint factor using season time span restrictions
        # first/last data day are used filter low min temps out of season
        # do this by filtering temps out of mint by setting them to -4
        # but always count min temps above 16 degrees C (factor == 1)
        first_date = first_hour.date()
        last_date = first_date + datetime.timedelta(days=mint.shape[0] - 1)
        if first_date < self.season_start:
            if last_date < self.season_start:
                mint_factor[N.where(mint_factor != 1)] = -4
            else:
                the_date = first_date
                index = 0
                while the_date < self.season_start:
                    index += 1
                    the_date += ONE_DAY
                # index is for season start
                mint_factor[N.where(mint_factor[:index, :, :] != 1)] = -4

        elif last_date > self.season_end:
            if first_date > self.season_start:
                mint_factor[N.where(mint_factor != 1)] = -4
            else:
                index = 0
                the_date = last_date
                while the_date < self.season_start:
                    the_date += ONE_DAY
                    index += 1
                # index is for  season end
                mint_factor[N.where(mint_factor[index:, :, :] != 1)] = -4

        # threat index is sum of avgrh, rh92, lwet and mint factors
        index = avgrh_factor + rh95_factor + lwet_factor + mint_factor

        # 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, 0)
Example #6
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
Example #7
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)
Example #8
0
    def threatIndex(self, temp, dewpt, pcpn, temp_units, pcpn_units):
        """
        Anhtracnose utilizes 3-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
            precip: hourly precipitation. Default is None
            dewpt: hourly dewpoint temperatures. Default is None
            temp_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. 
            precip_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. 

        Note: Must pass valid array for precip OR dewpt (not both).
              Either may be used estimate the leaf wetness variable
              that is required to calulate Anthracnose threat index.

        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 mssing value == N.nan

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

        if self.debug:
            print '\nAnthracnose.threatIndex :'
            print '         offset :', offset
            print '           span :', span
            print '           step :', step
            print '    temperature :', temp.shape, temp_units
            print '      dew point :', dewpt.shape
            print '         precip :', pcpn.shape, pcpn_units

        if temp.shape[0] < span:
            errmsg = 'Input arrays must contain at least %d hours of data.'
            raise ValueError, errmsg % span

        tmp_units = self.config.units.tmp
        if temp_units == tmp_units: tmp = temp
        else: tmp = convertUnits(temp, temp_units, tmp_units)

        # each day of interest needs average temp for previous 3 days
        avgt = funcs.calcTimespanAvg(tmp, step, span, offset, N.nan)
        if self.debug: print '     avgt shape :', avgt.shape
        avgt_nans = N.where(N.isnan(avgt))

        # each day of interest needs average leaf wetness for previous 3 days
        leaf_wet = self.leafWetness(temp, dewpt, pcpn, tmp_units, pcpn_units)
        wet_count = funcs.countTimespanGT(leaf_wet, 0, step, span, offset) / 3.
        if self.debug:
            print 'wet_count shape :', wet_count.shape
            print '  wet_count min :', N.min(wet_count)
            print '  wet_count max :', N.max(wet_count)

        index = 4.0233 - (wet_count * 0.2283) - (avgt * 0.5308) - \
                         (wet_count**2 * 0.0013) + (avgt**2 * 0.0197) + \
                         (avgt * wet_count * 0.0155 )
        # avoid issues with NimPy runtime warnings
        index[avgt_nans] = -99999. 
        if self.debug: print '    index shape :', index.shape

        index[N.where(avgt < 0)] = -1 # prevent positive index @ temp < 0C
        if self.debug: print '      index < 0 :', len(N.where(index < 0)[0])

        index[avgt_nans] = N.nan
        too_low = N.where(wet_count < 8)
        index[too_low] -= 3
        if self.debug:
            print '      index < 8 :', len(too_low[0])
            print '      index min :', N.nanmin(index)
            print '      index max :', N.nanmax(index)

        span = self.period.num_days
        if self.debug: print 'period.num_days :', span
        if span == 1: return index
        else:
            # get average threat over last 'span' consecutive days
            return funcs.calcTimespanAvg(index, 1, span, 0)