Created
June 23, 2021 13:15
-
-
Save btseytlin/5c1d3eaf47fa4451fe7cb674fe572c16 to your computer and use it in GitHub Desktop.
Medium "How to actually forecast COVID-19" embed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class BarebonesSEIR: | |
def __init__(self, params=None): | |
self.params = params | |
def get_fit_params(self): | |
params = lmfit.Parameters() | |
params.add("population", value=12_000_000, vary=False) | |
params.add("epidemic_started_days_ago", value=10, vary=False) | |
params.add("r0", value=4, min=3, max=5, vary=True) | |
params.add("alpha", value=0.0064, min=0.005, max=0.0078, vary=True) # CFR | |
params.add("delta", value=1/3, min=1/14, max=1/2, vary=True) # E -> I rate | |
params.add("gamma", value=1/9, min=1/14, max=1/7, vary=True) # I -> R rate | |
params.add("rho", expr='gamma', vary=False) # I -> D rate | |
return params | |
def get_initial_conditions(self, data): | |
# Simulate such initial params as to obtain as many deaths as in data | |
population = self.params['population'] | |
epidemic_started_days_ago = self.params['epidemic_started_days_ago'] | |
t = np.arange(epidemic_started_days_ago) | |
(S, E, I, R, D) = self.predict(t, (population - 1, 0, 1, 0, 0)) | |
I0 = I[-1] | |
E0 = E[-1] | |
Rec0 = R[-1] | |
D0 = D[-1] | |
S0 = S[-1] | |
return (S0, E0, I0, Rec0, D0) | |
def step(self, initial_conditions, t): | |
population = self.params['population'] | |
delta = self.params['delta'] | |
gamma = self.params['gamma'] | |
alpha = self.params['alpha'] | |
rho = self.params['rho'] | |
rt = self.params['r0'].value | |
beta = rt * gamma | |
S, E, I, R, D = initial_conditions | |
new_exposed = beta * I * (S / population) | |
new_infected = delta * E | |
new_dead = alpha * rho * I | |
new_recovered = gamma * (1 - alpha) * I | |
dSdt = -new_exposed | |
dEdt = new_exposed - new_infected | |
dIdt = new_infected - new_recovered - new_dead | |
dRdt = new_recovered | |
dDdt = new_dead | |
assert S + E + I + R + D - population <= 1e10 | |
assert dSdt + dIdt + dEdt + dRdt + dDdt <= 1e10 | |
return dSdt, dEdt, dIdt, dRdt, dDdt | |
def predict(self, t_range, initial_conditions): | |
ret = odeint(self.step, initial_conditions, t_range) | |
return ret.T |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment