Skip to content

Commit

Permalink
Update version 1.0.0
Browse files Browse the repository at this point in the history
  • Loading branch information
26-jorge-01 committed Feb 16, 2022
1 parent 0ee3150 commit 092b4ab
Show file tree
Hide file tree
Showing 13 changed files with 2,241 additions and 1,388 deletions.
141 changes: 141 additions & 0 deletions CAsimulation/AgeManagement.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
from typing import Type
import numpy as np
import random
import math
import EpidemiologicalModels.Models as Models
import EpidemiologicalModels.CellManagement as CellManagement
import EpidemiologicalModels.DataManager as DataManager
import EpidemiologicalModels.CellSpaceConfiguration as CellSpaceConfiguration

class AgesMatrix:

ranges = []

def __init__(self, ranges, cellSpace):
self.ranges = ranges
self.cellSpace = cellSpace
self.agesMatrix = self.__create()

def __validate(self):
if len(self.ranges) == 0:
print("Debe definir los rangos de edades en el sistema.")
return False
if str(type(self.cellSpace)) != "<class 'EpidemiologicalModels.CellSpaceConfiguration.CellSpaceConfiguration'>":
print("Asegurese de pasar un sistema con el tipo <class 'EpidemiologicalModels.CellSpaceConfiguration.CellSpaceConfiguration'>")
return False
else:
for r in self.ranges:
if len(r) != 3:
print("Asegurese de que todos los rangos de edad posean límite inferior, límite superior y la proporción en el sistema.")
return False
elif r[2] > 1:
print("Asegurese de que todas las proporciones sean menores o iguales a 1.")
return False
else:
return True

def __agesDivisions(self, amoungIndividuals):
agesDivisions = []
for r in self.ranges:
agesDivisions.append([0] * math.ceil(r[2] * amoungIndividuals))
return agesDivisions

def __create(self):
'''Arreglo de edades aleatorias'''
if self.__validate():
amoungIndividuals = DataManager.SystemMetrics(self.cellSpace, [Models.State.S.value, Models.State.I.value, Models.State.R.value, Models.State.H.value]).numberOfIndividuals()
agesDivisions = self.__agesDivisions(amoungIndividuals)
for divition in range(len(agesDivisions)):
for individualPerGroup in range(len(agesDivisions[divition])):
agesDivisions[divition][individualPerGroup] = random.randint(self.ranges[divition][0], self.ranges[divition][1])
concatenatedAgeList = agesDivisions[0]
for i in range(1, len(agesDivisions)):
concatenatedAgeList = concatenatedAgeList + agesDivisions[i]
matrixOfAges = -np.ones((self.cellSpace.nRows, self.cellSpace.nColumns))
for r in range(self.cellSpace.nRows):
for c in range(self.cellSpace.nColumns):
if self.cellSpace.system[r,c] != Models.State.H.value and self.cellSpace.system[r,c] != Models.State.D.value:
randomAge = random.choice(concatenatedAgeList)
matrixOfAges[r,c] = randomAge
elif self.cellSpace.system[r,c] == Models.State.D.value: matrixOfAges[r,c] = 0
return matrixOfAges

class AgeMatrixEvolution:

def __init__(self, systemAges, birthRate, annualUnit = 365, probabilityOfDyingByAgeGroup = [[0, 100, 1]]):
self.birthRate = birthRate # Valor en [0,1)
self.systemAges = systemAges
self.nRows, self.nColumns = systemAges.shape
self.probabilityOfDyingByAgeGroup = probabilityOfDyingByAgeGroup
self.annualUnit = annualUnit

def ageGroupPositions(self, inferiorLimit, superiorLimit):
'''Genera las posiciones de los individuos que tienen entre minAge y maxAge años en el sistema'''
groupPositions = []
for r in range(self.nRows):
for c in range(self.nColumns):
if inferiorLimit < self.systemAges[r][c] and self.systemAges[r][c] < superiorLimit:
groupPositions.append([r,c])
return groupPositions

def __birthCell(self):
rate = random.random()
if rate < self.birthRate: return 1
else: return 0

def __birthdaysAndBirths(self, timeUnit):
agesMatrix = CellSpaceConfiguration.CellSpaceConfiguration(self.nRows, self.nColumns)
newYearMatrix = CellManagement.CellManagement(agesMatrix).InsideCopy().system
if timeUnit % self.annualUnit == 0:
for r in range(self.nRows):
for c in range(self.nColumns):
if self.systemAges[r][c] != 0 and self.systemAges[r][c] != -1:
newYearMatrix[r][c] = self.systemAges[r][c] + 1
elif self.systemAges[r][c] == 0:
newYearMatrix[r][c] = self.__birthCell()
else:
for r in range(self.nRows):
for c in range(self.nColumns):
newYearMatrix[r][c] = self.systemAges[r][c]
return newYearMatrix

