Skip to content

Commit

Permalink
Merge pull request #4 from garethjns/imperfect_immunity
Browse files Browse the repository at this point in the history
Update readme, tidy
  • Loading branch information
garethjns authored Apr 5, 2020
2 parents a307847 + 2beef8d commit 30193bf
Show file tree
Hide file tree
Showing 20 changed files with 479 additions and 162 deletions.
16 changes: 14 additions & 2 deletions README.MD
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@ This package models disease spread through a population consisting of sub commun

The code aims to be as simple and understandable as possible, and can be summarised in two graphs:

![Example cats vs responsible](https://github.com/garethjns/social-distancing-sim/blob/master/images/joined.gif)
![Example cats vs responsible](https://github.com/garethjns/social-distancing-sim/blob/master/images/joined.gif)
([Discussion](https://new.reddit.com/r/dataisbeautiful/comments/fov56p/oc_comparing_the_effect_of_social_distancing_on/))

# Set up

Expand Down Expand Up @@ -119,4 +120,15 @@ In the observed model, a proportion of the population (here ~4%) is tested per
- For known infected nodes, status is switched to "dead" or "immune" at the end of disease, depending on survival
- For unknown infected nodes, status is set to "dead" if they die, but left as unknown if they survive - this is based on the assumption we know about all deaths, but don't know about acquired immunity unless we know about infection.

![Example cats vs responsible](https://github.com/garethjns/social-distancing-sim/blob/master/images/joined_2.gif)
![Example testing rate](https://github.com/garethjns/social-distancing-sim/blob/master/images/joined_2.gif)
([Discussion](https://new.reddit.com/r/dataisbeautiful/comments/fse6l1/oc_the_importance_of_testing_and_effect_on/))

# Immunity effects
Version 0.2.0 adds incomplete immunity and decay of immunity. These are part of the disease definition, and allow reinfection after a node has survived infection.

Run example with
````bash
python3 -m social-distancing-sim.scripts.compare_two_diseases_immunity
````

![Example testing rate](https://github.com/garethjns/social-distancing-sim/blob/master/images/joined_3.gif)
Binary file added images/immunity.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added images/joined_3.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,6 @@ matplotlib
imageio
dataclasses
seaborn
tqdm
joblib

34 changes: 13 additions & 21 deletions scripts/compare_testing_rate.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,28 +5,20 @@
from social_distancing_sim.population.population import Population

if __name__ == "__main__":
save = True

disease = Disease(name='COVID-19')
healthcare = Healthcare()

pop_full_knowledge = Population(name='A herd of cats, reality',
disease=disease,
healthcare=healthcare,
observation_space=ObservationSpace(graph=Graph(community_n=40,
community_size_mean=16,
seed=123),
test_rate=1))
pop_poor_testing_knowledge = Population(name='A herd of cats, observed',
disease=disease,
healthcare=healthcare,
observation_space=ObservationSpace(graph=Graph(community_n=40,
community_size_mean=16,
seed=123),
test_rate=0.01))

pop_full_knowledge.run(steps=130,
plot=False)
pop_full_knowledge.replay(duration=0.1)
pop = Population(name='A herd of cats, observed',
disease=disease,
healthcare=healthcare,
observation_space=ObservationSpace(graph=Graph(community_n=40,
community_size_mean=16,
seed=123),
test_rate=0.01))

pop_poor_testing_knowledge.run(steps=130,
plot=False)
pop_poor_testing_knowledge.replay(duration=0.1)
pop.run(steps=130,
plot=False)
if save:
pop.replay(duration=0.1)
53 changes: 53 additions & 0 deletions scripts/compare_two_diseases_immunity.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
"""Run a single population for 2 years with imperfect immunity and limited test rate."""

from joblib import Parallel, delayed

from social_distancing_sim.disease.disease import Disease
from social_distancing_sim.population.graph import Graph
from social_distancing_sim.population.healthcare import Healthcare
from social_distancing_sim.population.observation_space import ObservationSpace
from social_distancing_sim.population.population import Population


def run_and_replay(pop, *args, **kwargs):
pop.run(*args, **kwargs)
if save:
pop.replay(duration=duration)


if __name__ == "__main__":
save = True
duration = 0.1

common_args = {'plot_ts_fields_g2': ["Mean immunity (of immune nodes)",
"Mean immunity (of all alive nodes)"],
'plot_ts_obs_fields_g2': ["Known mean immunity (of immune nodes)",
"Known mean immunity (of all alive nodes)"],
'observation_space': ObservationSpace(graph=Graph(community_n=50,
community_size_mean=15,
community_p_in=0.08,
community_p_out=0.04),
test_rate=0.05),
'healthcare': Healthcare(capacity=200)}

pop_low_immunity = Population(name="Low immunity population",
disease=Disease(name='COVID-19',
virulence=0.005,
recovery_rate=0.99,
immunity_mean=0.66,
immunity_decay_mean=0.1),
**common_args)

pop_high_immunity = Population(name="High immunity population",
disease=Disease(name='COVID-19',
virulence=0.005,
recovery_rate=0.99,
immunity_mean=0.98,
immunity_decay_mean=0.01),
**common_args)

Parallel(n_jobs=2,
backend='loky')(delayed(run_and_replay)(pop,
steps=750,
plot=False,
save=True) for pop in [pop_low_immunity, pop_high_immunity])
58 changes: 58 additions & 0 deletions scripts/compare_two_diseases_immunity_small.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
"""Run a single population for 2 years with imperfect immunity and limited test rate."""

from joblib import Parallel, delayed

from social_distancing_sim.disease.disease import Disease
from social_distancing_sim.population.graph import Graph
from social_distancing_sim.population.healthcare import Healthcare
from social_distancing_sim.population.observation_space import ObservationSpace
from social_distancing_sim.population.population import Population


def run_and_replay(pop, *args, **kwargs):
pop.run(*args, **kwargs)
if save:
pop.replay(duration=duration)


if __name__ == "__main__":
save = True
duration = 0.1

common_args = {'plot_ts_fields_g2': ["Mean immunity (of immune nodes)",
"Mean immunity (of all alive nodes)"],
'plot_ts_obs_fields_g2': ["Known mean immunity (of immune nodes)",
"Known mean immunity (of all alive nodes)"],
'observation_space': ObservationSpace(graph=Graph(community_n=8,
community_size_mean=5,
community_p_in=0.2,
community_p_out=0.1,
seed=200),
test_rate=0.05,
seed=123),
'healthcare': Healthcare(capacity=300),
'seed': 124}

pop_low_immunity = Population(name="Low immunity population (small)",
disease=Disease(name='COVID-19',
virulence=0.035,
recovery_rate=0.99,
immunity_mean=0.66,
immunity_decay_mean=0.1,
seed=125),
**common_args)

pop_high_immunity = Population(name="High immunity population (small)",
disease=Disease(name='COVID-19',
virulence=0.035,
recovery_rate=0.99,
immunity_mean=0.95,
immunity_decay_mean=0.02,
seed=125),
**common_args)

Parallel(n_jobs=2,
backend='loky')(delayed(run_and_replay)(pop,
steps=365,
plot=False,
save=True) for pop in [pop_low_immunity, pop_high_immunity])
84 changes: 33 additions & 51 deletions scripts/compare_two_pop_testing_rate.py
Original file line number Diff line number Diff line change
@@ -1,61 +1,43 @@
from joblib import Parallel, delayed

from social_distancing_sim.disease.disease import Disease
from social_distancing_sim.population.graph import Graph
from social_distancing_sim.population.healthcare import Healthcare
from social_distancing_sim.population.observation_space import ObservationSpace
from social_distancing_sim.population.population import Population


def run_and_replay(pop, *args, **kwargs):
pop.run(*args, **kwargs)
if save:
pop.replay()


if __name__ == "__main__":
save = True
disease = Disease(name='COVID-19')
healthcare = Healthcare()

pop_close_tested = Population(name='A herd of cats',
disease=disease,
healthcare=healthcare,
observation_space=ObservationSpace(graph=Graph(community_n=40,
community_size_mean=16,
seed=123),
test_rate=1))

pop_close_untested = Population(name='A herd of cats, observed',
disease=disease,
healthcare=healthcare,
observation_space=ObservationSpace(graph=Graph(community_n=40,
community_size_mean=16,
seed=123),
test_rate=0.04))

pop_distanced_tested = Population(name='A socially responsible population',
disease=disease,
healthcare=healthcare,
observation_space=ObservationSpace(graph=Graph(community_n=40,
community_size_mean=16,
community_p_in=0.05,
community_p_out=0.04,
seed=123),
test_rate=1))

pop_distanced_untested = Population(name='A socially responsible population, observed',
disease=disease,
healthcare=healthcare,
observation_space=ObservationSpace(graph=Graph(community_n=40,
community_size_mean=16,
community_p_in=0.05,
community_p_out=0.04,
seed=123),
test_rate=0.04))

pop_close_tested.run(steps=130,
plot=False)
pop_close_tested.replay(duration=0.1)

pop_close_untested.run(steps=130,
plot=False)
pop_close_untested.replay(duration=0.1)

pop_distanced_tested.run(steps=130,
plot=False)
pop_distanced_tested.replay(duration=0.1)

pop_distanced_untested.run(steps=130,
plot=False)
pop_distanced_untested.replay(duration=0.1)
pop_close = Population(name='A herd of cats, observed',
disease=disease,
healthcare=healthcare,
observation_space=ObservationSpace(graph=Graph(community_n=40,
community_size_mean=16,
seed=123),
test_rate=0.04))

pop_distanced = Population(name='A socially responsible population, observed',
disease=disease,
healthcare=healthcare,
observation_space=ObservationSpace(graph=Graph(community_n=40,
community_size_mean=16,
community_p_in=0.05,
community_p_out=0.04,
seed=123),
test_rate=0.04))

Parallel(n_jobs=2,
backend='loky')(delayed(run_and_replay)(pop,
steps=130,
plot=False,
save=save) for pop in [pop_close, pop_distanced])
23 changes: 16 additions & 7 deletions scripts/compare_two_populations.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,21 @@
from joblib import Parallel, delayed

from social_distancing_sim.disease.disease import Disease
from social_distancing_sim.population.graph import Graph
from social_distancing_sim.population.healthcare import Healthcare
from social_distancing_sim.population.observation_space import ObservationSpace
from social_distancing_sim.population.population import Population


def run_and_replay(pop, *args, **kwargs):
pop.run(*args, **kwargs)
if save:
pop.replay()


if __name__ == "__main__":
save = False

disease = Disease(name='COVID-19')
healthcare = Healthcare()

Expand All @@ -26,10 +37,8 @@
seed=123),
test_rate=1))

pop_distanced.run(steps=130,
plot=False)
pop_distanced.replay(duration=0.1)

pop.run(steps=130,
plot=False)
pop.replay(duration=0.1)
Parallel(n_jobs=2,
backend='loky')(delayed(run_and_replay)(pop,
steps=300,
plot=False,
save=save) for pop in [pop, pop_distanced])
6 changes: 4 additions & 2 deletions scripts/run_single_population.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
"""Run a single population with perfrect testing."""

from social_distancing_sim.population.graph import Graph
from social_distancing_sim.population.healthcare import Healthcare
from social_distancing_sim.population.observation_space import ObservationSpace
Expand All @@ -16,8 +18,8 @@
observation_space=ObservationSpace(graph=graph,
test_rate=1))

pop.run(steps=100,
plot=False,
pop.run(steps=50,
plot=True,
save=True)

# Save .gif to './example population/replay.gif'
Expand Down
31 changes: 31 additions & 0 deletions scripts/run_single_population_long.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
"""Run a single population for 2 years with imperfect immunity and limited test rate."""
from social_distancing_sim.disease.disease import Disease
from social_distancing_sim.population.graph import Graph
from social_distancing_sim.population.healthcare import Healthcare
from social_distancing_sim.population.observation_space import ObservationSpace
from social_distancing_sim.population.population import Population

if __name__ == "__main__":
save = True

graph = Graph(community_n=50,
community_size_mean=15,
community_p_in=0.1,
community_p_out=0.05)

pop = Population(name="example population",
disease=Disease(name='COVID-19',
virulence=0.006,
immunity_mean=0.6,
immunity_decay_mean=0.15),
healthcare=Healthcare(),
observation_space=ObservationSpace(graph=graph,
test_rate=0.05))

pop.run(steps=750,
plot=True,
save=True)

# Save .gif to './example population/replay.gif'
if save:
pop.replay()
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,5 +22,5 @@
"Programming Language :: Python :: 3",
"Operating System :: OS Independent"],
python_requires='>=3.6',
install_requires=["networkx", "numpy", "matplotlib", "imageio", "dataclasses"]
install_requires=["networkx", "numpy", "matplotlib", "imageio", "dataclasses", "tqdm", "joblib"]
)
2 changes: 1 addition & 1 deletion social_distancing_sim/__init__.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
MAJOR = 0
MINOR = 1
MINOR = 2
PATCH = 0

__version__ = ".".join(str(v) for v in [MAJOR, MINOR, PATCH])
Loading

0 comments on commit 30193bf

Please sign in to comment.