Skip to content

Commit 5947411

Browse files
committed
Python script for generating epidemic plots
1 parent bb39d56 commit 5947411

File tree

1 file changed

+188
-0
lines changed

1 file changed

+188
-0
lines changed
Lines changed: 188 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,188 @@
1+
#!/usr/bin/env python
2+
# coding: utf-8
3+
4+
import argparse
5+
import os
6+
import re
7+
from collections import defaultdict
8+
import pandas as pd
9+
import numpy as np
10+
import matplotlib.pyplot as plt
11+
12+
parser = argparse.ArgumentParser(description='Script that generates epidemic plots and csv reports.')
13+
14+
parser.add_argument('-l', '--log_file', type=str, required=True, help='Input log file')
15+
parser.add_argument('-d', '--dim', type=str, default="200,200", help='Dimensions of the cell grid (WIDTH,HEIGHT)')
16+
parser.add_argument('-i', '--initial_val', default=0, help='Force initial val for the cells')
17+
parser.add_argument('-c', '--state_changes', action="store_true", help='Log state changes to csv file')
18+
19+
args = parser.parse_args()
20+
21+
log_filename = args.log_file
22+
dim = list(map(int, args.dim.split(",")))
23+
initial_val = args.initial_val
24+
#log_filename = "covid_store.log"
25+
#dim = 64, 100
26+
#initial_val = None
27+
log_state_changes_to_file = args.state_changes
28+
29+
patt_out_line = ".*Y / (?P<time>[0-9]{2}:[0-9]{2}:[0-9]{2}:[0-9]{3})(?::0)? / [a-zA-Z0-9]+\((?P<x>[0-9]+),(?P<y>[0-9]+)\)\([0-9]+\) / out / +(?P<state>[0-9.-]+) (?:/|para) [a-zA-Z0-9]+\([0-9]+\)"
30+
31+
ID_SUSCEPTIBLE = 0
32+
ID_INFECTED = 1
33+
ID_SICK = 8
34+
ID_RECOVERED = 16
35+
ID_DEAD = -1
36+
ID_WALL = -10
37+
38+
COLOR_SUSCEPTIBLE = "#3498db"
39+
COLOR_INFECTED = "#e74c3c"
40+
COLOR_SICK = "#f1c40f"
41+
COLOR_RECOVERED = "#2ecc71"
42+
COLOR_DEAD = "#9b59b6"
43+
44+
45+
def time_str_to_ts(time_str):
46+
patt_time = "([0-9]{2}):([0-9]{2}):([0-9]{2}):([0-9]{3})"
47+
match = re.match(patt_time, time_str)
48+
if not match:
49+
raise RuntimeError("Error converting simulation time")
50+
tu = list(map(int, match.groups()))
51+
return tu[3] + tu[2]*1000 + tu[1]*60000 + tu[0]*3600000
52+
53+
54+
def dict_to_states_row(states_dict):
55+
row = []
56+
row.append(states_dict[ID_SUSCEPTIBLE] if ID_SUSCEPTIBLE in states_dict else 0)
57+
58+
infected_count = 0
59+
for state in range(ID_INFECTED, ID_SICK):
60+
if state in states_dict:
61+
infected_count += states_dict[state]
62+
row.append(infected_count)
63+
64+
sick_count = 0
65+
for state in range(ID_SICK, ID_RECOVERED):
66+
if state in states_dict:
67+
sick_count += states_dict[state]
68+
row.append(sick_count)
69+
70+
for state in [ID_RECOVERED, ID_DEAD, ID_WALL]:
71+
row.append(states_dict[state] if state in states_dict else 0)
72+
return row
73+
74+
75+
state_count = defaultdict(int)
76+
df_rows = []
77+
curr_states = [[initial_val] * dim[1] for _ in range(dim[0])]
78+
if initial_val is not None:
79+
state_count[initial_val] = dim[0]*dim[1]
80+
81+
if log_state_changes_to_file:
82+
csv_file = open("state_changing.csv", "w")
83+
csv_file.write(",".join(("time", "x", "y", "previous_state", "current_state")) + "\n")
84+
curr_time = None
85+
86+
with open(log_filename, "r") as log_file:
87+
for line in log_file:
88+
line = line.strip()
89+
match = re.match(patt_out_line, line)
90+
if not match:
91+
if line.startswith("Mensaje Y"):
92+
print(line)
93+
continue
94+
if curr_time is None:
95+
curr_time = match.group("time")
96+
elif curr_time != match.group("time"):
97+
#print("Changed to " + match.group("time"))
98+
99+
row = [time_str_to_ts(curr_time)] + dict_to_states_row(dict(state_count.items()))
100+
df_rows.append(row)
101+
102+
curr_time = match.group("time")
103+
104+
x = int(match.group("x"))
105+
y = int(match.group("y"))
106+
107+
if not curr_states[x][y] is None:
108+
state_count[curr_states[x][y]] -= 1
109+
110+
if log_state_changes_to_file:
111+
csv_file.write((",".join((match.group("time"), match.group("x"), match.group("y"), str(curr_states[x][y]), str(int(float(match.group("state"))))))))
112+
csv_file.write("\n")
113+
#print("Time: %s, cell (%s, %s) changing from %d to %s" % (match.group("time"), match.group("x"), match.group("y"), curr_states[x][y], match.group("state")))
114+
curr_states[x][y] = int(float(match.group("state")))
115+
state_count[int(float(match.group("state")))] += 1
116+
117+
if log_state_changes_to_file:
118+
csv_file.close()
119+
120+
121+
# ## Dataframe creation and visualization
122+
columns = ["time", "susceptible", "infected", "sick", "recovered", "dead", "walls"]
123+
df = pd.DataFrame(df_rows, columns=columns)
124+
df = df.set_index("time")
125+
126+
total_cells = sum(df.iloc[0,:])
127+
population = total_cells - df.iloc[0,:]["walls"]
128+
print("Total cells: %d, population: %d" % (total_cells, population))
129+
130+
df_vis = df.copy()
131+
df_vis = df_vis.drop(["walls"], axis=1)
132+
df_vis = df_vis.divide(population)
133+
df_vis.index = df_vis.index.map(lambda x: x/1000)
134+
135+
base_name = os.path.splitext(os.path.basename(log_filename))[0]
136+
137+
col_names = ["infected", "sick", "recovered", "dead"]
138+
colors=[COLOR_INFECTED, COLOR_SICK, COLOR_RECOVERED, COLOR_DEAD]
139+
140+
x = list(df_vis.index)
141+
y = np.vstack([df_vis[col] for col in col_names])
142+
143+
fig, ax = plt.subplots(figsize=(12,7))
144+
ax.stackplot(x, y, labels=col_names, colors=colors)
145+
plt.legend(loc='upper right')
146+
plt.margins(0,0)
147+
plt.title('Epidemic percentages (%s)' % base_name)
148+
#plt.show()
149+
plt.xlabel("Time (s)")
150+
plt.ylabel("Population (%)")
151+
plt.savefig(base_name + "_area.png")
152+
153+
154+
fig, ax = plt.subplots(figsize=(12,7))
155+
linewidth = 2
156+
157+
x = list(df_vis.index)
158+
ax.plot(x, df_vis["susceptible"], label="susceptible", color=COLOR_SUSCEPTIBLE, linewidth=linewidth)
159+
ax.plot(x, df_vis["infected"], label="infected", color=COLOR_INFECTED, linewidth=linewidth)
160+
ax.plot(x, df_vis["sick"], label="sick", color=COLOR_SICK, linewidth=linewidth)
161+
ax.plot(x, df_vis["recovered"], label="recovered", color=COLOR_RECOVERED, linewidth=linewidth)
162+
ax.plot(x, df_vis["dead"], label="dead", color=COLOR_DEAD, linewidth=linewidth)
163+
plt.legend(loc='upper right')
164+
plt.margins(0,0)
165+
plt.title('Epidemic percentages (%s)' % base_name)
166+
plt.xlabel("Time (s)")
167+
plt.ylabel("Population (%)")
168+
plt.savefig(base_name + "_lines.png")
169+
170+
171+
df_nums = df.drop("walls", axis=1)
172+
df_nums.to_csv(base_name + ".csv")
173+
174+
175+
fig, ax = plt.subplots(figsize=(12,7))
176+
linewidth = 2
177+
178+
x = list(df_vis.index)
179+
ax.plot(x, df_vis["infected"], label="infected", color=COLOR_INFECTED, linewidth=linewidth)
180+
ax.plot(x, df_vis["sick"], label="sick", color=COLOR_SICK, linewidth=linewidth)
181+
ax.plot(x, df_vis["recovered"], label="recovered", color=COLOR_RECOVERED, linewidth=linewidth)
182+
ax.plot(x, df_vis["dead"], label="dead", color=COLOR_DEAD, linewidth=linewidth)
183+
plt.legend(loc='upper right')
184+
plt.margins(0,0)
185+
plt.title('Epidemic percentages (%s)' % base_name)
186+
plt.xlabel("Time (s)")
187+
plt.ylabel("Population (%)")
188+
plt.savefig(base_name + "_lines_nosus.png")

0 commit comments

Comments
 (0)