# ---
# jupyter:
#   jupytext:
#     text_representation:
#       extension: .py
#       format_name: light
#       format_version: '1.5'
#       jupytext_version: 1.14.4
#   kernelspec:
#     display_name: Python 3
#     language: python
#     name: python3
# ---

# + [markdown] slideshow={"slide_type": "skip"}
# ![Callysto.ca Banner](https://github.com/callysto/curriculum-notebooks/blob/master/callysto-notebook-banner-top.jpg?raw=true)

# + [markdown] slideshow={"slide_type": "skip"}
# ## To use this slideshow:
# - Run All, using the menu item: Kernel/Restart & Run All
# - Return to this top cell
# - click on "Slideshow" menu item above, that looks like this:
# ![](images/SlideIcon.png)

# + [markdown] slideshow={"slide_type": "slide"}
# ## Mathematical Modeling
#
# ### August 5, 2020 with <NAME>  

# + [markdown] slideshow={"slide_type": "slide"}
# ## Session III
#
# In this session, we’ll explore our implementation of the “<b>S</b>usceptible, <b>E</b>xposed, <b>I</b>nfected and <b>R</b>ecovered” (<b>SEIR</b>) model used in epidemiology, the study of how disease occurs in populations. 
#

# + [markdown] slideshow={"slide_type": "slide"}
# ## Recap: What is a Mathematical Model
#
# A mathematical model is a description of a system using <b>mathematical concepts</b> and <b>mathematical language</b>.
#
# You can think of a math model as a tool to help us describe what we believe about the workings of phenomena in the world. 
#
# <b>We use the language of mathematics to express our beliefs.</b>
#
# <b>We use mathematics (theoretical and numerical analysis) to evaluate the model, and get insights about the original phenomenon.</b>

# + [markdown] slideshow={"slide_type": "slide"}
# ### Building Models: Our Road Map for The Course
#
# |Topic | Session |
# |-|-|
# |<font color=#000000><b>Choose what phenomenon you want to model|1|</b></font>
# |<font color=#000000><b>What assumptions are you making about the phenomenon|1|</b></font>   
# |<font color=#000000><b>Use a flow diagram to help you determine the structure of your model|1|</b></font>
# |<font color=#000000><b>Choose equations|2|</b></font>
# |<font color=#000000><b>Implement equations using Python|2|</b></font>
# |<font color=#000000><b>Solve equations|2|</b></font>
# |<font color=#1f78b4><b>Study the behaviour of the model|3|</b></font>
# |<font color=#1f78b4><b>Test the model|3|</b></font>
# |<font color=#1f78b4><b>Use the model|3|</b></font>
#

# + [markdown] slideshow={"slide_type": "slide"}
# ## Recap: Our assumptions
#
# 1. Mode of transmission of the disease from person to person is through contact ("contact transmission") between a person who interacts with an infectious person. 
#     
# 2. Once a person comes into contact with the pathogen, there is a period of time (called the latency period) in which they are infected, but cannot infect others (yet!). 
#
# 3. Population is not-constant (that is, people are born and die as time goes by).

# + [markdown] slideshow={"slide_type": "subslide"}
# ## Recap: Our assumptions
#
#
# 4. A person in the population is either one of:
#     - <b>S</b>usceptible, i.e. not infected but not yet exposed, 
#     - <b>E</b>xposed to the infection, i.e. exposed to the virus, but not yet infectious, 
#     - <b>I</b>nfectious, and 
#     - <b>R</b>ecovered from the infection. 
#     
# 5. People can die by "natural causes" during any of the stages. We assume an additional cause of death associated with the infectious stage. 

# + [markdown] slideshow={"slide_type": "slide"}
# ## Recap: Flow diagram
#
# How does a person move from one stage into another? In other words, how does a person go from susceptible to exposed, to infected, to recovered? 
#
# $\Delta$: Per-capita birth rate.
#
# $\mu$: Per-capita natural death rate.
#
# $\alpha$: Virus-induced average fatality rate.
#
# $\beta$: Probability of disease transmission per contact (dimensionless) times the number of contacts per unit time.
#
# $\epsilon$: Rate of progression from exposed to infectious (the reciprocal is the incubation period).
#
# $\gamma$: Recovery rate of infectious individuals (the reciprocal is the infectious period).
#

