JSXGraph logo
JSXGraph
JSXGraph share

Share

Epidemiology: SIR model
QR code
<iframe 
    src="https://www.jsxgraph.uni-bayreuth.de/share/iframe/epidemiology-sir-model" 
    style="border: 1px solid black; overflow: hidden; width: 550px; aspect-ratio: 55 / 65;" 
    name="JSXGraph example: Epidemiology: SIR model" 
    allowfullscreen
></iframe>
This code has to
<input type="button" value="clear and run a simulation of 100 days" onClick="clearTurtle(); run()"><br/>
<input type="button" value="stop" onClick="stop()"><br/>
<input type="button" value="continue" onClick="goOn()">

<div id="board-0-wrapper" class="jxgbox-wrapper " style="width: 100%; ">
   <div id="board-0" class="jxgbox" style="aspect-ratio: 1 / 1; width: 100%;" data-ar="1 / 1"></div>
</div>

<script type = "text/javascript"> 
    /*
    This example is licensed under a 
    Creative Commons Attribution 4.0 International License.
    https://creativecommons.org/licenses/by/4.0/
    
    Please note you have to mention 
    The Center of Mobile Learning with Digital Technology
    in the credits.
    */
    
    const BOARDID = 'board-0';

    const board = JXG.JSXGraph.initBoard(BOARDID, {
        axis: true,
        boundingbox: [-5, 1.2, 100, -1.2],
        showNavigation: false
    });
    
    // Turtles
    var S = board.create('turtle', [], {
        strokeColor: 'blue',
        strokeWidth: 3
    });
    var I = board.create('turtle', [], {
        strokeColor: 'red',
        strokeWidth: 3
    });
    var R = board.create('turtle', [], {
        strokeColor: 'green',
        strokeWidth: 3
    });
    
    // Sliders
    var s = board.create('slider', [
        [0, -0.6],
        [30, -0.6],
        [0, 1.27E-6, 1]
    ], {
        name: 's'
    });
    board.create('text', [10, -0.3, "initially infected population rate (on load: I(0)=1.27E-6)"]);
    var beta = board.create('slider', [
        [0, -0.7],
        [30, -0.7],
        [0, 0.5, 1]
    ], {
        name: 'β'
    });
    board.create('text', [45, -0.7, "β: infection rate"]);
    var gamma = board.create('slider', [
        [0, -0.8],
        [30, -0.8],
        [0, 0.3, 1]
    ], {
        name: 'γ'
    });
    board.create('text', [45, -0.8, "γ: recovery rate = 1/(days of infection)"]);
    
    var t = 0; // global
    
    board.create('text', [10, -0.2,
        function() {
            return "Day " + t + ": infected=" + (7900000 * I.Y()).toFixed(1) + " recovered=" + (7900000 * R.Y()).toFixed(1);
        }
    ]);
    
    // Reset the turtles
    var clearTurtle = function () {
      S.cs();
      I.cs();
      R.cs();
    
      S.hideTurtle();
      I.hideTurtle();
      R.hideTurtle();
    };
    
    // Start the animation
    var run = function() {
        S.setPos(0, 1.0 - s.Value());
        R.setPos(0, 0);
        I.setPos(0, s.Value());
    
        delta = 1; // global
        t = 0; // global
        loop();
    };
    
    var turtleMove = function (turtle, dx, dy) {
        turtle.moveTo([dx + turtle.X(), dy + turtle.Y()]);
    };
    
    // Animation
    var loop = function() {
        var dS = -beta.Value() * S.Y() * I.Y();
        var dR = gamma.Value() * I.Y();
        var dI = -(dS + dR);
        turtleMove(S, delta, dS);
        turtleMove(R, delta, dR);
        turtleMove(I, delta, dI);
    
        t += delta;
        if (t < 100.0) {
            active = setTimeout(loop, 10);
        }
    };
    
    // Stop animation
    var stop = function() {
        if (active) clearTimeout(active);
        active = null;
    };
    
    // Continue
    var goOn = function() {
        if (t > 0) {
            if (active === null) {
                active = setTimeout(loop, 10);
            }
        } else {
            run();
        }
    };
    
    clearTurtle();
 </script> 