def evolutionRuleForAges(self, timeUnit):
agePositions = []
mortalityApplicationGroups = []
for probabilityOfDying in self.probabilityOfDyingByAgeGroup:
ageGroupPosition = self.ageGroupPositions(probabilityOfDying[0], probabilityOfDying[1])
agePositions.append(ageGroupPosition)
mortalityApplicationGroups.append(math.ceil(len(ageGroupPosition) * probabilityOfDying[2]) - 1)
deadPositions = []
for g in range(len(mortalityApplicationGroups)):
for age in range(mortalityApplicationGroups[g]):
numberOfDead = random.randint(0, len(agePositions[g]) - 1)
deadPositions.append(agePositions[g][numberOfDead])
newYearMatrix = self.__birthdaysAndBirths(timeUnit)
for p in range(len(deadPositions)):
newYearMatrix[deadPositions[p][0]][deadPositions[p][1]] = 0
return newYearMatrix

def deathByDiseaseRule(self,cellSpace,deathFromDiseaseByAgeRange):
'''Aplica probabilidades de muerte por enfermedad a grupos de edad sobre el sistema'''
deathPositions = []
infectedIndividualsPerGroup = []
numberOfInfectedIndividualsDeathPerGroup = []
systemCopy = CellManagement.CellManagement(cellSpace).InsideCopy()
for group in range(len(deathFromDiseaseByAgeRange)):
groupPositions = self.ageGroupPositions(deathFromDiseaseByAgeRange[group][0], deathFromDiseaseByAgeRange[group][1])
infectedIndividuals = []
for individual in range(len(groupPositions)):
if cellSpace.system[groupPositions[individual][0],groupPositions[individual][1]] == Models.State.I.value:
infectedIndividuals.append(groupPositions[individual])
numberOfInfectedIndividualsDeath = math.ceil(len(infectedIndividuals) * deathFromDiseaseByAgeRange[group][2]) - 1
infectedIndividualsPerGroup.append(infectedIndividuals)
numberOfInfectedIndividualsDeathPerGroup.append(numberOfInfectedIndividualsDeath)
for group in range(len(numberOfInfectedIndividualsDeathPerGroup)):
for infectedIndividual in range(numberOfInfectedIndividualsDeathPerGroup[group]):
randomIndividual = random.randint(0,len(infectedIndividualsPerGroup[group]) - 1)
deathPositions.append(infectedIndividualsPerGroup[group][randomIndividual])
for position in range(len(deathPositions)):
self.systemAges[deathPositions[position][0]][deathPositions[position][1]] = 0
systemCopy.system[deathPositions[position][0]][deathPositions[position][1]] = 3
return [systemCopy, self.systemAges]
60 changes: 60 additions & 0 deletions CAsimulation/CellManagement.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import numpy as np
import random
import math
import EpidemiologicalModels.Models as Models
import EpidemiologicalModels.CellSpaceConfiguration as CellSpaceConfiguration

class CellManagement:

def __init__(self, cellSpace):
self.cellSpace = cellSpace

def InsideCopy(self, extraRows = 0, extraColumns = 0):
"""Copia del sistema en un entorno extendido
extraRows => Cantidad de filas extra del entorno
extraColumns => Cantidad de columnas extra del entorno"""
copy = -np.ones((self.cellSpace.nRows + (extraRows * 2), self.cellSpace.nColumns + (extraColumns * 2)))
for row in range(self.cellSpace.nRows):
for column in range(self.cellSpace.nColumns):
copy[row + extraRows][column+extraColumns] = self.cellSpace.system[row][column]
nRows, nColumns, unRows, unColumns, xnRows, xnColumns = self.cellSpace.basicParameters()
cellSpaceCopy = CellSpaceConfiguration.CellSpaceConfiguration(nRows, nColumns, unRows, unColumns, xnRows, xnColumns)
cellSpaceCopy.system = copy
return cellSpaceCopy

def StateCoordinates(self, stateIndicator):
"""Enlista los agentes que tengan un estado especifico
stateIndicator : 0 -> Susceptibles; 1 -> Infectados; 2 -> Recuperados; -1 -> Espacios vacios; 3 -> Fallecidos"""
coordinates = []
for i in range(self.cellSpace.nRows):
for j in range(self.cellSpace.nColumns):
if self.cellSpace.system[i,j] == stateIndicator:
coordinates.append([i,j])
return coordinates

def StatePercentageInSpace(self,a,b,state,spatialState=0):
"""Porcentaje de individuos con el estado en el espacio (a de cada b tienen el estado)
a,b => Porcentage visto como fracción
state => Estado que van a adquirir los individuos
spatialState => Estado que se considera como base para el cambio al estado state"""
percentageInSpace = []
space = spatialState*np.ones((1,b))
for j in range(a):
i = random.randint(1,b-1)
space[0][i] = state
for m in range(1,b):
percentageInSpace.append(int(space[0][m]))
return percentageInSpace