# + [markdown] slideshow={"slide_type": "subslide"}
# ## Recap: Flow diagram
#
# $$\stackrel{\Delta N} {\longrightarrow} \text{S} \stackrel{\beta\frac{S}{N} I}{\longrightarrow} \text{E} \stackrel{\epsilon}{\longrightarrow} \text{I}  \stackrel{\gamma}{\longrightarrow} \text{R}$$
# $$\hspace{1.1cm} \downarrow \mu \hspace{0.6cm} \downarrow \mu  \hspace{0.5cm} \downarrow \mu, \alpha  \hspace{0.1cm} \downarrow \mu $$

# + [markdown] slideshow={"slide_type": "slide"}
# ## Our system of equations
#
# $N$ is updated at each time step, and infected peopel die at a higher rate. 
#
# $$ N = S + E + I + R$$
#
# We can then express our model using differential equations
#
# $$\frac{dS}{dt} = \Delta N - \beta \frac{S}{N}I - \mu S$$
#
# $$\frac{dE}{dt} = \beta \frac{S}{N}I - (\mu + \epsilon )E$$
#
# $$\frac{dI}{dt} = \epsilon E - (\gamma+ \mu + \alpha )I$$
#
# $$\frac{dR}{dt} = \gamma I - \mu R$$
#
#

# + [markdown] slideshow={"slide_type": "subslide"}
# ## Our system of equations
#
#
# Also, we can keep track of the dead people, dead due to the infection. 
#
# $$\frac{dD}{dt} = \alpha I $$

# + [markdown] slideshow={"slide_type": "slide"}
# ## Initial conditions
#
# If $N(t)$ denotes the total population, then at a given time $t$,
#
# $$N(t) = S(t) + E(t) + I(t) + R(t).$$
#
# In particular, if for $t = 0$ (also known as "day 0") we set  
#
# $$S(0) = S_0, E(0) = E_0, I(0) = I_0, R(0) = R_0, $$
#
# then the population at day 0 is:
#
# $$N(0) = S_0 + E_0 + I_0 + R_0.$$
#
# $S_0, E_0, I_0, R_0$ are known as "initial conditions" - we will need them to solve our system.

# + slideshow={"slide_type": "skip"}
import numpy as np
from scipy.integrate import odeint
import matplotlib.pyplot as plt
from ipywidgets import interact, interact_manual, widgets, Layout, VBox, HBox, Button
from IPython.display import display, Javascript, Markdown, HTML, clear_output
import pandas as pd
import plotly.express as px 
import plotly.graph_objects as go

# A grid of time points (in days)
t = np.linspace(0, 750, 750)


# The SEIR model differential equations.
def deriv(y, t, Delta, beta, mu, epsilon,gamma,alpha):
    S, E, I, R, D = y
    N = S + E + I + R
    dS = Delta*N  - beta*S*I/N - mu*S
    dE = beta*S*I/N - (mu + epsilon)*E
    dI = epsilon*E - (gamma + mu + alpha)*I
    dR = gamma*I - mu*R
    dD = alpha*I 
    
    return [dS,dE, dI, dR, dD]


def plot_infections(Delta, beta, mu, epsilon,gamma,alpha):
    
    # Initial number of infected and recovered individuals, I0 and R0.
    S0, E0,I0, R0 ,D0 = 37000000,0,100,0,0
    # Total population, N.
    N = S0 + E0 + I0 + R0
    # Initial conditions vector
    y0 = S0,E0, I0, R0, D0
    # Integrate the SIR equations over the time grid, t.
    ret = odeint(deriv, y0, t, args=(Delta, beta, mu, epsilon,gamma,alpha))
    S, E,I, R, D = ret.T
    
    S,E,I,R,D = np.ceil(S),np.ceil(E),np.ceil(I),np.ceil(R),np.ceil(D)

    seir_simulation = pd.DataFrame({"Susceptible":S,"Exposed":E,"Infected":I,"Recovered":R,"Deaths":D, "Time (days)":t})

    layout = dict( xaxis=dict(title='Time (days)', linecolor='#d9d9d9', mirror=True),
              yaxis=dict(title='Number of people', linecolor='#d9d9d9', mirror=True))
    
    fig = go.Figure(layout=layout)
    
