```python
from IPython.display import HTML

HTML('''
The raw code for this IPython notebook is by default hidden for easier reading.
To toggle on/off the raw code, click <a href="javascript:code_toggle()">here</a>.''')

```

The raw code for this IPython notebook is by default hidden for easier reading.
To toggle on/off the raw code, click here.

```python
# Modules

import string
import numpy as np
import pandas as pd
import qgrid as q
import matplotlib.pyplot as plt

# Widgets & Display modules, etc..

from ipywidgets import widgets as w
from ipywidgets import Button, Layout, widgets
from IPython.display import display, Javascript, Markdown

# grid features for interactive grids

grid_features = { 'fullWidthRows': True,
                  'syncColumnCellResize': True,
                  'forceFitColumns': True,
                  'rowHeight': 40,
                  'enableColumnReorder': True,
                  'enableTextSelectionOnCells': True,
                  'editable': True,
                  'filterable': False,
                  'sortable': False,
                  'highlightSelectedRow': True}
```

```python
from ipywidgets import Button , Layout , interact,widgets
from IPython.display import Javascript, display

# Function: executes previous cell on button widget click event and hides achievement indicators message

def run_current(ev):

    display(Javascript('IPython.notebook.execute_cell_range(IPython.notebook.get_selected_index()+0,IPython.notebook.get_selected_index()+1)'))

# Counter for toggling achievement indicator on/off

button_ctr = 0

# Achievement Indicators

line_1 = "#### Achievement Indicators"
line_2 = "**General Outcome: **"
line_3 = "* Examine and visualize concepts and examples related to the bubonic plague."
line_4 = "* Examine the timeline/map of the Black Death."
line_5 = "* Visualize mathematical model that shows the recovery, infection, and removal rates."

# Use to print lines, then save in lines_list

def print_lines(n):

    lines_str = ""

    for i in range(1,n+1):
        lines_str = lines_str + "line_"+str(i)+","

    lines_str = lines_str[:-1]

    print(lines_str)

lines_list = [line_1,line_2,line_3,line_4,line_5]

# Show/Hide buttons

ai_button_show = widgets.Button(button_style='info',description="Show Achievement Indicators", layout=Layout(width='25%', height='30px') )
ai_button_hide = widgets.Button(button_style='info',description="Hide Achievement Indicators", layout=Layout(width='25%', height='30px') )

display(Markdown("For instructors:"))
```

For instructors:

```python
button_ctr += 1

if(button_ctr % 2 == 0):

    for line in lines_list:
        display(Markdown(line))

    display(ai_button_hide)
    ai_button_hide.on_click( run_current )

else:

    display(ai_button_show)
    ai_button_show.on_click( run_current )
```

    <IPython.core.display.Javascript object>

#### Achievement Indicators

**General Outcome: **

* Examine and visualize concepts and examples related to the bubonic plague.

* Examine the timeline/map of the Black Death.

* Visualize mathematical model that shows the recovery, infection, and removal rates.

Failed to display Jupyter Widget of type Button.

  If you're reading this message in the Jupyter Notebook or JupyterLab Notebook, it may mean
  that the widgets JavaScript is still loading. If this message persists, it
  likely means that the widgets JavaScript library is either not installed or
  not enabled. See the Jupyter
  Widgets Documentation for setup instructions.

  If you're reading this message in another frontend (for example, a static
  rendering on GitHub or NBViewer),
  it may mean that your frontend doesn't currently support widgets.

Black Death

 $\mid$ Grade 8 $\mid$ Social Sciences $\mid$

Abstract

The **Black Death** is an important historical event, that took place in the XIVth century in Europe. It was an *outbreak* of a disease called the *bubonic plague* that impacted mainly Europe and resulted in the death of roughly half of the European population over the course of five years.

In this notebook we will discuss this disease, the bubonic plague, illustrate the dynamic of how it did spread through Europe during the Black Death period, and illustrate the dramatic effect of the plague over a small English village through a mathematical model.

---

The bubonic plague: an overview

The bubonic plague is a very serious *infectious disease* that has been impacting human population for above two thousand years now. Infectious means that it is caused by a *pathogen*, i.e. a micro-organism that enters the human body and develops within the body, disrupting its normal way to function. This results in an *infection* which, in the case of the bubonic plague, is likely to be fatal unless it is treated by appropriate medications, a plague vaccine.

The pathogen responsible of the bubonic plague is a *bacteria* called *Yersinia pestis*. This name is composed of the Latin name of the plague, *pestis* prefixed by a Latin version of the name of the person who first discovered the bacteria, Alexandre Yersin.

The infection caused by *Yersinia pestis* causes flu-like symptoms such as headaches and a high fever, a common symptom of many infections, together with visible symptoms such as the apparition in some specific parts of the body of swelling (named *bubos*, which gave the name bubonic to the plague) and the development of black spots on the skin, which motivated the "Black Death" name. In general, an untreated patient dies within a few days.

---

Infectious diseases

Infectious diseases, as mentioned above, are caused by pathogens. There are various types of pathogens, including *viruses*, *bacterias* and *parasites*. Viruses causes for example diseases such as the flu (influenza), measles or mumps. Bacterias are responsible for many diseases such as  tuberculosis, or plague. Last parasites are larger micro-organisms, such as roundworms for example; examples of parasitic diseases include malaria or the dengue.

---

How does the bubonic plague pathogen infect humans?