/*
This example is licensed under a 
Creative Commons Attribution 4.0 International License.
https://creativecommons.org/licenses/by/4.0/

Please note you have to mention 
The Center of Mobile Learning with Digital Technology
in the credits.
*/

const BOARDID = 'your_div_id'; // Insert your id here!

const board = JXG.JSXGraph.initBoard(BOARDID, {
    axis: true,
    boundingbox: [-5, 1.2, 100, -1.2],
    showNavigation: false
});

// Turtles
var S = board.create('turtle', [], {
    strokeColor: 'blue',
    strokeWidth: 3
});
var I = board.create('turtle', [], {
    strokeColor: 'red',
    strokeWidth: 3
});
var R = board.create('turtle', [], {
    strokeColor: 'green',
    strokeWidth: 3
});

// Sliders
var s = board.create('slider', [
    [0, -0.6],
    [30, -0.6],
    [0, 1.27E-6, 1]
], {
    name: 's'
});
board.create('text', [10, -0.3, "initially infected population rate (on load: I(0)=1.27E-6)"]);
var beta = board.create('slider', [
    [0, -0.7],
    [30, -0.7],
    [0, 0.5, 1]
], {
    name: 'β'
});
board.create('text', [45, -0.7, "β: infection rate"]);
var gamma = board.create('slider', [
    [0, -0.8],
    [30, -0.8],
    [0, 0.3, 1]
], {
    name: 'γ'
});
board.create('text', [45, -0.8, "γ: recovery rate = 1/(days of infection)"]);

var t = 0; // global

board.create('text', [10, -0.2,
    function() {
        return "Day " + t + ": infected=" + (7900000 * I.Y()).toFixed(1) + " recovered=" + (7900000 * R.Y()).toFixed(1);
    }
]);

// Reset the turtles
var clearTurtle = function () {
  S.cs();
  I.cs();
  R.cs();

  S.hideTurtle();
  I.hideTurtle();
  R.hideTurtle();
};

// Start the animation
var run = function() {
    S.setPos(0, 1.0 - s.Value());
    R.setPos(0, 0);
    I.setPos(0, s.Value());

    delta = 1; // global
    t = 0; // global
    loop();
};

var turtleMove = function (turtle, dx, dy) {
    turtle.moveTo([dx + turtle.X(), dy + turtle.Y()]);
};

// Animation
var loop = function() {
    var dS = -beta.Value() * S.Y() * I.Y();
    var dR = gamma.Value() * I.Y();
    var dI = -(dS + dR);
    turtleMove(S, delta, dS);
    turtleMove(R, delta, dR);
    turtleMove(I, delta, dI);

    t += delta;
    if (t < 100.0) {
        active = setTimeout(loop, 10);
    }
};

// Stop animation
var stop = function() {
    if (active) clearTimeout(active);
    active = null;
};

// Continue
var goOn = function() {
    if (t > 0) {
        if (active === null) {
            active = setTimeout(loop, 10);
        }
    } else {
        run();
    }
};

clearTurtle();

Epidemiology: SIR model

