def test_moving_sum(self):
        """Test moving_sum calculation."""
        start_date = datetime(year=2011, month=9, day=6)
        end_date = datetime(year=2011, month=9, day=8)

        td_step = timedelta(hours=24)

        generate_values_kwargs = {'dt_start': start_date,
                                  'dt_stop': end_date,
                                  'td_step': td_step,
                                  'unit': 'AnyUnit',
                                  'value': 1}

        # Make start_date and end_date tz aware, just as in rain_stats from
        # adapter
        start_date = UTC.localize(start_date)
        end_date = UTC.localize(end_date)

        moving_sum_kwargs = {
            'values': generate_values(**generate_values_kwargs),
            'td_window': timedelta(hours=1),
            'td_value': td_step,
            'start_date_utc': start_date,
            'end_date_utc': end_date}

        # 24 hour data and a 1 hour window, there should be no max_values
        self.assertEqual(len(moving_sum(**moving_sum_kwargs)), 0)

        # 3 values of 24 hour data and a 24 hour window, there will be 3
        # max_values of 1 each
        moving_sum_kwargs['td_window'] = timedelta(days=1)
        self.assertEqual(len(moving_sum(**moving_sum_kwargs)), 3)

        # if there are more values before and after the window, they are
        # neglected.
        generate_values_kwargs['dt_start'] -= timedelta(days=2)
        generate_values_kwargs['dt_stop'] += timedelta(days=2)
        moving_sum_kwargs['values'] = generate_values(**generate_values_kwargs)
        self.assertEqual(len(moving_sum(**moving_sum_kwargs)), 3)

        # if the values are offset compared to the daterange by
        # some hours, only 2 values fit within the daterange that is
        # exactly two calendar days.
        generate_values_kwargs['dt_start'] -= timedelta(hours=7)
        generate_values_kwargs['dt_stop'] += timedelta(hours=7)
        moving_sum_kwargs['values'] = generate_values(**generate_values_kwargs)
        self.assertEqual(len(moving_sum(**moving_sum_kwargs)), 2)

        # A 48 hour window should reveal at least the maximum of 2,
        # which is the sum of two 24 hour values of 1
        moving_sum_kwargs['td_window'] = timedelta(days=2)
        ms = moving_sum(**moving_sum_kwargs)
        sums = [m['value'] for m in ms]
        self.assertEqual(max(sums), 2)
Exemplo n.º 2
0
    def rain_stats(self,
                   values,
                   area_km2,
                   td_window,
                   start_date_utc,
                   end_date_utc):
        """Calculate stats.

        Expects utc, returns site timezone datetimes... Sorry."""

        logger.debug(('Calculating rain stats for' +
                      'start=%s, end=%s, td_window=%s') %
                     (start_date_utc, end_date_utc, td_window))
        if not values:
            return {
                'td_window': td_window,
                'max': None,
                'start': None,
                'end': None,
                't': self._t_to_string(None)}

        td_value = UNIT_TO_TIMEDELTA[values[0]['unit']]
        max_values = moving_sum(values,
                                td_window,
                                td_value,
                                start_date_utc,
                                end_date_utc)

        if max_values:
            max_value = max(max_values, key=lambda i: i['value'])

            hours = td_window.days * 24 + td_window.seconds / 3600.0
            t = herhalingstijd(hours, area_km2, max_value['value'])
        else:
            max_value = {'value': None,
                         'datetime_start_utc': None,
                         'datetime_end_utc': None}
            t = None

        if max_value['datetime_start_utc'] is not None:
            datetime_start_site_tz = max_value[
                'datetime_start_utc'].astimezone(self.tz)
        else:
            datetime_start_site_tz = None
        if max_value['datetime_end_utc'] is not None:
            datetime_end_site_tz = max_value[
                'datetime_end_utc'].astimezone(self.tz)
        else:
            datetime_end_site_tz = None

        return {
            'td_window': td_window,
            'max': max_value['value'],
            'start': datetime_start_site_tz,
            'end': datetime_end_site_tz,
            't': self._t_to_string(t)}