Skip to content

Commit c016072

Browse files
authored
Merge pull request #223 from cmu-delphi/handle_wip_signal_ccad
Combo cases & deaths: standardizing signal names
2 parents 87f5234 + 5c20e7e commit c016072

File tree

6 files changed

+150
-40
lines changed

6 files changed

+150
-40
lines changed
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
"""Registry for signal names, geo types and other constants"""
2+
METRICS = [
3+
"confirmed",
4+
"deaths",
5+
]
6+
SMOOTH_TYPES = [
7+
"",
8+
"7dav",
9+
]
10+
SENSORS = [
11+
"incidence_num",
12+
"cumulative_num",
13+
"incidence_prop",
14+
"cumulative_prop",
15+
]
16+
GEO_RESOLUTIONS = [
17+
"county",
18+
"state",
19+
"msa",
20+
"hrr",
21+
]
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
"""
2+
Handle signal names.
3+
4+
Author: Vishakha
5+
Created: 2020-08-07
6+
"""
7+
8+
import covidcast
9+
10+
11+
def add_prefix(signal_names, wip_signal, prefix="wip_"):
12+
"""Adds prefix to signal if there is a WIP signal
13+
Parameters
14+
----------
15+
signal_names: List[str]
16+
Names of signals to be exported
17+
prefix : 'wip_'
18+
prefix for new/non public signals
19+
wip_signal : List[str] or bool
20+
a list of wip signals: [], OR
21+
all signals in the registry: True OR
22+
only signals that have never been published: False
23+
Returns
24+
-------
25+
List of signal names
26+
wip/non wip signals for further computation
27+
"""
28+
29+
if wip_signal is True:
30+
return [prefix + signal for signal in signal_names]
31+
if isinstance(wip_signal, list):
32+
make_wip = set(wip_signal)
33+
return[
34+
prefix + signal if signal in make_wip else signal
35+
for signal in signal_names
36+
]
37+
if wip_signal in {False, ""}:
38+
return [
39+
signal if public_signal(signal)
40+
else prefix + signal
41+
for signal in signal_names
42+
]
43+
raise ValueError("Supply True | False or '' or [] | list()")
44+
45+
46+
def public_signal(signal_):
47+
"""Checks if the signal name is already public using COVIDcast
48+
Parameters
49+
----------
50+
signal_ : str
51+
Name of the signal
52+
Returns
53+
-------
54+
bool
55+
True if the signal is present
56+
False if the signal is not present
57+
"""
58+
epidata_df = covidcast.metadata()
59+
for index in range(len(epidata_df)):
60+
if epidata_df['signal'][index] == signal_:
61+
return True
62+
return False

combo_cases_and_deaths/delphi_combo_cases_and_deaths/run.py

Lines changed: 20 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,10 @@
11
# -*- coding: utf-8 -*-
22
"""Functions to call when running the function.
3-
43
This module should contain a function called `run_module`, that is executed when
54
the module is run with `python -m delphi_combo_cases_and_deaths`.
6-
75
This module produces a combined signal for jhu-csse and usa-facts. This signal
86
is only used for visualization. It sources Puerto Rico from jhu-csse and
97
everything else from usa-facts.
10-
118
"""
129
from datetime import date, timedelta, datetime
1310
from itertools import product
@@ -18,29 +15,10 @@
1815
import pandas as pd
1916

2017
from delphi_utils import read_params, create_export_csv
18+
from .constants import *
19+
from .handle_wip_signal import *
2120

2221

