-
Martin Lange authored
make dispersal a function that assigns and disperses (brings all dispersal code into the submodel); mention code acces from NetLogo
f027a7b4
Literate NetLogo
This is an example project to demonstrate Literate Programming to create NetLogo models from ODD+C protocols using Yarner.
The document you are currently reading contains the ODD protocol (Grimm et al. 2006, 2010) of a model for Rabies in red foxes. The ODD description is interleaved with code blocks showing the NetLogo code used for the described aspect (ODD+C). Using the Literate Programming tool Yarner, these code blocks are extracted from the document and arranged into a working NetLogo model.
How to use it
Read the ODD
The best way to understand how to use Literate Programming with Yarner to create a NetLogo model from an ODD protocol is to read the ODD+C of the Rabies model, below. It contains the complete code of the model, except the UI elements.
See section How it works for how the model is extracted from this document.
Run from downloads
The Downloads contain a folder model
with files Model.nlogo
and Code.nls
. Open the .nlogo
file with NetLogo.
Build from sources
- Install Yarner
- Clone the sources of this example:
git clone https://git.ufz.de/oesa/literate-netlogo.git
-
cd
into folderliterate-netlogo
- Run command
yarner
to extract the model code - Open file
model/Model.nlogo
with NetLogo
How it works
Yarner scans the document for code blocks and puts them together using macros. Each code block has a name, given in its first line and prefixed with ;-
:
;- A code block
let x 0
When a code block is referenced by another code block using a macro with ; ==>
, it is placed inside the referencing code block:
;- Outer code block
; ==> A code block.
let y 1
The resulting extracted code would look like this:
let x 0
let y 1
See the Yarner documentation for a comprehensive guide and a description of all features.
Rabies model - ODD protocol
- Purpose
- Entities, state variables, and scales
- Process overview and scheduling
- Design concepts
- Initialization
- Input data
- Submodels
Purpose
The purpose of this model is to demonstrate how NetLogo models can be created from ODD protocols, using Literate Programming with Yarner.
Entities, state variables, and scales
The model landscape is represented by a grid of 1km x 1km cells, each representing a potential home range of a fox family. The model progresses in discrete ticks of one month each.
The only entity in the model are fox families. Each fox family is represented by a NetLogo patch (i.e. a grid cell).
Each patch (i.e. each potential fox family) has four state variables:
;- State variables
patches-own [
state
infected-neighbours
tick-of-death
dispersal-tick
]
The disease state (state
) represents the state of the patch. Possible states are EMPTY
, S
usceptible, I
nfected and R
ecovered:
;- Disease states
globals [
EMPTY
S
I
R
]
Disease states are internally represented by whole numbers 0-3:
;- Setup disease states
set EMPTY 0
set S 1
set I 2
set R 3
State variable infected-neighbours
is a counter for the number of infected neighbouring families. tick-of-death
is the model step of death for infected families. dispersal-tick
indicates the month of the year (index [0..11]) of the family's next dispersal event.
Process overview and scheduling
Processes simulated by the model are Dispersal, Infection and Disease course. Processes are executed on every monthly time step in the above order.
After to model processes, the patch colour is updated for Visualization and the model tick is increased by one.
;- Go
to go
disperse-offspring
infect-patches
age-infection
update-patches
tick
end
; ==> Submodels.
Design concepts
Fox families as the only model entities live on a rectangular grid of habitat patches. Patches can be empty or occupied.
Reproduction and juvenile dispersal are subsumed under a single process Dispersal. Once a year, a certain number of female offspring disperses from each fox family. Time and target location of dispersal are stochastic. Dispersal is restricted by a maximum dispersal radius.
Fox families can become infected with Rabies. Rabies can be transmitted to the 8 immediate neighbouring families. Infection is stochastic and infection probability depends on the number of infected neighbours.
Initialization
The model is initialized by populating each habitat patch with a S
usceptible fox family. One randomly selected family is infected.
;- Setup
to setup
clear-all
; ==> Setup disease states.
ask patches [
set state S
]
ask one-of patches [
infect-patch 0
]
update-patches
reset-ticks
end
Input data
The model uses no input data.
Submodels
The model is composed of four submodels:
;- Submodels
; ==> Dispersal.
; ==> Infection.
; ==> Disease course.
; ==> Update patches.
Dispersal
The month of dispersal of each fox family is determined once per year. Actual dispersals are processed at every tick.
;- Dispersal
to disperse-offspring
if ticks mod 12 = 0 [
assign-dispersal
]
disperse
end
; ==> Assign dispersal.
; ==> Disperse.
At the start of each year, the month of the next dispersal (dispersal-tick
) is assigned to each fox family (i.e. to each non-empty patch), drawn from a uniform distribution covering the dispersal period.
;- Assign dispersal
to assign-dispersal
ask patches with [ state != EMPTY ] [
set dispersal-tick (ticks + start-dispersal + random length-dispersal)
]
end
Each fox family disperses in their designated month of dispersal dispersal-tick
so that all foxes disperse uniformly distributed over the dispersal period. In each step, dispersals are executed in arbitrary order and immediately occupy their target patches. However, the results are independent of that order.
Each female offspring of each family's num-offspring
tries to occupy an empty patch in radius dispersal-radius
. If the number of offspring exceeds the available patches, only as many offspring as there are patches available can disperse.
The target patch of each disperser is set to S
usceptible. It is assumed that animals infected with Rabies do not disperse.
;- Disperse
to disperse
ask patches with [ state != EMPTY and dispersal-tick = ticks ] [
let candidates other patches
in-radius dispersal-radius
with [ state = EMPTY ]
let num-candidates num-offspring
if count candidates < num-candidates [
set num-candidates count candidates
]
ask n-of num-candidates candidates [
set state S
]
]
end
Infection
Infection depends on the number of infected neighbouring families. For synchronous update, the number of infected neighbours is determined for each patch and stored in state variable infected-neighbours
.
Then, S
usceptible patches are infected with a probability calculated from this state variable.
;- Infection
to infect-patches
ask patches [
set infected-neighbours 0
]
ask patches with [ state = I ] [
ask neighbors [
set infected-neighbours infected-neighbours + 1
]
]
ask patches with [ state = S ] [
if random-float 1 < calc-infection-prob [
infect-patch ticks
]
]
end
; ==> Infection probability.
; ==> Infect patch.
Infection probability P_{inf}
per patch is calculated from the number of infected neighbours using the Reed-Frost model (Abbey 1952) with parameter beta
.
P_{inf} = 1 - (1 - \beta)^{I}
With \beta
being the infection probability to be infected by one infected neighbour, and I
being the number of infected neighbouring patches.
;- Infection probability
to-report calc-infection-prob
report 1 - (1 - beta) ^ infected-neighbours
end
Upon infection of a patch, its state
is set to I
nfected. The duration of infection is determined (here, the constant ticks-infected
), and the model step of death is assigned to the patch state variable tick-of-death
(see the Disease course submodel).
;- Infect patch
to infect-patch [ curr-tick ]
set state I
set tick-of-death curr-tick + ticks-infected
end
Disease course
All Rabies infections are lethal. When the tick-of-death
of an infected fox family equals the current tick ticks
, the family is removed from the simulation, leaving an empty patch.
;- Disease course
to age-infection
ask patches with [ state = I ] [
if tick-of-death = ticks [
set state EMPTY
]
]
end
Visualization
After each model update, patches are coloured by their disease state: white for empty, blue for susceptible, red for infected and green for recovered patches/families.
;- Update patches
to update-patches
ask patches [
ifelse state = EMPTY [ set pcolor white ]
[ ifelse state = S [ set pcolor blue ]
[ ifelse state = I [ set pcolor red ]
[ set pcolor green ] ] ]
]
end
References
Abbey H. 1952: An examination of the Reed Frost theory of epidemics. Human Biology, 24:201-233.
Grimm V, Berger U, Bastiansen F, Eliassen S, Ginot V, Giske J, Goss-Custard J, Grand T, Heinz S, Huse G, Huth A, Jepsen JU, Jørgensen C, Mooij WM, Müller B, Pe’er G, Piou C, Railsback SF, Robbins AM, Robbins MM, Rossmanith E, Rüger N, Strand E, Souissi S, Stillman RA, Vabø R, Visser U, DeAngelis DL. 2006. A standard protocol for describing individual-based and agent-based models. Ecological Modelling 198:115-126.
Grimm V, Berger U, DeAngelis DL, Polhill G, Giske J, Railsback SF. 2010. The ODD protocol: a review and first update. Ecological Modelling 221: 2760-2768.
Appendix
Code entrypoint
This is the entrypoint to this "literate program". The blocks referenced by the macros in the code block below are collected here (recursively), and the result is written to file model/Code.nls
.
;- file:Code.nls
; ==> Disease states.
; ==> State variables.
; ==> Setup.
; ==> Go.
NetLogo file
In the main .nlogo
file, we only "include" the .nls
file to allow for the reverse mode.
Yarner's reverse mode requires automatically generated comments in the code output to be able to identify the source blocks in this Markdown document. NetLogo, however, supports comments only in the code part, but not in the rest of the content of a .nlogo
file.
Moving the actual model code into the separate .nls
file resolves this limitation.
The Code tab has this single line of content:
__includes["Code.nls"]
Access the file in NetLogo via the Included files
dropdown in the Code tab.
The file Model.nlogo
is simply copied from the nlogo
directory via option code_files
in the [paths]
section of the Yarner.toml
.
This separation of model code (Code.nls
) and user interface (Model.nlogo
) also allows to edit the model's UI elements in NetLogo's GUI builder tool, while using Literate Programming for the code.