#    fig.add_trace(go.Scatter(x=seir_simulation["Time (days)"], y=seir_simulation["Susceptible"],
#                        mode='lines',
#                        name='Susceptible'))
    
    fig.add_trace(go.Scatter(x=seir_simulation["Time (days)"], y=seir_simulation["Exposed"],
                        mode='lines',
                        name='Exposed'))
    
    fig.add_trace(go.Scatter(x=seir_simulation["Time (days)"], y=seir_simulation["Infected"],
                    mode='lines',
                    name='Infected'))
    
    fig.add_trace(go.Scatter(x=seir_simulation["Time (days)"], y=seir_simulation["Recovered"],
                        mode='lines', name='Recovered'))

    fig.add_trace(go.Scatter(x=seir_simulation["Time (days)"], y=seir_simulation["Deaths"],
                        mode='lines', name='Deaths'))

    fig.update_layout(title_text="Projected Susceptible, Exposed, Infectious, Recovered, Deaths")

    fig.show();



# + slideshow={"slide_type": "slide"}
# Our code
# A grid of time points (in days)
t = np.linspace(0, 750, 750)

# The SEIR model differential equations.
def deriv(y, t, Delta, beta, mu, epsilon,gamma,alpha):
    S, E, I, R, D = y
    N = S + E + I + R
    dS = Delta*N  - beta*S*I/N - mu*S
    dE = beta*S*I/N - (mu + epsilon)*E
    dI = epsilon*E - (gamma + mu + alpha)*I
    dR = gamma*I - mu*R
    dD = alpha*I 
    
    return [dS,dE, dI, dR, dD]



# + [markdown] slideshow={"slide_type": "slide"}
# ## When is there equilibrium? 
#
# Another way to think about rate of change is in terms of slope. One value that is of interest to mathematicians is the value in which a rate changes from positive to negative. 
#
# At equlibrium the slope is horizontal. We can find this value using mathematics by setting a derivative equal to zero. 
#
# We can find the equilibrium for our system by setting
#
# $$\frac{dS}{dt} =\frac{dE}{dt} =\frac{dI}{dt} =\frac{dR}{dt}  = 0 $$
#
# Playing some more with the equations indicates that R can be manipulated to be in terms of E or I. So that if the number of infectious (or exposed) is zero, then the number of exposed and recovered is zero too. This makes sense - if no one is infected in our population, then no one can catch the virus. 

# + [markdown] slideshow={"slide_type": "slide"}
# ## When is there equilibrium?
#
# Let's suppose there is at least one infectious person in the population. 
#
# We can do a bit of algebra to compute a very important number called $R_0$. This number is called "general (or basic) reproduction number". This is the number that epidemiologists use to determine the number of new cases a single individual will produce. 
#
# We can do a bit of math to get this number. I will show you the simulation first, then the math behind it. 
#
# For now, believe me. 
#
# $$R_0 = \frac{\Delta \beta \epsilon}{\delta (\delta + \gamma) (\delta + \epsilon)}$$
#
# If $R_0 < 1$ - this is disease free.
#
# If $R_0 > 1$ - this is called "endemic" and indicates there is an outbreak.

