-
Notifications
You must be signed in to change notification settings - Fork 5
/
sirtoy.js
239 lines (181 loc) · 16.3 KB
/
sirtoy.js
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
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
G =
{"directed": false, "graph": [["name", "barabasi_albert_graph(150,2)"]], "nodes": [{"name": 0}, {"name": 1}, {"name": 2}, {"name": 3}, {"name": 4}, {"name": 5}, {"name": 6}, {"name": 7}, {"name": 8}, {"name": 9}, {"name": 10}, {"name": 11}, {"name": 12}, {"name": 13}, {"name": 14}, {"name": 15}, {"name": 16}, {"name": 17}, {"name": 18}, {"name": 19}, {"name": 20}, {"name": 21}, {"name": 22}, {"name": 23}, {"name": 24}, {"name": 25}, {"name": 26}, {"name": 27}, {"name": 28}, {"name": 29}, {"name": 30}, {"name": 31}, {"name": 32}, {"name": 33}, {"name": 34}, {"name": 35}, {"name": 36}, {"name": 37}, {"name": 38}, {"name": 39}, {"name": 40}, {"name": 41}, {"name": 42}, {"name": 43}, {"name": 44}, {"name": 45}, {"name": 46}, {"name": 47}, {"name": 48}, {"name": 49}, {"name": 50}, {"name": 51}, {"name": 52}, {"name": 53}, {"name": 54}, {"name": 55}, {"name": 56}, {"name": 57}, {"name": 58}, {"name": 59}, {"name": 60}, {"name": 61}, {"name": 62}, {"name": 63}, {"name": 64}, {"name": 65}, {"name": 66}, {"name": 67}, {"name": 68}, {"name": 69}, {"name": 70}, {"name": 71}, {"name": 72}, {"name": 73}, {"name": 74}, {"name": 75}, {"name": 76}, {"name": 77}, {"name": 78}, {"name": 79}, {"name": 80}, {"name": 81}, {"name": 82}, {"name": 83}, {"name": 84}, {"name": 85}, {"name": 86}, {"name": 87}, {"name": 88}, {"name": 89}, {"name": 90}, {"name": 91}, {"name": 92}, {"name": 93}, {"name": 94}, {"name": 95}, {"name": 96}, {"name": 97}, {"name": 98}, {"name": 99}, {"name": 100}, {"name": 101}, {"name": 102}, {"name": 103}, {"name": 104}, {"name": 105}, {"name": 106}, {"name": 107}, {"name": 108}, {"name": 109}, {"name": 110}, {"name": 111}, {"name": 112}, {"name": 113}, {"name": 114}, {"name": 115}, {"name": 116}, {"name": 117}, {"name": 118}, {"name": 119}, {"name": 120}, {"name": 121}, {"name": 122}, {"name": 123}, {"name": 124}, {"name": 125}, {"name": 126}, {"name": 127}, {"name": 128}, {"name": 129}, {"name": 130}, {"name": 131}, {"name": 132}, {"name": 133}, {"name": 134}, {"name": 135}, {"name": 136}, {"name": 137}, {"name": 138}, {"name": 139}, {"name": 140}, {"name": 141}, {"name": 142}, {"name": 143}, {"name": 144}, {"name": 145}, {"name": 146}, {"name": 147}, {"name": 148}, {"name": 149}], "links": [{"source": 0, "target": 2}, {"source": 0, "target": 6}, {"source": 0, "target": 9}, {"source": 0, "target": 10}, {"source": 0, "target": 15}, {"source": 0, "target": 17}, {"source": 0, "target": 18}, {"source": 0, "target": 19}, {"source": 0, "target": 21}, {"source": 0, "target": 22}, {"source": 0, "target": 30}, {"source": 0, "target": 35}, {"source": 0, "target": 37}, {"source": 0, "target": 38}, {"source": 0, "target": 39}, {"source": 0, "target": 40}, {"source": 0, "target": 46}, {"source": 0, "target": 55}, {"source": 0, "target": 138}, {"source": 0, "target": 134}, {"source": 0, "target": 68}, {"source": 0, "target": 94}, {"source": 0, "target": 107}, {"source": 0, "target": 116}, {"source": 0, "target": 122}, {"source": 0, "target": 123}, {"source": 1, "target": 2}, {"source": 1, "target": 3}, {"source": 1, "target": 68}, {"source": 1, "target": 5}, {"source": 1, "target": 98}, {"source": 1, "target": 15}, {"source": 1, "target": 91}, {"source": 1, "target": 119}, {"source": 1, "target": 24}, {"source": 1, "target": 59}, {"source": 2, "target": 3}, {"source": 2, "target": 4}, {"source": 2, "target": 5}, {"source": 2, "target": 135}, {"source": 2, "target": 8}, {"source": 2, "target": 9}, {"source": 2, "target": 10}, {"source": 2, "target": 13}, {"source": 2, "target": 143}, {"source": 2, "target": 16}, {"source": 2, "target": 147}, {"source": 2, "target": 20}, {"source": 2, "target": 149}, {"source": 2, "target": 137}, {"source": 2, "target": 27}, {"source": 2, "target": 28}, {"source": 2, "target": 31}, {"source": 2, "target": 33}, {"source": 2, "target": 34}, {"source": 2, "target": 44}, {"source": 2, "target": 45}, {"source": 2, "target": 55}, {"source": 2, "target": 56}, {"source": 2, "target": 64}, {"source": 2, "target": 71}, {"source": 2, "target": 82}, {"source": 2, "target": 85}, {"source": 2, "target": 102}, {"source": 2, "target": 109}, {"source": 2, "target": 121}, {"source": 3, "target": 4}, {"source": 3, "target": 133}, {"source": 3, "target": 65}, {"source": 3, "target": 104}, {"source": 3, "target": 105}, {"source": 3, "target": 135}, {"source": 3, "target": 77}, {"source": 3, "target": 142}, {"source": 3, "target": 17}, {"source": 3, "target": 114}, {"source": 3, "target": 26}, {"source": 3, "target": 29}, {"source": 4, "target": 7}, {"source": 4, "target": 138}, {"source": 4, "target": 11}, {"source": 4, "target": 12}, {"source": 4, "target": 13}, {"source": 4, "target": 16}, {"source": 4, "target": 131}, {"source": 4, "target": 20}, {"source": 4, "target": 21}, {"source": 4, "target": 22}, {"source": 4, "target": 37}, {"source": 4, "target": 38}, {"source": 4, "target": 40}, {"source": 4, "target": 42}, {"source": 4, "target": 47}, {"source": 4, "target": 52}, {"source": 4, "target": 65}, {"source": 4, "target": 76}, {"source": 4, "target": 95}, {"source": 4, "target": 101}, {"source": 4, "target": 108}, {"source": 4, "target": 117}, {"source": 5, "target": 101}, {"source": 5, "target": 6}, {"source": 5, "target": 12}, {"source": 5, "target": 112}, {"source": 5, "target": 24}, {"source": 6, "target": 32}, {"source": 6, "target": 7}, {"source": 6, "target": 140}, {"source": 6, "target": 78}, {"source": 6, "target": 25}, {"source": 7, "target": 8}, {"source": 7, "target": 73}, {"source": 7, "target": 43}, {"source": 7, "target": 80}, {"source": 7, "target": 124}, {"source": 7, "target": 61}, {"source": 8, "target": 63}, {"source": 8, "target": 118}, {"source": 9, "target": 75}, {"source": 9, "target": 70}, {"source": 9, "target": 41}, {"source": 9, "target": 11}, {"source": 9, "target": 148}, {"source": 9, "target": 53}, {"source": 9, "target": 28}, {"source": 10, "target": 32}, {"source": 10, "target": 36}, {"source": 10, "target": 76}, {"source": 10, "target": 14}, {"source": 10, "target": 18}, {"source": 11, "target": 66}, {"source": 11, "target": 72}, {"source": 11, "target": 106}, {"source": 11, "target": 111}, {"source": 11, "target": 82}, {"source": 11, "target": 19}, {"source": 11, "target": 53}, {"source": 11, "target": 54}, {"source": 11, "target": 36}, {"source": 11, "target": 27}, {"source": 11, "target": 127}, {"source": 12, "target": 39}, {"source": 12, "target": 14}, {"source": 12, "target": 111}, {"source": 12, "target": 115}, {"source": 12, "target": 84}, {"source": 12, "target": 121}, {"source": 12, "target": 31}, {"source": 13, "target": 49}, {"source": 14, "target": 120}, {"source": 14, "target": 35}, {"source": 15, "target": 42}, {"source": 15, "target": 107}, {"source": 15, "target": 48}, {"source": 15, "target": 146}, {"source": 15, "target": 23}, {"source": 15, "target": 124}, {"source": 15, "target": 93}, {"source": 16, "target": 25}, {"source": 16, "target": 132}, {"source": 18, "target": 98}, {"source": 18, "target": 131}, {"source": 18, "target": 130}, {"source": 18, "target": 110}, {"source": 18, "target": 23}, {"source": 18, "target": 26}, {"source": 19, "target": 33}, {"source": 19, "target": 100}, {"source": 19, "target": 69}, {"source": 20, "target": 97}, {"source": 20, "target": 113}, {"source": 20, "target": 49}, {"source": 20, "target": 30}, {"source": 22, "target": 41}, {"source": 22, "target": 86}, {"source": 22, "target": 59}, {"source": 22, "target": 126}, {"source": 24, "target": 34}, {"source": 24, "target": 67}, {"source": 24, "target": 102}, {"source": 24, "target": 108}, {"source": 24, "target": 109}, {"source": 24, "target": 148}, {"source": 24, "target": 54}, {"source": 24, "target": 88}, {"source": 24, "target": 122}, {"source": 24, "target": 130}, {"source": 26, "target": 64}, {"source": 26, "target": 47}, {"source": 27, "target": 51}, {"source": 27, "target": 92}, {"source": 27, "target": 78}, {"source": 28, "target": 133}, {"source": 28, "target": 125}, {"source": 28, "target": 145}, {"source": 28, "target": 58}, {"source": 28, "target": 29}, {"source": 29, "target": 60}, {"source": 29, "target": 74}, {"source": 31, "target": 120}, {"source": 31, "target": 81}, {"source": 31, "target": 46}, {"source": 32, "target": 56}, {"source": 32, "target": 89}, {"source": 33, "target": 61}, {"source": 34, "target": 73}, {"source": 34, "target": 50}, {"source": 34, "target": 87}, {"source": 35, "target": 110}, {"source": 35, "target": 143}, {"source": 35, "target": 51}, {"source": 35, "target": 116}, {"source": 35, "target": 57}, {"source": 36, "target": 52}, {"source": 37, "target": 48}, {"source": 37, "target": 45}, {"source": 37, "target": 142}, {"source": 38, "target": 128}, {"source": 38, "target": 50}, {"source": 38, "target": 60}, {"source": 38, "target": 62}, {"source": 40, "target": 44}, {"source": 40, "target": 67}, {"source": 40, "target": 43}, {"source": 41, "target": 74}, {"source": 41, "target": 105}, {"source": 41, "target": 88}, {"source": 41, "target": 58}, {"source": 43, "target": 119}, {"source": 43, "target": 84}, {"source": 44, "target": 147}, {"source": 44, "target": 134}, {"source": 45, "target": 62}, {"source": 47, "target": 103}, {"source": 48, "target": 89}, {"source": 49, "target": 96}, {"source": 49, "target": 90}, {"source": 50, "target": 85}, {"source": 50, "target": 71}, {"source": 52, "target": 100}, {"source": 52, "target": 79}, {"source": 53, "target": 99}, {"source": 53, "target": 69}, {"source": 53, "target": 144}, {"source": 53, "target": 91}, {"source": 56, "target": 57}, {"source": 56, "target": 123}, {"source": 57, "target": 81}, {"source": 57, "target": 86}, {"source": 58, "target": 66}, {"source": 58, "target": 99}, {"source": 58, "target": 97}, {"source": 59, "target": 75}, {"source": 59, "target": 141}, {"source": 59, "target": 87}, {"source": 59, "target": 63}, {"source": 59, "target": 95}, {"source": 60, "target": 83}, {"source": 63, "target": 136}, {"source": 64, "target": 96}, {"source": 64, "target": 79}, {"source": 64, "target": 83}, {"source": 64, "target": 93}, {"source": 65, "target": 112}, {"source": 65, "target": 132}, {"source": 65, "target": 104}, {"source": 65, "target": 80}, {"source": 66, "target": 70}, {"source": 66, "target": 106}, {"source": 66, "target": 114}, {"source": 66, "target": 117}, {"source": 68, "target": 72}, {"source": 71, "target": 141}, {"source": 71, "target": 77}, {"source": 73, "target": 103}, {"source": 73, "target": 139}, {"source": 74, "target": 94}, {"source": 76, "target": 92}, {"source": 81, "target": 129}, {"source": 84, "target": 145}, {"source": 85, "target": 113}, {"source": 86, "target": 90}, {"source": 87, "target": 115}, {"source": 89, "target": 129}, {"source": 91, "target": 140}, {"source": 92, "target": 128}, {"source": 93, "target": 127}, {"source": 98, "target": 144}, {"source": 102, "target": 118}, {"source": 104, "target": 137}, {"source": 117, "target": 139}, {"source": 117, "target": 125}, {"source": 117, "target": 126}, {"source": 118, "target": 146}, {"source": 129, "target": 149}, {"source": 135, "target": 136}], "multigraph": false}
// -----------------------------------------------------------
var valid_data = 1;
var running = 0;
var p_SI = 0.2;
var p_IR = 0.08;
var time_interval = 500;
var count = 0;
var timeseries;
var nodeArray = G.nodes;
var edgeArray = G.links;
var sir_color = {S: "#00ffff", I: "#ffff00", R: "#ff00ff" }
var epi_state = { S: nodeArray.length, I: 0, R: 0 };
function reset_history () {
timeseries = {S: {label: "S", color: sir_color.S, data: []},
I: {label: "I", color: sir_color.I, data: []},
R: {label: "R", color: sir_color.R, data: []}};
timeseries.S.data.push([count, epi_state.S]);
timeseries.I.data.push([count, epi_state.I]);
timeseries.R.data.push([count, epi_state.R]);
}
reset_history();
var plotOptions = {
// lines: { show: true },
// points: { show: true },
xaxis: {min: 0},
series: { shadowSize: 0 }
};
var plot = $.plot($("#epicurves"), [], plotOptions);
var kArray = [];
for (i in nodeArray) {
kArray[nodeArray[i].name] = 0;
}
for (i in edgeArray) {
kArray[edgeArray[i].source]++;
kArray[edgeArray[i].target]++;
}
for (i in nodeArray) {
nodeArray[i].k = kArray[i];
nodeArray[i].state = "S";
}
var w = "100%";
var h = 500;
var vis = d3.select("#graph-layout")
.append("svg:svg")
.attr("width", w)
.attr("height", h);
var force = d3.layout.force()
.charge(-100)
.friction(0.6)
.gravity(0.02)
.linkDistance(100)
.nodes(nodeArray)
.links(edgeArray)
.size([900, h]);
force.on("tick", function() {
vis.selectAll("line.link")
.attr("x1", function(d) { return d.source.x; })
.attr("y1", function(d) { return d.source.y; })
.attr("x2", function(d) { return d.target.x; })
.attr("y2", function(d) { return d.target.y; });
vis.selectAll("circle.node")
.attr("cx", function(d) { return d.x; })
.attr("cy", function(d) { return d.y; })
.style("fill", function(d) { return sir_color[d.state]; } );
});
$("#p_SI").val(p_SI)
$("#p_SI").keyup(update_p_SI);
$("#p_IR").val(p_IR)
$("#p_IR").keyup(update_p_IR);
update_graph();
update_plot();
update_counters();
$("#reset-button").click(reset_all);
setInterval(run_SIR, time_interval);
function run_SIR() {
if (running == 0)
return;
for (k in nodeArray)
nodeArray[k].new_state = nodeArray[k].state;
for (k in edgeArray) {
i = edgeArray[k].source;
j = edgeArray[k].target;
if (i.state == "S" && j.state == "I") {
tmp = i; i = j; j = tmp;
}
if (i.state == "I" && j.state == "S" && j.new_state == "S") {
if (Math.random() < p_SI) {
j.new_state = "I";
epi_state.I ++;
epi_state.S --;
}
}
}
for (k in nodeArray) {
if (nodeArray[k].state == "I") {
if (Math.random() < p_IR) {
nodeArray[k].new_state = "R";
epi_state.R ++;
epi_state.I --;
}
}
}
for (k in nodeArray)
nodeArray[k].state = nodeArray[k].new_state;
update_graph();
count++;
timeseries.S.data.push([count, epi_state.S]);
timeseries.I.data.push([count, epi_state.I]);
timeseries.R.data.push([count, epi_state.R]);
update_plot();
update_counters();
if (epi_state.I == 0)
running = 0;
}
function update_graph () {
x = vis.selectAll("line.link").data(edgeArray, function(d) { return d.source.name + "-" + d.target.name; });
x.enter().insert("svg:line", "circle.node")
.attr("class", "link")
.attr("x1", function(d) { return d.source.x; })
.attr("y1", function(d) { return d.source.y; })
.attr("x2", function(d) { return d.target.x; })
.attr("y2", function(d) { return d.target.y; });
x.exit().remove();
x = vis.selectAll("circle.node").data(nodeArray, function(d) { return d.name; });
x.enter().insert("svg:circle")
.attr("class", "node")
.attr("cx", function(d) { return d.x; })
.attr("cy", function(d) { return d.y; })
.attr("r", function(d) { return 3*Math.sqrt(d.k); })
.style("fill", function(d) { return sir_color[d.state]; } )
.call(force.drag)
.on("click", function(d,i) { if (running == 0 && valid_data == 1 && d.state == "S") {d.state = "I"; epi_state.S--; epi_state.I++; running = 1; $("#start-text").fadeOut(); }} );
x.exit().remove();
force.start();
}
function update_plot () {
plot.setData([timeseries.S, timeseries.I, timeseries.R]);
plot.setupGrid();
plot.draw();
}
function update_counters () {
$("#count_S").html(epi_state.S);
$("#count_I").html(epi_state.I);
$("#count_R").html(epi_state.R);
}
function update_p_SI () {
p = Number($("#p_SI").val());
if (isNaN(p) || p<0.0 || p>1.0) {
valid_data = 0;
$("#p_SI").css("background-color", "#f88");
} else {
p_SI = p;
valid_data = 1;
$("#p_SI").css("background-color", "#fff");
}
}
function update_p_IR () {
p = Number($("#p_IR").val());
if (isNaN(p) || p<0.0 || p>1.0) {
valid_data = 0;
$("#p_IR").css("background-color", "#f88");
} else {
p_IR = p;
valid_data = 1;
$("#p_IR").css("background-color", "#fff");
}
}
function reset_all () {
running = 0;
count = 0;
epi_state = { S: nodeArray.length, I: 0, R: 0 };
reset_history();
update_plot();
update_counters();
for (k in nodeArray)
nodeArray[k].state = "S";
update_graph();
$("#start-text").fadeIn();
}