def InitialCondition(self, initialPercentageInfected):
"""Condición inicial aplicada al sistema
initialPercentageInfected => Porcentage inicial de infectados en el sistema"""
susceptibleCoordinates = self.StateCoordinates(Models.State.S.value)
initialInfectedNumber = math.ceil(len(susceptibleCoordinates)*initialPercentageInfected)
# Lista de posiciones de los idividuos que se infectaron y de los que se mantuvieron sanos al aplicar la condicion inicial
percentageInSpace = self.StatePercentageInSpace(initialInfectedNumber,len(susceptibleCoordinates)+1,Models.State.I.value)
cellSpaceCopy = self.InsideCopy()
for i in range(len(percentageInSpace)):
# Los vectores en las posiciones descritas en la lista percentageInSpace adquieren el estado de infección
cellSpaceCopy.system[susceptibleCoordinates[i][0]][susceptibleCoordinates[i][1]] = percentageInSpace[i]
return cellSpaceCopy
104 changes: 104 additions & 0 deletions CAsimulation/CellSpaceConfiguration.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
import numpy as np
import EpidemiologicalModels.CellManagement as CellManagement

class CellSpaceConfiguration:

def __init__(self, nRows, nColumns, xnRows = -1, xnColumns = -1, unRows = 0, unColumns = 0):
self.__nRows = nRows; self.__nColumns = nColumns # Dimensiones de la región interna inicial
self.__xnRows = xnRows; self.__xnColumns = xnColumns # Ubicación de la región interna inicial
self.__unRows = unRows; self.__unColumns = unColumns # Dimensiones del área externa
self.nRows = max(self.__nRows, self.__xnRows)
self.nColumns = max(self.__nColumns, self.__xnColumns)
self.__createInternalSpace()

def __validate(self):
if self.__nRows < 0:
print("Debe definir un número de filas mayor a cero.")
return False
elif self.__nColumns < 0:
print("Debe definir un número de columnas mayor a cero.")
return False
else:
return True

def basicParameters(self):
"""Parámetros con los que se definió el sistema inicialmente."""
return (self.__nRows, self.__nColumns, self.__xnRows, self.__xnColumns, self.__unRows, self.__unColumns)

# Forma del espacio de células

def __createInternalSpace(self):
if self.__validate():
if self.__xnRows == -1 or self.__nColumns == -1:
self.system = np.zeros((self.__nRows, self.__nColumns))
else:
self.system = -np.ones((self.__xnRows, self.__xnColumns))
self.system = self.rectangularBoundary(self.__nRows, self.__nColumns, self.__unRows, self.__unColumns)

def __boundaryDefinition(self, boundaryConditions):
"""Definición de la estructura del sistema dadas las condiciones de frontera
boundaryConditions : Lista con las posiciones con individuos dentro del sistema"""
for condition in range(len(boundaryConditions)):
self.system[boundaryConditions[condition][0],boundaryConditions[condition][1]] = 0
return self.system

def rectangularBoundary(self, rectangleRows, rectangleColumns, rowPosition, columnPosition):
"""Ubica una matriz nula de tamaño rectangleRows*rectangleColumns en la posición a,b del sistema"""
boundaryConditions = []
for row in range(rectangleRows):
for column in range(rectangleColumns):
boundaryConditions.append((rowPosition + row,columnPosition + column))
return self.__boundaryDefinition(boundaryConditions)

# Condición inicial para aplicar el modelo epidemiológico

def initialLocationOfInfected(self, initialPercentageInfected, position = "random", percentageOfInfectedMisplaced = 0):
"""ubicación inicial de infectados
position : random
northwest north northeast
west center east
southwest south southeast"""
if position == "random":
return CellManagement.CellManagement(self).InitialCondition(initialPercentageInfected)
else:
# Se divide la zona rectángular en 9 bloques
a = int(self.nRows/3); b = int(self.nColumns/3)
system = CellManagement.CellManagement(self).InitialCondition(initialPercentageInfected*percentageOfInfectedMisplaced).system
infectedBlock = CellManagement.CellManagement(CellSpaceConfiguration(a,b)).InitialCondition(initialPercentageInfected-percentageOfInfectedMisplaced,).system
if position == "northwest":
for i in range(a):
for j in range(b):
system[i][j] = infectedBlock[i][j]
elif position == "north":
for i in range(a):
for j in range(b,2*b):
system[i][j] = infectedBlock[i][j-b]
elif position == "northeast":
for i in range(a):
for j in range(2*b,3*b):
system[i][j] = infectedBlock[i][j-2*b]
elif position == "west":
for i in range(a,a*2):
for j in range(b):
system[i][j] = infectedBlock[i-a][j]
elif position == "center":
for i in range(a,a*2):
for j in range(b,2*b):
system[i][j] = infectedBlock[i-a][j-b]
elif position == "east":
for i in range(a,a*2):
for j in range(2*b,3*b):
system[i][j]=infectedBlock[i-a][j-2*b]
elif position == "southwest":
for i in range(2*a,3*a):
for j in range(b):
system[i][j] = infectedBlock[i-2*a][j]
elif position == "south":
for i in range(2*a,3*a):
for j in range(b,2*b):
system[i][j] = infectedBlock[i-2*a][j-b]
elif position == "southeast":
for i in range(2*a,3*a):
for j in range(2*b,3*b):
system[i][j] = infectedBlock[i-2*a][j-2*b]
return system
Loading

0 comments on commit 092b4ab

Please sign in to comment.