Skip to content

Commit af67cc6

Browse files
committed
Merge develop
2 parents 6938e80 + 051d404 commit af67cc6

File tree

12 files changed

+172
-56
lines changed

12 files changed

+172
-56
lines changed

docs/CONTRIBUTING.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ As of March 21, help is especially wanted from contributors with experience in K
3030
- Request review from the relevant maintainer(s).
3131
- Check your pull request periodically to see if any changes have been requested or any merge conflicts have arisen.
3232
- If a merge conflict arises, rebase against the latest `develop` branch and force-push the new branch as early as you can. You may need to do this more than once before your changes get merged. Do your best to keep your branch in a mergeable state until it is finished being reviewed and accepted.
33+
- If your change affects the results calculated or presented, update `change_date` in `src/penn_chime/parameters.py` when the pull request is ready for merge, so users can see when results have last changed
3334
- Note: Frequent contributors with write access can submit pull requests from a new branch in the `CodeforPhilly/chime` repository.
3435

3536
## Review & Release

e2e/cypress/integration/tests/actions.spec.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,9 @@ context('Actions', () => {
88
it('All + elements are clickable', () => {
99
cy.get('.step-up').click( { multiple: true } )
1010

11+
// This gets the "first" input from the sidebar. From clicking step up,
12+
// the number of days to project should increase from default 60 to 70.
1113
cy.get('input.st-al')
12-
.should('has.value', '7')
14+
.should('has.value', '70')
1315
})
1416
})

src/app.py

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44
import streamlit as st # type: ignore
55

66
from penn_chime.presentation import (
7-
# additional_projections_chart,
87
display_header,
98
display_sidebar,
109
draw_census_table,
@@ -22,6 +21,7 @@
2221
additional_projections_chart,
2322
admitted_patients_chart,
2423
new_admissions_chart,
24+
chart_descriptions
2525
)
2626

2727
# This is somewhat dangerous:
@@ -39,36 +39,38 @@
3939
notes = "The total size of the susceptible population will be the entire catchment area for Penn Medicine entities (HUP, PAH, PMC, CCH)"
4040
show_more_info_about_this_tool(st=st, model=m, parameters=p, defaults=DEFAULTS, notes=notes)
4141

42-
# PRESENTATION
43-
# Two more combination variable initialization / input element creation
44-
as_date = st.checkbox(label="Present result as dates instead of days", value=False)
45-
4642
st.subheader("New Admissions")
4743
st.markdown("Projected number of **daily** COVID-19 admissions at Penn hospitals")
44+
new_admit_chart = new_admissions_chart(alt, m.admits_df, parameters=p)
4845
st.altair_chart(
49-
new_admissions_chart(alt, m.admits_df, parameters=p, as_date=as_date),
46+
new_admissions_chart(alt, m.admits_df, parameters=p),
5047
use_container_width=True,
5148
)
49+
50+
st.markdown(chart_descriptions(new_admit_chart))
51+
5252
if st.checkbox("Show Projected Admissions in tabular form"):
53-
draw_projected_admissions_table(st, m.admits_df, as_date=as_date)
53+
draw_projected_admissions_table(st, m.admits_df, as_date=p.as_date)
5454
st.subheader("Admitted Patients (Census)")
5555
st.markdown(
5656
"Projected **census** of COVID-19 patients, accounting for arrivals and discharges at Penn hospitals"
5757
)
58+
census_chart = admitted_patients_chart(alt=alt, census=m.census_df, parameters=p)
5859
st.altair_chart(
59-
admitted_patients_chart(alt=alt, census=m.census_df, parameters=p, as_date=as_date),
60+
admitted_patients_chart(alt=alt, census=m.census_df, parameters=p),
6061
use_container_width=True,
6162
)
63+
st.markdown(chart_descriptions(census_chart, suffix=" Census"))
6264
if st.checkbox("Show Projected Census in tabular form"):
63-
draw_census_table(st, m.census_df, as_date=as_date)
65+
draw_census_table(st, m.census_df, as_date=p.as_date)
6466
st.markdown(
6567
"""**Click the checkbox below to view additional data generated by this simulation**"""
6668
)
6769
if st.checkbox("Show Additional Projections"):
6870
show_additional_projections(
69-
st, alt, additional_projections_chart, model=m, parameters=p, as_date=as_date
71+
st, alt, additional_projections_chart, model=m, parameters=p
7072
)
7173
if st.checkbox("Show Raw SIR Simulation Data"):
72-
draw_raw_sir_simulation_table(st, model=m, parameters=p, as_date=as_date)
74+
draw_raw_sir_simulation_table(st, model=m, parameters=p)
7375
write_definitions(st)
7476
write_footer(st)

