Skip to content

Commit 8b8d4ab

Browse files
Merge branch 'develop' into expand_max_days_input
2 parents 6a209f0 + 4177e46 commit 8b8d4ab

File tree

5 files changed

+101
-15
lines changed

5 files changed

+101
-15
lines changed

src/app.py

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,10 @@
1818
)
1919
from penn_chime.settings import DEFAULTS
2020
from penn_chime.models import sim_sir_df, build_admissions_df, build_census_df
21-
from penn_chime.charts import (
22-
additional_projections_chart,
23-
admitted_patients_chart,
24-
new_admissions_chart,
25-
)
21+
from penn_chime.charts import (additional_projections_chart,
22+
admitted_patients_chart,
23+
new_admissions_chart,
24+
chart_descriptions)
2625

2726
# This is somewhat dangerous:
2827
# Hide the main menu with "Rerun", "run on Save", "clear cache", and "record a screencast"
@@ -46,20 +45,24 @@
4645

4746
st.subheader("New Admissions")
4847
st.markdown("Projected number of **daily** COVID-19 admissions at Penn hospitals")
48+
new_admit_chart = new_admissions_chart(alt, admissions_df, parameters=p, as_date=as_date)
4949
st.altair_chart(
50-
new_admissions_chart(alt, admissions_df, parameters=p),
51-
use_container_width=True,
50+
new_admit_chart, use_container_width=True
5251
)
52+
53+
st.markdown(chart_descriptions(new_admit_chart))
54+
5355
if st.checkbox("Show Projected Admissions in tabular form"):
5456
draw_projected_admissions_table(st, admissions_df, as_date=p.as_date)
5557
st.subheader("Admitted Patients (Census)")
5658
st.markdown(
5759
"Projected **census** of COVID-19 patients, accounting for arrivals and discharges at Penn hospitals"
5860
)
61+
census_chart = admitted_patients_chart(alt=alt, census=census_df, parameters=p, as_date=as_date)
5962
st.altair_chart(
60-
admitted_patients_chart(alt=alt, census=census_df, parameters=p),
61-
use_container_width=True,
63+
census_chart, use_container_width=True
6264
)
65+
st.markdown(chart_descriptions(census_chart, suffix=" Census"))
6366
if st.checkbox("Show Projected Census in tabular form"):
6467
draw_census_table(st, census_df, as_date=p.as_date)
6568
st.markdown(

src/cli.py

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,8 @@
99
from pandas import DataFrame
1010

1111
from penn_chime.parameters import Parameters
12-
from penn_chime.utils import build_admissions_df, build_census_df, RateLos
13-
12+
from penn_chime.utils import RateLos
13+
from penn_chime.models import build_admissions_df, build_census_df
1414

1515
class FromFile(Action):
1616
"""From File."""
@@ -123,8 +123,9 @@ def main():
123123
"Recovered": p.recovered_v,
124124
}
125125
)
126-
admits_df = build_admissions_df(p.n_days, *p.dispositions)
127-
census_df = build_census_df(admits_df, *p.lengths_of_stay)
126+
127+
admits_df = build_admissions_df(p)
128+
census_df = build_census_df(admits_df, p)
128129

129130
prefix = a.prefix
130131
for df, name in (

src/penn_chime/charts.py

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
2+
from math import ceil
3+
import datetime
14
from altair import Chart # type: ignore
25
import pandas as pd # type: ignore
36
import numpy as np # type: ignore
@@ -120,3 +123,43 @@ def additional_projections_chart(
120123
)
121124
.interactive()
122125
)
126+
127+
128+
def chart_descriptions(chart: Chart, suffix: str = ""):
129+
"""
130+
131+
:param chart: Chart: The alt chart to be used in finding max points
132+
:param suffix: str: The assumption is that the charts have similar column names.
133+
The census chart adds " Census" to the column names.
134+
Make sure to include a space or underscore as appropriate
135+
:return: str: Returns a multi-line string description of the results
136+
"""
137+
messages = []
138+
139+
cols = ["Hospitalized", "ICU", "Ventilated"]
140+
asterisk = False
141+
day = "date" if "date" in chart.data.columns else "day"
142+
143+
for col in cols:
144+
if chart.data[col].idxmax() + 1 == len(chart.data):
145+
asterisk = True
146+
147+
on = chart.data[day][chart.data[col].idxmax()]
148+
if day == "date":
149+
on = datetime.datetime.strftime(on, "%b %d") # todo: bring this to an optional arg / i18n
150+
else:
151+
on += 1 # 0 index issue
152+
153+
messages.append(
154+
"{}{} peaks at {:,} on day {}{}".format(
155+
col,
156+
suffix,
157+
ceil(chart.data[col].max()),
158+
on,
159+
"*" if asterisk else "",
160+
)
161+
)
162+
163+
if asterisk:
164+
messages.append("_* The max is at the upper bound of the data, and therefore may not be the actual max_")
165+
return "\n\n".join(messages)