# + slideshow={"slide_type": "slide"}
# Initial number of infected and recovered individuals, I0 and R0.
S0, E0,I0, R0 ,D0 = 37000000,0,1,0,0
# Total population, N.
N = S0 + E0 + I0 + R0
# Initial conditions vector
y0 = S0,E0, I0, R0, D0
# Integrate the SEIR equations over the time grid, t.
ret = odeint(deriv, y0, t, args=(Delta, beta, mu, epsilon,gamma,alpha))
S, E,I, R,D = ret.T
numerator = beta*epsilon
denominator = (alpha + gamma + mu)*(epsilon + mu)
print("R_0 is equal to", numerator/denominator)  
seir_simulation = pd.DataFrame({"Susceptible":S,"Exposed":E,"Infectious":I,"Recovered":R,"Time (days)":t})
px.line(seir_simulation,"Time (days)",'Infectious',title="Number of infectious people")


# + [markdown] slideshow={"slide_type": "slide"}
# ## Playing with the parameters

# + slideshow={"slide_type": "fragment"}
def f(beta,eps,gamma,alpha):
    numerator = beta*eps
    denominator = (alpha + gamma + mu)*(eps + mu)
    print("R_0 is equal to", numerator/denominator)
    plot_infections(0, beta, 0, eps, gamma, alpha)


# + slideshow={"slide_type": "slide"}
interact_manual(f, 
         beta=widgets.FloatSlider(min=0, max=1, step=0.01, value=0.5),
         eps =widgets.FloatSlider(min=.1, max=1.0, step=.1, value=.1),
         gamma=widgets.FloatSlider(min=.1, max=1.0, step=.1, value=.1),
         alpha  =widgets.FloatSlider(min=.005, max=1.0, step=.005, value=.005)
         );

# + [markdown] slideshow={"slide_type": "slide"}
# ## Let's get some real data
#
# Using COVID-19 Open Data [1], we are going to compare our model to the number of daily cases reported in Canada. 
#
# [1] COVID-19 Data Repository by the Center for Systems Science and Engineering (CSSE) at Johns Hopkins University, https://github.com/CSSEGISandData/COVID-19

# + slideshow={"slide_type": "fragment"}
import requests as r
import pandas as pd

# + slideshow={"slide_type": "fragment"}
API_response_confirmed = r.get("https://covid19api.herokuapp.com/confirmed")
data = API_response_confirmed.json() # Check the JSON Response Content documentation below
confirmed_df = pd.json_normalize(data,record_path=["locations"])

# + slideshow={"slide_type": "fragment"}
# Flattening the data 
flat_confirmed = pd.json_normalize(data=data['locations'])
flat_confirmed.set_index('country', inplace=True)


# + slideshow={"slide_type": "skip"}
# Define a function to drop the history.prefix
# Create function drop_prefix
def drop_prefix(self, prefix):
    self.columns = self.columns.str.lstrip(prefix)
    return self

# Call function
pd.core.frame.DataFrame.drop_prefix = drop_prefix

# Define function which removes history. prefix, and orders the column dates in ascending order
def order_dates(flat_df):

    # Drop prefix
    flat_df.drop_prefix('history.')
    flat_df.drop_prefix("coordinates.")
    # Isolate dates columns
    flat_df.iloc[:,6:].columns = pd.to_datetime(flat_df.iloc[:,6:].columns)
    # Transform to datetim format
    sub = flat_df.iloc[:,6:]
    sub.columns = pd.to_datetime(sub.columns)
    # Sort
    sub2 = sub.reindex(sorted(sub.columns), axis=1)
    sub3 = flat_df.reindex(sorted(flat_df.columns),axis=1).iloc[:,-5:]
    # Concatenate
    final = pd.concat([sub2,sub3], axis=1, sort=False)
    return final


# + [markdown] slideshow={"slide_type": "slide"}
# ## Formatting the data a bit more

# + slideshow={"slide_type": "fragment"}
# Apply function
final_confirmed = order_dates(flat_confirmed)
country = "Canada"
by_prov = final_confirmed[final_confirmed.index==country].set_index("province").T.iloc[:-4,]
by_prov["TotalDailyCase"] = by_prov.sum(axis=1)

# + slideshow={"slide_type": "fragment"}
display(by_prov.tail(1))

# + slideshow={"slide_type": "fragment"}
# This variable contains data on COVID 19 daily cases
non_cumulative_cases = by_prov.diff(axis=0)
display(non_cumulative_cases.tail(1))