An individual becomes sick with the bubonic plague when the pathogen agent Yersinia pestis enters its body. The most common way this happens is when the individual is bitten by a flea that carries the pathogen in its gut and injects it when biting (it is a little more complicated actually). The flea is called a vector of the disease: it does not cause the disease by itself, but helps the pathogen to move from the environment to within an individual.

It is widely accepted that the kinds of fleas that carry Yersinia pestis are not human fleas (i.e. the kind of fleas that naturally feed on human blood) but rodent fleas, that usually feed on the blood of rats, mice, squirrels, prairie dogs and so on. So why do they suddenly bite humans? This is because the rodents they use to feed on are also infected by the plague agent, and so they die, forcing the fleas to look for other sources of food. If the concerned rodent population (called the reservoir of the disease) lives close to human populations (like urban rats), then the natural new hosts are humans. The figure below illustrates this cycle.

We will get back to this when explaining how the plague spread so well in Europe during the Black Death.

---

Infectious diseases outbreaks

An *outbreak* occurs when a disease, that might have been present or not within a population, suddenly starts to infect more people than usual in a given place (in general a city or a region ). When an outbreak spreads over a larger region it is called an epidemic, or even a pandemic when it happens over a very large region such as a continent.

Outbreaks occur very often. We can think for example to the annual flu outbreak that hits every Canadian city every winter. This is not too scary and the local health authorities know how to handle it, through a campaign of flu vaccination. But even now more serious outbreaks occur quite often, such as the Ebola epidemic in Western Africa in 2013-2016 that caused thousands of death and was very challenging for local and global health authorities.

There has been many other dramatic outbreaks, epidemic and pandemics in history, the Black Death that we will describe below being one of the most present in human memory. But closer to us, we can think about several smallpox epidemic in the late XIXth century that spread through first nations communities of the Pacific North West and had a devastating impact.

---

The Black Death Timeline

The Black Death was a bubonic plague pandemic, that concerned all of Western Europe. It started outside of Europe, in Asia, where it infected soldiers of a Mongol army who were besieging a Genoese trade post in Crimea, the city of Kaffa. After the siege, the Genoese traders (from the Italian city of Geona) sailed back home without knowing they were themselves infected. This is how the disease was introduced in Western Europe, through Italy.

At the time people did not know the principles of infectious diseases and did not intervene quickly to try to conceal the disease to a city or a few cities where the outbreak(s) would have ended likely quickly. Instead, unaware of the dramatic situation that was unfolding, traders from Italian cities maintained very active relationships with the rest of Europe, through marine or land trading routes. This resulted in the disease spreading very fast to Southern Europe within 6 months, and from there turning into a European-wide pandemic within three years.

The dynamic map below illustrates this.

Given there was no precise record of population numbers at this time, it is difficult to have a precise estimation of the number of death. But by analyzing local reports of casualties, historians have arrived to the conclusion that roughly half of the European population at this time died from the bubonic plague. We propose at the end of this notebook a small example based on real data of a 1665 plague outbreak in an English village that illustrates how quickly the bubonic plague can wipe out a community.

```python
%%html

<style>

* {box-sizing:border-box}

/* Slideshow container */
.slideshow-container {
  max-width: 1000px;
  position: relative;
  margin: auto;
}

/* Hide the images by default */
.mySlides {
    display: none;
}

/* Next & previous buttons */
.prev, .next {
  cursor: pointer;
  position: absolute;
  top: 50%;
  width: auto;
  margin-top: -22px;
  padding: 16px;
  color: black;
  font-weight: bold;
  font-size: 18px;
  transition: 0.6s ease;
  border-radius: 0 3px 3px 0;
}

/* Position the "next button" to the right */
.next {
  right: 0;
  border-radius: 3px 0 0 3px;
}

/* On hover, add a black background color with a little bit see-through */
.prev:hover, .next:hover {
  background-color: rgba(0,0,0,0.8);
}

/* Caption text */
.text {
  color: #000000;
  font-size: 15px;
  padding: 8px 12px;
  position: absolute;
  bottom: 8px;
  width: 100%;
  text-align: right;
}

/* Number text (1/3 etc) */
.numbertext {
  color: #f2f2f2;
  font-size: 12px;
  padding: 8px 12px;
  position: absolute;
  top: 0;
}

/* The dots/bullets/indicators */
.dot {
  cursor: pointer;
  height: 15px;
  width: 15px;
  margin: 0 2px;
  background-color: black;
  border-radius: 50%;
  display: inline-block;
  transition: background-color 0.6s ease;
}

.active, .dot:hover {
  background-color: #717171;
}

/* Fading animation */
.fade {
  -webkit-animation-name: fade;
  -webkit-animation-duration: 1.5s;
  animation-name: fade;
  animation-duration: 1.5s;
}

@-webkit-keyframes fade {
  from {opacity: .4}
  to {opacity: 1}
}

@keyframes fade {
  from {opacity: .4}
  to {opacity: 1}
}

</style>

<body>
<div class="slideshow-container">

  <!-- Full-width images with number and caption text -->
  <div class="mySlides">
    <div class="numbertext">1 / 9</div>

    <div class="text">Before Plague</div>
  </div>

  <div class="mySlides">
    <div class="numbertext">2 / 9</div>

    <div class="text">Plague Expansion 1347</div>
  </div>

  <div class="mySlides">
    <div class="numbertext">3 / 9</div>

    <div class="text">Plague Expansion Mid 1348</div>
  </div>

  <div class="mySlides">
    <div class="numbertext">4 / 9</div>

    <div class="text">Plague Expansion Early 1349</div>
  </div>

<div class="mySlides">
    <div class="numbertext">5 / 9</div>

    <div class="text">Plague Expansion Late 1349</div>
  </div>

<div class="mySlides">
    <div class="numbertext">6 / 9</div>

    <div class="text">Plague Expansion by 1350</div>
  </div>

<div class="mySlides">
    <div class="numbertext">7 / 9</div>

    <div class="text">Plague Expansion by 1351</div>
  </div>

<div class="mySlides">
    <div class="numbertext">8 / 9</div>

    <div class="text">Plague Expansion After 1351</div>
  </div>

<div class="mySlides">
    <div class="numbertext">9 / 9</div>

    <div class="text">Minor Outbreak</div>
  </div>

  <!-- Next and previous buttons -->
  <a class="prev" onclick="plusSlides(-1)">❮</a>
  <a class="next" onclick="plusSlides(1)">❯</a>
</div>
<br>

<!-- The dots/circles -->
<div style="text-align:center">
  <span class="dot" onclick="currentSlide(1)"></span>
  <span class="dot" onclick="currentSlide(2)"></span>
  <span class="dot" onclick="currentSlide(3)"></span>
    <span class="dot" onclick="currentSlide(4)"></span>
    <span class="dot" onclick="currentSlide(5)"></span>
    <span class="dot" onclick="currentSlide(6)"></span>
    <span class="dot" onclick="currentSlide(7)"></span>
    <span class="dot" onclick="currentSlide(8)"></span>
    <span class="dot" onclick="currentSlide(9)"></span>
</div>
<figure>
<center>
<figcaption>The Black Death Timeline. Images Retrieved https://en.wikipedia.org/wiki/Consequences_of_the_Black_Death</figcaption>
</center>
</figure>

</body>

```

