Skip to content

Commit ce6fa6c

Browse files
author
Corey Chivers
committed
Put social distancing effect back in. Starts at current day.
1 parent 8d2cdcb commit ce6fa6c

File tree

1 file changed

+36
-24
lines changed

1 file changed

+36
-24
lines changed

src/penn_chime/models.py

Lines changed: 36 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -80,21 +80,19 @@ def __init__(self, p: Parameters):
8080
# Simplify equation to avoid division by zero:
8181
# self.r_naught = r_t / (1.0 - relative_contact_rate)
8282
r_naught = (intrinsic_growth_rate + gamma) / gamma
83-
doubling_time_t = 1.0 / np.log2(
84-
beta * susceptible - gamma + 1)
83+
8584

8685
self.susceptible = susceptible
8786
self.infected = infected
8887
self.recovered = p.recovered
8988

9089
self.detection_probability = detection_probability
91-
self.doubling_time_t = doubling_time_t
90+
9291
self.beta = beta
9392
self.gamma = gamma
93+
self.beta_t = get_beta(intrinsic_growth_rate, self.gamma, self.susceptible, p.relative_contact_rate)
9494
self.intrinsic_growth_rate = intrinsic_growth_rate
95-
self.r_t = r_t
96-
self.r_naught = r_naught
97-
self.infected = 1.0 / p.hospitalized.rate / p.market_share
95+
self.infected = infected
9896

9997
if p.date_first_hospitalized is None and p.doubling_time is not None:
10098
logger.info('Using doubling_time.')
@@ -104,13 +102,19 @@ def __init__(self, p: Parameters):
104102
/ susceptible
105103
)
106104

105+
self.i_day = 0 # seed to the full length
106+
self.beta_t = self.beta
107107
self.run_projection(p)
108108
self.i_day = i_day = int(get_argmin_ds(self.census_df, p.current_hospitalized))
109+
110+
self.beta_t = get_beta(intrinsic_growth_rate, self.gamma, self.susceptible, p.relative_contact_rate)
109111
self.run_projection(p)
110112
self.infected = self.raw_df['infected'].values[i_day]
111113
self.susceptible = self.raw_df['susceptible'].values[i_day]
112114
self.recovered = self.raw_df['recovered'].values[i_day]
113115
self.n_days_since = i_day
116+
self.r_t = self.beta_t / gamma * susceptible
117+
self.r_naught = self.beta / gamma * susceptible
114118
logger.info('Set i_day = %s', i_day)
115119

116120
elif p.date_first_hospitalized is not None and p.doubling_time is None:
@@ -123,6 +127,7 @@ def __init__(self, p: Parameters):
123127
for i, i_dt in enumerate(dts):
124128
intrinsic_growth_rate = get_growth_rate(i_dt)
125129
self.beta = get_beta(intrinsic_growth_rate, self.gamma, self.susceptible, 0.0)
130+
self.beta_t = get_beta(intrinsic_growth_rate, self.gamma, self.susceptible, p.relative_contact_rate)
126131

127132
self.run_projection(p)
128133
loss = self.get_loss()
@@ -132,17 +137,20 @@ def __init__(self, p: Parameters):
132137
logger.info('Set doubling_time = %s', doubling_time)
133138
intrinsic_growth_rate = get_growth_rate(p.doubling_time)
134139
self.beta = get_beta(intrinsic_growth_rate, self.gamma, self.susceptible, 0.0)
140+
self.beta_t = get_beta(intrinsic_growth_rate, self.gamma, self.susceptible, p.relative_contact_rate)
135141
self.run_projection(p)
136142

137143
self.intrinsic_growth_rate = intrinsic_growth_rate
138-
self.beta = beta
139-
self.doubling_time_t = doubling_time_t
140144
self.population = p.population
141-
self.r_t = r_t
142-
self.r_naught = r_naught
143145
else:
144146
raise AssertionError('doubling_time or date_first_hospitalized must be provided.')
145147

148+
self.r_t = self.beta_t / gamma * susceptible
149+
self.r_naught = self.beta / gamma * susceptible
150+
151+
doubling_time_t = 1.0 / np.log2(
152+
self.beta_t * susceptible - gamma + 1)
153+
self.doubling_time_t = doubling_time_t
146154

147155
self.sim_sir_w_date_df = build_sim_sir_w_date_df(self.raw_df, p.current_date)
148156

@@ -154,10 +162,12 @@ def run_projection(self, p):
154162
self.susceptible,
155163
self.infected,
156164
p.recovered,
157-
self.beta,
158165
self.gamma,
159-
p.n_days + self.i_day,
160-
-self.i_day
166+
-self.i_day,
167+
self.beta,
168+
self.i_day,
169+
self.beta_t,
170+
p.n_days
161171
)
162172
self.dispositions_df = build_dispositions_df(self.raw_df, self.rates, p.market_share, p.current_date)
163173
self.admits_df = build_admits_df(self.dispositions_df)
@@ -225,28 +235,30 @@ def sir(
225235

226236

227237
def gen_sir(
228-
s: float, i: float, r: float,
229-
beta: float, gamma: float, n_days: int, i_day: int = 0
238+
s: float, i: float, r: float, gamma: float, i_day: int = 0, *args
230239
) -> Generator[Tuple[int, float, float, float], None, None]:
231-
"""Simulate SIR model forward in time yielding tuples."""
240+
"""Simulate SIR model forward in time yielding tuples.
241+
Parameter order has changed to allow multiple (beta, n_days)
242+
to reflect multiple changing social distancing policies.
243+
"""
232244
s, i, r = (float(v) for v in (s, i, r))
233245
n = s + i + r
234246
d = i_day
235-
# TODO: Ask corey if n_days is really required for the sim
236-
# while i >= 0.5:
237-
for _ in range(n_days):
238-
yield d, s, i, r
239-
s, i, r = sir(s, i, r, beta, gamma, n)
240-
d += 1
247+
while args:
248+
beta, n_days, *args = args
249+
for _ in range(n_days):
250+
yield d, s, i, r
251+
s, i, r = sir(s, i, r, beta, gamma, n)
252+
d += 1
241253
yield d, s, i, r
242254

243255

244256
def sim_sir_df(
245-
s: float, i: float, r: float, beta: float, gamma: float, n_days: int, i_day: int = 0
257+
s: float, i: float, r: float, gamma: float, i_day: int = 0, *args
246258
) -> pd.DataFrame:
247259
"""Simulate the SIR model forward in time."""
248260
return pd.DataFrame(
249-
data=gen_sir(s, i, r, beta, gamma, n_days, i_day),
261+
data=gen_sir(s, i, r, gamma, i_day, *args),
250262
columns=("day", "susceptible", "infected", "recovered"),
251263
)
252264

0 commit comments

Comments
 (0)