# + [markdown] slideshow={"slide_type": "slide"}
# ## Fitting our model into the real data
#
# We will begin by attempting a first guess - you can tinker with the values to get something close to the real data. 

# + slideshow={"slide_type": "slide"}
# Initial number of infected and recovered individuals, I0 and R0.
S0, E0,I0, R0,D0 = 37000000,0,1,0,0
# Total population, N.
N = S0 + E0 + I0 + R0
# Initial conditions vector
y0 = [S0,E0, I0, R0,D0]
t = np.linspace(0, len(non_cumulative_cases["TotalDailyCase"]), len(non_cumulative_cases["TotalDailyCase"]))

# Integrate the SEIR equations over the time grid, t.
Delta = 0.01# natural birth rate. Set to zero for simplicity
mu = 0.06 # natural death rate. Set to zero for simplicity
alpha = 0.009  # death rate due to disease
beta = 0.7# an interaction parameter. Rate for susceptible to exposed. 
epsilon = 0.23# rate from exposed to infectious
gamma = 0.15 # rate from infectious to recovered (We expect this to be bigger than mu)
numerator = beta*epsilon
denominator = (alpha + gamma + mu)*(epsilon + mu)
print("R_0 is equal to", numerator/denominator)  
ret = odeint(deriv, y0, t, args=(Delta, beta, mu, epsilon,gamma,alpha))
S, E,I, R ,D= ret.T
S,E,I,R,D = np.ceil(S),np.ceil(E),np.ceil(I),np.ceil(R),np.ceil(D)

# Let's add a date
seir_simulation = pd.DataFrame({"Susceptible":S,"Exposed":E,"Infectious":I,"Recovered":R,"Time (days)":t})
seir_simulation['date'] = pd.date_range(start='01/24/2020', periods=len(seir_simulation), freq='D')

# + slideshow={"slide_type": "slide"}
non_cumulative_cases = by_prov.diff(axis=0)

trace3 = go.Scatter(x = non_cumulative_cases.index,y=non_cumulative_cases["TotalDailyCase"])
trace2 = go.Scatter(x = seir_simulation["date"],y=seir_simulation["Infectious"],yaxis='y2')
layout = go.Layout(
    title= ('First guess to fit model: infectious against number of reported cases in ' + str(country)),
    yaxis=dict(title='Daily Number of  Reported Infections',\
               titlefont=dict(color='blue'), tickfont=dict(color='blue')),
        yaxis2=dict(title='Number of infectious members (our model)', titlefont=dict(color='red'), \
                    tickfont=dict(color='red'), overlaying='y', side='right'),
        showlegend=False)
fig = go.Figure(data=[trace3,trace2],layout=layout)

fig.show()


# + slideshow={"slide_type": "notes"}
# The SEIR model differential equations.
def deriv(y, t, Delta, beta, mu, epsilon,gamma,alpha):
    S, E, I, R, D = y
    N = S + E + I + R
    dS = Delta*N  - beta*S*I/N - mu*S
    dE = beta*S*I/N - (mu + epsilon)*E
    dI = epsilon*E - (gamma + mu + alpha)*I
    dR = gamma*I - mu*R
    dD = alpha*I 
    
    return [dS,dE, dI, dR, dD]


# + slideshow={"slide_type": "skip"}
# !conda install -y -c conda-forge symfit

# + slideshow={"slide_type": "skip"}
from symfit import variables, Parameter, ODEModel, Fit, D

import numpy as np

tdata = [i for i in range(1,len(seir_simulation["date"]))]
adata = [seir_simulation["Infectious"].to_list()[i] for i in range(1,len(seir_simulation["Infectious"].to_list()))]

# tdata = [i for i in range(1,len(non_cumulative_cases.index))]
# adata = [non_cumulative_cases["TotalDailyCase"].to_list()[i] for i in range(1,len(non_cumulative_cases["TotalDailyCase"].to_list()))]