1 / 9

Before Plague

2 / 9

Plague Expansion 1347

3 / 9

Plague Expansion Mid 1348

4 / 9

Plague Expansion Early 1349

5 / 9

Plague Expansion Late 1349

6 / 9

Plague Expansion by 1350

7 / 9

Plague Expansion by 1351

8 / 9

Plague Expansion After 1351

9 / 9

Minor Outbreak

  ❮
  ❯

The Black Death Timeline. Images Retrieved https://en.wikipedia.org/wiki/Consequences_of_the_Black_Death

Historical plague outbreaks

The Black Death was not the only major plague pandemic. Before this medieval pandemic, in the Vth century (in 541-542 precisely), the *Justinian Plague* developed as an epidemic in the  Eastern part of the Mediteranean region and many Mediterranean port cities. It is known as the first major plague pandemic.

The Black Death itself lasted much longer than the few years illustrated in the map above. The years 1347-1351 correspond to the most acute part of the pandemic. But after this, plague remained present in Europe for almost 400 years, flaring up here and there in dramatic outbreaks, although none that turned into a pandemic. People had learned from the Black Death, and as soon as plague reappeared in a community, the community was isolated to prevent the disease spread. Nevertheless, some important outbreaks impacted large cities such as the Great Plague of London (1665-1666) or the Marseille Plague (1722). This very long pandemic is known as the second major plague pandemic.

Past the Marseille plague in 1722, the disease seemed to disappear from Europe, although it remained present in Asia. This is there, in the Chinese province of the Yunan, in 1855 precisely, that the third major plague pandemic started. It did not move out of China for a long time, but then reached Hong-Kong in 1894, and from there, following again the maritime trade routes, it reached the rest of the world and was considered as an active pandemic by the World Health Organization until 1959.

Currently, there is no bubonic plague pandemic, but outbreaks occur regularly. The most serious ones are in the African island of Madagascar, but there are also regular small outbreaks in the South-West of the United States, where prairie dogs act as a reservoir for the disease.

---

The discovery of the Yersinia pestis bacteria

This is during the 1894 Hong-Kong outbreak of the third pandemic that, finally, scientists discovered the cause of the bubonic plague. Until this date, people did not know what caused this dramatic disease. But during the 1984 outbreak, both French and Japanese authorities sent scientists, Alexandre Yersin for the French side and Kitasato Shibasaburō for the Japanese side, to try to discover the cause of the disease.

Kitasato Shibasaburō (left) and Alexandre Yersin (right)

Both were competing hard to be the first one to find the pathogen causing the disease. Yersin was fortunate enough that his lab was actually a shed with no cooling system, which resulted in the bacteria Yersinia pestis reproducing faster than in the well equipped lab of Shibasaburō, which lead him the finding the tiny micro-organisms in large numbers in the lungs of deceased patients.

---

Was the Black Death a bubonic plague outbreak?

This is actually a good question. Indeed, nobody did the same work than Yersin and  Shibasaburō during the Black Death pandemic. Bacterias were actually not known at the time. So in order to declare it a plague, historians relied on written records from people chronicling the dramatic pandemic. Nevertheless, most chroniclers were not physicians and as such they did not use the medical vocabulary developed in the XIXth century when the mechanisms of infectious diseases were discovered. It did not help that, at the time of the Black Death, the word *plague* was   a generic word used to describe infectious diseases outbreaks in general.

As a result of this lack of precise documentation about the Black Death pandemic, there was a long-standing debate about the cause of this pandemic, with a strongly supported hypothesis that the disease was actually due to an Ebola-like virus.

