One Host SEIR + One Vector SEI model in Julia
Author: Carl A. B. Pearson
Date: 2 OCT 2018
First, create a system of ODEs conforming to the required signature:
function F(du,u,p,t)
S_H, E_H, I_H, R_H, S_V, E_V, I_V = u
# host dynamics
host_infection = (p.β*S_H*I_V)/p.N_H
host_mortality = p.μ_H .* u[1:4] # include S_H, so easier to remove mortality
host_births = sum(host_mortality)
host_progression = p.σ_H*E_H
recovery = p.λ*I_H
du[1] = -host_infection + host_births
du[2] = host_infection - host_progression
du[3] = host_progression - recovery
du[4] = recovery
du[1:4] -= host_mortality
# vector dynamics
vec_infection = (p.β*S_V*I_H)/p.N_H
vec_mortality = p.μ_V .* u[5:7] # include S_V, so easier to remove mortality
vec_births = sum(vec_mortality)
vec_progression = p.σ_V*E_V
du[5] = -vec_infection + vec_births
du[6] = vec_infection - vec_progression
du[7] = vec_progression
du[5:7] -= vec_mortality
end
F (generic function with 1 method)
Set initial conditions and dynamic parameters, then apply the ODE solver. Note this will also display the solver run time; this will be slow for the first run, though quite fast if you re-run it (even after changing parameters or initial conditions).
using DifferentialEquations
using IterableTables, DataFrames
using NamedTuples
# nb: in >= Julia v0.7, can eliminate this import
# and the @NT syntax
u0 = [
S_H=100.0, E_H=0.0, I_H=1.0, R_H=0.0,
S_V=10000.0, E_V=0.0, I_V=0.0
]
p = @NT(
μ_H=1/365, μ_V=1/30, σ_H=1/3, σ_V=1/7, λ=1/14,
β=0.05, N_H = sum(u0[1:4])
)
tspan = (0.0, 365.0)
prob = ODEProblem(F, u0, tspan, p)
sol = @time solve(prob,Tsit5(),reltol=1e-8,abstol=1e-8,saveat=linspace(0,365,365*10+1))
df = DataFrame(sol)
rename!(df, Dict(:timestamp => :t,
:value1 => :S_H, :value2 => :E_H, :value3 => :I_H, :value4 => :R_H,
:value5 => :S_V, :value6 => :E_V, :value7 => :I_V
))
mlt = melt(df,:t) # convert results into long format for plotting
mlt[:host] = contains.(string.(mlt[:variable]),"H"); # tag which entries are host vs vector
df
3.965556 seconds (3.46 M allocations: 192.139 MiB, 1.64% gc time)
t | S_H | E_H | I_H | R_H | S_V | E_V | I_V | |
---|---|---|---|---|---|---|---|---|
1 | 0.0 | 100.0 | 0.0 | 1.0 | 0.0 | 10000.0 | 0.0 | 0.0 |
2 | 0.1 | 100.00026814164985 | 5.745401288701111e-6 | 0.9926106550187419 | 0.007115457930112796 | 9999.50761607706 | 0.4888811777907883 | 0.0035027451477435017 |
3 | 0.2 | 100.00050177829016 | 4.525792070955373e-5 | 0.9852765739814515 | 0.014176389807693479 | 9999.020532914787 | 0.9655880127981552 | 0.013879072414963943 |
4 | 0.3 | 100.00066737984612 | 0.00015040567741793047 | 0.9779990053871515 | 0.021183209089312854 | 9998.538704686205 | 1.4303611143782462 | 0.030934199416335188 |
5 | 0.4 | 100.00073237948628 | 0.0003510652956395811 | 0.9707802135129932 | 0.028136341705096376 | 9998.062084857795 | 1.8834377432379645 | 0.05447739896513851 |
6 | 0.5 | 100.00066515369967 | 0.0006752070897406001 | 0.963623406156655 | 0.03503623305394339 | 9997.5906257077 | 2.3250523506169727 | 0.08432194168190127 |
7 | 0.6 | 100.00043500273485 | 0.0011489770693011803 | 0.9565326657056807 | 0.041883354490183024 | 9997.124277880717 | 2.7554370730797264 | 0.12028504620147329 |
8 | 0.7 | 100.00001213141086 | 0.0017967756786389124 | 0.9495128836036143 | 0.04867820930690247 | 9996.662989979597 | 3.1748221839374784 | 0.16218783646455837 |
9 | 0.8 | 99.99936763012019 | 0.0026413340720121085 | 0.9425696975069388 | 0.05542133830087409 | 9996.206708186579 | 3.5834365085203954 | 0.20985530490011298 |
10 | 0.9 | 99.99847345594463 | 0.00370378797506614 | 0.935709431179207 | 0.06211332490111005 | 9995.755375916528 | 3.9815078018550603 | 0.2631162816177185 |
11 | 1.0 | 99.99730241455798 | 0.00500374674442986 | 0.9289390389534903 | 0.06875479974410777 | 9995.308933509126 | 4.369263081472214 | 0.32180340940160024 |
12 | 1.1 | 99.9958281411404 | 0.006559364435790144 | 0.9222660492620383 | 0.07534644516179213 | 9994.867317928649 | 4.746928949742029 | 0.38575312160914144 |
13 | 1.2 | 99.99402508304243 | 0.008387402053565977 | 0.9156985160745399 | 0.08188899882947635 | 9994.43046252214 | 5.11473185068202 | 0.45480562717867207 |
14 | 1.3 | 99.99186848062837 | 0.010503295303662025 | 0.9092449664472831 | 0.08838325762069417 | 9993.998296764821 | 5.4728983393429 | 0.528804895835597 |
15 | 1.4 | 99.98933435043577 | 0.012921211210917136 | 0.9029143578800672 | 0.09483008047325146 | 9993.57074607381 | 5.821655275564482 | 0.6075986506255675 |
16 | 1.5 | 99.98639946576401 | 0.01565411301160372 | 0.8967160295734984 | 0.10123039165090672 | 9993.147731596253 | 6.161230044422309 | 0.6910383593243803 |
17 | 1.6 | 99.98304134053252 | 0.01871381087842438 | 0.8906596656812472 | 0.10758518290781208 | 9992.72917007232 | 6.491850695317421 | 0.7789792323625186 |
18 | 1.7 | 99.97923820920528 | 0.022111024888270103 | 0.8847552497174251 | 0.11389551618904671 | 9992.314973663997 | 6.813746116346348 | 0.8712802196570351 |
19 | 1.8 | 99.9749690114076 | 0.025855430503449094 | 0.8790130328327947 | 0.12016252525617195 | 9991.905049855464 | 7.127146132897464 | 0.9678040116372855 |
20 | 1.9 | 99.97021337156639 | 0.029955717708979524 | 0.8734434930259793 | 0.12638741769866832 | 9991.499301331016 | 7.432281627876439 | 1.0684170411069502 |
21 | 2.0 | 99.9649515828934 | 0.03441963633162285 | 0.8680573044314721 | 0.1325714763435111 | 9991.097625891161 | 7.7293846231762835 | 1.1729894856613798 |
22 | 2.1 | 99.95916458894199 | 0.03925404480785851 | 0.8628653058725415 | 0.13871606037763487 | 9990.699916391362 | 8.018688335574598 | 1.2813952730626423 |
23 | 2.2 | 99.95283396455962 | 0.044464961696772165 | 0.8578784670388516 | 0.1448226067047723 | 9990.306060664585 | 8.300427250046441 | 1.3935120853669343 |
24 | 2.3 | 99.94594190064402 | 0.05005760246742591 | 0.853107866491243 | 0.15089263039732773 | 9989.915941503974 | 8.57483713113998 | 1.5092213648849446 |
25 | 2.4 | 99.9384711825094 | 0.05603643341442274 | 0.8485646584553629 | 0.15692772562082902 | 9989.52943661802 | 8.842155061154639 | 1.6284083208239846 |
26 | 2.5 | 99.93040517498355 | 0.06240520682808333 | 0.8442600521800281 | 0.16292956600835462 | 9989.14641861804 | 9.102619447381544 | 1.7509619345776433 |
27 | 2.6 | 99.92172780354208 | 0.06916700268500087 | 0.8402052889902647 | 0.16889990478267222 | 9988.76675502676 | 9.356470006726369 | 1.8767749665126119 |
28 | 2.7 | 99.91242353405677 | 0.07632427518811552 | 0.8364116156084753 | 0.17484057514665405 | 9988.390308269225 | 9.603947768150924 | 2.00574396262303 |
29 | 2.8 | 99.90247735877468 | 0.08387888092361276 | 0.8328902702538351 | 0.18075349004788635 | 9988.016935701668 | 9.845295039200272 | 2.1377692591325457 |
30 | 2.9 | 99.89187477418837 | 0.0918321245595308 | 0.8296524592467466 | 0.18664064200537545 | 9987.646489642992 | 10.080755368056721 | 2.2727549889506884 |
⋮ | ⋮ | ⋮ | ⋮ | ⋮ | ⋮ | ⋮ | ⋮ | ⋮ |
Now that we have a solution, we want to view what is happening in host vs mosquito population:
using Gadfly
fig1a = plot(mlt[mlt[:host] .== true,:], x=:t, y=:value, color=:variable, Geom.line)
fig1b = plot(mlt[mlt[:host] .!= true,:], x=:t, y=:value, color=:variable, Geom.line)
vstack(fig1a,fig1b)