s,e,i,r, d,t = variables('S,E,I,R,D,t')
Delta = Parameter('Delta', 0.01/N)
mu = Parameter("mu",0.06)
beta = Parameter("beta",0.7)
epsilon = Parameter("epsilon",0.23)
gamma  = Parameter("gamma",0.15)
alpha  = Parameter("alpha",0.009)

model_dict = {
    D(s, t): Delta*N  - beta*s*i/N - mu*s,
    D(e, t): beta*s*i/N - (mu + epsilon)*e,
    D(i,t): epsilon*e - (gamma + mu + alpha)*i,
    D(r,t): gamma*i - mu*r,
    D(d,t): alpha*i
}

ode_model = ODEModel(model_dict, initial={t: 0.0, s:S0, e:E0, i:I0, r:R0,d:D0})

fit = Fit(ode_model, t=tdata, S=None,E=None,I=adata,R=None,D=None)
fit_result = fit.execute()

print(ode_model)
print(fit_result)

tvec = np.linspace(0, len(seir_simulation["date"]),len(seir_simulation["date"]))
plt.figure(figsize=(10,10))
SEIRD = ode_model(t=tvec, **fit_result.params)
plt.plot(tvec, I, label='[Infectious]')
#plt.plot(tvec, E, label='[E]')
plt.scatter(tdata, adata)
plt.legend()
plt.grid(True)
plt.show()

# + slideshow={"slide_type": "skip"}
from symfit import variables, Parameter, ODEModel, Fit, D

import numpy as np

tdata = [i for i in range(1,len(seir_simulation["date"]))]
adata = [seir_simulation["Infectious"].to_list()[i] +0.0001 for i in range(1,len(seir_simulation["Infectious"].to_list()))]

# tdata = [i for i in range(1,len(non_cumulative_cases.index))]
# adata = [non_cumulative_cases["TotalDailyCase"].to_list()[i] for i in range(1,len(non_cumulative_cases["TotalDailyCase"].to_list()))]


s,e,i,r, d,t = variables('S,E,I,R,D,t')
Delta = Parameter('Delta', 0.01)
mu = Parameter("mu",0.06)
beta = Parameter("beta",0.7)
epsilon = Parameter("epsilon",0.23)
gamma  = Parameter("gamma",0.15)
alpha  = Parameter("alpha",0.009)

model_dict = {
    D(s, t): Delta*N  - beta*s*i/N - mu*s,
    D(e, t): beta*s*i/N - (mu + epsilon)*e,
    D(i,t): epsilon*e - (gamma + mu + alpha)*i,
    D(r,t): gamma*i - mu*r,
    D(d,t): alpha*i
}

ode_model = ODEModel(model_dict, initial={t: 0.0, s:S0, e:E0, i:I0, r:R0,d:D0})

fit = Fit(ode_model, t=tdata, S=None,E=None,I=adata,R=None,D=None)
fit_result = fit.execute()

print(ode_model)
print(fit_result)

tvec = np.linspace(0, len(seir_simulation["date"]),len(seir_simulation["date"]))
plt.figure(figsize=(10,10))
SEIRD = ode_model(t=tvec, **fit_result.params)
plt.plot(tvec, I, label='[Infectious]')
#plt.plot(tvec, E, label='[E]')
plt.scatter(tdata, adata)
plt.legend()
plt.grid(True)
plt.show()

# + slideshow={"slide_type": "skip"}
tdata = [i for i in range(1,len(non_cumulative_cases.index))]
adata = [non_cumulative_cases["TotalDailyCase"].to_list()[i] for i in range(1,len(non_cumulative_cases["TotalDailyCase"].to_list()))]



N= 30000
s,e,i,r, d,t = variables('S,E,I,R,D,t')
Delta = Parameter('Delta', value=0.01, min=0.01, max=1.0)
mu = Parameter("mu",value=0.06,min=0.01, max=1.0)
beta = Parameter("beta",value=0.7,min=0.01, max=1.0)
epsilon = Parameter("epsilon",value=0.23,min=0.01, max=1.0)
gamma  = Parameter("gamma",value=0.15,min=0.01, max=1.0)
alpha  = Parameter("alpha",value=0.009,min=0.01, max=1.0)

