This repository has been archived by the owner on Sep 30, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 5
/
contagion.py
96 lines (79 loc) · 2.78 KB
/
contagion.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
"""Simple grid model of contagion"""
import grid_view
import change_listener
import model
import contagion_stats
import time
import config
import argparse
import logging
logging.basicConfig()
log = logging.getLogger(__name__)
log.setLevel(logging.WARN)
def cli() -> object:
"""Command line interface returns an object with
an instance variable for each command line argument.
"""
parser = argparse.ArgumentParser(
description="Contagion, a simple model of disease spread")
parser.add_argument("conf", nargs="?",
default="contagion.ini")
return parser.parse_args()
def main():
"""View a simulation of contagion"""
args = cli()
config.configure(args.conf)
n_rows = config.get_int("Grid", "rows")
n_cols = config.get_int("Grid", "cols")
population = model.Population(n_rows, n_cols)
# View of the main model
view = grid_view.GridView(config.get_int("Grid", "Width"),
config.get_int("Grid", "Height"),
nrows=n_rows, ncols=n_cols,
title="Contagion", autoflush=False)
# Summary statistics
stats_view = contagion_stats.Stats(population)
# Monitor changes to cells ---
# - for monitoring progress
# - for updating the main view
monitor = change_listener.ChangeListener()
# Attach listeners to each cell
for row in range(n_rows):
for col in range(n_cols):
cell_view = grid_view.CellView(row, col, view)
population.cells[row][col].add_listener(cell_view) # Graphics
population.cells[row][col].add_listener(monitor) # Change tracking
view.update(rate=5)
# Initial view, before simulation starts
view.update()
time.sleep(1)
log.info("Seeding")
population.seed() # Note this should set change monitor
view.update()
time.sleep(1)
# Evolve until it reaches quiescence
log.info("Running")
steps = 0
epoch = 0
monitor.set(True)
while monitor.check():
monitor.set(False) # No changes yet in this cycle
# An 'epoch' is 10 steps. We stop when an epoch has
# gone by without a noticeable state change, and we
# chart each epoch rather than each step
for _ in range(10):
steps += 1
log.debug(f"Step {steps}")
population.step()
view.update()
stats_view.update(day=steps)
time.sleep(0.1)
epoch += 1
# Print stats and update bar graph after each epoch
stats_view.show(day=steps, epoch=epoch)
# Simulation is no longer changing. Leave view open
# until the user presses enter
stats_view.show_summary()
_ = input("Press enter to close")
if __name__ == "__main__":
main()