COVID-19 epidemics with Non-Pharmaceutical Interventions and zonal restraints

COVID-19 epidemics with Non-Pharmaceutical Interventions and zonal restraints preview image

1 collaborator

Tags

epidemics 

Tagged by Sergio Rojas-Galeano 2 months ago

virus spread 

Tagged by Sergio Rojas-Galeano about 1 month ago

Visible to everyone | Changeable by everyone
Model was written in NetLogo 6.1.0 • Viewed 458 times • Downloaded 7 times • Run 0 times
Download the 'COVID-19 epidemics with Non-Pharmaceutical Interventions and zonal restraints' modelDownload this modelEmbed this model

Do you have questions or comments about this model? Ask them here! (You'll first need to log in.)


WHAT IS IT?

This is an agent-based model to simulate the evolution of the COVID-19 epidemics and the mitigation impact of Non-Pharmaceutical Interventions (NPI) within an hypothetical city. NPIs are the mechanisms that public health offices around the world are using to attempt to contain the spread of the virus.

We consider a number of NPIs, including social distancing, case isolation, home quarantine, total lockdown, sentinel testing, mask protection and a proposed zonal restriction where these interventions can be applied to separated districts or zones of the city. The effect of these strategies are measured in terms of morbidity, mortality, lethality -infection fatality rate (IFR) and case fatality rate (CFR)-, doubling time, reproduction number and plots of infection, recovery and death during the simulation timeline. The main purpose of the tool is to let modelers assess which NPIs or combination of NPIs can help flattening or crushing the curve of spread of the disease (mitigate or suppress, respectively), and the effects on the corresponding epidemics indicators.

HOW IT WORKS

The model implements the NPIs within the epidemic SIRE+CARDS model (see [1]) as well as the agent behavior rules. We build upon the compartmental SIRE epidemic framework (Susceptible-Infectious-Recovered-Extinct), but we regarded the Infectious compartment as an extended-state consisting of a number of conditions: Confirmed or not (indicating the patient will remain isolated), Risky or not (meaning predisposition to develop severe or critical disease), Asymptomatic or not (meaning patient is unaware of being a virus carrier), Severe or not (meaning it requires to be hospitalized to avoid dead), and Deadly or not (indicating the patient requires Intensive Care Unit -ICU- assistance). The details of event transition rules and condition activation are described in [1].

The simulation tracks an individual disease path for every agent, from susceptible to recovery or death, according to the SIRE+CARDS epidemic model described above. Each agent is assigned a daily routine consisting of going outdoors and returning home with a commuting distance range randomly chosen from {25, 50, 100, 200} unit steps; the actual route the agent follows varies slightly due to random fluctuations in his orientation. In addition the length of each step can be set as a global parameter between 0.1 and 1 units. Similarly, the day length can be defined with a given number of ticks in the range between 600 and 2400.

Individuals interact randomly with other agents around. Virus transmission occurs due to proximity of an infectious agent with other susceptible agent within a spatial radius of 0.5 units; the chance of contagion depends on what mask protection intervention is applied. On recovery from the disease, individuals acquire immunity to the virus so they cannot be re-infected. In this model all deaths are considered to be caused by COVID-19. The flow of events applied to each agent at each timestep are: lifestyle, epidemic, isolation, quarantine, distancing, sentinel, lockdown, illness, clock and indicators (see code and [1] for further details).

In the simulation view area, agents are represented with different shapes according to the zone where they reside. The color of the agent represents its extended state (healthy: same color as zone ground; immune: white; sick: red or yellow if asymptomatic; dead: black X). Special agents intended to implement some of the NPIs such as households for home-quarantine and ambulances for sentinel-testing can also be seen.

HOW TO USE IT

The control panel is organised in sections related to general, city and COVID-19 settings, monitors of epidemic indicators, parameters, action commands to execute the simulation, and a dedicated section for NPI activation with their corresponding parameters.

A typical setup for a simulation run is: POP-SIZE=400 (total number of simulated people or agents), ZONES=9 (number of residential zones), DAYS=60 (period of observation days or simulation length), %-HIGH-RISK=30 (percentage of population with co-morbidities), HOSPITAL-BEDS=12 (total number of hospital beds available), ICU-BEDS=2 (total number of ICU beds available), AMBULANCES-ZONE=1 (number of ambulances or sentinels per zone), HOUSING?=on (show households in the view area), AVG-DURATION=18 (average day period to recover from illness), %-ASYMPTOMATIC=50 (percentage of patients showing mild or no symptoms), TICKS-DAY=1200 (number of ticks after one day elapse), STEP-SIZE=0.1 (distance each agent move every tick), END-DAY=60 (simulation timeframe).

Once setup is done, activate or deactivate the NPIs you want to assess (the details of meaning and implementation of each NPI can be found in [1]), then press SETUP, then GO. After a few simulated hours (or ticks) you can seed a patient zero randomly (or many other, if you want) by pressing INFECT. Alternatively, using OUTBREAK you can randomly infect a percentage (%-SPREAD) of the population. Afterwards, you will be able to see the emergence of the epidemic SIRE curves in the plot area, as well as the other epidemic indicators in the monitor area, while the contagion, recover and death of people unfolds as a result of the development of the COVID-19 epidemics with such particular settings.

THINGS TO NOTICE

The NPIs control panel can be used to control their application even as the epidemic unfolds. For example, you can activate/disactivate a total lockdown at any time, and it will take effect at the 00:00 of the next simulated day. Or you can isolate or release confirmed cases inmmediately, by switching it on or off. Similar thing occurs with the rest of NPIs. In contrast, you should not change any of the other parameters (general, city, or COVID-19 settings), as they are used to setup the model just and only before running the simulation.

There are two distinctive features in this model that allows the application of NPIs with a zonal scope. This means, firstly, you can restrict mobility of agents within their zone of residence; hence, you can try and see if this kind of restriction (ZONE-ENFORCING) is advantageous in flattening the curve when combined with other NPIs compared to the single application of said NPIs. Secondly, when enforcing a TOTAL-LOCKDOWN, you are able to lift this NPI in an arbitrary zone or zones using the UNLOCK-ZONE button. Again, you can see how the resulting emergencies compare to maintaining the total lockdown in the entire city. These features may yield interesting insights about alternative implementation of these measures that usually have a hard impact on the economy of the city. Notice that TOTAL-LOCKDOWN has an associated parameter %-PERMITS that determines the amount of agents permitted to go out of their households.

The SENTINEL-TESTING intervention is also useful to assess the impact of mass-test campaigns in the population. Sentinels are shown as ambulances moving around the city while testing any agent they find in their ways; again, you can restrict sentinels mobility with a zonal scope (ZONAL?) and see the difference with respect to allowing city-wide mobility. Notice that since test kits are a finite resource, the model assigns an initial stock of tests equals to the population size. When ambulances run out of tests they stop and stay still. You can of course replenish the stock for each ambulance using the RESUPPLY button to re-activate sentinels' journeys.

Lastly, the mask protection NPI obtained by combining the MASK-SICKS and MAKS-HEALTHIES switches, will define the probability of contagion or virus transmission during a single encounter between two agents (such probability is shown in the CONTAGION PROBABILITY monitor at the beginning of the simulation).

THINGS TO TRY

Start-off by defining the general, city, COVID-19 and NPI settings you want to simulate in a single run (a suggested set of settings was given above, see HOW TO USE TI). Execute the simulation to observe how the contagion spreads and how the epidemics evolve by inspecting the monitors, plots and view areas. Then try changing the NPI parameters to assess their mitigation impact by comparing with previous outputs (see also THINGS TO NOTICE). If you like, start running the simulation with only one zone (choose 1 in the ZONES pull down menu); this will be equivalent to have a single district in the entire city, so agents will to move around freely. Then experiment simulations with many districts or multi-zone (choose ZONES in {4, 9, 16}), and try to apply ZONE-ENFORCING to see how agents mobility becomes restricted to their zones of residence.

The HOUSING? switch is used as a decoration and as a behaviour feature. When this switch is on, the model shows households in the simulation view area and assigns agents randomly to each one with a proportion of one house per four agents approximately. When this switch is off, the household of an agent would be the patch were he/she was created randomly at the beginning of the simulation; no houses will be seen. If you try the CASE-ISOLATION or TOTAL-LOCKDOWN interventions with HOUSING? on, agents will be sent home and stay confined in their corresponding households (they will be hidden as they stay inside the house); in contrast, if HOUSING? is off, they will move to their home patch and stay quiet there, being visible and showing their shape, color and state.

Finally, the SEE-SUNSET is a decoration feature. Try it and surprise yourself!

EXTENDING THE MODEL

Given the complex nature of human behavior and virus infection, attempting to model every mechanism of the COVID-19 epidemic may prove difficult; necessary assumptions have to be made to simplify the representation of the agents and their interactions. We have made a few of them, as described above, so evidently there are interesting aspects that can be addressed to extend the model. We mention just some ideas here (for a more comprehensive discussion we refer the reader to [1]):

  • consider virus incubation periods after infection,
  • model infectiousness, aggresiveness or symptomatic severity levels,
  • include age or gender structures,
  • account for births or deaths due to other causes,
  • expand further risk stratification for co-morbidities and age windows,
  • add hubs or attractor sites (i.e. mass transport, schools, cinemas, etc.),
  • incorporate explicit sites for hospitals were severe or critical patients are moved instead of staying still,
  • involve individual habits and preferences (e.g. like wearing masks being an individual choice, influence of citizen education, routinely washing hands, etc.),
  • set up daily schedules for agent routines (e.g. going forth and back to/from work, or leisure or shopping, etc.),
  • measure the economical impact of NPIs (model food or money supply at a population or individual level),
  • simulate cotagions not only by direct contact, but also indirect by surface contact (virus particles adhered to patches),
  • implement of other epidemic indicators (different estimates of R0) or additional NPIs.

CREDITS AND REFERENCES

Authors:

Sergio Rojas-Galeano and Lindsay Alvarez

Copyright (c) June 2020

email: srojas@udistrital.edu.co, lalvarez@udistrital.edu.co

Version 1.24

Licenses:

References:

[1] Alvarez, L. and Rojas-Galeano, S. "Simulation of Non-Pharmaceutical Interventions on COVID-19 with an Agent-based Model of Zonal Restraint". medRxiv pre-print 2020/06/13; https://www.medrxiv.org/content/10.1101/2020.06.13.20130542v1 doi: 10.1101/2020.06.13.20130542

Comments and Questions

Please start the discussion about this model! (You'll first need to log in.)

Click to Run Model

;; --------------------------------------------------------------------------
;; COVID-19 epidemic simulation with Non-Pharmaceutical Interventions,
;; including a novel zonal restraint NPI.
;;
;; A model by Sergio Rojas-Galeano and Lindsay Alvarez
;; v1.24 Copyright (c) June 2020 The authors
;; Correspondance email: srojas@udistrital.edu.co
;; Universidad Distrital Francisco Jose de Caldas, Bogota, Colombia
;;
;; This program is free software: you can redistribute it and/or modify
;; it under the terms of the GNU General Public License (GPLv3)
;; (see license at: https://www.gnu.org/licenses/gpl-3.0.txt)
;;
;; The model is made publicly available in the hope that it will be useful
;; to modelers, but WITHOUT ANY WARRANTY whatsoever (see license for details).
;; --------------------------------------------------------------------------

;; Define globals
globals [
  daytime?      ; is it day or night? ( 1 day + 1 night = ticks-day)
  sort-codes    ; a list of codes to identify each zone of a city
  shapes-list   ; a list of shapes to identify agents of the same zone
  colors-list   ; a list of colors to identify different zones
  day hour      ; the current day and hour since simulation started
  sicks-day     ; list of daily count of sicks
  n-cases       ; number of overall COVID-19 sick people
  n-confirmed   ; number of confirmed COVID-19 sick people
  n-tested      ; number of overall people tested by sentinel
  n-positives   ; number of people that tested COVID-19 positive
  doubling-time ; estimated days to double today's number of sicks
  R0 S0 R0_     ; reproduction number and initial Susceptibles
  p-contagion   ; probability of contagion on a single encounter
]

;; Define breeds for healthy and infected people
breed[ healthies healthy ]
breed[ sicks sick ]
breed[ deaths death ]
breed[ houses house ]
breed[ ambulances ambulance ]

;; Define attributes for patches
patches-own [
  zone                   ; the zone code of this patch
]

;; Define attributes of all the people
turtles-own [
  homebase               ; the home patch of this person
  scope                  ; the reach of distance away from home for this person
  speed                  ; how fast does he/she move? A speed of 0 is still
  unlocked?              ; is the person free from lockdown?
  tested?                ; was the person tested by sentinel test?
  contagions             ; how many people this person infected if he/she ever got sick
]

;; Define attributes for sick people only
sicks-own [
  days-to-cure           ; the actual duration of the illness for this person
  recovery               ; counter of days remaining to recovery
  confirmed?             ; is the person isolated at homebase?
  asymptomatic?          ; is the person asymptomatic?
  risky?                 ; is the person high-risk due to existing factor (obese, diabetes, older, etc)
  severe?                ; is the person in severe condition?
  deadly?                ; is the person in deadly (critical) condition?
  hospitalised?          ; has he/she been admitted to hospital?
  ICU-admitted?          ; has he/she been admitted to ICU?
]

;; Define attributes for healthy people only
healthies-own [
  immune?                ; has the person recovered and acquired immunity?
]

;; Define attributes for ambulances
ambulances-own [
  tests-stock            ; how many tests in stock
  tests-supply           ; numbers of tests to top-up (depends on amount of zone residents)
]

;; One iteration of simulation's steps

to go
  ifelse day < end-day [ tick ] [ stop ] ;screenshot stop ]
  lifestyle
  epidemic
  isolation
  quarantine
  distancing
  sentinel
  lockdown
  illness
  clock
  indicators
end 

;; Simulate everyday routine of people

to lifestyle
    ask (turtle-set healthies sicks with [not confirmed?] ) [
    if zone-enforcing? [
      if zone != [zone] of homebase [ face homebase fd 0.5 ]  ; if away from resident zone, head back
    ]
    forward speed                                             ; move ahead
    if distance homebase > scope [ face homebase ]            ; if too far from home, head back
    set heading heading + (random-float 3 - random-float 3)   ; change direction swiftly
  ]
end 

;; Spread the infection from sicks not yet isolated, to healthies

to epidemic
  ask sicks with [not confirmed?] [
    let counter 0
    ask healthies with [not immune?] in-radius .5 [
      ;; Disease spreads depending on contagion probability
      if random-float 1 < p-contagion [
        get-sick
        set counter counter + 1
      ]
    ]
    set contagions contagions + counter
  ]
end 

;; Make a single person ill

to get-sick
  ;; S->I (set the initial properties of a sick person)
  set breed sicks
  set shape item ([zone] of homebase) shapes-list
  set confirmed? false
  set tested? false
  set severe? false
  set deadly? false
  set hospitalised? false
  set ICU-admitted? false

  ;; Set stochastic attributes
  set days-to-cure abs int random-normal avg-duration 4         ; duration of illness for this sick
  set recovery 0                                                ; initial count of days until recovery
  set asymptomatic? (random 100) < %-asymptomatics              ; is this an asymptomatic patient?
  set risky? (random 100) < %-high-risk  and not asymptomatic?  ; is it high-risk (co-morbidities) given not asymptomatic?
  set color ifelse-value asymptomatic? [ yellow ] [ red ]

  ;; Update how many cases so far
  set n-cases n-cases + 1
end 

;; Ask confirmed sick people to stay home

to isolation
  ;; If quarantine on, enforce isolation of symptomatic
  ifelse case-isolation? [
    ask sicks with [ not asymptomatic? and not confirmed? ] [
      move-to homebase
      set confirmed? true
      set n-confirmed n-confirmed + 1         ; these sicks are now confirmed cases
    ]
  ]
  ;; Else lift isolation, except if was sent sentinel testing
  [
    ask sicks with [ not tested? and confirmed? ] [
      set confirmed? false
      set n-confirmed n-confirmed - 1         ; these sicks are set back to not confirmed cases
    ]
  ]

  ;; Decorate houses with color of isolated people
  ask houses [
    set color ifelse-value any? sicks-here with [ not asymptomatic? ] [ red ]
            [ ifelse-value any? sicks-here with [ asymptomatic? ] [ yellow ] [ white ] ]
  ]
end 

;; Ask housemates of isolated  people to stay home

to quarantine
  if home-quarantine? [
    ask sicks with [ confirmed? ] [
      let sick-home homebase
      ask other turtles with [ homebase = sick-home ] [ move-to homebase ]
    ]
  ]

  ;; Decorate houses with color of quarantined people
  ask houses [
    set color ifelse-value any? sicks-here with [ not asymptomatic? ] [ red ]
            [ ifelse-value any? sicks-here with [ asymptomatic? ] [ yellow ] [ white ] ]
  ]
end 

;; Avoid contacting nearby people (closer than than min-dist)

to distancing
  if social-distancing?
  [ let people (turtle-set healthies sicks)
    let willings (count people * %-willings / 100)
    ask n-of willings people [
      if any? other people in-radius 0.6 [  ; a radius of 0.6 is slightly higher than the 0.5 threshold to contagion
        let closest min-one-of other people [distance myself]
        face closest rt 180                 ; head in the opposite direction of closest person
      ]
    ]
  ]
end 

;; Ask ambulances to catch sicks by mass testing

to sentinel
  ifelse sentinel-testing? [
    ask ambulances [
      st
      if tests-stock > 0 [
        ;; Move ambulances around
        forward speed
        if zonal? [ if zone != [zone] of homebase [ face homebase fd 0.5 ] ]  ; keep ambulance in-zone
        set heading heading + (random-float 10 - random-float 10)             ; change ambulance's heading randomly

        ;; Pick nearbys and perform tests
        let target-people ((turtle-set healthies sicks) in-radius 5) with [not tested?]
        ask target-people  [
          if is-sick? self and not confirmed? [                               ; if sick and not isolated, target is positive
            move-to homebase set confirmed? true
            set n-positives n-positives + 1                                   ; update count positives tests so far
            set n-confirmed n-confirmed + 1                                   ; update count of confirmed cases so far
          ]
          set tested? true                                                    ; mark this person as tested
        ]
        set n-tested n-tested + (count target-people)                         ; update count of tests made so far
        set tests-stock tests-stock - (count target-people)                   ; update stock of tests available
      ]
    ]
  ]
  ;; Else, stop and hide ambulances
  [ ask ambulances [ ht ] ]
end 

;; Enforce everyone staying home, except for a few permits

to lockdown
  if hour mod 24 = 0 [                                              ; lockdown starts or ends at 00:00 of next day
    ifelse total-lockdown?[
      let people (turtle-set healthies sicks) with [not unlocked?]  ; for people not in an unlocked zone
      ask people [ move-to homebase set speed 0 ]                   ; sent everyone home, not confirmed
      foreach sort-codes [
        z -> let residents people with [ zone = z ]
        let permits (count residents * %-permits / 100)
        ask n-of permits residents [ set speed step-size ]
      ]
    ]
    ;; Else unlock everyone
    [ ask (turtle-set healthies sicks) [ set speed step-size set unlocked? false ] ]
  ]
end 

;; Lift total lockdown by unlocking zones gradually

to unlock-zone
  let unlocked-zone random zones
  ask (turtle-set healthies sicks) with [zone = unlocked-zone] [ set speed step-size set unlocked? true ]
end 

;; Simulate illness evolution in each person

to illness
  if ticks mod ticks-day = 0 [                        ; illness unfolds in a daily basis

    ;; I->R (sicks recovering after days-to cure)
    ask sicks [
      set recovery recovery + 1                       ; countdown of days left to recover
      if recovery >= days-to-cure [ get-well ]        ; if recovery time over, the person is cured
    ]

    ;; I->E (sicks getting extinct, that is, dead)
    ask sicks with [not asymptomatic?] [
      ;; Define probability of death
      let p 0.005                                     ; P(Extinct ∣ Symptomatic)
      if deadly? and not ICU-admitted? [ set p 1.0  ] ; P(Extinct ∣ Deadly, no ICU)
      if deadly? and     ICU-admitted? [ set p 0.5  ] ; P(Extinct ∣ Deadly, ICU)
      if severe? and not hospitalised? [ set p 0.2  ] ; P(Extinct ∣ Severe, Hospitalised)
      if severe? and     hospitalised? [ set p 0.05 ] ; P(Extinct ∣ Severe, no Hospitalised)

      ;; Death may occur any day within days-to-cure, with triangular probability distribution peaking at half the days-to-cure
      let day-chance cdf-triangle recovery days-to-cure ; CDF of triangle distribution

      ;; Simulate death
      let r random-float 1.0
      if r < (p * day-chance) [ pass-away ]
    ]

    ;; I+Severe
    ask sicks with [not asymptomatic? and not (severe? or deadly?)] [
      let p 0.0
      if not risky? [ set p 0.05 ]                    ; P(Severe ∣ Symptomatic, no Risky)
      if risky?     [ set p 0.25 ]                    ; P(Severe ∣ Symptomatic, Risky)

      ;; Severity may arise any day within days-to-cure, following an uniform distribution
      let day-chance recovery / days-to-cure          ; CDF of uniform distribution

      ;; Simulate severity
      let r random-float 1.0
      if r < (p * day-chance) [ set severe? true ]
    ]

    ;; I+Deadly
    ask sicks with [severe?] [
      let p 0.0
      if not risky? [ set p 0.05 ]                    ; P(Deadly ∣ Severe, no Risky)
      if risky?     [ set p 0.25 ]                    ; P(Deadly ∣ Severe, Risky)

      ;; Deadliness may arise any day within days-to-cure, following an uniform distribution
      let day-chance recovery / days-to-cure          ; CDF of uniform distribution

      ;; Simulate deadliness
      let r random-float 1.0
      if r < (p * day-chance) [ set deadly? true set severe? false ]
    ]

    ;; I+Hospitalised
    let occupied count sicks with [severe? and hospitalised?]
    let required count sicks with [severe? and not hospitalised?]
    let incoming min list (hospital-beds - occupied) required                   ; how many can be hospitalised?
    ask n-of incoming sicks with [severe? and not hospitalised?] [              ; hospitalised as many as possible
      set hospitalised? true
      set tested? true                                                          ; so they can't move even when isolation off
      if not confirmed? [ set confirmed? true set n-confirmed n-confirmed + 1 ] ; if wasn't confirmed yet, confirm and update count
    ]

    ;; I+ICU-admitted
    set occupied count sicks with [deadly? and ICU-admitted?]
    set required count sicks with [deadly? and not ICU-admitted?]
    set incoming min list (ICU-beds - occupied) required                        ; how many can be admitted to ICU?
    ask n-of incoming sicks with [deadly? and not ICU-admitted?] [              ; ICU-admit as many as possible
      set ICU-admitted? true
      set tested? true                                                          ; so they can't move even when isolation off
      if not confirmed? [ set confirmed? true set n-confirmed n-confirmed + 1 ] ; if wasn't confirmed yet, confirm and update count
    ]
  ]
end 

;; Compute Cumulative Distribution Function (CDF) of triangular distribution at a given number of days elapsed (x) within illness period (width)

to-report cdf-triangle [x width]
  ;; Height of the inner triangle to obtain CDF, i.e. the value of the PDF on x
  let height 2 * (width - abs (width - (2 * x))) / (width ^ 2)

  ;; If x is before peak, CDF is the area of the inner triangle with base x
  ifelse x <= (width / 2) [
    let base x
    report height * base / 2
  ]
  ;; Else if x is after peak, CDF is to total area (1) minus area of inner triangle with base (width - x)
  [
    let base (width - x)
    report 1 - (height * base / 2)
  ]
end 

;; Become healthy again

to get-well
  let old-shape shape
  set breed healthies
  set immune? true
  set shape old-shape
  set color white
  set speed step-size
end 

;; Become dead

to pass-away
  if not confirmed? [ set confirmed? true set n-confirmed n-confirmed + 1 ]  ; some cases are confirmed only at death
  set breed deaths
  set shape "x"
  set speed 0
  set color black
end 

;; Update counters of days and hours

to clock
  set day int (ticks / ticks-day)           ; track of number of days elapsed since beginning
  set hour int ((ticks / ticks-day) * 24)   ; track of number of hours elapsed since beginning
  sunset
end 

;; Record epidemic indicators

to indicators
  ;; Daily statistics are sicks per day and doubling-time
  if ticks mod ticks-day = 0 [
    set sicks-day lput (count sicks) sicks-day

    ;; Compute doubling time
    ;; see (Bakir, 2016, "Compound Interest Doubling Time Rule: Extensions and Examples from Antiquities.")
    if any? sicks[
      ifelse (last sicks-day) > (item (day - 1) sicks-day)
      [ set doubling-time ln 2 / ln ((last sicks-day) / (item (day - 1) sicks-day + 1E-10)) ]
      [ set doubling-time "Inf" ]
    ]
  ]

  if ticks mod (ticks-day / 24) = 0 [
    ;; Estimate R0 based on the final size of susceptibles in population
    ;; see (Dietz, 1993, "The estimation of the basic reproduction number for infectious diseases.")
    if S0 != 0 [
      let Sn count healthies with [ not immune? ] / pop-size
      set R0 (ln (S0 + 1E-10) - ln (Sn + 1E-10)) / (S0 - Sn + 1E-10)
    ]
    ;; Estimate R0_ with an individual-based approach, as the average of contagions per sick
    if any? turtles with [contagions > 0] [
      set R0_ mean [contagions] of turtles with [contagions > 0]
    ]
  ]
end 

;; Inoculate infection on one agent

to infect
  if any? healthies with [not immune?][
    ask one-of healthies with [not immune?] [ get-sick ]
  ]

  ;; Record the initial count of susceptibles for R0 computation
  set S0 (count healthies with [not immune?]) / pop-size
end 

;; Contagion by an outbreak

to outbreak
  ;; Infect a percentage of population
  repeat pop-size * (%-spread / 100) [ infect ]

  ;; Record the initial count of susceptibles for R0 computation
  set S0 (count healthies with [not immune?]) / pop-size
end 

;; Light up or down the city depending on daytime

to sunset
  if see-sunset? [
    if (ticks mod (ticks-day / 2)) = 0 [
      ifelse daytime?
      [ ask patches [ set pcolor pcolor + 4 ] ]
      [ ask patches [ set pcolor pcolor - 4 ] ]
      set daytime? not daytime?
    ]
  ]
end 

;; Setup procedures

to setup
  clear-all
  reset-ticks
  setup-globals
  setup-city
  setup-people
  setup-ambulances
  set daytime? false
end 

;; Initialize global variables

to setup-globals
  ;; Codes to identify zones
  set sort-codes n-values zones [ i -> i ]

  ;; Residents of each zone are identified with different shapes and color
  set shapes-list [ "dog" "cat" "cow skull" "fish 2" "chess knight" "ant 2" "wolf 7" "bird"
    "butterfly 2" "rabbit" "bug" "spider" "ghost" "monster" "person" "fish" "sheep" "bee 2"]
  set colors-list [ cyan pink violet green brown turquoise gray sky lime violet blue
    brown gray sky pink turquoise ]

  ;; Initalise daily sicks, positives, total-tested, total and confirmed cases
  set sicks-day [0]
  set n-positives 0 set n-tested  0 set n-cases 0 set n-confirmed 0


  ;; Probablity of contagion depending on mask wearing combination
  if not mask-sicks? and not mask-healthies? [ set p-contagion 0.9 ]  ; P(Contagion ∣ sick, healthy)
  if not mask-sicks? and     mask-healthies? [ set p-contagion 0.5 ]  ; P(Contagion ∣ sick, healthy+mask )
  if     mask-sicks? and not mask-healthies? [ set p-contagion 0.08 ] ; P(Contagion ∣ sick+mask, healthy)
  if     mask-sicks? and     mask-healthies? [ set p-contagion 0.03 ] ; P(Contagion ∣ sick+mask, healthy+mask)

  ;; Initial value for doubling time
  set doubling-time 0.0
end 

;; Split the city into zones and setup facilities

to setup-city
  set-patch-size 1.9

  ;; Layout a grid of patch square zones by assingning auxiliary codes
  let step world-width / sqrt zones
  ask patches[
    let units int ((pxcor + max-pxcor) / step)
    let tens  int ((pycor + max-pycor) / step)
    set zone 10 * tens + units
  ]

  ;; Now map those auxiliary codes to consecutive sort-codes and corresponding colors
  let aux-codes sort remove-duplicates [zone] of patches
  (foreach aux-codes sort-codes [ [old new] -> ask patches with [zone = old] [set zone new] ])
  ask patches [ set pcolor (item zone colors-list) + 1 ]
  ;foreach sort-codes [ c -> ask one-of patches with [zone = c] [set plabel zone] ] ; display zone code on view area

  ;; If housing, create houses
  if housing? [
    create-houses pop-size / 4 [
      setxy random-xcor random-ycor
      set color white set shape "house" set size 9
    ]
  ]
end 

;; Create initial population

to setup-people
  create-healthies pop-size [
    ;; Assign as homebase either a house if any, otherwise his initial position
    ifelse housing?
    [  set homebase one-of houses
       move-to homebase
    ][ setxy random-xcor random-ycor
       set homebase patch-here
    ]

    ;; Assign color and shape depending on homebase's zone
    set color item zone colors-list - 2
    set shape item zone shapes-list
    set size 9
    set heading random 360
    set scope one-of (list 25 50 100 200) ; choose radomly movement range
    set immune? false
    set unlocked? false
    set tested? false
    set contagions 0
    set speed step-size
    forward 3           ; peek out of house to be seen at the beginning
  ]
end 

;; Create ambulances

to setup-ambulances
  foreach range zones [ z ->
    create-ambulances ambulances-zone [
      move-to one-of patches with [ zone = z ]
      set homebase patch-here
      set shape "ambulance 2" set size 12 set color white
      set speed 4 * step-size        ; ambulances move faster than people
      let residents (turtle-set healthies sicks) with [ zone = z ]

      ;; The amount of tests supply depends on residents population
      set tests-supply round (count residents * (%-tests / 100) / ambulances-zone )
      set tests-stock tests-supply   ; initialise stock of tests
    ]
  ]
end 

;; Replenish the stock of available tests in ambulances

to supply-ambulances
  ask ambulances [ set tests-stock tests-stock + tests-supply ]
end 

;; Replenish an infinite stock of tests in ambulances

to supply-infinity
  ask ambulances [ set tests-stock 1000000 ]
end 

;; Save a screenshot of the interface (view+plots, etc) in a file

to screenshot
  display
  ;export-interface (word "COVID19-NPI-ABM-" random 1000 random 1000 ".png")
end 

There are 15 versions of this model.

Uploaded by When Description Download
Sergio Rojas-Galeano about 1 month ago medrxiv reference update Download this version
Sergio Rojas-Galeano 2 months ago Info tab encoding error fixed Download this version
Sergio Rojas-Galeano 2 months ago Info tab fixed Download this version
Sergio Rojas-Galeano 2 months ago Info tab encoding error fixed Download this version
Sergio Rojas-Galeano 2 months ago Info tab encoding error fixed Download this version
Sergio Rojas-Galeano 2 months ago Info tab encoding error fixed Download this version
Sergio Rojas-Galeano 2 months ago Info tab fixed Download this version
Sergio Rojas-Galeano 2 months ago Info tab fixed Download this version
Sergio Rojas-Galeano 2 months ago Info tab fixed Download this version
Sergio Rojas-Galeano 2 months ago Info tab fixed Download this version
Sergio Rojas-Galeano 2 months ago Info tab fixed Download this version
Sergio Rojas-Galeano 2 months ago Info tab fixed Download this version
Sergio Rojas-Galeano 2 months ago Info tab fixed Download this version
Sergio Rojas-Galeano 2 months ago export interface disabled Download this version
Sergio Rojas-Galeano 2 months ago Initial upload Download this version

Attached files

File Type Description Last updated
COVID-19 epidemics with Non-Pharmaceutical Interventions and zonal restraints.png preview Preview for 'COVID-19 epidemics with Non-Pharmaceutical Interventions and zonal restraints' 2 months ago, by Sergio Rojas-Galeano Download
COVID_19_NPI_Zones_UserGuide.pdf pdf User guide 18 days ago, by Sergio Rojas-Galeano Download

This model does not have any ancestors.

This model does not have any descendants.