diff --git a/changehc/delphi_changehc/__init__.py b/changehc/delphi_changehc/__init__.py index 29577dcba..a8df7b6ce 100644 --- a/changehc/delphi_changehc/__init__.py +++ b/changehc/delphi_changehc/__init__.py @@ -12,7 +12,6 @@ from . import load_data from . import run from . import sensor -from . import smooth from . import update_sensor from . import weekday diff --git a/changehc/delphi_changehc/sensor.py b/changehc/delphi_changehc/sensor.py index 4bc04ebc6..949e12ede 100644 --- a/changehc/delphi_changehc/sensor.py +++ b/changehc/delphi_changehc/sensor.py @@ -12,15 +12,19 @@ # third party import numpy as np import pandas as pd +from delphi_utils import Smoother # first party from .config import Config -from .smooth import left_gauss_linear + class CHCSensor: """Sensor class to fit a signal using Covid counts from Change HC outpatient data. """ + smoother = Smoother("savgol", + poly_fit_degree=1, + gaussian_bandwidth=Config.SMOOTHER_BANDWIDTH) @staticmethod def gauss_smooth(count,total): @@ -29,8 +33,8 @@ def gauss_smooth(count,total): Args: count, total: array """ - count_smooth = left_gauss_linear(count) - total_smooth = left_gauss_linear(total) + count_smooth = CHCSensor.smoother.smooth(count) + total_smooth = CHCSensor.smoother.smooth(total) total_clip = np.clip(total_smooth, 0, None) count_clip = np.clip(count_smooth, 0, total_clip) return count_clip, total_clip diff --git a/changehc/delphi_changehc/smooth.py b/changehc/delphi_changehc/smooth.py deleted file mode 100644 index 710f4053f..000000000 --- a/changehc/delphi_changehc/smooth.py +++ /dev/null @@ -1,36 +0,0 @@ -""" -This file contains a left gauss filter used to smooth a 1-d signal. -Code is courtesy of Addison Hu (minor adjustments by Maria). - -Author: Maria Jahja -Created: 2020-04-16 - -""" -import numpy as np - -from .config import Config - - -def left_gauss_linear(s, h=Config.SMOOTHER_BANDWIDTH): - """Smooth the y-values using a local linear left Gaussian filter. - - Args: - y: one dimensional signal to smooth. - h: smoothing bandwidth (in terms of variance) - - Returns: a smoothed 1D signal. - """ - - n = len(s) - t = np.zeros_like(s) - X = np.vstack([np.ones(n), np.arange(n)]).T - for idx in range(n): - wts = np.exp(-((np.arange(idx + 1) - idx) ** 2) / h) - XwX = np.dot(X[: (idx + 1), :].T * wts, X[: (idx + 1), :]) - Xwy = np.dot(X[: (idx + 1), :].T * wts, s[: (idx + 1)].reshape(-1, 1)) - try: - beta = np.linalg.solve(XwX, Xwy) - t[idx] = np.dot(X[: (idx + 1), :], beta)[-1] - except np.linalg.LinAlgError: - t[idx] = np.nan - return t diff --git a/changehc/tests/test_sensor.py b/changehc/tests/test_sensor.py index 5161750d2..a1745dff0 100644 --- a/changehc/tests/test_sensor.py +++ b/changehc/tests/test_sensor.py @@ -2,7 +2,7 @@ import pytest # third party -from delphi_utils import read_params +from delphi_utils import read_params, Smoother import numpy as np import numpy.random as nr import pandas as pd @@ -20,7 +20,12 @@ class TestLoadData: combined_data = load_combined_data(DENOM_FILEPATH, COVID_FILEPATH, DROP_DATE, - "fips") + "fips") + # change smoother window length for test data + CHCSensor.smoother = Smoother("savgol", + poly_fit_degree=1, + gaussian_bandwidth=Config.SMOOTHER_BANDWIDTH, + window_length=20) def test_backfill(self): num0 = np.array([0, 1, 2, 3, 4, 5, 6, 7, 8], dtype=float).reshape(-1, 1) diff --git a/changehc/tests/test_smooth.py b/changehc/tests/test_smooth.py deleted file mode 100644 index b3a27b9ae..000000000 --- a/changehc/tests/test_smooth.py +++ /dev/null @@ -1,17 +0,0 @@ -# standard -import pytest - -# third party -import numpy as np - -# first party -from delphi_changehc.smooth import left_gauss_linear - - -class TestLeftGaussSmoother: - def test_gauss_linear(self): - signal = np.ones(10) - assert np.allclose(left_gauss_linear(signal)[1:], signal[1:]) - - signal = np.arange(1, 10) + np.random.normal(0, 1, 9) - assert np.allclose(left_gauss_linear(signal, h=0.1)[1:], signal[1:])