import numpy as np
import matplotlib.pyplot as plt
import matplotlib
from matplotlib import animation, rc
from IPython.display import HTML
import random
import pandas as pd
#Graph Modules
import plotly.io as pio
import plotly.express as px
import plotly
pio.renderers.default = 'iframe_connected'
import seaborn as sns
%matplotlib inline
defaultY = 200
defaultX = 400
class Person():
def __init__(self, infected, xPlus, yPlus, boardX = defaultX, boardY = defaultY, borders = None):
self.position = [int(random.uniform(1, boardX)), int(random.uniform(1, boardY))]
self.rateX = xPlus
self.rateY = yPlus
self.infected = infected
self.immune = False
self.xPlus = random.choice([int(random.uniform(2, self.rateX)), int(random.uniform(-int(self.rateX), -2))])
self.yPlus = random.choice([int(random.uniform(2, self.rateY)), int(random.uniform(-int(self.rateY), -2))])
self.boardX = boardX
self.boardY = boardY
self.border = borders
# [ [x, y, True], [x, y, False] ]
# True -> Vertical False -> Horizontal
def move(self):
#print('before : ', self.position)
self.position = [int(self.position[0] + self.xPlus), int(self.position[1] + self.yPlus)]
#print('after : ', self.position)
#Hit the Corner
if (self.position[0] + self.xPlus) < 0:
self.xPlus = int(random.uniform(2, self.rateX))
elif (self.position[0] + self.xPlus) >= self.boardX:
self.xPlus = int(random.uniform(-self.rateX, -2))
if (self.position[1] + self.yPlus) < 0:
self.yPlus = int(random.uniform(2, self.rateY))
elif (self.position[1] + self.yPlus) > self.boardY:
self.yPlus = int(random.uniform(-self.rateY, -2))
#Hit the Border
if self.border != None:
for b in self.border:
if b[2] == True:
#Vertical
if b[1] <= (self.position[1] + self.yPlus) or self.position[1] == b[1] or b[1] == (self.position[1] + self.yPlus):
self.yPlus = int(random.uniform(2, self.rateY))
if b[1] >= (self.position[1] + self.yPlus) or self.position[1] == b[1] or b[1] == (self.position[1] + self.yPlus):
self.yPlus = int(random.uniform(2, self.rateY))
else:
#Horizontal
if b[0] <= (self.position[0] + self.xPlus) or self.position[0] == b[0] or b[0] == (self.position[0] + self.xPlus):
self.xPlus = int(random.uniform(2, self.rateX))
if b[0] >= (self.position[0] + self.xPlus) or self.position[0] == b[0] or b[0] == (self.position[0] + self.xPlus):
self.xPlus = int(random.uniform(2, self.rateX))
class Board():
def __init__(self, boardX, boardY, Num, infectionPercentage, perPersonSpeedX, perPersonSpeedY, radius, infectionLength, borders = None):
self.boardSizeX = boardX
self.boardSizeY = boardY
self.infectionPercentage = infectionPercentage
self.radius = radius
self.infectionLength = infectionLength
self.borders = borders
self.population = []
#Add Infected Person
self.population.append(Person(True, perPersonSpeedX, perPersonSpeedY, self.boardSizeX, self.boardSizeY))
self.population = self.population + [Person(False, int(random.uniform(1, perPersonSpeedX)), int(random.uniform(1, perPersonSpeedY)), self.boardSizeX, self.boardSizeY, self.borders) for i in range(Num-1)]
self.infected = [0] #Only index values
self.infectedIndexes = [0]
self.infectiousPositions = [self.population[0].position]
self.infectionCount = 1
self.recoveredCount = 0
self.infectionRecords = [[0,1]]
def move(self):
for i in range(len(self.population)):
self.population[i].move()
#Get infectious Positions
self.infectiousPositions = [self.radiusPositionSpread(self.population[personIndex].position) for personIndex in self.infectedIndexes][0]
#Update Infection
self.infectionRecords = [[infectionData[0], infectionData[1]+0.1] for infectionData in self.infectionRecords]
#most Infection end around 2 weeks so we are going to make many people immune after 2 weeks 40% to be immune after 2 weeks
tempRecords = []
for i in range(len(self.infectionRecords)):
if self.infectionRecords[i][1] > self.infectionLength:
per = random.uniform(0, 1)
if per < 0.4:
tempRecords.append(self.infectionRecords[i])
else:
self.population[self.infectionRecords[i][0]].immune = True
self.recoveredCount += 1
else:
tempRecords.append(self.infectionRecords[i])
self.infectionRecords = tempRecords
temp = self.population
for x in range(len(temp)):
if temp[x].infected == False and temp[x].position in self.infectiousPositions and temp[x].immune == False:
per = random.uniform(0, 1)
if per < self.infectionPercentage:
self.infectionCount += 1
self.infectedIndexes.append(x)
temp[x].infected = True
self.infectionRecords.append([x,1])
if temp[x].immune == True and temp[x].infected == True:
temp[x].infected == False
self.population = temp
def radiusPositionSpread(self, position):
ans = [position]
for i in range(self.radius):
ans.append([position[0] + i, position[1]])
ans.append([position[0], position[1] + i])
ans.append([position[0] + i, position[1] + i])
ans.append([position[0] - i, position[1]])
ans.append([position[0], position[1] - i])
ans.append([position[0] - i, position[1] - i])
ans.append([position[0] + i, position[1] - i])
ans.append([position[0] - i, position[1] + i])
return ans[:]
populationSize = 500
InfectionPercentage = 1
xSpeedMax = 6
ySpeedMax = 8
spreadRadius = 10
maxFrames = 1000
infectionLength = 14
def makeData():
board = Board(defaultX, defaultY, populationSize, InfectionPercentage, xSpeedMax, ySpeedMax, spreadRadius, infectionLength)
df = pd.DataFrame(columns=['frame', 'x', 'y', 'color', 'totalInfected'])
for frame in range(maxFrames):
board.move()
xValue = []
yValue = []
color = []
pID = []
personType = []
for personID in range(len(board.population)):
if board.population[personID].immune == True:
xValue.append(board.population[personID].position[0])
yValue.append(board.population[personID].position[1])
color.append('green')
pID.append(personID)
personType.append('Immune')
elif board.population[personID].infected == True:
xValue.append(board.population[personID].position[0])
yValue.append(board.population[personID].position[1])
color.append('red')
pID.append(personID)
personType.append('Infecious')
else:
xValue.append(board.population[personID].position[0])
yValue.append(board.population[personID].position[1])
color.append('blue')
pID.append(personID)
personType.append('Normal')
tempDF_UnInfected = pd.DataFrame({
'frame': frame,
'id':pID,
'x': xValue,
'y': yValue,
'color': color,
'totalInfected': board.infectionCount,
'Recovered': board.recoveredCount,
'Type': personType
})
#Add Immune People Before hand
tempDF_UnInfected = tempDF_UnInfected.append({
'frame': frame,
'id':len(pID),
'x': 10000,
'y': 10000,
'color': 'green',
'totalInfected': board.infectionCount,
'Recovered': board.recoveredCount,
'Type': 'Immune'
}, ignore_index = True)
tempDF_UnInfected = tempDF_UnInfected.sort_values(['id'])
df = pd.concat([df, tempDF_UnInfected])
return df
data = makeData()
data.to_csv('data/simulation1.csv')
fig = px.scatter(data, x = 'x', y = 'y', animation_frame='frame', animation_group = 'id', color='Type', range_x=[0,defaultX], range_y=[0, defaultY], title='Infections over 10 days')
fig.show()
fig_infections = px.area(data, x='frame', y='totalInfected')
fig_infections.show()
fig_recovered = px.area(data, x='frame', y='Recovered')
fig_recovered.show()
populationSize = 500
InfectionPercentage = 1
xSpeedMax = 6
ySpeedMax = 8
spreadRadius = 10
maxFrames = 1000
infectionLength = 14
border = [[200, 0, True]]
xValue = 100
yValue = 200
def makeData_Border():
xValue = 100
yValue = 200
board = Board(xValue, yValue, populationSize, InfectionPercentage, xSpeedMax, ySpeedMax, spreadRadius, infectionLength, None)
df = pd.DataFrame(columns=['frame', 'x', 'y', 'color', 'totalInfected'])
for frame in range(maxFrames):
board.move()
xValue = []
yValue = []
color = []
pID = []
personType = []
for personID in range(len(board.population)):
if board.population[personID].immune == True:
xValue.append(board.population[personID].position[0])
yValue.append(board.population[personID].position[1])
color.append('green')
pID.append(personID)
personType.append('Immune')
elif board.population[personID].infected == True:
xValue.append(board.population[personID].position[0])
yValue.append(board.population[personID].position[1])
color.append('red')
pID.append(personID)
personType.append('Infecious')
else:
xValue.append(board.population[personID].position[0])
yValue.append(board.population[personID].position[1])
color.append('blue')
pID.append(personID)
personType.append('Normal')
tempDF_UnInfected = pd.DataFrame({
'frame': frame,
'id':pID,
'x': xValue,
'y': yValue,
'color': color,
'totalInfected': board.infectionCount,
'Recovered': board.recoveredCount,
'Type': personType
})
#Add Immune People Before hand
tempDF_UnInfected = tempDF_UnInfected.append({
'frame': frame,
'id':len(pID),
'x': 1000,
'y': 1000,
'color': 'green',
'totalInfected': board.infectionCount,
'Recovered': board.recoveredCount,
'Type': 'Immune'
}, ignore_index = True)
tempDF_UnInfected = tempDF_UnInfected.sort_values(['id'])
df = pd.concat([df, tempDF_UnInfected])
return df
data_border = makeData_Border()
data_border.to_csv('data/simulation1_smallBorder.csv')
fig_Dense = px.scatter(data_border, x = 'x', y = 'y', animation_frame='frame', animation_group = 'id', color='Type', range_x=[0,xValue], range_y=[0, yValue], title='Infections over 10 days for Dense Population')
fig_Dense.show()
fig_infections_dense = px.area(data_border, x='frame', y='totalInfected')
fig_infections_dense.show()
populationSize = 500
InfectionPercentage = 1
xSpeedMax = 6
ySpeedMax = 8
spreadRadius = 10
maxFrames = 1000
infectionLength = 14
border = [[200, 0, True]]
xValue = 400
yValue = 800
def makeData_Border():
xValue = 400
yValue = 800
board = Board(xValue, yValue, populationSize, InfectionPercentage, xSpeedMax, ySpeedMax, spreadRadius, infectionLength, None)
df = pd.DataFrame(columns=['frame', 'x', 'y', 'color', 'totalInfected'])
for frame in range(maxFrames):
board.move()
xValue = []
yValue = []
color = []
pID = []
personType = []
for personID in range(len(board.population)):
if board.population[personID].immune == True:
xValue.append(board.population[personID].position[0])
yValue.append(board.population[personID].position[1])
color.append('green')
pID.append(personID)
personType.append('Immune')
elif board.population[personID].infected == True:
xValue.append(board.population[personID].position[0])
yValue.append(board.population[personID].position[1])
color.append('red')
pID.append(personID)
personType.append('Infecious')
else:
xValue.append(board.population[personID].position[0])
yValue.append(board.population[personID].position[1])
color.append('blue')
pID.append(personID)
personType.append('Normal')
tempDF_UnInfected = pd.DataFrame({
'frame': frame,
'id':pID,
'x': xValue,
'y': yValue,
'color': color,
'totalInfected': board.infectionCount,
'Recovered': board.recoveredCount,
'Type': personType
})
#Add Immune People Before hand
tempDF_UnInfected = tempDF_UnInfected.append({
'frame': frame,
'id':len(pID),
'x': 1000,
'y': 1000,
'color': 'green',
'totalInfected': board.infectionCount,
'Recovered': board.recoveredCount,
'Type': 'Immune'
}, ignore_index = True)
tempDF_UnInfected = tempDF_UnInfected.sort_values(['id'])
df = pd.concat([df, tempDF_UnInfected])
return df
data_border_notDense = makeData_Border()
data_border_notDense.to_csv('data/simulation1_largeBorder.csv')
fig_notDense = px.scatter(data_border_notDense, x = 'x', y = 'y', animation_frame='frame', animation_group = 'id', color='Type', range_x=[0,xValue], range_y=[0, yValue], title='Infections over 10 days for Dense Population')
fig_notDense.show()
fig_infections_notDense = px.area(data_border_notDense, x='frame', y='totalInfected')
fig_infections_notDense.show()
Density Data: https://www.kaggle.com/tanuprabhu/population-by-country-2020
Covid-19: https://ourworldindata.org/coronavirus-source-data
ISO codes: https://www.kaggle.com/juanumusic/countries-iso-codes
isoDF = pd.read_csv('data/wikipedia-iso-country-codes.csv')
population_df = pd.read_csv('data/population_by_country_2020.csv')
population_df['Country_ISO'] = [isoDF.loc[isoDF['English short name lower case'] == country]['Alpha-3 code'].values[0] for country in population_df['Country']]
print(population_df.shape)
population_df.head()
population_df_bar = px.bar(population_df.sort_values("Density (P/Km)", ascending=False).head(30), x='Country', y='Density (P/Km)')
population_df_bar.show()
fig_Density = px.choropleth(population_df, locations='Country_ISO', color = 'Density (P/Km)', hover_name='Country', color_continuous_scale='Plasma',
range_color=(0, 400))
fig_Density.show()
isoDF['Country'] = isoDF['English short name lower case']
covid_df = pd.read_csv('data/owid-covid-data.csv')
covid_df['Country'] = covid_df['location']
covid_df = covid_df.groupby(['location']).max()
covid_df = pd.merge(covid_df, isoDF, how='left', on='Country')
covid_df.head()
covid_df_bar = px.bar(covid_df.sort_values("total_cases", ascending=False).head(30), x='Country', y='total_cases')
covid_df_bar.show()
fig_covidCases = px.choropleth(covid_df, locations='Alpha-3 code', color = 'total_cases', hover_name='English short name lower case', color_continuous_scale='Plasma',
range_color=(0, 1000000))
fig_covidCases.show()
Data: https://ourworldindata.org/grapher/face-covering-policies-covid
maskData = pd.read_csv('data/face-covering-policies-covid.csv')
maskData['Country'] = maskData['Entity']
maskData = maskData.groupby(['Entity']).max()
maskData.head()
masks_bar = px.bar(maskData.sort_values("facial_coverings", ascending=False).head(30), x='Country', y='facial_coverings')
masks_bar.show()
fig_maskPolicy = px.choropleth(maskData, locations='Code', color = 'facial_coverings', hover_name='Country', color_continuous_scale='Plasma',
range_color=(0, 5))
fig_maskPolicy.show()
correlationDF = pd.merge(covid_df, pd.read_csv('data/population_by_country_2020.csv'), how='left', on='Country')
correlationDF = correlationDF[['Country', 'total_cases', 'Density (P/Km)']]
sns.heatmap(correlationDF.corr(), cmap=sns.diverging_palette(20, 220))
How?
The daily growth of cumulative number of infections is caculated using the natural LOG scale.
Data: https://www.kaggle.com/fireballbyedimyrnmom/us-counties-covid-19-dataset
covidData = pd.read_csv('data/us-counties.csv')
print(covidData.shape)
covidData.head()
We will the reproductive number for Europe as in Europe there are many developed countries
x = []
y = []
total = 0
for date in covidData['date'].unique().tolist():
x.append(date)
y.append(covidData[covidData['date'] == date]['cases'].sum())
cumDataEurope = pd.DataFrame({'date':x,'cases':y})
cumDataEurope['date'] = pd.to_datetime(cumDataEurope['date'])
cumDataEurope = cumDataEurope.sort_values('date')
casesFig = px.bar(cumDataEurope, x='date', y='cases', title = 'Total Cases USA')
casesFig.show()
We can see December 2020 to Jan 2021 has the highest increase rate therefore we will data from that.
Covid-19 will show symptoms after 14 days therefore, Nov 10th infection numbers will show up Nov 24th.
nov10 = covidData[covidData['date'] == '2020-11-04']['cases'].sum() - covidData[covidData['date'] == '2020-11-03']['cases'].sum()
nov24 = covidData[covidData['date'] == '2020-11-18']['cases'].sum() - covidData[covidData['date'] == '2020-11-17']['cases'].sum()
print("New cases Nov 4th : " + str(nov10))
print("New cases Nov 18th : " + str(nov24))
print(str(nov10) + " people gave covid-19 to " + str(nov24) + ' people')
With restrictions imposed covid-19 has 1.7 times its infections.
The actual Basic Reprodcution Number is 2.2 which our data with restrictions have shown.
x = []
y = []
t = []
stages = 11
prev = 0
deathRate = 0.02
for i in range(stages):
x.append(i)
x.append(i)
if i == 0:
y.append(i+1)
t.append('infection')
y.append(0)
t.append('infection')
prev = i+1
else:
prev = 2 * prev
y.append(prev)
t.append('infection')
y.append(int(prev * deathRate))
t.append('death')
reproductionNum = pd.DataFrame({
'x':x,
'y':y,
'type': t
})
reproductionNumFig = px.line(reproductionNum, x='x', y='y', color='type', title = 'Rproduction of Covid-19')
reproductionNumFig.show()
print("Infections : ", reproductionNum[reproductionNum['type'] == 'infection']['y'].sum()-1)
print("Deaths : ", reproductionNum[reproductionNum['type'] == 'death']['y'].sum())