From 97e928df4a47e4af8febfe111f05982f51d67c26 Mon Sep 17 00:00:00 2001 From: Aaron Bach Date: Fri, 2 Nov 2018 08:48:22 -0600 Subject: [PATCH] Update Pollen.com to use numpy for trend analysis (#18107) * Update Pollen.com to use numpy for trend analysis * Hound * Linting --- homeassistant/components/sensor/pollen.py | 40 +++++++++++------------ requirements_all.txt | 1 + requirements_test_all.txt | 1 + 3 files changed, 22 insertions(+), 20 deletions(-) diff --git a/homeassistant/components/sensor/pollen.py b/homeassistant/components/sensor/pollen.py index 62fdd5b4955..818404aa3fe 100644 --- a/homeassistant/components/sensor/pollen.py +++ b/homeassistant/components/sensor/pollen.py @@ -18,7 +18,7 @@ from homeassistant.helpers import aiohttp_client from homeassistant.helpers.entity import Entity from homeassistant.util import Throttle -REQUIREMENTS = ['pypollencom==2.2.2'] +REQUIREMENTS = ['numpy==1.15.3', 'pypollencom==2.2.2'] _LOGGER = logging.getLogger(__name__) ATTR_ALLERGEN_AMOUNT = 'allergen_amount' @@ -97,7 +97,6 @@ RATING_MAPPING = [{ 'maximum': 12 }] -TREND_FLAT = 'Flat' TREND_INCREASING = 'Increasing' TREND_SUBSIDING = 'Subsiding' @@ -140,6 +139,23 @@ def calculate_average_rating(indices): return max(set(ratings), key=ratings.count) +def calculate_trend(indices): + """Calculate the "moving average" of a set of indices.""" + import numpy as np + + def moving_average(data, samples): + """Determine the "moving average" (http://tinyurl.com/yaereb3c).""" + ret = np.cumsum(data, dtype=float) + ret[samples:] = ret[samples:] - ret[:-samples] + return ret[samples - 1:] / samples + + increasing = np.all(np.diff(moving_average(np.array(indices), 4)) > 0) + + if increasing: + return TREND_INCREASING + return TREND_SUBSIDING + + class BaseSensor(Entity): """Define a base Pollen.com sensor.""" @@ -217,19 +233,11 @@ class ForecastSensor(BaseSensor): if i['minimum'] <= average <= i['maximum'] ] - slope = (data['periods'][-1]['Index'] - data['periods'][-2]['Index']) - if slope > 0: - trend = TREND_INCREASING - elif slope < 0: - trend = TREND_SUBSIDING - else: - trend = TREND_FLAT - self._attrs.update({ ATTR_CITY: data['City'].title(), ATTR_RATING: rating, ATTR_STATE: data['State'], - ATTR_TREND: trend, + ATTR_TREND: calculate_trend(indices), ATTR_ZIP_CODE: data['ZIP'] }) @@ -256,19 +264,11 @@ class HistoricalSensor(BaseSensor): indices = [p['Index'] for p in data['periods']] average = round(mean(indices), 1) - slope = (data['periods'][-1]['Index'] - data['periods'][-2]['Index']) - if slope > 0: - trend = TREND_INCREASING - elif slope < 0: - trend = TREND_SUBSIDING - else: - trend = TREND_FLAT - self._attrs.update({ ATTR_CITY: data['City'].title(), ATTR_RATING: calculate_average_rating(indices), ATTR_STATE: data['State'], - ATTR_TREND: trend, + ATTR_TREND: calculate_trend(indices), ATTR_ZIP_CODE: data['ZIP'] }) diff --git a/requirements_all.txt b/requirements_all.txt index b89b496dd50..42aa2c08cc8 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -669,6 +669,7 @@ nuheat==0.3.0 # homeassistant.components.binary_sensor.trend # homeassistant.components.image_processing.opencv +# homeassistant.components.sensor.pollen numpy==1.15.3 # homeassistant.components.google diff --git a/requirements_test_all.txt b/requirements_test_all.txt index 8035918d3f2..6059917892c 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -118,6 +118,7 @@ mficlient==0.3.0 # homeassistant.components.binary_sensor.trend # homeassistant.components.image_processing.opencv +# homeassistant.components.sensor.pollen numpy==1.15.3 # homeassistant.components.mqtt