-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
0ee3150
commit 092b4ab
Showing
13 changed files
with
2,241 additions
and
1,388 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
Oops, something went wrong.