Spatially-aware virus transmission
Do you have questions or comments about this model? Ask them here! (You'll first need to log in.)
WHAT IS IT?
This model simulates the spread of an infectious disease in a closed population.
It diverges from the classical Kermack-McKendrick model, which we henceforth call the Standard model, in that it takes account of spatial proximity on transmission. It is novel in that it doesn't model the movement of persons but instead assumes that transmission is between static households, and that households can transmit at a distance. Of course in reality, the way this remote transmission takes place is by the movement of persons from the households. However, we don't need to model this movement. We simply assume that transmission is between static households and that it is more likely to be between nearer households. For simplicity, every patch is a household.
This proximity effect is determined by a Reach parameter which is the average distance of transmission to other households. For example, a Reach of 1% means that transmissions are to households that are at a 1% radius of the transmitter, on average. The households at 1% radius are those on the boundary of the 1% of all households that are closest to the transmitter. Note that this 1% radius is only an average. The actual transmission radius is a random-Poisson of the 1% radius.
This is a simple model that is designed only to show the Reach-effect on the spread of infection. It is for experimental purposes only, so that users can see how the Reach% compresses and depresses the spread of the infection and how it differs significantly from the non-spatial Standard model.
I have avoided using the standard term R_0 as it is often misused and could be confused with some of my terms relating to the Removeds measure. Instead I use the term Transmission# (also abbreviated to T#) as I think this is much more self-descriptive.
There are 3 main parameters that can be experimented with using the sliders:
- generation-perHousehold
- meanReach%, and
- Transmission#
The first, generation-perHousehold, requires a little explanation. It means the average number of days from first infection in a household till the day it reinfects other households. This is complicated as there will sometimes be a delay from the first infection in a household and any reinfection of other members in the household who will in turn elongate the total reinfection interval of the household. I have assumed a default which is my guess for Covid-19 and have assumed that secondary infections within the household have little effect on the household reinfection interval. In terms of the Standard Model it equals 1/gamma.
HOW IT WORKS
Initially, the household at the centre of the World is infected. This household transmits an average T# times at the end of its reinfection interval to other nearby households and then becomes Removed (i.e. recovered or deceased). Infected households, in turn do the same. Thus all households transmit at the end of their reinfection interval, making the model temporally-aware as well as spatially-aware. Temporal awareness only makes a difference because the model is spatially-aware. Restricting transmission to the end of the reinfection interval ensures that the oldest (and hence the less-distributed) households transmit each day. This transmission by the oldest infected is implemented using a queueing system for infected households.
The state of each household is shown by its colour:
- red for the Infectious
- green for the Removed
- black for the still Susceptible
The %Infectious and the %Removed is plotted by day. Examination of the %Infectious plot shows it is approximately the shape of a Normal-distribution curve. It is therefore overlaid with a fitted Normal-distribution curve and the %Removed curve is overlaid with the corresponding fitted curve that is gamma * (the daily accumulated fitted %Infectious). You can see that they are a very good fit.
The reason why the Normal-distribution curve is a better fit than the Standard-model curves is because infection is suppressed by the Reach-effect and the Standard-model does not take this into account. Also, the Standard-model %Infectious curves show a positive-skew (increasing markedly with T# above 4). Whereas, the Reach-model shows very little skew in the Reach% range of 0.6% to 1.4%, a slight negative-skew when Reach% < 0.6% and a slight positive-skew when Reach% > 1.4%. I suspect that this could be corrected by introducing a skew coefficient into the Random-distribution formula.
HOW TO USE IT
First, run it with the "view updates" on and observe how the red and green household dots spread through the World, eventually leaving just completely-randomised green households. However, this slows down the model and you will soon want to speed up the runs and plotting by unclicking "view updates" in the Interface ribbon.
As per usual, you can adjust the input-parameter sliders then click the Setup button and then click the Go-forever button (or you can click the Go botton to run single daily steps).
However, you can just click the "run current Transmission#" button to do both. Alternatively, you can click the "run the next Transmission#" button to step-up to the next Transmission# and automatically run that. This latter button is a great-way of observing dynamically how the increasing Transmission# affects the plots.
You can observe how good the Normal-curve fit is. This fit will vary on repeated runs due to stochastic noise and occasionally you will observe an almost perfect fit.
The other item that you may want to vary is the number of households. The default is 250,000 for a World that is 500 by 500. The only way to change this is to resize the World which you can do by clicking Settings on the Interface ribbon.For example, you can set a World that is 1000 by 1000 to produce a number of households (N) of 1 million. I have tested this up to 20 million households, which equates to an approximate population of 50 million persons. Beware though that changing to a bigger World size can be slow and it slows down the run time considerably.
HOW TO CITE
If you mention this model or the NetLogo software in a publication, we ask that you include the citations below.
For the model itself:
- Ian J Heath, the author, an independent researcher in Canterbury, UK
For the NetLogo software:
- Wilensky, U. (1999). NetLogo. http://ccl.northwestern.edu/netlogo/. Center for Connected Learning and Computer-Based Modeling, Northwestern University, Evanston, IL.
Comments and Questions
globals [ #I ;; # of Infectious - red #R ;; # of Removeds - green (note: not exactly the integral of #I) nI ;; fractional I for the fitted Normal curve nR ;; fractional R for the fitted Normal curve rR0 ;; to align Normal-R with Reach-R at liftoff RedsQ ;; list of red patches - to remove the oldest first T# ;; # of transmissible (i.e. always infects susceptibles) contacts per household meanReach ;; mean infection distance = radius that spans meanReach% of HHs gamma ;; the removal rate per day for infectious households N ;; # households (that fill the whole World) #Imax ;; peak #I ImaxDay ;; peak #I day Istdev ;; standard deviation (width of the "bell") for a Normal curve that best fits the Proximity model I-curve Ilist ;; list of daily #Is - used to calc VAR of the fitted I curve plottingReach;; a switch to turn this off when plotting over it liftoff ;; switch = (#I / N > .001) day ;; for plotting Normal curves stopGos ] to runCurrentT# ;; avoid having to setup first setup while [not stopGos] [go] ;; run for current T# end to runNextT# ;; to dynamically show the effect of stepping up through each T# set Transmission# precision (Transmission# + 0.1) 5 ;; Increment the T# (note: precision is to correct an anomylous addition error) runCurrentT# end to setup clear-all set stopGos false ;; enable resumption of go's for this Transmission# - used in runCurrentTransmission# ;; setup the Reach model set N count patches set T# Transmission# ;; the T# abbreviation will be used throughout this model set gamma 1 / generation-perHousehold ;; removeds per day per infectious HH set meanReach sqrt(meanReach% / 100 * N / pi) set RedsQ [] ask patch (world-width / 2) (world-width / 2) [turn-infectious] ;; infect the origin set #I 1 set #R 0 set #Imax #I set Ilist [] ;; LIFTOFF - startup until liftoff (when #I >= N * .001). During liftoff "infect&remove" avoids accidentally exhausting all infections. set liftoff false ;; start liftoff while [#I < N * .001] [goReachModel] ;; run till liftoff set liftoff true ;; achieved liftoff set rR0 #R / N ;; to align Normal-R with Reach-R at liftoff in plotNORMdistFit set plottingReach true ;; enable plot of Reach curves until we plot Normal curves over the top of them reset-ticks end to go goReachModel ;; tally Imax and ImaxDay if #I > #Imax [ set #Imax #I set ImaxDay ticks + 1 ] ;; stop when I is passed its peak and nearly exhausted if (ticks > ImaxDay) and (#I <= N * .0001) [ print (word "N=" N ", genDays=" generation-perHousehold ", Reach=" meanReach% "%, T#=" PadRight T# 3 ", ImaxDay=" PadRight ImaxDay 4 ", %Imax=" precision (#Imax / N * 100) 2 ", %R=" precision (#R / N * 100) 1) plotNORMdistFit set stopGos true ;; tell runNextTransmission# to stop go's stop ] tick ;; advance to next day end to goReachModel ;; step the proximity model today. Transmit then remove the oldest reds, according to the removal rate, gamma set Ilist lput #I Ilist ;; append #I to Ilist if #I = 0 [stop] let #newR max list 1 round(gamma * #I) ;; the number of oldest reds - to transmit and then remove foreach (sublist RedsQ 0 #newR ) [HH -> ask HH [infect&remove]] ;; transmit these oldest reds (those at the front of the queue), which adds new reds to the back of the queue set RedsQ (sublist RedsQ #newR (length RedsQ)) ;; drop these oldest reds from the front of the list, now that they have been processed end to infect&remove ;; infect and then remove let #Contacts ifelse-value liftoff [random-poisson T# ] [1 + random-poisson (T# - 1) ] let Reach ifelse-value liftoff [random-exponential meanReach] [1 + random-exponential (meanReach - 1)] repeat #Contacts [ ;; make a transmissible contact at distance random-exponential of meanReach ask patch-at-heading-and-distance (random 360) Reach [if pcolor = black [turn-infectious]] ] turn-removed ;; remove this HH, now that it has transmitted end to turn-infectious ;; turn into an "infectious" set RedsQ lput self RedsQ ;; put new red at the back of the queue set pcolor red ;; set infectious set #I #I + 1 end to turn-removed ;; turn into a "removed" set pcolor green ;; set removed set #I #I - 1 set #R #R + 1 end to-report PadRight [number to-length] ;; to align decimal columns in output report substring (word number " ") 0 to-length end to plotNORMdistFit ;; plot nI (the Normal curve that fits the Reach I curve) and nR (the R curve that is the accumulation of nI * gamma), alongside the Reach I and R curves set plottingReach false ;; to cease plotting the Reach curves while plotting the Normal curves over the Reach curves ;; plot the nI and nR plots let Imax #Imax / N let cumI #R / gamma ;; cumI = the integral of the Reach #I-curve set Istdev cumI / (#Imax * sqrt(2 * pi)) set nR rR0 ;; to align nR with rR at liftoff set day (- 1) set day 0 repeat ticks + 1 [ set day day + 1 set nI Imax * exp(-(((day - ImaxDay)/ Istdev)^ 2)/ 2) ;; the Normal distribution with this ImaxDay and Istdev set nR nR + nI * gamma update-plots ] end
There are 2 versions of this model.
This model does not have any ancestors.
This model does not have any descendants.
Ian Heath
Please add your thoughts on this model here (Question)
I would love to see any comments.
Posted about 4 years ago