Skip to content

Commit

Permalink
Merge pull request #58 from SABS-R3-Epidemiology/spatial-weighting
Browse files Browse the repository at this point in the history
Spatial weighting
  • Loading branch information
KCGallagher authored Mar 1, 2022
2 parents 7c960f6 + bfa6cf4 commit ff3acd1
Show file tree
Hide file tree
Showing 38 changed files with 16,545 additions and 369 deletions.
1 change: 1 addition & 0 deletions pyEpiabm/docs/source/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ Contents
properties
routines
sweeps
utility


Search
Expand Down
15 changes: 15 additions & 0 deletions pyEpiabm/docs/source/utility.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
*********
Utilities
*********

.. currentmodule:: pyEpiabm.utility

Utilites provides various methods that don't act on a population directly.

Overview:

- :class:`DistanceFunctions`

.. autoclass:: DistanceFunctions
:members:

1 change: 1 addition & 0 deletions pyEpiabm/pyEpiabm/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
from . import property
from . import routine
from . import sweep
from . import utility

# Expose modules in core within pyEpiabm namespace

Expand Down
23 changes: 14 additions & 9 deletions pyEpiabm/pyEpiabm/core/_compartment_counter.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,15 +28,6 @@ def identifier(self):
"""
return self._identifier

def initialize(self, n_people) -> None:
"""Initialize Compartments with n_people susceptible and 0 in all
of compartments (i.e. for all other InfectionStatus).
:param n_people: Number of people CompartmentCounter is tracking
:type n_people: int
"""
self._compartments[InfectionStatus.Susceptible] = n_people

def report(self, old_status: InfectionStatus,
new_status: InfectionStatus) -> None:
"""Report Person has changed state.
Expand All @@ -47,9 +38,23 @@ def report(self, old_status: InfectionStatus,
:param new_status: Person's new infection state
:type new_status: InfectionStatus
"""
if self._compartments[old_status] <= 0:
raise ValueError("No people of this status in this cell.")
self._compartments[old_status] -= 1
self._compartments[new_status] += 1

def _increment_compartment(self, n_persons: int,
infection_status: InfectionStatus) -> None:
"""Funtion to add a block of people with the same infection status
to a compartment.
:param n_person: number of people being added to cell or microcell
:type n_person: int
:param infection_status: status of people being added
:type infection_status: InfectionStatus
"""
self._compartments[infection_status] += n_persons

def retrieve(self) -> typing.Dict[InfectionStatus, int]:
"""Get Compartment Counts.
Returns dictionary of compartment counts.
Expand Down
28 changes: 12 additions & 16 deletions pyEpiabm/pyEpiabm/core/cell.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,10 @@ def __init__(self, loc: typing.Tuple[float, float] = (0, 0)):
self.person_queue = Queue()
self.compartment_counter = _CompartmentCounter(f"Cell {id(self)}")

if not (len(loc) == 2 and isinstance(loc[0], (float, int)) and
isinstance(loc[1], (float, int))):
raise ValueError("Location must be a tuple of float-type")

def __repr__(self):
"""Returns a string representation of the Cell.
Expand All @@ -48,14 +52,6 @@ def add_microcells(self, n):
for i in range(n):
self.microcells.append(Microcell(self))

def set_location(self, loc: typing.Tuple[float, float]):
"""Updates location of cell (used in population configuration).
:param loc: Location of the cell, as an (x,y) tuple
:type loc: Tuple(float, float)
"""
self.location = loc

def set_id(self, id: float):
"""Updates ID of cell (i.e. for input from file).
Expand All @@ -72,14 +68,6 @@ def enqueue_person(self, person: Person):
"""
self.person_queue.put(person)

def _setup(self) -> None:
"""Setup method. Should be called once Population has been setup.
Called by population (doesn't need to be called manually).
"""
self.compartment_counter.initialize(len(self.persons))
for mcell in self.microcells:
mcell._setup()

def notify_person_status_change(
self,
old_status: InfectionStatus,
Expand All @@ -106,3 +94,11 @@ def number_infectious(self):
+ cell_data[InfectionStatus.InfectGP])

return total_infectors

def set_location(self, loc: typing.Tuple[float, float]):
"""Method to set or change the location of a cell.
:param loc: (x,y) coordinates of the place
:type loc: Tuple[float, float]
"""
self.location = loc
4 changes: 4 additions & 0 deletions pyEpiabm/pyEpiabm/core/household.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,10 @@ def __init__(self, loc: typing.Tuple[float, float] = (1.0, 1.0),
self.susceptibility = susceptibility
self.infectiousness = infectiousness

if not (len(loc) == 2 and isinstance(loc[0], (float, int)) and
isinstance(loc[1], (float, int))):
raise ValueError("Location must be a tuple of float-type")

def __repr__(self):
"""Returns a string representation of Household.
Expand Down
12 changes: 4 additions & 8 deletions pyEpiabm/pyEpiabm/core/microcell.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,11 +55,13 @@ def add_people(self, n, status=InfectionStatus.Susceptible):
:param status: Status of persons to add to cell
:type status: InfectionStatus
"""
for i in range(n):
self.compartment_counter._increment_compartment(n, status)
self.cell.compartment_counter._increment_compartment(n, status)
for _ in range(n):
p = Person(self)
p.update_status(status)
self.cell.persons.append(p)
self.persons.append(p)
p.infection_status = status

def add_place(self, n: int, loc: typing.Tuple[float, float],
place_type):
Expand All @@ -73,12 +75,6 @@ def add_place(self, n: int, loc: typing.Tuple[float, float],
self.cell.places.append(p)
self.places.append(p)

def _setup(self) -> None:
"""Setup method. Should be called once Population has been setup.
Called by population (doesn't need to be called manually).
"""
self.compartment_counter.initialize(len(self.persons))

def notify_person_status_change(
self,
old_status: InfectionStatus,
Expand Down
4 changes: 4 additions & 0 deletions pyEpiabm/pyEpiabm/core/place.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,10 @@ def __init__(self, loc: typing.Tuple[float, float],
if not (self.microcell.cell == self.cell):
raise KeyError("Microcell is not contained in cell")

if not (len(loc) == 2 and isinstance(loc[0], (float, int)) and
isinstance(loc[1], (float, int))):
raise ValueError("Location must be a tuple of float-type")

def set_max_cap(self, max_capacity: int):
"""Sets the maximum capacity of a place.
Expand Down
6 changes: 0 additions & 6 deletions pyEpiabm/pyEpiabm/core/population.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,12 +31,6 @@ def add_cells(self, n):
for i in range(n):
self.cells.append(Cell())

def setup(self) -> None:
"""Setup method. Should be called once Population has been setup.
"""
for cell in self.cells:
cell._setup()

def total_people(self):
"""Returns the total number of people in the population.
Will obviously match the configuration parameter, but useful
Expand Down
1 change: 0 additions & 1 deletion pyEpiabm/pyEpiabm/routine/file_population_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,6 @@ def make_pop(input_file: str, random_seed: int = None):
FilePopulationFactory.add_households(new_microcell,
households)

new_pop.setup()
return new_pop

@staticmethod
Expand Down
16 changes: 4 additions & 12 deletions pyEpiabm/pyEpiabm/routine/spatial_infection.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
# Calculate spatial force of infection based on Covidsim code
#

import random
from pyEpiabm.core import Person, Cell, Parameters


Expand All @@ -25,17 +24,10 @@ def cell_inf(inf_cell: Cell, timestep: int):
R_0 = Parameters.instance().basic_reproduction_num
total_infectors = inf_cell.number_infectious()

number_to_infect = total_infectors * R_0
# This gives a possible decimal for number to infect.
# Choose randomly for the integers either side
# with weights corrsponding to the distance to either
# integer.
floor = int(number_to_infect)

weights = [number_to_infect - floor, 1 - (number_to_infect - floor)]
number_to_infect = random.choices([floor, floor + 1],
weights=weights, k=1)[0]
return (number_to_infect)
average_number_to_infect = total_infectors * R_0
# This gives the expected number of infection events
# caused by people within this cell.
return (average_number_to_infect)

@staticmethod
def space_susc(susc_cell: Cell, infectee: Person,
Expand Down
1 change: 0 additions & 1 deletion pyEpiabm/pyEpiabm/routine/toy_population_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,6 @@ def make_pop(pop_params: typing.Dict):
if place_number > 0:
ToyPopulationFactory.add_places(new_pop, place_number)

new_pop.setup()
return new_pop

@staticmethod
Expand Down
Loading

0 comments on commit ff3acd1

Please sign in to comment.