src/penn_chime/presentation.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -401,7 +401,6 @@ def draw_projected_admissions_table(
401401
admits_table = add_date_column(
402402
admits_table, drop_day_column=True, date_format=DATE_FORMAT
403403
)
404-
405404
st.table(admits_table)
406405
return None
407406

tests/test_app.py

Lines changed: 41 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
11
"""Tests."""
22

3+
from math import ceil # type: ignore
4+
import datetime # type: ignore
35
import pytest # type: ignore
46
import pandas as pd # type: ignore
57
import numpy as np # type: ignore
68
import altair as alt # type: ignore
79

8-
from src.penn_chime.charts import new_admissions_chart, admitted_patients_chart
10+
from src.penn_chime.charts import new_admissions_chart, admitted_patients_chart, chart_descriptions
911
from src.penn_chime.models import sir, sim_sir, build_admissions_df
1012
from src.penn_chime.parameters import Parameters
1113
from src.penn_chime.presentation import display_header
@@ -254,3 +256,41 @@ def test_parameters():
254256
0.05 * 0.05 * (param.infected_v[1:-1] + param.recovered_v[1:-1]) - 100
255257
)
256258
assert (diff.abs() < 0.1).all()
259+
assert len(param.susceptible_v) == len(param.infected_v) == len(param.recovered_v) == param.n_days + 1 == 3
260+
261+
262+
def test_chart_descriptions():
263+
# new admissions chart
264+
projection_admits = pd.read_csv('tests/projection_admits.csv')
265+
projection_admits = projection_admits.rename(columns={'hosp': 'Hospitalized', 'icu': 'ICU', 'vent': 'Ventilated'})
266+
chart = new_admissions_chart(alt, projection_admits, PARAM)
267+
description = chart_descriptions(chart)
268+
269+
hosp, icu, vent, asterisk = description.split("\n\n") # break out the description into lines
270+
271+
max_hosp = chart.data['Hospitalized'].max()
272+
assert str(ceil(max_hosp)) in hosp
273+
274+
max_icu_ix = chart.data['ICU'].idxmax()
275+
assert max_icu_ix + 1 == len(chart.data)
276+
assert "*" in icu
277+
278+
# test asterisk
279+
param = PARAM
280+
param.n_days = 600
281+
282+
projection_admits = pd.read_csv('tests/projection_admits.csv')
283+
projection_admits = projection_admits.rename(columns={'hosp': 'Hospitalized', 'icu': 'ICU', 'vent': 'Ventilated'})
284+
chart = new_admissions_chart(alt, projection_admits, PARAM)
285+
description = chart_descriptions(chart)
286+
assert "*" not in description
287+
288+
# census chart
289+
census_df = pd.read_csv('tests/census_df.csv')
290+
census_df = census_df.rename(columns={'hosp': 'Hospitalized', 'icu': 'ICU', 'vent': 'Ventilated'})
291+
chart = admitted_patients_chart(alt, census_df, PARAM, as_date=True)
292+
description = chart_descriptions(chart)
293+
294+
assert str(ceil(chart.data['Ventilated'].max())) in description
295+
assert str(chart.data['ICU'].idxmax()) not in description
296+
assert datetime.datetime.strftime(chart.data.iloc[chart.data['ICU'].idxmax()].date, '%b %d') in description

0 commit comments

Comments
 (0)