Self-isolation duration¶
In the last section we saw how self-isolation and a population that took steps to reduce transmissability of the virus could dramatically reduce the spread of the disease. However, in that model infected individuals were moved into self-isolation for the entire duration of the outbreak. This is clearly unrealistic.
Using demographics to represent days¶
Typical advice to someone who is self-isolating is that they should self-isolate for a set number of days. We can model this by using different self-isolation demographics to represent the different days that individuals start their self-isolation. For example, if self-isolation was for seven days, then we could have a self-isolation demographic for each day of the week. Once a week is up, then the individuals who are self-isolating in that day-demographic are released and moved to the “released” demographic. Newly infected individuals for that day are then moved into the now-empty day-demographic.
To do this, create a new demographics file called demographics.json
and copy in the below;
{
"demographics" : ["home", "released",
"isolate_0", "isolate_1", "isolate_2",
"isolate_3", "isolate_4", "isolate_5",
"isolate_6" ],
"work_ratios" : [ 1.0, 0.0,
0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 ],
"play_ratios" : [ 1.0, 0.0,
0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 ]
}
This creates the home
demographic, plus one isolate
demographic
for each day of the week. There is also a released
demographic
that will be used to release individuals from self-isolation.
Moving daily¶
We start with all individuals placed into the home
demographic. We will
now write a custom move function that will move individuals into the
assigned isolate_N
demographic for the day in which they develop
symptoms. This move function will move them into the released
demographic
once they have spent seven days in self-isolation. To do this,
create a move function called move_isolate.py
and copy in the below;
from metawards import Population
from metawards.movers import go_isolate, go_to
def move_isolate(population: Population, **kwargs):
day = population.day % 7
isolate = f"isolate_{day}"
go_isolate_day = lambda **kwargs: go_isolate(
go_from="home",
go_to=isolate,
self_isolate_stage=3,
**kwargs)
go_released = lambda **kwargs: go_to(go_from=isolate,
go_to="released",
**kwargs)
return [go_released, go_isolate_day]
This function works out which isolate_N
demographic to use based
on the day of the week (population.day % 7
returns a number from 0
to 6
).
It then creates two go functions
. The first, go_isolate_day
is a go_isolate()
that moves infected
individuals from home
into the isolate_N
demographic of that day.
The second, go_released
calls go_to()
to
send all individuals who are in that isolate_N
demographic
to the released
demographic.
The move_isolate
function returns go_released
first, so that
everyone who ends their self-isolation leaves before go_isolate_day
then sends in the new cohort of infected individuals.
Mixing home and released¶
Next, create a mixing function
that merges the FOIs of the home
and released
demographics evenly, while making sure that everyone
in the isolate_N
demographics is isolated and does not contribute
to any FOI.
Do this by creating a mixing function called mix_isolate.py
and
copying in the below;
from metawards import Networks
from metawards.mixers import merge_using_matrix, InteractionMatrix
def mix_isolate(network: Networks, **kwargs):
matrix = InteractionMatrix.ones(n=2)
matrix.resize(2 + 7, value=0.0)
network.demographics.interaction_matrix = matrix
return [merge_using_matrix]
Note
Note that we are using merge_using_matrix()
.
This may not be the right choice depending on how we want the
population dynamics to mix, e.g.
merge_matrix_single_population()
or
merge_matrix_multi_population()
may
be a better choice. See here for more information.
Here we use metawards.mixers.InteractionMatrix
to simplify the
creation of the interation matrix. We first create a 2x2 matrix;
[ [1, 1],
[1, 1] ]
using InteractionMatrix.ones(n=2)
.
We then resize this to be a 9x9 matrix using
InteractionMatrix.resize(2 + 7, value=0.0)
,
where the new values are equal to
zero. You can double-check that this matrix is correct using, e.g.
ipython or a jupyter notebook;
>>> from metawards.mixers import InteractionMatrix
>>> matrix = InteractionMatrix.ones(n=2)
>>> print(matrix)
| 1.000, 1.000 |
| 1.000, 1.000 |
>>> matrix.resize(2 + 7, value=0.0)
>>> print(matrix)
| 1.000, 1.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000 |
| 1.000, 1.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000 |
| 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000 |
| 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000 |
| 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000 |
| 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000 |
| 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000 |
| 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000 |
| 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000 |
Note
You could have created this matrix manually, but that is error-prone.
The InteractionMatrix
class has lots
of helper functions that are useful for setting interactions between
different demographics.
With this mixer created, you can now run metawards
using;
metawards -d lurgy4 -D demographics.json -a ExtraSeedsLondon.dat --mixer mix_isolate --mover move_isolate --extractor extract_none --nsteps 365
Note
We’ve limited the number of days to model to 365 (one year), as
self-isolation significantly slows down the spread of the disease,
and modelling more than a year is unhelpful. We’ve also here used
the extract_none()
extractor to limit
the amount of output. Outputting data can be a little slow when
there are a large number of demographics.
What do you see? In some cases self-isolation will cause the outbreak to quickly die out. However, for most runs, we see that the infectious asymptomatic allows new infections to be seeded before the individual develops symptoms and moves into self-isolation.
Of more interest, we also see that as the outbreak grows, about 1% of
infected individuals have not recovered after 7 days. They leave
self-isolation and are able to contribute to the force of infection
in the home
demographic.
...
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ Day 11 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
S: 56082064 E: 0 I: 6 R: 7 IW: 2 POPULATION: 56082077
home S: 56082064 E: 0 I: 6 R: 2 IW: 2 POPULATION: 56082072
released S: 0 E: 0 I: 0 R: 0 IW: 0 POPULATION: 0
isolate_0 S: 0 E: 0 I: 0 R: 1 IW: 0 POPULATION: 1
isolate_1 S: 0 E: 0 I: 0 R: 1 IW: 0 POPULATION: 1
isolate_2 S: 0 E: 0 I: 0 R: 0 IW: 0 POPULATION: 0
isolate_3 S: 0 E: 0 I: 0 R: 1 IW: 0 POPULATION: 1
isolate_4 S: 0 E: 0 I: 0 R: 0 IW: 0 POPULATION: 0
isolate_5 S: 0 E: 0 I: 0 R: 2 IW: 0 POPULATION: 2
isolate_6 S: 0 E: 0 I: 0 R: 0 IW: 0 POPULATION: 0
Number of infections: 6
...
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ Day 39 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
S: 56081874 E: 19 I: 95 R: 89 IW: 13 POPULATION: 56082077
home S: 56081874 E: 19 I: 71 R: 13 IW: 13 POPULATION: 56081977
released S: 0 E: 0 I: 0 R: 48 IW: 0 POPULATION: 48
isolate_0 S: 0 E: 0 I: 2 R: 5 IW: 0 POPULATION: 7
isolate_1 S: 0 E: 0 I: 0 R: 8 IW: 0 POPULATION: 8
isolate_2 S: 0 E: 0 I: 3 R: 4 IW: 0 POPULATION: 7
isolate_3 S: 0 E: 0 I: 5 R: 2 IW: 0 POPULATION: 7
isolate_4 S: 0 E: 0 I: 13 R: 0 IW: 0 POPULATION: 13
isolate_5 S: 0 E: 0 I: 0 R: 3 IW: 0 POPULATION: 3
isolate_6 S: 0 E: 0 I: 1 R: 6 IW: 0 POPULATION: 7
Number of infections: 114
...
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ Day 139 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
S: 56064409 E: 566 I: 4253 R: 12849 IW: 524 POPULATION: 56082077
home S: 56064409 E: 566 I: 2938 R: 585 IW: 524 POPULATION: 56068498
released S: 0 E: 0 I: 28 R: 10553 IW: 0 POPULATION: 10581
isolate_0 S: 0 E: 0 I: 23 R: 374 IW: 0 POPULATION: 397
isolate_1 S: 0 E: 0 I: 42 R: 377 IW: 0 POPULATION: 419
isolate_2 S: 0 E: 0 I: 85 R: 341 IW: 0 POPULATION: 426
isolate_3 S: 0 E: 0 I: 121 R: 272 IW: 0 POPULATION: 393
isolate_4 S: 0 E: 0 I: 218 R: 232 IW: 0 POPULATION: 450
isolate_5 S: 0 E: 0 I: 364 R: 115 IW: 0 POPULATION: 479
isolate_6 S: 0 E: 0 I: 434 R: 0 IW: 0 POPULATION: 434
Number of infections: 4819
...
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ Day 364 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
S: 54653198 E: 14724 I: 126080 R: 1288075 IW: 6273 POPULATION: 56082077
home S: 54653198 E: 14724 I: 84809 R: 14613 IW: 6273 POPULATION: 54767344
released S: 0 E: 0 I: 1014 R: 1218000 IW: 0 POPULATION: 1219014
isolate_0 S: 0 E: 0 I: 14010 R: 0 IW: 0 POPULATION: 14010
isolate_1 S: 0 E: 0 I: 834 R: 12575 IW: 0 POPULATION: 13409
isolate_2 S: 0 E: 0 I: 1490 R: 11998 IW: 0 POPULATION: 13488
isolate_3 S: 0 E: 0 I: 2482 R: 11212 IW: 0 POPULATION: 13694
isolate_4 S: 0 E: 0 I: 4150 R: 9327 IW: 0 POPULATION: 13477
isolate_5 S: 0 E: 0 I: 6926 R: 6897 IW: 0 POPULATION: 13823
isolate_6 S: 0 E: 0 I: 10365 R: 3453 IW: 0 POPULATION: 13818
Number of infections: 140804
As you can see above, by day 364, there were 1014 infected individuals in
the released
demographic, indicating that they have left self-isolation
too early.