src/cli.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@
1212
from penn_chime.models import SimSirModel
1313
from penn_chime.utils import RateLos
1414

15-
1615
class FromFile(Action):
1716
"""From File."""
1817

src/penn_chime/charts.py

Lines changed: 60 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,21 @@
1+
2+
from math import ceil
3+
import datetime
4+
15
from altair import Chart # type: ignore
26
import pandas as pd # type: ignore
3-
import numpy as np # type: ignore
47

58
from .parameters import Parameters
69
from .utils import add_date_column
710

811

912
def new_admissions_chart(
10-
alt, projection_admits: pd.DataFrame, parameters: Parameters, as_date: bool = False,
13+
alt, projection_admits: pd.DataFrame, parameters: Parameters
1114
) -> Chart:
1215
"""docstring"""
1316
plot_projection_days = parameters.n_days - 10
1417
max_y_axis = parameters.max_y_axis
18+
as_date = parameters.as_date
1519

1620
y_scale = alt.Scale()
1721

@@ -45,12 +49,13 @@ def new_admissions_chart(
4549

4650

4751
def admitted_patients_chart(
48-
alt, census: pd.DataFrame, parameters: Parameters, as_date: bool = False
52+
alt, census: pd.DataFrame, parameters: Parameters
4953
) -> Chart:
5054
"""docstring"""
5155

5256
plot_projection_days = parameters.n_days - 10
5357
max_y_axis = parameters.max_y_axis
58+
as_date = parameters.as_date
5459
if as_date:
5560
census = add_date_column(census)
5661
x_kwargs = {"shorthand": "date:T", "title": "Date"}
@@ -84,10 +89,20 @@ def admitted_patients_chart(
8489

8590

8691
def additional_projections_chart(
87-
alt, i: np.ndarray, r: np.ndarray, as_date: bool = False, max_y_axis: int = None
92+
alt, model, parameters
8893
) -> Chart:
89-
dat = pd.DataFrame({"Infected": i, "Recovered": r})
94+
95+
# TODO use subselect of df_raw instead of creating a new df
96+
raw_df = model.raw_df
97+
dat = pd.DataFrame({
98+
"infected": raw_df.infected,
99+
"recovered": raw_df.recovered
100+
})
90101
dat["day"] = dat.index
102+
103+
as_date = parameters.as_date
104+
max_y_axis = parameters.max_y_axis
105+
91106
if as_date:
92107
dat = add_date_column(dat)
93108
x_kwargs = {"shorthand": "date:T", "title": "Date"}
@@ -112,3 +127,43 @@ def additional_projections_chart(
112127
)
113128
.interactive()
114129
)
130+
131+
132+
def chart_descriptions(chart: Chart, suffix: str = ""):
133+
"""
134+
135+
:param chart: Chart: The alt chart to be used in finding max points
136+
:param suffix: str: The assumption is that the charts have similar column names.
137+
The census chart adds " Census" to the column names.
138+
Make sure to include a space or underscore as appropriate
139+
:return: str: Returns a multi-line string description of the results
140+
"""
141+
messages = []
142+
143+
cols = ["hospitalized", "icu", "ventilated"]
144+
asterisk = False
145+
day = "date" if "date" in chart.data.columns else "day"
146+
147+
for col in cols:
148+
if chart.data[col].idxmax() + 1 == len(chart.data):
149+
asterisk = True
150+
151+
on = chart.data[day][chart.data[col].idxmax()]
152+
if day == "date":
153+
on = datetime.datetime.strftime(on, "%b %d") # todo: bring this to an optional arg / i18n
154+
else:
155+
on += 1 # 0 index issue
156+
157+
messages.append(
158+
"{}{} peaks at {:,} on day {}{}".format(
159+
col,
160+
suffix,
161+
ceil(chart.data[col].max()),
162+
on,
163+
"*" if asterisk else "",
164+
)
165+
)
166+
167+
if asterisk:
168+
messages.append("_* The max is at the upper bound of the data, and therefore may not be the actual max_")
169+
return "\n\n".join(messages)

src/penn_chime/defaults.py

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -32,22 +32,27 @@ def __init__(
3232
icu: RateLos,
3333
ventilated: RateLos,
3434

35-
recovery_days: int = 14,
35+
as_date: bool = False,
3636
market_share: float = 1.0,
37+
max_y_axis: int = None,
3738
n_days: int = 60,
39+
recovery_days: int = 14,
3840
):
3941
self.region = region
4042
self.current_hospitalized = current_hospitalized
4143
self.known_infected = known_infected
4244
self.doubling_time = doubling_time
43-
self.market_share = market_share
44-
self.n_days = n_days
45-
self.recovery_days = recovery_days
4645
self.relative_contact_rate = relative_contact_rate
4746

4847
self.hospitalized = hospitalized
4948
self.icu = icu
5049
self.ventilated = ventilated
5150

51+
self.as_date = as_date
52+
self.market_share = market_share
53+
self.max_y_axis = max_y_axis
54+
self.n_days = n_days
55+
self.recovery_days = recovery_days
56+
5257
def __repr__(self) -> str:
5358
return f"Constants(susceptible_default: {self.region.susceptible}, known_infected: {self.known_infected})"

src/penn_chime/models.py

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,9 @@
1-
"""Models."""
1+
"""Models.
2+
3+
Changes affecting results or their presentation should also update
4+
parameters.py `change_date`, so users can see when results have last
5+
changed
6+
"""
27

38
from __future__ import annotations
49

@@ -31,10 +36,7 @@ def __init__(self, p: Parameters) -> SimSirModel:
3136
self.intrinsic_growth_rate = intrinsic_growth_rate = \
3237
(2.0 ** (1.0 / p.doubling_time) - 1.0) if p.doubling_time > 0.0 else 0.0
3338

34-
# TODO make this configurable, or more nuanced
35-
self.recovery_days = recovery_days = 14.0
36-
37-
self.gamma = gamma = 1.0 / recovery_days
39+
self.gamma = gamma = 1.0 / p.recovery_days
3840

3941
# Contact rate, beta
4042
self.beta = beta = (

src/penn_chime/parameters.py

Lines changed: 19 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,8 @@
1-
"""Parameters."""
1+
"""Parameters.
2+
3+
Changes affecting results or their presentation should also update
4+
`change_date`, so users can see when results have last changed
5+
"""
26

37
from .utils import RateLos
48

@@ -19,33 +23,38 @@ def __init__(
1923
icu: RateLos,
2024
ventilated: RateLos,
2125

26+
as_date: bool = False,
2227
market_share: float = 1.0,
2328
max_y_axis: int = None,
24-
n_days: int = 0,
29+
n_days: int = 60,
2530
recovery_days: int = 14,
2631
):
27-
"""
28-
__init__.
29-
"""
3032
self.current_hospitalized = current_hospitalized
3133
self.doubling_time = doubling_time
3234
self.known_infected = known_infected
3335
self.relative_contact_rate = relative_contact_rate
3436
self.susceptible = susceptible
3537

38+
self.hospitalized = hospitalized
39+
self.icu = icu
40+
self.ventilated = ventilated
41+
42+
self.as_date = as_date
3643
self.market_share = market_share
3744
self.max_y_axis = max_y_axis
3845
self.n_days = n_days
3946
self.recovery_days = recovery_days
4047

41-
self.hospitalized = hospitalized
42-
self.icu = icu
43-
self.ventilated = ventilated
44-
45-
# TODO dataframe
4648
self.dispositions = {
4749
"hospitalized": hospitalized,
4850
"icu": icu,
4951
"ventilated": ventilated,
5052
}
5153

54+
def change_date(self):
55+
"""
56+
This reflects a date from which previously-run reports will no
57+
longer match current results, indicating when users should
58+
re-run their reports
59+
"""
60+
return "March 23 2020"

0 commit comments

Comments
 (0)