23-
METRICS = [
24-
"confirmed",
25-
"deaths",
26-
]
27-
SMOOTH_TYPES = [
28-
"",
29-
"7dav",
30-
]
31-
SENSORS = [
32-
"incidence_num",
33-
"cumulative_num",
34-
"incidence_prop",
35-
"cumulative_prop",
36-
]
37-
GEO_RESOLUTIONS = [
38-
"county",
39-
"state",
40-
"msa",
41-
"hrr",
42-
]
43-
4422
def check_not_none(data_frame, label, date_range):
4523
"""Exit gracefully if a data frame we attempted to retrieve is empty"""
4624
if data_frame is None:
@@ -78,7 +56,6 @@ def extend_raw_date_range(params, sensor_name):
7856
"""A complete issue includes smoothed signals as well as all raw data
7957
that contributed to the smoothed values, so that it's possible to use
8058
the raw values in the API to reconstruct the smoothed signal at will.
81-
8259
The smoother we're currently using incorporates the previous 7
8360
days of data, so we must extend the date range of the raw data
8461
backwards by 7 days.
@@ -155,11 +132,21 @@ def run_module():
155132
params['date_range'] = [date1, date2]
156133

157134
for metric, geo_res, sensor_name, signal in variants:
158-
create_export_csv(
159-
combine_usafacts_and_jhu(signal, geo_res, extend_raw_date_range(params, sensor_name)),
160-
export_dir=params['export_dir'],
161-
start_date=pd.to_datetime(params['export_start_date']),
162-
metric=metric,
163-
geo_res=geo_res,
164-
sensor=sensor_name,
165-
)
135+
136+
df = combine_usafacts_and_jhu(signal, geo_res, extend_raw_date_range(params, sensor_name))
137+
138+
df = df.copy()
139+
df["timestamp"] = pd.to_datetime(df["timestamp"])
140+
start_date = pd.to_datetime(params['export_start_date'])
141+
export_dir = params["export_dir"]
142+
dates = pd.Series(
143+
df[df["timestamp"] >= start_date]["timestamp"].unique()
144+
).sort_values()
145+
146+
signal_name = add_prefix([signal], wip_signal=params["wip_signal"], prefix="wip_")
147+
for date_ in dates:
148+
export_fn = f'{date_.strftime("%Y%m%d")}_{geo_res}_' f"{signal_name[0]}.csv"
149+
df[df["timestamp"] == date_][["geo_id", "val", "se", "sample_size", ]].to_csv(
150+
f"{export_dir}/{export_fn}", index=False, na_rep="NA"
151+
)
152+

combo_cases_and_deaths/params.json.template

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,5 +4,6 @@
44
"cache_dir": "./cache",
55
"export_start_date":[2020,4,1],
66
"date_range":"new",
7-
"source":"indicator-combination"
7+
"source":"indicator-combination",
8+
"wip_signal": ""
89
}
Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
{
2-
"static_file_dir": "../static",
2+
"static_file_dir": "./static",
33
"export_dir": "./receiving",
4-
"cache_dir": "./cache"
4+
"cache_dir": "./cache",
5+
"export_start_date":[2020,4,1],
6+
"date_range": "",
7+
"source":"",
8+
"wip_signal": ""
59
}
Lines changed: 39 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,23 @@
11
from datetime import date
22
from itertools import product
33
import pytest
4+
import unittest
5+
6+
from delphi_combo_cases_and_deaths.run import extend_raw_date_range, sensor_signal
7+
from delphi_combo_cases_and_deaths.handle_wip_signal import add_prefix
8+
from delphi_utils import read_params
9+
from delphi_combo_cases_and_deaths.constants import *
410

5-
from delphi_combo_cases_and_deaths.run import extend_raw_date_range,sensor_signal,METRICS,SENSORS,SMOOTH_TYPES
611

712
def test_issue_dates():
8-
reference_dr = [date.today(),date.today()]
13+
reference_dr = [date.today(), date.today()]
914
params = {'date_range': reference_dr}
1015
n_changed = 0
1116
variants = [sensor_signal(metric, sensor, smoother) for
1217
metric, sensor, smoother in
13-
product(METRICS,SENSORS,SMOOTH_TYPES)]
18+
product(METRICS, SENSORS, SMOOTH_TYPES)]
1419
variants_changed = []
15-
for sensor_name,signal in variants:
20+
for sensor_name, signal in variants:
1621
dr = extend_raw_date_range(params, sensor_name)
1722
if dr[0] != reference_dr[0]:
1823
n_changed += 1
@@ -21,3 +26,33 @@ def test_issue_dates():
2126
All variants: {variants}
2227
Date-extended variants: {variants_changed}
2328
"""
29+
30+
31+
def test_handle_wip_signal():
32+
33+
signal_list = [sensor_signal(metric, sensor, smoother)[1]
34+
for (metric, sensor, smoother) in
35+
product(METRICS, SENSORS, SMOOTH_TYPES)]
36+
37+
# Test wip_signal = True (all signals should receive prefix)
38+
signal_names = add_prefix(signal_list, True, prefix="wip_")
39+
assert all(s.startswith("wip_") for s in signal_names)
40+
41+
# Test wip_signal = list (only listed signals should receive prefix)
42+
signal_names = add_prefix(signal_list, [signal_list[0]], prefix="wip_")
43+
print(signal_names)
44+
assert signal_names[0].startswith("wip_")
45+
assert all(not s.startswith("wip_") for s in signal_names[1:])
46+
47+
# Test wip_signal = False (only unpublished signals should receive prefix)
48+
signal_names = add_prefix(["xyzzy", signal_list[0]], False, prefix="wip_")
49+
assert signal_names[0].startswith("wip_")
50+
assert all(not s.startswith("wip_") for s in signal_names[1:])
51+
52+
53+
class MyTestCase(unittest.TestCase):
54+
pass
55+
56+
57+
if __name__ == '__main__':
58+
unittest.main()

0 commit comments

Comments
 (0)