Share JSXGraph: example "Epidemiology: SEIR model"

JSXGraph
Share JSXGraph: example "Epidemiology: SEIR model"
This website is a beta version. The official release will be in **2024**.

Epidemiology: SEIR model

Have also a look at "Epidemiology: SIR model".
This is an example of simulation of differential equations with __turtle graphics__. The SEIR model is an extension of the [SIR model](https://jsxgraph.org/share/example/epidemiology-sir-model) for an introduction. Below, also the Hong Kong flu is used as example. For many important infections there is a significant period of time during which the individual has been infected but is not yet infectious himself. During this latent period the individual is in compartment $E$ (for exposed). Assuming that the period of staying in the latent state is a random variable with exponential distribution with parameter a (i.e. the average latent period is $a^{-1}$), and also assuming the presence of vital dynamics with birth rate equal to death rate, we have the model: $$ \begin{aligned} \frac{dS}{dt} &= \mu N - \mu S - \beta \frac{I}{N} S \\ \frac{dE}{dt} &= \beta \frac{I}{N} S - (\mu +a ) E \\ \frac{dI}{dt} &= a E - (\gamma +\mu ) I \\ \frac{dR}{dt} &= \gamma I - \mu R. \\ \end{aligned} $$ Additionally, we have that $S+E+I+R=N$. ### 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$ The lines in the JSXGraph-simulation below have the following meaning: - Blue: Rate of susceptible population - Black: Rate of exposed population - Red: Rate of infectious 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 E = board.create('turtle', [], {
    strokeColor: 'black',
    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.5],
    [30, -0.5],
    [0, 1.27E-6, 1]
], {
    name: 's'
});
var beta = board.create('slider', [
    [0, -0.6],
    [30, -0.6],
    [0, 0.5, 1]
], {
    name: 'β'
});
var gamma = board.create('slider', [
    [0, -0.7],
    [30, -0.7],
    [0, 0.3, 1]
], {
    name: 'γ'
});
var mu = board.create('slider', [
    [0, -0.8],
    [30, -0.8],
    [0, 0.0, 1]
], {
    name: 'μ'
});
var a = board.create('slider', [
    [0, -0.9],
    [30, -0.9],
    [0, 1.0, 1]
], {
    name: 'a'
});

board.create('text', [10, -0.3, "initially infected population rate (on load: I(0)=1.27E-6)"]);
board.create('text', [50, -0.6, "β: infection rate"]);
board.create('text', [50, -0.7, "γ: 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();
    E.cs();
    I.cs();
    R.cs();

    S.hideTurtle();
    E.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());
    E.setPos(0, 0);

    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 = mu.Value() * (1.0 - S.Y()) - beta.Value() * I.Y() * S.Y();
    var dE = beta.Value() * I.Y() * S.Y() - (mu.Value() + a.Value()) * E.Y();
    var dI = a.Value() * E.Y() - (gamma.Value() + mu.Value()) * I.Y();
    var dR = gamma.Value() * I.Y() - mu.Value() * R.Y();

    turtleMove(S, delta, dS);
    turtleMove(E, delta, dE);
    turtleMove(I, delta, dI);
    turtleMove(R, delta, dR);

    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();