It is only in 2011, that an international team led by a Canadian scientist, Hendrik Poinar, from McMaster University in Hamilton, was able to extract, from the dental pulp of the body of victims of the Black Death in London, the genome of the bacteria *Yersinia pestis*, thus closing the debate over the actual disease that caused the Black Death.

---

Conclusion

The  Black Death was a dramatic event in European history, as shown by the extant and speed of its spread across the continent.  While it is now a well known event (a plague pandemic), it is interesting to reflect on the fact that this results from tremendous progress of sciences over the last century or so. Our understanding of this pandemic follows up from the discovery of infectious diseases, the precise identification of the plague agent and even very recent work on ancient DNA. The story is however not closed. The Plague stayed in Europe for almost 400 years after the Black Death before disappearing from the continent; it is still an open question to understand both how a disease can last for so long and why it can vanish quite suddenly with no human intervention.

---

Modeling a Bubonic Plague Outbreak

 $\mid$ Grade 11 $\mid$ Social Sciences $\mid$

We are interested in modeling a bubonic plague outbreak. We part from the assumption that the total population can be subdivided into a set of classes, each of which depends on the state of the infection. The **SIR Model** is the simplest one and, as its name suggests, it divides the population into three classes.

The SIR Outbreak Model

### Population Parameters

In this model, the total population considered is divided into three groups of individuals:

* Susceptible: the individuals that are not infected but can become infected
* Infected: the individuals that are infected
* Removed: the individuals that are either dead (the pessimistic point of view) or survived

We are concerned about the predicting the changes, over the course of an outbreak, of the **number of people who are susceptible**, the **number of people who are infected**, and the **number of people who are removed**. We denote these parameters to be $S, I, R$ respectively. In other words we want to understand how, when time passes, the number of individuals in each group evolves.

If we have a realistic model, then it might be useful to predict the long-term outcome of an outbreak and inform public health interventions. For example if we can predict that the number of removed people will stay low and the number of infected people will quickly go down to zero, then there is no need to intervene and we can let the outbreak ends by itself, only taking care to provide medical attention to the infected people. Conversely if we predict a large increase of the numbers of infected and removed individuals, then the outbreak needs a quick intervention to be tamed before it touches too many people and results in a large number of casualties. In a plague outbreak this intervention would for example be to make sure there is no contact between infected and susceptible people.

We now describe the SIR mathematical model (SIR stands for Susceptible, Infected, Removed) of an outbreak. We assume we record the number of individuals at several time points (for example every week). We write $S_n, I_n, R_n$ to denote the number, respectively, of susceptible, infected and removed individuals at time point $n$ (with $n=1$ being the first recorded time point, $n=2$ the second and so on). We call *time unit* the time elapsed between two time points.

In this model, we assume that the **total population is constant** (so births and deaths are ignored) for the duration of the model simulation. We denote the total population size by $N$, and so at any time point $n$ we have $$N=S_n + I_n + R_n.$$

### Modelling the outbreak / disease progression

We assume that a susceptible individual can become infected only by contact with an already infected individual. Once infected, we assume that the disease takes a constant amount of time to progress within an individual until he/she is removed (i.e. either dies or recovers). So there are two processes in play: infection and removal. We need to define these processes and model how they impact the transition from a state of the population at time point $n$, described by the triplet of numbers  $(S_n,I_n,R_n)$, to the next state $(S_{n+1},I_{n+1},R_{n+1})$ at time point $n+1$.

The occurrences of new infections of is modeled using a parameter $\beta$, that gives the proportion of contacts between susceptible people and infected people, during one time unit, that results in a susceptible being infected. Then we can describe the number of newly infected people  as $\dfrac{\beta S_n I_n}{N}$, where the term $S_n I_n$ represents the set of all possible contacts between susceptible and infected individuals. We discuss this term later.

The occurrence of removals of infected people is modeled using a parameter denoted by $\gamma$. It is defined to be proportion of infected individuals that die or recover between two time points. If we are given that the duration of an infection is $T$ (i.e. how many time points it takes for an individual between its infection and its removal), then $\gamma = \dfrac{1}{T}$.

Taking into account the rate of contact $\beta$ and rate of removal $\gamma$, then each group population changes within one unit of time (i.e. between two successive time points) as follows

$$
\begin{align}
S_{n+1} &= S_n -  \dfrac{{\beta} S_n I_n}{N}\\
I_{n+1} &= I_n +  \dfrac{{\beta} S_n I_n}{N} - \gamma I_n \\
R_{n+1} &= R_n + \gamma I_n\\
N&=S_n + I_n + R_n
\end{align}
$$

These equations form the SIR model. They allow, from knowing the parameters of the model (i.e. the characteristics of the disease outbreak at play, $\beta$ and $\gamma$) and the current state $(S_n,I_n,R_n)$ of a population to predict the next states of the population for later time points. Such models are critical in our days for monitoring and controlling infectious diseases outbreaks.

##### Technical remarks.
First, note that the SIR model does not enforce that the values $S_n,I_n,R_n$ at a given time point are integers. As $\beta$ and $\gamma$ are actually floating numbers, these values are actually most of the time not integers. This is fine as the SIR model is an approximate model and aims mostly at predicting the general dynamics of an outbreak, not the precise values for the number of susceptible, infected and removed individuals.

Next, one can ask how to find the values of the parameters $\beta$ and $\gamma$, that are necessary to have a full SIR model.

As discussed above, the parameter $\gamma$ is relatively easy to find from knowing how the disease progress in a patient, as it is mostly the inverse of the average time a patient is sick.