This is an example of simulation of differential equations with __turtle graphics__. ### SIR model without vital dynamics The SIR model measures the number of susceptible, infected, and recovered individuals in a host population. Given a fixed population, let $S(t)$ be the fraction that is susceptible to an infectious, but not deadly, disease at time $t$, let $I(t)$ be the fraction that is infected at time $t$ and let $R(t)$ be the fraction that has recovered. Let $\beta$ be the rate at which an infected person infects a susceptible person. Let $\gamma$ be the rate at which infected people recover from the disease. A single epidemic outbreak is usually far more rapid than the vital dynamics of a population, thus, if the aim is to study the immediate consequences of a single epidemic, one may neglect birth-death processes. In this case the SIR system can be expressed by the following set of differential equations: $$ \begin{aligned} \frac{dS}{dt} &= - \beta I S \\ \frac{dR}{dt} &= \gamma I \\ \frac{dI}{dt} &= -(\frac{dS}{dt}+\frac{dR}{dt}) \end{aligned} $$ ### Example Hong Kong flu - initially 7.9 million people, - 10 infected, - 0 recovered. - estimated average period of infection: 3 days, so $\gamma = 1/3$ - infection rate: one new person every other day, so $\beta = 1/2$ Thus $S(0) = 1$, $I(0) = 1.27E-6$, $R(0) = 0$, see [https://www.cs.princeton.edu/introcs/94diffeq/](https://www.cs.princeton.edu/introcs/94diffeq/). The lines in the JSXGraph-simulation below have the following meaning: - Blue: Rate of susceptible population - Red: Rate of infected population - Green: Rate of recovered population (which means: immune, isolated or dead)


<input type="button" value="clear and run a simulation of 100 days" onClick="clearTurtle(); run()"><br/>
<input type="button" value="stop" onClick="stop()"><br/>
<input type="button" value="continue" onClick="goOn()">
// Define the id of your board in BOARDID

const board = JXG.JSXGraph.initBoard(BOARDID, {
    axis: true,
    boundingbox: [-5, 1.2, 100, -1.2],
    showNavigation: false
});

// Turtles
var S = board.create('turtle', [], {
    strokeColor: 'blue',
    strokeWidth: 3
});
var I = board.create('turtle', [], {
    strokeColor: 'red',
    strokeWidth: 3
});
var R = board.create('turtle', [], {
    strokeColor: 'green',
    strokeWidth: 3
});

// Sliders
var s = board.create('slider', [
    [0, -0.6],
    [30, -0.6],
    [0, 1.27E-6, 1]
], {
    name: 's'
});
board.create('text', [10, -0.3, "initially infected population rate (on load: I(0)=1.27E-6)"]);
var beta = board.create('slider', [
    [0, -0.7],
    [30, -0.7],
    [0, 0.5, 1]
], {
    name: 'β'
});
board.create('text', [45, -0.7, "β: infection rate"]);
var gamma = board.create('slider', [
    [0, -0.8],
    [30, -0.8],
    [0, 0.3, 1]
], {
    name: 'γ'
});
board.create('text', [45, -0.8, "γ: recovery rate = 1/(days of infection)"]);

var t = 0; // global

board.create('text', [10, -0.2,
    function() {
        return "Day " + t + ": infected=" + (7900000 * I.Y()).toFixed(1) + " recovered=" + (7900000 * R.Y()).toFixed(1);
    }
]);

// Reset the turtles
var clearTurtle = function () {
  S.cs();
  I.cs();
  R.cs();

  S.hideTurtle();
  I.hideTurtle();
  R.hideTurtle();
};

// Start the animation
var run = function() {
    S.setPos(0, 1.0 - s.Value());
    R.setPos(0, 0);
    I.setPos(0, s.Value());

    delta = 1; // global
    t = 0; // global
    loop();
};

var turtleMove = function (turtle, dx, dy) {
    turtle.moveTo([dx + turtle.X(), dy + turtle.Y()]);
};

// Animation
var loop = function() {
    var dS = -beta.Value() * S.Y() * I.Y();
    var dR = gamma.Value() * I.Y();
    var dI = -(dS + dR);
    turtleMove(S, delta, dS);
    turtleMove(R, delta, dR);
    turtleMove(I, delta, dI);

    t += delta;
    if (t < 100.0) {
        active = setTimeout(loop, 10);
    }
};

// Stop animation
var stop = function() {
    if (active) clearTimeout(active);
    active = null;
};

// Continue
var goOn = function() {
    if (t > 0) {
        if (active === null) {
            active = setTimeout(loop, 10);
        }
    } else {
        run();
    }
};

clearTurtle();

license

This example is licensed under a Creative Commons Attribution 4.0 International License.
Please note you have to mention The Center of Mobile Learning with Digital Technology in the credits.