Modelling Infectious Disease

During Covid-19, I built a simple model of infectious disease in Typescript and D3.js

A recurring theme during the Covid-19 pandemic has been discussion of the efforts of epidemiologists to model1 the spread of the virus through the population under various proposed scenarios of government measures, such as lockdowns and social distancing.

These efforts have produced column-miles of debate about the efficacy and accuracy of such modelling, and the implications of using taxpayers' money to pay for old, poorly-designed and buggy models to produce policy decisions with enormous implications for the whole society2. Though this topic is fascinating in its own right, I don't propose to weigh in on it here, but merely to present my own toy model, built for amusement purposes only.

Earlier in the course of the pandemic, while locked at home with not much to do, I decided to build a very basic 'SIR' model in javascript, accompanied by some live visualisations of the data made with the D3.js library.

The model looks something like this:

A screenshot of my basic SIR model
My basic SIR model consists of many turtles, bouncing around at random in fixed regions. They're allowed to travel from region to region at random, thus spreading the virus to other segments of the population.

The population is modelled as a collection of disks, which I fancifully named 'turtles'. Initially, a random turtle is infected with the disease, and displayed in a foreboding red colour. Surrounding each infected turtle is a radius of contagion. If any susceptible turtle (show in grey) comes within another turtle's radius of contagion, it risks catching the disease. Whether or not it actually does so is controlled probabilistically.

Each infected turtle remains infectious for a fixed period, and subsequently either dies (shown in bright red) or recovers (shown in green). The proportion of deaths to recoveries is controlled by an Infection Fatality Ratio (IFR). Once recovered, a turtle cannot catch the virus again.

The turtles are confined to fixed regions (by default there are 9). Think of these like separate countries. The turtles have a propensity to travel from one country to another and, like everything else, this is controlled probabilistically. If you play with the model, you'll see some turtles occassionally whipping across from one box to another at random.

And that's pretty much it. There's a near infinite amount of possibility to extend models like this and play with new variables, but I stopped here.

You'll also see on the page a section with sliders to control the variables which influence the model. These are:

  • Total number of turtles
  • Number of regions
  • Size of the infection radius
  • Propensity of a given turtle to switch region
  • Probabilty of an infected turtle infecting a healthy turtle in a given interaction
  • Period each turtle remains infectious
  • Infection fatality ratio

There's also a live chart which shows the evolution of the population in terms of numbers of healthy, infected, recovered and dead turtles.

Chart of turtle population split by health status
The model displays the typical exponential wave of infection through the population.

An immediate observation of interest from playing with the model is the high degree of variability introduced in a highly "dynamical" system like this stochastic behaviour. The following chart was created by running a second simulation with precisely the same settings as produced the screenshot above.

Second chart of turtle population split by health status, using same simulation settings as before
The model is chaotic - the same exact parameters can yield quite different results.

With many configurations of the settings, the spread of the infection is rapid and corresponds to a high RR number3. However, tweaking the settings to have a low infection radius and relatively low probability of infection per interaction, it's possible to generate a simulation where the infection peaks at a fairly low proportion of the population before dying out. Here the effective RR number has reduced below 1 once a portion of the population has recovered, and the case rate dies down. This represents herd immunity.

A chart showing herd immunity reached in the population after the virus spreads
The population can reach herd immunity for diseases with low transmissibility. Once enough people have been infected, the effective rate of transmission drops below 1 infection per infectious individual.

The chart below shows a population which has reached herd immunity, but then has had new cases reintroduced to the population on two further occasions (I did this with the 'Infect Random' button in the control pane). Here, the new outbreaks die out very quickly, again because RR is too low to sustain exponential growth.

A chart showing that once herd immunity is reached, the population remains relatively safe from further outbreaks
Once this population reached herd immunity, it was safe from further outbreaks.

Likely none of this comes as a big surprise, given the simplicity of the model and the fact that 2020 was the year everyone became an armchair epidemiologist, but hopefully it's a fun little widget to play around with.


Further Resources

  • The excellent YouTube channel 3blue1brown has a great video which does a very similar experiment and introduces some additional variables.

  1. Impact of non-pharmaceutical interventions (NPIs) to reduce COVID-19 mortality and healthcare demand, Ferguson, Neil M., et al, March, 2020
  2. A Review of the Ferguson Imperial Model of COVID-19 Infection, Hales, Thomas C., November, 2020
  3. RR refers to the rate of transmission in the sense of number of individuals infected per infectious individual, assuming no measures taken to slow the spread, and assuming all other individuals are susceptible.