@@ -32,6 +32,9 @@ def __init__(self, p: Parameters):
32
32
for key , d in p .dispositions .items ()
33
33
}
34
34
35
+ self ._rates = rates
36
+ self ._lengths_of_stay = lengths_of_stay
37
+
35
38
# Note: this should not be an integer.
36
39
# We're appoximating infected from what we do know.
37
40
# TODO market_share > 0, hosp_rate > 0
@@ -44,8 +47,9 @@ def __init__(self, p: Parameters):
44
47
detection_probability = (
45
48
p .known_infected / infected if infected > 1.0e-7 else None
46
49
)
47
- intrinsic_growth_rate = \
48
- (2.0 ** (1.0 / p .doubling_time ) - 1.0 ) if p .doubling_time > 0.0 else 0.0
50
+
51
+ # (2.0 ** (1.0 / p.doubling_time) - 1.0) if p.doubling_time > 0.0 else 0.0
52
+ intrinsic_growth_rate = self ._intrinsic_growth_rate (p .doubling_time )
49
53
50
54
gamma = 1.0 / recovery_days
51
55
@@ -77,7 +81,6 @@ def __init__(self, p: Parameters):
77
81
admits_df = build_admits_df (dispositions_df )
78
82
census_df = build_census_df (admits_df , lengths_of_stay )
79
83
80
-
81
84
self .susceptible = susceptible
82
85
self .infected = infected
83
86
self .recovered = recovered
@@ -94,11 +97,113 @@ def __init__(self, p: Parameters):
94
97
self .dispositions_df = dispositions_df
95
98
self .admits_df = admits_df
96
99
self .census_df = census_df
100
+
101
+ if p .n_days_since_first_hospitalized is not None and p .doubling_time is None :
102
+ # optimize doubling_time
103
+ argmin_dt = None
104
+ min_loss = 2.0 ** 99
105
+ censes = dict ()
106
+ for dt in np .linspace (1 ,15 ,29 ):
107
+ censes [dt ] = self .run_projection (p , dt )
108
+ self .census_df = censes [dt ] # log it into state for loss
109
+ loss_dt = self .loss_dt (p )
110
+ if loss_dt < min_loss :
111
+ min_loss = loss_dt
112
+ argmin_dt = dt
113
+ self .census_df = censes [dt ]
114
+ p .doubling_time = argmin_dt
115
+ #
116
+ # update all state dependent on doubling time.
117
+ intrinsic_growth_rate = self ._intrinsic_growth_rate (p .doubling_time )
118
+ gamma = 1 / recovery_days
119
+ beta = self ._beta (intrinsic_growth_rate , gamma , susceptible , p .relative_contact_rate )
120
+ r_t = beta / gamma * susceptible
121
+ r_naught = (intrinsic_growth_rate + gamma ) / gamma
122
+ doubling_time_t = 1.0 / np .log2 (beta * susceptible - gamma + 1 )
123
+ raw_df = sim_sir_df (
124
+ susceptible ,
125
+ infected ,
126
+ recovered ,
127
+ beta ,
128
+ gamma ,
129
+ p .n_days
130
+ )
131
+ dispositions_df = build_dispositions_df (raw_df , rates , p .market_share )
132
+ admits_df = build_admits_df (dispositions_df )
133
+ census_df = build_census_df (admits_df , lengths_of_stay )
134
+
135
+ self .intrinsic_growth_rate = intrinsic_growth_rate
136
+ self .gamma = gamma
137
+ self .beta = beta
138
+ self .r_t = r_t
139
+ self .r_naught = r_naught
140
+ self .doubling_time_t = doubling_time_t
141
+ self .raw_df = raw_df
142
+ self .dispositions_df = dispositions_df
143
+ self .admits_df = admits_df
144
+ self .census_df = census_df
145
+
97
146
self .daily_growth = daily_growth_helper (p .doubling_time )
98
147
self .daily_growth_t = daily_growth_helper (doubling_time_t )
99
148
100
149
return None
101
150
151
+ def run_projection (self , p : Parameters , doubling_time : float ) -> pd .DataFrame :
152
+ intrinsic_growth_rate = self ._intrinsic_growth_rate (doubling_time )
153
+
154
+ recovery_days = p .recovery_days
155
+ market_share = p .market_share
156
+ initial_i = 1 / p .hospitalized .rate / market_share
157
+
158
+ S , I , R = self .susceptible , self .infected , self .recovered
159
+
160
+ # mean recovery rate (inv_recovery_days)
161
+ gamma = 1 / recovery_days
162
+
163
+ # contact rate
164
+ beta = (intrinsic_growth_rate + gamma ) / S
165
+
166
+ n_days = p .n_days
167
+
168
+ raw_df = sim_sir_df (S ,I ,R ,beta ,gamma ,n_days )
169
+
170
+ dispositions_df = build_dispositions_df (raw_df , self ._rates , p .market_share )
171
+ admits_df = build_admits_df (dispositions_df )
172
+ census_df = build_census_df (admits_df , self ._lengths_of_stay )
173
+ return census_df
174
+
175
+ def loss_dt (self , p : Parameters ) -> float :
176
+ """Squared error: predicted_current_hospitalized vs. actual current hospitalized
177
+
178
+ gets prediction of current hospitalized from a census_df which
179
+ is dependent on a given doubling_time in state.
180
+ """
181
+ # get the predicted number of hospitalized today
182
+ predicted_current_hospitalized = self .census_df .hospitalized .loc [p .n_days_since_first_hospitalized ]
183
+
184
+ # compare against actual / user inputted number
185
+ # we shall optimize squared distance
186
+ return (p .current_hospitalized - predicted_current_hospitalized ) ** 2
187
+
188
+
189
+ @staticmethod
190
+ def _intrinsic_growth_rate (doubling_time : Optional [float ]) -> float :
191
+ if doubling_time is not None :
192
+ return (2.0 ** (1.0 / doubling_time ) - 1.0 ) if doubling_time > 0.0 else 0.0
193
+ return 0.0
194
+
195
+ @staticmethod
196
+ def _beta (
197
+ intrinsic_growth_rate : float ,
198
+ gamma : float ,
199
+ susceptible : float ,
200
+ relative_contact_rate : float ) -> float :
201
+ return (
202
+ (intrinsic_growth_rate + gamma )
203
+ / susceptible
204
+ * (1.0 - relative_contact_rate )
205
+ )
206
+
102
207
###################
103
208
## MODEL FUNCS ##
104
209
###################
0 commit comments