JSXGraph logo
JSXGraph
JSXGraph share

Share

Epidemiology: SEIR model
QR code
<iframe 
    src="https://www.jsxgraph.org/share/iframe/epidemiology-seir-model" 
    style="border: 1px solid black; overflow: hidden; width: 550px; aspect-ratio: 55 / 65;" 
    name="JSXGraph example: Epidemiology: SEIR 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 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();
 </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 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();

Epidemiology: SEIR 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();

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.