The parameter $\beta$ is less easy to obtain. Reading the equations , we can see that during a time point, out of the $S_n$ susceptible individuals, the number that get infected is $(\dfrac{{\beta}}{N}) S_n I_n$. As mentioned above, the product $S_nI_n$ can be interpreted as the set of all possible contacts between the $S_n$ susceptible individuals and the $I_n$ infected individuals and is often a large number, much larger than $S_n$ and in the order of $N^2$. The division by $N$ aims to lower this number, mostly to normalize it by the total population, to make sure it is in order of $N$ and not quadratic in $N$. So in order for the number of newly infected individuals during a time unit to be reasonable, $\beta$ is generally a  small number between $0$ and $1$. But formally, if we pick a value for $\beta$ that is too large, then the SIR model will predict value for $S_n$ that can be negative, which is inconsistent with the modeled phenomenon. So choosing the value of $\beta$ is the crucial step in modelling an outbreak.

---

```python
# This function takes as input a vector y holding all initial values,
#    n the number of time points
#    beta: beta parameter of the SIR
#    gamma: gamma parameter of the SIR
#    S1,I1,R1 = initial values

def discrete_SIR(S1,I1,R1,n,beta,gamma):
    # Empy arrays for each class
    S = []
    I = []
    R = []
    N = S1+I1+R1

    # Append initial values
    S.append(S1)
    I.append(I1)
    R.append(R1)

    # apply SIR model: iterate over the total number of days - 1
    for i in range(n-1):
        S_next = S[i] - (beta/N)*((S[i]*I[i]))
        S.append(S_next)

        I_next = I[i] + (beta/N)*((S[i]*I[i])) - gamma*I[i]
        I.append(I_next)

        R_next = R[i] + gamma * I[i]
        R.append(R_next)

    # return arrays S,I,R whose entries are various values for susceptible, infected, removed
    return((S,I,R))
```

 Modeling an outbreak related to the Great Plague of London

Between 1665 and 1666 occurred the last major epidemic of the bubonic plague in England ([click here for further reading](https://www.britannica.com/event/Great-Plague-of-London)). This epidemic did not kill as many people as the Black Death (1347 - 1351), however it is remembered as the "Great Plague of London" as it was the last widespread outbreak that affected England.

"City records indicate that some 68,596 people died during the epidemic, though the actual number of deaths is suspected to have exceeded 100,000 out of a total population estimated at 460,000. " [Great Plague of London"; Encyclopædia Britannica; Encyclopædia Britannica, inc.; September 08, 2016](https://www.britannica.com/event/Great-Plague-of-London)

When the bubonic plague outbreak hit London, people started to leave the city and go to the countryside, hoping to avoid the disease. But as can be expected, some of these people were already infected when they left London, and so carried the disease to start other outbreaks in some nearby villages. This happened in the village of Eyam. When Eyam authorities realized a plague outbreak had started, they took the difficult decision to close the village in order to avoid to spread the disease further. So nobody was allowed to enter or leave the village and people stayed there hoping the outbreak would end by itself without too many casualties; note that from a mathematical point of view, that implies that the assumption that the sum of the numbers of susceptible, infected and removed individuals, the population, is constant. And also the village authorities recorded regularly the number of infected and dead people; these data are described in the table below, for the period from June 19 1665 to October 19 1665, with data being recorded every 2 weeks. Obviously this data is imperfect (some people did not declare they were sick by fear of being ostracized, some people died too fast for the plague to be diagnosed, ...), but nevertheless, they provide us with interesting data to see if the SIR model is an appropriate model for such a plague outbreak.

| Date  |Day Number |Susceptible | Infected |
|-------||-------------|----------|
|June 19 1665|0|254|7|
|July 3 1665|14|235|14|
|July 19 1665|28|201|22|
|Aug 3 1665|42|153|29|
|Aug 19 1665|56|121| 21|
|Sept 3 1665|70|108|8|
|Sept 19 1665|84|121|21|
|Oct 3 1665| 98|NA | NA|
|Oct 19 1665|112| 83 | 0|

The average time an infected individual remains infected by the bubonic plague is 11 days.

With the information above, we will be able to get the parameters of the SIR model for this outbreak and observe if indeed what this model predicts generates results corresponding to what happened in reality.

### Question 1:

Assuming that on June 19 no individuals had deceased, i.e. no one was in the Removed class, what is the value of $N$, i.e. the size (number of individuals) of the total population?

```python
from ipywidgets import interact_manual, widgets
# define style
s = {'description_width': 'initial'}

# Run Interact Button parameters
@interact_manual(answer=widgets.Textarea(
    value=' ',
    placeholder='Type something',
    description='What is the total population?',
    disabled=False,
    style=s
))

# Get correct answer
def get_pop(answer):
    if "261" in answer or answer=="Two hundred and sixty one":
        print("Correct! \nThe total population is given by S_1 + I_1 + R_1 = 254 + 7 + 0  = 261.")
    else:
        print("That does not look ok. Try again.\n \nRemember: N = S_1 + I_1 + R_1.\n \nS_1 = 254, I_1 = 7, R_1 = 0.");
```

Failed to display Jupyter Widget of type interactive.

  If you're reading this message in the Jupyter Notebook or JupyterLab Notebook, it may mean
  that the widgets JavaScript is still loading. If this message persists, it
  likely means that the widgets JavaScript library is either not installed or
  not enabled. See the Jupyter
  Widgets Documentation for setup instructions.

  If you're reading this message in another frontend (for example, a static
  rendering on GitHub or NBViewer),
  it may mean that your frontend doesn't currently support widgets.

```python
print("Press the Run Interact Button to Obtain the True Answer")
# Reveal true answer
def true_population():
    print("Since we are assuming the population is constant, and since S_1 = 254, I_1 = 7, R_1 = 0, then \nfrom our model we know N = 254 + 7 + 0 = 261.")

interact_manual(true_population);
```

    Press the Run Interact Button to Obtain the True Answer

Failed to display Jupyter Widget of type interactive.

  If you're reading this message in the Jupyter Notebook or JupyterLab Notebook, it may mean
  that the widgets JavaScript is still loading. If this message persists, it
  likely means that the widgets JavaScript library is either not installed or
  not enabled. See the Jupyter
  Widgets Documentation for setup instructions.

  If you're reading this message in another frontend (for example, a static
  rendering on GitHub or NBViewer),
  it may mean that your frontend doesn't currently support widgets.

### Question 2:

We know that the average time an individual remained infected is 11 days. With this information in mind, what is the rate of removal $\gamma$?

```python
from ipywidgets import interact_manual, widgets
# Define style
s = {'description_width': 'initial'}

# Set parameters for Run Interact button
@interact_manual(answer=widgets.Textarea(
    value=' ',
    placeholder='Type something',
    description='What is the value of $\gamma$?',
    disabled=False,
    style=s
))

# Set correct answer
def correct_answer(answer):
    if "1/11" in answer:
        print("Correct! \nThe rate of removal is equal to 1/11=0.0909..., as it takes on average 11 days for an individual to remain infected.")
    else:
        print("That does not look ok. Try again. \n \nRemember: 1 individual dies every 11 days.");
```

Failed to display Jupyter Widget of type interactive.

  If you're reading this message in the Jupyter Notebook or JupyterLab Notebook, it may mean
  that the widgets JavaScript is still loading. If this message persists, it
  likely means that the widgets JavaScript library is either not installed or
  not enabled. See the Jupyter
  Widgets Documentation for setup instructions.

  If you're reading this message in another frontend (for example, a static
  rendering on GitHub or NBViewer),
  it may mean that your frontend doesn't currently support widgets.

