Source code for pyEpiabm.sweep.initial_demographics_sweep

#
# Sweep to record demographic information of the population in a .csv file
#

import os
import typing

from pyEpiabm.core import Parameters
from pyEpiabm.output import _CsvDictWriter

from .abstract_sweep import AbstractSweep


[docs] class InitialDemographicsSweep(AbstractSweep): """Class to sweep through the population at the beginning of the simulation and record their demographic information. """ def __init__(self, dem_file_params: typing.Dict): """Initiate file parameters referring to the file location and which columns are to be included. dem_file_params Contains: * `output_dir`: String for the location of the output file, \ as a relative path * `spatial_output`: Boolean to determine whether a spatial output \ should be used * `age_output`: Boolean to determine whether the output will \ have ages """ # Must have an output directory if "output_dir" not in dem_file_params: raise ValueError("output_dir must be specified in dem_file_params") # Check for invalid keys invalid_keys = set(dem_file_params.keys()) - \ {"output_dir", "age_output", "spatial_output"} if len(invalid_keys) != 0: raise ValueError(f"dem_file_params contains invalid keys: " f"{invalid_keys}") self.spatial_output = dem_file_params["spatial_output"] \ if "spatial_output" in dem_file_params else False self.age_output = dem_file_params["age_output"] \ if "age_output" in dem_file_params else False if self.age_output and not Parameters.instance().use_ages: raise ValueError("age_output cannot be True as Parameters" ".instance().use_ages is False") # Here we set up the writer folder = os.path.join(os.getcwd(), dem_file_params["output_dir"]) file_name = "demographics.csv" self.titles = ["id"] if self.age_output: self.titles.append("age") if self.spatial_output: self.titles += ["location_x", "location_y"] self.titles.append("kw_or_chr") self.writer = _CsvDictWriter( folder, file_name, self.titles) num_age_groups = (len(Parameters.instance().age_proportions) if Parameters.instance().age_proportions.size and self.age_output else 1) self.count_titles = (["Cell"] + [f"Age group {i}" for i in range(num_age_groups)]) self.counts_writer = _CsvDictWriter( folder, "counts.csv", self.count_titles)
[docs] def __call__(self, *args): """During the initial sweeps, this will be called, and will loop through everyone in the population and write their demographic data to a .csv file titled "demographics.csv". This file will have one row per person, and will have the following columns: id (str), age_group (int, optional), location_x (float, optional), location_y (float, optional), kw_or_chr (str). Furthermore, we write up the counts of how many people there are per age group within each cell in a contingency table .csv file titled "counts.csv". Note that kw_or_chr stands for 'key worker or care home resident'. For kw_or_chr, 'W' refers to a key worker, 'C' refers to a care home resident and 'X' refers to a person who is neither. """ for cell in self._population.cells: cell_count_dict = {title: 0 for title in self.count_titles} cell_count_dict["Cell"] = cell.id for person in cell.persons: data = {"id": person.id, "age": person.age if self.age_output else None, "location_x": cell.location[0] if self.spatial_output else None, "location_y": cell.location[1] if self.spatial_output else None, "kw_or_chr": "W" if person.key_worker else ("C" if person.care_home_resident else "X")} data = {k: data[k] for k in data if data[k] is not None} self.writer.write(data) # Update cell_count_dict age_str = (f"Age group {person.age_group}" if self.age_output else "Age group 0") # The below line will increment the age group count in the # dictionary cell_count_dict.update({age_str: cell_count_dict[age_str] + 1}) self.counts_writer.write(cell_count_dict)