-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathCA_mac3.2.py
231 lines (181 loc) · 7.7 KB
/
CA_mac3.2.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
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
import pygame
import random
import math
import time
import pdb
import matplotlib.pyplot as plt
# global parameters
V_AGE = 10
I_AGE = 10
PROB_INFECT = .1
VIRUS_BURN_NO = 2
class Virus():
'''Virus Class:
Two attributes: location and age ([0,10])
also able to : move(width, height)
'''
def __init__(self,loc,age):
self.loc = loc
self.age = age
def move(self,width,height):
self.loc[0] = random.choice(range(width))
self.loc[1] = random.choice(range(height))
# virus list
class MapGrid():
def __init__(self, map_width, map_height,moi):
# set map values
self.map_width = map_width
self.map_height = map_width
self.moi = moi
# generate outside rooms
self.Virus_list,self.init_grids = self._generate_init_grids(self.map_width,self.map_height,self.moi)
self.ICell_set = {}# key is (x,y), value is age
self.Dead_set = set([])
def _generate_init_grids(self, map_width, map_height, moi):
'''
creates a random distirubted virus in the map with moi from 0 to 1
'''
global V_AGE
Virus_list = []
# init 1: fill the grids with T (state 3)
new_map_grid = [[3]* map_width for i in xrange(map_height)]
# init 2: random distribute moi virus.
num_grids = map_height*map_width
virus_seq = random.sample(range(num_grids),int(moi*num_grids)) #1D
for virus in virus_seq: # 1D-> 2D
virus_ind = [virus%map_width,virus/map_height]
new_map_grid[virus_ind[0]][virus_ind[1]] = 4
Virus_list.append(Virus(virus_ind,random.choice(range(V_AGE)))) # random asign age
# return grids and virus_list
return Virus_list,new_map_grid
def _remove(self,age_limit,class_list):
'''Input class which have age'''
return filter(lambda a:a.age!=age_limit,class_list)
def _virus_update(self,grids,ind):
'''Update the virus which is free'''
pre_loc = self.Virus_list[ind].loc
self.Virus_list[ind].move(self.map_width,self.map_height)
tmp_loc = self.Virus_list[ind].loc
if tmp_loc != pre_loc:
if grids[pre_loc[0]][pre_loc[1]] == 1:
grids[pre_loc[0]][pre_loc[1]] = 0
elif grids[pre_loc[0]][pre_loc[1]] == 4:
grids[pre_loc[0]][pre_loc[1]] = 3
if grids[tmp_loc[0]][tmp_loc[1]] == 0:
grids[tmp_loc[0]][tmp_loc[1]] = 1
elif grids[tmp_loc[0]][tmp_loc[1]] == 3:
grids[tmp_loc[0]][tmp_loc[1]] = 4
return grids
def _update_whole_CA(self, pre_grids):
'''
Update the whole CA model here.
'''
global VIRUS_BURN_NO
global I_AGE
global PROB_INFECT
global V_AGE
grids = pre_grids
# 1. Update the ICell age, death and virus production
for ICell in self.ICell_set:
self.ICell_set[ICell] += 1
if self.ICell_set[ICell] >= I_AGE and random.random() < 0.5: #ICell explode to Virus
self.ICell_set[ICell] = 1000
for tmp in range(VIRUS_BURN_NO): #budding virus copy number
self.Virus_list.append(Virus(list(ICell),-1))
grids[ICell[0]][ICell[1]] = 1
else:
grids[ICell[0]][ICell[1]] = 2
# remove dead
self.Dead_set = self.Dead_set | {k for k,v in self.ICell_set.items() if v==1000}
self.ICell_set = {k:v for k,v in self.ICell_set.items() if v!=1000}
for xy in self.Dead_set:
grids[xy[0]][xy[1]] = 0
# 2. Update Virus
for i in range(len(self.Virus_list)):
loc_tmp =self.Virus_list[i].loc
if self.Virus_list[i].age!=-1:
self.Virus_list[i].age +=1 # update age
if grids[loc_tmp[0]][loc_tmp[1]] ==4: # T+V already
p_tmp = random.random() # random number to determine infection
if p_tmp > PROB_INFECT: #if infected
# add this cell to I Cells (age 0)
self.ICell_set[tuple(loc_tmp)] = 0
grids[loc_tmp[0]][loc_tmp[1]] = 2 # Update grid to Infected state
self.Virus_list[i].age = V_AGE # mark this virus to remove
else: # not infected
grids = self._virus_update(grids,i)
else: # not T+V
grids = self._virus_update(grids,i)
else: # just born, set age to 0
self.Virus_list[i].age += 1
grids[loc_tmp[0]][loc_tmp[1]] = 1 # Update grid to Infected state
self.Virus_list = self._remove(V_AGE,self.Virus_list)
return grids
if __name__ == '__main__':
# general map stats
map_width = 100
map_height = 100
moi = 0.1
no_cells = float(map_width*map_height)
# start with one generation
tile_size = 8
unit_size = 8
map_grid = MapGrid(map_width, map_height,moi) #init a random grid filled with 0s and 1s
pygame.init()
screen = pygame.display.set_mode((map_width * tile_size,map_height * tile_size))#return Surface
zero_tile = pygame.Surface((unit_size, unit_size))
zero_tile.fill((0,0,0))#blue, nothing
one_tile = pygame.Surface((unit_size,unit_size))
one_tile.fill((255,255,0)) # yellow , virus
two_tile = pygame.Surface((unit_size,unit_size))
two_tile.fill((0,255,0)) # green, infected cell
three_tile = pygame.Surface((unit_size,unit_size))
three_tile.fill((255,0,0)) # red, target cell
four_tile = pygame.Surface((unit_size,unit_size))
four_tile.fill((255,165,0)) # orange, T + V
colors = {0: zero_tile, 1: zero_tile,2: two_tile , 3: three_tile, 4:three_tile}
background = pygame.Surface((map_width * tile_size,map_height * tile_size))
clock = pygame.time.Clock()#an object to help track time
first_gen = True
timer = 1
running = True
generation = 0
# plot setting
fig = plt.figure()
plt.axis = ([0,100,0,1])
plt.ion()
plt.show()
# running
while running == True:
clock.tick(1)
for event in pygame.event.get():#get the events from queue
if event.type == pygame.QUIT:
running = False
if first_gen:
themap = map_grid.init_grids
else:
themap1 = map_grid._update_whole_CA(themap) #update 1 generation
themap = themap1
# visualization
for column_index, column in enumerate(themap):
for tile_index, tile in enumerate(column):
screen.blit(colors[tile], (tile_index * tile_size, column_index * tile_size))
pygame.display.flip()
if first_gen:
timer -= 1
if timer <= 0:
first_gen = False
virus_frac = float(len(map_grid.Virus_list)/no_cells)
I_frac = float(len(map_grid.ICell_set)/(no_cells-len(map_grid.Dead_set)))
generation += 1
pygame.display.set_caption('G: ' + str(generation) + ' VF: ' + str(virus_frac)
+' IF: '+str(I_frac) )
# plot
plt.scatter(generation,I_frac)
plt.draw()
# save windows
if generation%5 == 0:
filename = "s"+ str(generation) +".jpeg"
pygame.image.save(screen,filename)
if generation == 100:
pygame.quit()