```python
print("Press the Run Interact Button to Obtain the True Answer")

# reveal true value of gamma
def true_gamma():
    print("We know that, on average, every 11 days an infected person dies. \nThis is equivalent to stating that 1 individual moves to the removed class for every 11 days. \nWe can express this idea mathematically as 1/11.")

interact_manual(true_gamma);
```

    Press the Run Interact Button to Obtain the True Answer

Failed to display Jupyter Widget of type interactive.

  If you're reading this message in the Jupyter Notebook or JupyterLab Notebook, it may mean
  that the widgets JavaScript is still loading. If this message persists, it
  likely means that the widgets JavaScript library is either not installed or
  not enabled. See the Jupyter
  Widgets Documentation for setup instructions.

  If you're reading this message in another frontend (for example, a static
  rendering on GitHub or NBViewer),
  it may mean that your frontend doesn't currently support widgets.

### Question 3:

We are now trying something more difficult but more interesting. We introduced a mathematical model for outbreaks, but nothing so far shows that this SIR model is appropriate to model an outbreak such as the Eyam plague outbreak. we want to answer this question now.

From questions 1 and 2 above, we know the values of $N$ and $\gamma$. From the data table we also know $S_1,I_1,R_1$, the state of the population aty the start of the outbreak. So if we want to apply the SIR model we need to find  a value for $\beta$ the parameter involved in the equation giving the number susceptible people becoming infected during a time uni. We consider here that a time unit is 1 day; the Eyam outbreak spanned 112 days, so 112 time units, even if data were recorded every 2 weeks only.

A standard scientific approach for the problem of finding $\beta$ is to try various values and see if there is one that leads to predicted values for $S_n,I_n,R_n$ for various time points that match the observed data given in the data table. In order to evaluate this match, we focus on the number of infected people, the most important element of an outbreak.

The activity below allows you to do this: you can choose a value of $\beta$, click on the "Run interact" button and it will show on the same graph a set of 8 blue dots (the true number of infected people from the data table) and a set of 112 red dots, corresponding to the predicted number of infected individuals for the chosen value of $\beta$.

While there are several mathematical ways to define what would be the *best fit*, here we are not getting into this and you are just asked to try to find a value of $\beta$ that generated blue dots being more or less on the graph defined by the red dots.

##### Warning.
The SIR model is a very simple approximation of the dynamics of a true outbreak, so do not expect to find a value of $\beta$ that generates a graph that contains exactly all data points (blue dots). In particular note that the data points of September 3 and 19 seem to be somewhat of an anomaly as we observe a sharp decrease in the number of infected followed by a surge. This could be due to many reasons, for example poor statistics recording (we are considering a group of people under heavy stress likely more motivated by trying to stay alive than to record accurate vital statistics). So here we are interested in finding a parameter $\beta$ that captures the general dynamics (increase followed by a post-peak decrease) of the outbreak. You can expect to find a reasonable value for $\beta$ but be aware that many values, especially too high, will result in a very poor match between real data and model predictions.