model_dict = {
    D(s, t): Delta  - beta*s*i - mu*s,
    D(e, t): beta*s*i - (mu + epsilon)*e,
    D(i,t): epsilon*e - (gamma + mu + alpha)*i,
    D(r,t): gamma*i - mu*r,
    D(d,t): alpha*i
}

ode_model = ODEModel(model_dict, initial={t: 0.0, s:30000, e:E0, i:I0, r:R0,d:D0})

fit = Fit(ode_model, t=tdata, S=None,E=None,I=adata,R=None,D=None)
fit_result = fit.execute()

print(ode_model)
print(fit_result)

tvec = np.linspace(0, len(seir_simulation["date"]),len(seir_simulation["date"]))
plt.figure(figsize=(10,10))
SEIRD = ode_model(t=tvec, **fit_result.params)
plt.plot(tvec, I, label='[Infectious]')
#plt.plot(tvec, E, label='[E]')
plt.scatter(tdata, adata)
plt.legend()
plt.grid(True)
plt.show()

# + [markdown] slideshow={"slide_type": "slide"}
# ## Model's Limitations:
#
# 1. Our model does not capture the "second" wave we observe in real data. 
#
# 2. Our model assumes immunity post recovery - which is yet to be proven or disproven. 
#
# 3. Out model does not take into account inner circles having higher probability of exposure and infection when a member is infectious. 
#
# 4. Our model does not take into account a shift in activities and their impact on spread of disease. 
#
# 5. Our model does not take into account other factors, such as age, immunodeficiencies, and groups who might be more impacted than others. 
#
# 6. Model is extremely sensitive to perturbations - small changes in parameters lead to significant changes in number of people in Exposed and Infected categories. 

# + [markdown] slideshow={"slide_type": "slide"}
# ## Data's Limitations:
#
# 1. Infected individuals are those who got tested and obtained a positive result - it does not take into account actual cases that were never reported. 
#
# 2. Infected individuals present symptoms - difficult to measure asymptomatic transmission.
#
# 3. Data does not represent accurately whether report is from the same individual at different times. 
#
# 4. Data is based on test accuracy - a false negative means there might be infected people who tested negative, similar to a false positive, i.e. people who are not infected who test as if they were. 
#

# + [markdown] slideshow={"slide_type": "slide"}
# ## Session III Take Away
#
# In this session we learned:
#
# 1. Exploring different values of $\Delta, \beta, \alpha, \gamma, \epsilon$ results in significant differences in the number of infectious people. 
#
# 2. Our model is limited in that it only accounts for a single wave of cases, assumes immunity after recovery, and does not take into account age, health and activity differences in the population. 
#
# 3. Data also brings limitations - as not all true cases are reported or captured in testing. 
#
# 4. It is unclear how significant is the role of asymptomatic transmission from either the data or our model, would be interesting to add a parameter for asymptomatic transmission as well as indirect transmission (touching infected surfaces and then touching one's face for example).

# + [markdown] slideshow={"slide_type": "skip"}
# ## Further reading 
#
# https://people.maths.bris.ac.uk/~madjl/course_text.pdf
#
# Infectious Disease Modelling https://towardsdatascience.com/infectious-disease-modelling-beyond-the-basic-sir-model-216369c584c4
#
# Model adapted from <NAME>., <NAME>., <NAME>, <NAME>, A Simulation of a COVID-19 Epidemic Based on a Deterministic SEIR Model. <b>Frontiers in Public Health</b> Vol 8, 2020 https://www.frontiersin.org/article/10.3389/fpubh.2020.00230   DOI=10.3389/fpubh.2020.00230 

# + [markdown] slideshow={"slide_type": "skip"}
# [![Callysto.ca License](https://github.com/callysto/curriculum-notebooks/blob/master/callysto-notebook-banner-bottom.jpg?raw=true)](https://github.com/callysto/curriculum-notebooks/blob/master/LICENSE.md)

StarcoderdataJupyterScriptsDedupFiltered