```python
from ipywidgets import interact_manual, widgets
import matplotlib.pyplot as plt

# set style
s = {'description_width': 'initial'}

# Set interact manual box widget for beta
@interact_manual(answer=widgets.FloatText(
    value=1.50,
    description='Enter a value for ' + r'$ \beta$',
    disabled=False,
    style = s,
    step=0.01
))

# define function to find the appropriate value of beta
# this function takes as input a floating value and outputs a plot with the best fit curve
def find_beta(answer):

    # set initial values for SIR model
    S1,I1,R1 = 254,7,0

    # Use original data on Number of infected from table in the notebook
    ori_data = [7,14,22,29,21,8,21,0]

    # use days, time data was provided biweekly, we transform to days here
    ori_days = [1,14,28,42,56,70,84,112]

    # set number of days as the second to last entry on the ori_days array
    n = ori_days[len(ori_days)-1]-ori_days[0]+1

    # get beta from answer - to be sure transform to float
    beta = float(answer)

    # Gamma was obtained from disease
    gamma = 1/11

    # Compute SIR values using our discrete_SIR function
    (S,I,R) = discrete_SIR(S1,I1,R1,n,beta,gamma)

    # Figure
    fig,ax = plt.subplots(figsize=(10,10))

    # Scatter plot of original number of infected in the course of 112 days
    plt.scatter(ori_days,ori_data,c="blue", label="Original data")

    # Scatter plot of infected obtained from SIR mode, in the course of 112 days
    plt.scatter(range(n),I,c="red",label="SIR Model Predictions")

    # Make the plot pretty
    plt.xlabel('Time (days)')
    plt.ylabel('Infected Individuals')
    plt.title('Real Data vs Model')
    legend = ax.legend()
    plt.show()
```

Failed to display Jupyter Widget of type interactive.

  If you're reading this message in the Jupyter Notebook or JupyterLab Notebook, it may mean
  that the widgets JavaScript is still loading. If this message persists, it
  likely means that the widgets JavaScript library is either not installed or
  not enabled. See the Jupyter
  Widgets Documentation for setup instructions.

  If you're reading this message in another frontend (for example, a static
  rendering on GitHub or NBViewer),
  it may mean that your frontend doesn't currently support widgets.

```python
print("Press the Run Interact Button to Obtain the True Answer")

def true_beta():
    print('The best value for Beta is approximately   0.14909440503418078.')

interact_manual(true_beta);
```

    Press the Run Interact Button to Obtain the True Answer

Failed to display Jupyter Widget of type interactive.

  If you're reading this message in the Jupyter Notebook or JupyterLab Notebook, it may mean
  that the widgets JavaScript is still loading. If this message persists, it
  likely means that the widgets JavaScript library is either not installed or
  not enabled. See the Jupyter
  Widgets Documentation for setup instructions.

  If you're reading this message in another frontend (for example, a static
  rendering on GitHub or NBViewer),
  it may mean that your frontend doesn't currently support widgets.

Simulating a Disease Outbreak

To conclude, we will use the widgets below to simulate a disease outbreak using the SIR model.
You can chose the values of all the elements of the model (sizes of the compartments of the population at the beginning of the outbreak, parameters $\gamma$ and $\beta$, duration in days (one time unit is one day then) of the outbreak. The default parameters are the ones of the Eyam plague outbreak.

The result is a series of three graphs that shows how the three compartment of the population evolve during the outbreak. It gives you the possibility to appreciate visually the impact of changes in the parameters $\gamma$ and $\beta$, such as increasing $\beta$ (making the outbreak progress faster) or reducing $\gamma$ (i.e. reducing the rate of removal).

You can use this interactive tool to try to apply by hand the SIR model with simple parameters and see if your calculations match with the model outcome.

```python
import matplotlib.pyplot as plt
import numpy as np
from math import ceil

# This function takes as input initial values of susceptible, infected and removed, number of days, beta and gamma
# it plots the SIR model with the above conditions
def plot_SIR(S1,I1,R1,n,beta,gamma):

    # Initialize figure
    fig = plt.figure(facecolor='w',figsize=(17,5))
    ax  = fig.add_subplot(111,facecolor = '#ffffff')

    # Compute SIR values for our initial data and parameters
    (S_f,I_f,R_f) = discrete_SIR(S1,I1,R1,n,beta,gamma)

    # Set x axis
    x = [i for i in range(n)]

    # Scatter plot of evolution of susceptible over the course of x days
    plt.scatter(x,S_f,c= 'b',label='Susceptible')

    # Scatter plot of evolution of infected over the course of x days
    plt.scatter(x,I_f,c='r',label='Infected')

    # Scatter plot of evolution of removed over the course of x days
    plt.scatter(x,R_f,c='g',label='Removed')

    # Make the plot pretty
    plt.xlabel('Time (days)')
    plt.ylabel('Number of individuals')
    plt.title('Simulation of a disease outbreak using the SIR model')
    legend = ax.legend()
    plt.show()

    # Print messages to aid student understand and interpret what is happening in the plot
    print("SIMULATION DATA\n")
    print("Beta: " + str(beta))
    print("Gamma: " + str(gamma))
    print("\n")
    print("Initial Conditions:")
    print("Total number of Susceptible: "  + str(ceil(S_f[0])))
    print("Total number of Infected: "  + str(ceil(I_f[0])))
    print("Total number of Removed: "  + str(ceil(R_f[0])))
    print("\n")
    print("After " + str(n) + " days:")
    print("Total number of Susceptible: "  + str(ceil(S_f[n-1])))
    print("Total number of Infected: "  + str(ceil(I_f[n-1])) )
    print("Total number of Removed: "  + str(ceil(R_f[n-1])))
# Tweaking initial Values
from ipywidgets import widgets, interact, interact_manual

# Set function above so that the user can set all parameters and manually start simulation
s = {'description_width': 'initial'}
interact_manual(plot_SIR,
        S1  =widgets.IntSlider(value = 254,
                               min = 200,
                               max = 1000,
                               step = 1,
                               style=s,
                               description="Susceptible Initial",
                               disabled=False,
                               orientation='horizontal',
                               readout=True),
        I1 = widgets.IntSlider(value = 7,
                               min = 0,
                               max = 500,
                               step = 1,
                               style=s,
                               description="Infected Initial",
                               disabled=False,
                               orientation='horizontal',
                               readout=True),
         R1 = widgets.IntSlider(value = 0,
                               min = 0,
                               max = 500,
                               step = 1,
                               style=s,
                               description="Removed Initial",
                               disabled=False,
                               orientation='horizontal',
                               readout=True),
         n = widgets.IntSlider(value = 112,
                               min = 0,
                               max = 500,
                               step = 1,
                               style=s,
                               description="Time (days)",
                               disabled=False,
                               orientation='horizontal',
                               readout=True),
         beta = widgets.FloatText(
    value=1.50,
    description=r'$ \beta$ parameter',
    disabled=False,
    style = s,
    step=0.01
),
        gamma = widgets.FloatText(
    value=1.50,
    description= r'$ \gamma$ parameter',
    disabled=False,
    style = s,
    step=0.01
)
        );
```

Failed to display Jupyter Widget of type interactive.

  If you're reading this message in the Jupyter Notebook or JupyterLab Notebook, it may mean
  that the widgets JavaScript is still loading. If this message persists, it
  likely means that the widgets JavaScript library is either not installed or
  not enabled. See the Jupyter
  Widgets Documentation for setup instructions.

  If you're reading this message in another frontend (for example, a static
  rendering on GitHub or NBViewer),
  it may mean that your frontend doesn't currently support widgets.

Conclusion

In this notebook we learned about the SIR discrete model to model an outbreak. We learned that this model is one of the simplest ones and that it separates the total population $N$ (a constant) into three categories: Infected, Susceptible and Removed. We learned about rates of infection and removal and how this affects the number of individuals in each class.

We also ran a basic but realistic simulation of a bubonic plague outbreak of the Great Plague of London that took place in the village Eyam in 1665 and learned about the devastating effect this had on the population.

```python
# Counter for toggling achievement indicator on/off

photo_ctr = 0

# Photo sources

#### Picture Sources:

pline_1 = "#### Picture Sources"
pline_2 = "The sources of pictures (ordered by appearance in the notebook from top to bottom) are listed below:"
pline_2 = "[1] The plague transmission cycle. http://www.columbia.edu/itc/cerc/danoff-burg/invasion_bio/inv_spp_summ/Yersinia_pestis.htm on June 13, 2018."
pline_3 = "[2] The Black Death Timeline. https://en.wikipedia.org/wiki/Consequences_of_the_Black_Death and modified by notebook authors."
pline_4 = "[3] Kitasato Shibasaburō (left) and Alexandre Yersin (right). Left image retrieved from https://commons.wikimedia.org/wiki/File:Shibasaburo_Kitasato.jpg ; Right image retrieved from https://en.wikipedia.org/wiki/Alexandre_Yersin#/media/File:Petit-Yersin.jpg"

# Use to print lines, then save in lines_list

def print_plines(n):

    lines_str = ""

    for i in range(1,n+1):
        lines_str = lines_str + "pline_"+str(i)+","

    lines_str = lines_str[:-1]

    print(lines_str)

plines_list = [pline_1,pline_2,pline_3,pline_4]

# Show/Hide buttons

ps_button_show = widgets.Button(button_style='info',description="Show Picture Sources", layout=Layout(width='25%', height='30px') )
ps_button_hide = widgets.Button(button_style='info',description="Hide Picture Sources", layout=Layout(width='25%', height='30px') )
```

```python
photo_ctr += 1

if(photo_ctr % 2 == 0):

    for pline in plines_list:
        display(Markdown(pline))

    display(ps_button_hide)
    ps_button_hide.on_click( run_current )

else:

    display(ps_button_show)
    ps_button_show.on_click( run_current )
```

    <IPython.core.display.Javascript object>

#### Picture Sources

[1] The plague transmission cycle. http://www.columbia.edu/itc/cerc/danoff-burg/invasion_bio/inv_spp_summ/Yersinia_pestis.htm on June 13, 2018.

[2] The Black Death Timeline. https://en.wikipedia.org/wiki/Consequences_of_the_Black_Death and modified by notebook authors.

[3] Kitasato Shibasaburō (left) and Alexandre Yersin (right). Left image retrieved from https://commons.wikimedia.org/wiki/File:Shibasaburo_Kitasato.jpg ; Right image retrieved from https://en.wikipedia.org/wiki/Alexandre_Yersin#/media/File:Petit-Yersin.jpg

Failed to display Jupyter Widget of type Button.

  If you're reading this message in the Jupyter Notebook or JupyterLab Notebook, it may mean
  that the widgets JavaScript is still loading. If this message persists, it
  likely means that the widgets JavaScript library is either not installed or
  not enabled. See the Jupyter
  Widgets Documentation for setup instructions.

  If you're reading this message in another frontend (for example, a static
  rendering on GitHub or NBViewer),
  it may mean that your frontend doesn't currently support widgets.