From 2b7ef3b9e37a5d311618114939cee22fae5fc768 Mon Sep 17 00:00:00 2001 From: willGraham01 Date: Thu, 18 Jul 2024 14:04:20 +0100 Subject: [PATCH 01/38] Typehints and general implementation for initialise_population --- src/tlo/core.py | 38 ++++++++++++++++++++++++-------------- 1 file changed, 24 insertions(+), 14 deletions(-) diff --git a/src/tlo/core.py b/src/tlo/core.py index 3d3fd3c171..427c6ea21b 100644 --- a/src/tlo/core.py +++ b/src/tlo/core.py @@ -8,7 +8,7 @@ import json from enum import Enum, auto -from typing import TYPE_CHECKING +from typing import TYPE_CHECKING, Dict, FrozenSet import numpy as np import pandas as pd @@ -17,6 +17,9 @@ from typing import Optional from tlo.simulation import Simulation + from tlo.population import Population + from tlo.methods import Metadata + from tlo.methods.causes import Cause class Types(Enum): """Possible types for parameters and properties. @@ -201,47 +204,46 @@ class attribute on a subclass. # Subclasses can override this to declare the set of initialisation dependencies # Declares modules that need to be registered in simulation and initialised before # this module - INIT_DEPENDENCIES = frozenset() + INIT_DEPENDENCIES: FrozenSet[str] = frozenset() # Subclasses can override this to declare the set of optional init. dependencies # Declares modules that need to be registered in simulation and initialised before # this module if they are present, but are not required otherwise - OPTIONAL_INIT_DEPENDENCIES = frozenset() + OPTIONAL_INIT_DEPENDENCIES: FrozenSet[str] = frozenset() # Subclasses can override this to declare the set of additional dependencies # Declares any modules that need to be registered in simulation in addition to those # in INIT_DEPENDENCIES to allow running simulation - ADDITIONAL_DEPENDENCIES = frozenset() + ADDITIONAL_DEPENDENCIES: FrozenSet[str] = frozenset() # Subclasses can override this to declare the set of modules that this module can be # used in place of as a dependency - ALTERNATIVE_TO = frozenset() + ALTERNATIVE_TO: FrozenSet[str] = frozenset() # Subclasses can override this set to add metadata tags to their class # See tlo.methods.Metadata class - METADATA = {} + METADATA: FrozenSet[Metadata] = frozenset() - # Subclasses can override this set to declare the causes death that this module contributes to + # Subclasses can override this dict to declare the causes death that this module contributes to # This is a dict of the form { None: """Set our property values for the initial population. Must be implemented by subclasses. @@ -340,7 +342,15 @@ def initialise_population(self, population): :param population: the population of individuals """ - raise NotImplementedError + df = population.props + + for property_name, property in self.PROPERTIES.items(): + # Types.CATEGORICAL Properties are default set to float("nan") + # We might need to overwrite this behaviour in the Property class itself, + # or just skip any CATEGORICAL dtypes...? + df.loc[df.is_alive, property_name] = ( + property._default_value + ) def initialise_simulation(self, sim): """Get ready for simulation start. From 6ae3e698acf60bd4c7ae6e1107651325987ad8aa Mon Sep 17 00:00:00 2001 From: willGraham01 Date: Thu, 18 Jul 2024 14:27:10 +0100 Subject: [PATCH 02/38] Allow CATEGORICAL Properties to be assigned a default value from the set of Categories, and add class typehints to Property and Module --- src/tlo/core.py | 70 +++++++++++++++++++++++++++++++++---------------- 1 file changed, 47 insertions(+), 23 deletions(-) diff --git a/src/tlo/core.py b/src/tlo/core.py index 427c6ea21b..d648ebf906 100644 --- a/src/tlo/core.py +++ b/src/tlo/core.py @@ -8,12 +8,14 @@ import json from enum import Enum, auto -from typing import TYPE_CHECKING, Dict, FrozenSet +from typing import TYPE_CHECKING, Any, Dict, FrozenSet, Optional, Set, Type import numpy as np import pandas as pd if TYPE_CHECKING: + from pathlib import Path + from typing import Optional from tlo.simulation import Simulation @@ -79,7 +81,7 @@ class Specifiable: Types.BITSET: int, } - def __init__(self, type_, description, categories=None): + def __init__(self, type_: Types, description: str, categories: Set[Any] = None): """Create a new Specifiable. :param type_: an instance of Types giving the type of allowed values @@ -97,16 +99,16 @@ def __init__(self, type_, description, categories=None): self.categories = categories @property - def python_type(self): + def python_type(self) -> Type[Any]: """Return the Python type corresponding to this Specifiable.""" return self.PYTHON_TYPE_MAP[self.type_] @property - def pandas_type(self): + def pandas_type(self) -> Type[Any]: """Return the Pandas type corresponding to this Specifiable.""" return self.PANDAS_TYPE_MAP[self.type_] - def __repr__(self): + def __repr__(self) -> str: """Return detailed description of Specifiable.""" delimiter = " === " @@ -134,8 +136,19 @@ class Property(Specifiable): object: float("nan"), np.uint32: 0, } - - def __init__(self, type_, description, categories=None, *, ordered=False): + # Default value for categorical-properties, which needs to be set at instantiation + # for Properties defined by modules. Leave as None to be ignored. + _default_category_value: Any + + def __init__( + self, + type_: Types, + description: str, + categories: Set[Any] = None, + *, + ordered: bool = False, + default_category_value: Optional[Any] = None, + ) -> None: """Create a new property specification. :param type_: An instance of ``Types`` giving the type of allowed values of this @@ -145,17 +158,30 @@ def __init__(self, type_, description, categories=None, *, ordered=False): ``Types.CATEGORICAL``. :param ordered: Whether categories are ordered if ``type_`` is ``Types.CATEGORICAL``. + :param default_category_value: The default category in the set of categories to + assign on instantiation (if ``type_`` is ``Types.CATEGORICAL``). """ if type_ in [Types.SERIES, Types.DATA_FRAME]: raise TypeError("Property cannot be of type SERIES or DATA_FRAME.") + super().__init__(type_, description, categories) self.ordered = ordered + if self.type_ is Types.CATEGORICAL: + assert default_category_value in categories + self._default_category_value = default_category_value + else: + self._default_category_value = None + @property - def _default_value(self): - return self.PANDAS_TYPE_DEFAULT_VALUE_MAP[self.pandas_type] + def _default_value(self) -> Type[Any]: + return ( + self.PANDAS_TYPE_DEFAULT_VALUE_MAP[self.pandas_type] + if self._default_category_value is None + else self._default_category_value + ) - def create_series(self, name, size): + def create_series(self, name: str, size: int) -> pd.Series: """Create a Pandas Series for this property. The values will be left uninitialised. @@ -244,7 +270,7 @@ class attribute on a subclass. # parameters created from the PARAMETERS specification. __slots__ = ('name', 'parameters', 'rng', 'sim') - def __init__(self, name=None): + def __init__(self, name: str = None) -> None: """Construct a new disease module ready to be included in a simulation. Initialises an empty parameters dictionary and module-specific random number @@ -257,7 +283,7 @@ def __init__(self, name=None): self.name = name or self.__class__.__name__ self.sim: Optional[Simulation] = None - def load_parameters_from_dataframe(self, resource: pd.DataFrame): + def load_parameters_from_dataframe(self, resource: pd.DataFrame) -> None: """Automatically load parameters from resource dataframe, updating the class parameter dictionary Goes through parameters dict self.PARAMETERS and updates the self.parameters with values @@ -318,7 +344,7 @@ def load_parameters_from_dataframe(self, resource: pd.DataFrame): # Save the values to the parameters self.parameters[parameter_name] = parameter_value - def read_parameters(self, data_folder): + def read_parameters(self, data_folder: str | Path) -> None: """Read parameter values from file, if required. Must be implemented by subclasses. @@ -331,28 +357,26 @@ def read_parameters(self, data_folder): def initialise_population(self, population: Population) -> None: """Set our property values for the initial population. - Must be implemented by subclasses. - This method is called by the simulation when creating the initial population, and is responsible for assigning initial values, for every individual, of those properties 'owned' by this module, i.e. those declared in its PROPERTIES dictionary. + By default, all ``Property``s in ``self.PROPERTIES`` will have + their columns set to the default value for their dtype in the population dataframe. + TODO: We probably need to declare somehow which properties we 'read' here, so the simulation knows what order to initialise modules in! - :param population: the population of individuals + :param population: The population of individuals in the simulation. """ df = population.props for property_name, property in self.PROPERTIES.items(): - # Types.CATEGORICAL Properties are default set to float("nan") - # We might need to overwrite this behaviour in the Property class itself, - # or just skip any CATEGORICAL dtypes...? df.loc[df.is_alive, property_name] = ( property._default_value ) - def initialise_simulation(self, sim): + def initialise_simulation(self, sim: Simulation) -> None: """Get ready for simulation start. Must be implemented by subclasses. @@ -363,7 +387,7 @@ def initialise_simulation(self, sim): """ raise NotImplementedError - def pre_initialise_population(self): + def pre_initialise_population(self) -> None: """Carry out any work before any populations have been initialised This optional method allows access to all other registered modules, before any of @@ -371,7 +395,7 @@ def pre_initialise_population(self): when a module's properties rely upon information from other modules. """ - def on_birth(self, mother_id, child_id): + def on_birth(self, mother_id: int, child_id: int) -> None: """Initialise our properties for a newborn individual. Must be implemented by subclasses. @@ -383,6 +407,6 @@ def on_birth(self, mother_id, child_id): """ raise NotImplementedError - def on_simulation_end(self): + def on_simulation_end(self) -> None: """This is called after the simulation has ended. Modules do not need to declare this.""" From 2acbee927b173c2a86d871a2957e6eb0eec53110 Mon Sep 17 00:00:00 2001 From: willGraham01 Date: Thu, 18 Jul 2024 14:47:05 +0100 Subject: [PATCH 03/38] Refactor Alri initialise_population --- src/tlo/core.py | 6 +-- src/tlo/methods/alri.py | 115 ++++++++++++++++++---------------------- 2 files changed, 55 insertions(+), 66 deletions(-) diff --git a/src/tlo/core.py b/src/tlo/core.py index d648ebf906..831f2a19b4 100644 --- a/src/tlo/core.py +++ b/src/tlo/core.py @@ -159,7 +159,8 @@ def __init__( :param ordered: Whether categories are ordered if ``type_`` is ``Types.CATEGORICAL``. :param default_category_value: The default category in the set of categories to - assign on instantiation (if ``type_`` is ``Types.CATEGORICAL``). + assign on instantiation (if ``type_`` is ``Types.CATEGORICAL``). Value must + be in the categories argument to take effect, otherwise this will not be set. """ if type_ in [Types.SERIES, Types.DATA_FRAME]: raise TypeError("Property cannot be of type SERIES or DATA_FRAME.") @@ -167,8 +168,7 @@ def __init__( super().__init__(type_, description, categories) self.ordered = ordered - if self.type_ is Types.CATEGORICAL: - assert default_category_value in categories + if self.type_ is Types.CATEGORICAL and default_category_value in categories: self._default_category_value = default_category_value else: self._default_category_value = None diff --git a/src/tlo/methods/alri.py b/src/tlo/methods/alri.py index c27a54dd30..b295a93166 100644 --- a/src/tlo/methods/alri.py +++ b/src/tlo/methods/alri.py @@ -748,54 +748,65 @@ class Alri(Module, GenericFirstAppointmentsMixin): PROPERTIES = { # ---- Alri status ---- - 'ri_current_infection_status': - Property(Types.BOOL, - 'Does the person currently have an infection with a pathogen that can cause Alri.' - ), - + "ri_current_infection_status": Property( + Types.BOOL, + "Does the person currently have an infection with a pathogen that can cause Alri.", + ), # ---- The pathogen which is the attributed cause of Alri ---- - 'ri_primary_pathogen': - Property(Types.CATEGORICAL, - 'If infected, what is the pathogen with which the person is currently infected. (np.nan if not ' - 'infected)', - categories=list(all_pathogens) - ), + "ri_primary_pathogen": Property( + Types.CATEGORICAL, + "If infected, what is the pathogen with which the person is currently infected. (np.nan if not " + "infected)", + categories=list(all_pathogens), + default_category_value=np.nan, + ), # ---- The bacterial pathogen which is the attributed co-/secondary infection ---- - 'ri_secondary_bacterial_pathogen': - Property(Types.CATEGORICAL, - 'If infected, is there a secondary bacterial pathogen (np.nan if none or not applicable)', - categories=list(pathogens['bacterial']) - ), + "ri_secondary_bacterial_pathogen": Property( + Types.CATEGORICAL, + "If infected, is there a secondary bacterial pathogen (np.nan if none or not applicable)", + categories=list(pathogens["bacterial"]), + default_category_value=np.nan, + ), # ---- The underlying Alri condition ---- - 'ri_disease_type': - Property(Types.CATEGORICAL, 'If infected, what disease type is the person currently suffering from.', - categories=disease_types - ), + "ri_disease_type": Property( + Types.CATEGORICAL, + "If infected, what disease type is the person currently suffering from.", + categories=disease_types, + default_category_value=np.nan, + ), # ---- The peripheral oxygen saturation level ---- - 'ri_SpO2_level': - Property(Types.CATEGORICAL, 'Peripheral oxygen saturation level (Sp02), measure for hypoxaemia', - categories=['<90%', '90-92%', '>=93%'] - ), - + "ri_SpO2_level": Property( + Types.CATEGORICAL, + "Peripheral oxygen saturation level (Sp02), measure for hypoxaemia", + categories=["<90%", "90-92%", ">=93%"], + default_category_value=">=93%", + ), # ---- Treatment Status ---- - 'ri_on_treatment': Property(Types.BOOL, 'Is this person currently receiving treatment.'), - + "ri_on_treatment": Property( + Types.BOOL, "Is this person currently receiving treatment." + ), # < --- (N.B. Other properties of the form 'ri_complication_{complication-name}' are added later.) --> - # ---- Internal variables to schedule onset and deaths due to Alri ---- - 'ri_start_of_current_episode': Property(Types.DATE, - 'date of onset of current Alri event (pd.NaT is not infected)'), - 'ri_scheduled_recovery_date': Property(Types.DATE, - '(scheduled) date of recovery from current Alri event (pd.NaT is not ' - 'infected or episode is scheduled to end in death)'), - 'ri_scheduled_death_date': Property(Types.DATE, - '(scheduled) date of death caused by current Alri event (pd.NaT is not ' - 'infected or episode will not cause death)'), - 'ri_end_of_current_episode': Property(Types.DATE, - 'date on which the last episode of Alri is resolved, (including allowing ' - 'for the possibility that a cure is scheduled following onset). This is ' - 'used to determine when a new episode can begin. This stops successive' - ' episodes interfering with one another.'), + "ri_start_of_current_episode": Property( + Types.DATE, "date of onset of current Alri event (pd.NaT is not infected)" + ), + "ri_scheduled_recovery_date": Property( + Types.DATE, + "(scheduled) date of recovery from current Alri event (pd.NaT is not " + "infected or episode is scheduled to end in death)", + ), + "ri_scheduled_death_date": Property( + Types.DATE, + "(scheduled) date of death caused by current Alri event (pd.NaT is not " + "infected or episode will not cause death)", + ), + "ri_end_of_current_episode": Property( + Types.DATE, + "date on which the last episode of Alri is resolved, (including allowing " + "for the possibility that a cure is scheduled following onset). This is " + "used to determine when a new episode can begin. This stops successive" + " episodes interfering with one another.", + ), } def __init__(self, name=None, resourcefilepath=None, log_indivdual=None, do_checks=False): @@ -873,27 +884,6 @@ def pre_initialise_population(self): Types.BOOL, f"Whether this person has complication {complication}" ) - def initialise_population(self, population): - """ - Sets that there is no one with Alri at initiation. - """ - df = population.props # a shortcut to the data-frame storing data for individuals - - # ---- Key Current Status Classification Properties ---- - df.loc[df.is_alive, 'ri_current_infection_status'] = False - df.loc[df.is_alive, 'ri_primary_pathogen'] = np.nan - df.loc[df.is_alive, 'ri_secondary_bacterial_pathogen'] = np.nan - df.loc[df.is_alive, 'ri_disease_type'] = np.nan - df.loc[df.is_alive, [f"ri_complication_{complication}" for complication in self.complications]] = False - df.loc[df.is_alive, 'ri_SpO2_level'] = ">=93%" - - # ---- Internal values ---- - df.loc[df.is_alive, 'ri_start_of_current_episode'] = pd.NaT - df.loc[df.is_alive, 'ri_scheduled_recovery_date'] = pd.NaT - df.loc[df.is_alive, 'ri_scheduled_death_date'] = pd.NaT - df.loc[df.is_alive, 'ri_end_of_current_episode'] = pd.NaT - df.loc[df.is_alive, 'ri_on_treatment'] = False - def initialise_simulation(self, sim): """ Prepares for simulation: @@ -1121,7 +1111,6 @@ def look_up_consumables(self): get_item_code(item='Salbutamol sulphate 1mg/ml, 5ml_each_CMST'): 2 } - def end_episode(self, person_id): """End the episode infection for a person (i.e. reset all properties to show no current infection or complications). From d52fcfe5aa34d8f32002ee2f849da14747804c54 Mon Sep 17 00:00:00 2001 From: willGraham01 Date: Thu, 18 Jul 2024 14:49:40 +0100 Subject: [PATCH 04/38] Refactor bed_days and healthsystem initialise_population --- src/tlo/methods/bed_days.py | 2 -- src/tlo/methods/healthsystem.py | 2 ++ 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/tlo/methods/bed_days.py b/src/tlo/methods/bed_days.py index ef501f3b2e..0b1edc334a 100644 --- a/src/tlo/methods/bed_days.py +++ b/src/tlo/methods/bed_days.py @@ -89,8 +89,6 @@ def pre_initialise_population(self): self.list_of_cols_with_internal_dates['entries'] + self.list_of_cols_with_internal_dates['exits'] def initialise_population(self, df): - df.loc[df.is_alive, 'hs_is_inpatient'] = False - # Put pd.NaT for all the properties concerned with entry/exit of different types of bed. df.loc[df.is_alive, self.list_of_cols_with_internal_dates['all']] = pd.NaT diff --git a/src/tlo/methods/healthsystem.py b/src/tlo/methods/healthsystem.py index 8099346ddf..de7b4f6fab 100644 --- a/src/tlo/methods/healthsystem.py +++ b/src/tlo/methods/healthsystem.py @@ -686,6 +686,8 @@ def pre_initialise_population(self): self.setup_priority_policy() def initialise_population(self, population): + super().initialise_population(population) + self.bed_days.initialise_population(population.props) def initialise_simulation(self, sim): From 879dcb009bad0d25c901a48246b80ae106b82c46 Mon Sep 17 00:00:00 2001 From: willGraham01 Date: Thu, 18 Jul 2024 14:52:41 +0100 Subject: [PATCH 05/38] Refactor bladder_cancer init pop method --- src/tlo/methods/bladder_cancer.py | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/src/tlo/methods/bladder_cancer.py b/src/tlo/methods/bladder_cancer.py index 113d19fde2..6903b5dc85 100644 --- a/src/tlo/methods/bladder_cancer.py +++ b/src/tlo/methods/bladder_cancer.py @@ -178,6 +178,7 @@ def __init__(self, name=None, resourcefilepath=None): Types.CATEGORICAL, "Current status of the health condition, bladder cancer", categories=["none", "tis_t1", "t2p", "metastatic"], + default_category_value="none", ), "bc_date_diagnosis": Property( Types.DATE, @@ -192,6 +193,7 @@ def __init__(self, name=None, resourcefilepath=None): "the cancer stage at which treatment is given (because the treatment only has an effect during the stage" "at which it is given ", categories=["none", "tis_t1", "t2p", "metastatic"], + default_category_value="none", ), "bc_date_palliative_care": Property( Types.DATE, @@ -227,17 +229,11 @@ def read_parameters(self, data_folder): def initialise_population(self, population): """Set property values for the initial population.""" + super().initialise_population(population=population) + df = population.props # a shortcut to the data-frame p = self.parameters - # defaults - df.loc[df.is_alive, "bc_status"] = "none" - df.loc[df.is_alive, "bc_date_diagnosis"] = pd.NaT - df.loc[df.is_alive, "bc_date_treatment"] = pd.NaT - df.loc[df.is_alive, "bc_stage_at_which_treatment_given"] = "none" - df.loc[df.is_alive, "bc_date_palliative_care"] = pd.NaT - df.loc[df.is_alive, "bc_date_death"] = pd.NaT - # -------------------- bc_status ----------- # Determine who has cancer at ANY cancer stage: # check parameters are sensible: probability of having any cancer stage cannot exceed 1.0 From 75571cdd27dbe7b167a31fb0d1a6399eb3d8b39f Mon Sep 17 00:00:00 2001 From: willGraham01 Date: Thu, 18 Jul 2024 14:57:49 +0100 Subject: [PATCH 06/38] Refactor care of women during pregnancy init pop method --- .../methods/care_of_women_during_pregnancy.py | 124 +++++++++++------- 1 file changed, 76 insertions(+), 48 deletions(-) diff --git a/src/tlo/methods/care_of_women_during_pregnancy.py b/src/tlo/methods/care_of_women_during_pregnancy.py index dba3bcda8e..9927bc1b5d 100644 --- a/src/tlo/methods/care_of_women_during_pregnancy.py +++ b/src/tlo/methods/care_of_women_during_pregnancy.py @@ -143,36 +143,82 @@ def __init__(self, name=None, resourcefilepath=None): } PROPERTIES = { - 'ac_total_anc_visits_current_pregnancy': Property(Types.INT, 'rolling total of antenatal visits this woman has ' - 'attended during her pregnancy'), - 'ac_date_next_contact': Property(Types.DATE, 'Date on which this woman is scheduled to return for her next ' - 'ANC contact'), - 'ac_to_be_admitted': Property(Types.BOOL, 'Whether this woman requires admission following an ANC visit'), - 'ac_receiving_iron_folic_acid': Property(Types.BOOL, 'whether this woman is receiving daily iron & folic acid ' - 'supplementation'), - 'ac_receiving_bep_supplements': Property(Types.BOOL, 'whether this woman is receiving daily balanced energy ' - 'and protein supplementation'), - 'ac_receiving_calcium_supplements': Property(Types.BOOL, 'whether this woman is receiving daily calcium ' - 'supplementation'), - 'ac_gest_htn_on_treatment': Property(Types.BOOL, 'Whether this woman has been initiated on treatment for ' - 'gestational hypertension'), - 'ac_gest_diab_on_treatment': Property(Types.CATEGORICAL, 'Treatment this woman is receiving for gestational ' - 'diabetes', categories=['none', 'diet_exercise', - 'orals', 'insulin']), - 'ac_ectopic_pregnancy_treated': Property(Types.BOOL, 'Whether this woman has received treatment for an ectopic ' - 'pregnancy'), - 'ac_received_post_abortion_care': Property(Types.BOOL, 'bitset list of interventions delivered to a woman ' - 'undergoing post abortion care'), - 'ac_received_abx_for_prom': Property(Types.BOOL, 'Whether this woman has received antibiotics as treatment for ' - 'premature rupture of membranes'), - 'ac_mag_sulph_treatment': Property(Types.BOOL, 'Whether this woman has received magnesium sulphate for ' - 'treatment of severe pre-eclampsia/eclampsia'), - 'ac_iv_anti_htn_treatment': Property(Types.BOOL, 'Whether this woman has received intravenous antihypertensive ' - 'drugs for treatment of severe hypertension'), - 'ac_admitted_for_immediate_delivery': Property(Types.CATEGORICAL, 'Admission type for women needing urgent ' - 'delivery in the antenatal period', - categories=['none', 'induction_now', 'induction_future', - 'caesarean_now', 'caesarean_future', 'avd_now']), + "ac_total_anc_visits_current_pregnancy": Property( + Types.INT, + "rolling total of antenatal visits this woman has " + "attended during her pregnancy", + ), + "ac_date_next_contact": Property( + Types.DATE, + "Date on which this woman is scheduled to return for her next " + "ANC contact", + ), + "ac_to_be_admitted": Property( + Types.BOOL, "Whether this woman requires admission following an ANC visit" + ), + "ac_receiving_iron_folic_acid": Property( + Types.BOOL, + "whether this woman is receiving daily iron & folic acid " + "supplementation", + ), + "ac_receiving_bep_supplements": Property( + Types.BOOL, + "whether this woman is receiving daily balanced energy " + "and protein supplementation", + ), + "ac_receiving_calcium_supplements": Property( + Types.BOOL, + "whether this woman is receiving daily calcium " "supplementation", + ), + "ac_gest_htn_on_treatment": Property( + Types.BOOL, + "Whether this woman has been initiated on treatment for " + "gestational hypertension", + ), + "ac_gest_diab_on_treatment": Property( + Types.CATEGORICAL, + "Treatment this woman is receiving for gestational " "diabetes", + categories=["none", "diet_exercise", "orals", "insulin"], + default_category_value="none", + ), + "ac_ectopic_pregnancy_treated": Property( + Types.BOOL, + "Whether this woman has received treatment for an ectopic " "pregnancy", + ), + "ac_received_post_abortion_care": Property( + Types.BOOL, + "bitset list of interventions delivered to a woman " + "undergoing post abortion care", + ), + "ac_received_abx_for_prom": Property( + Types.BOOL, + "Whether this woman has received antibiotics as treatment for " + "premature rupture of membranes", + ), + "ac_mag_sulph_treatment": Property( + Types.BOOL, + "Whether this woman has received magnesium sulphate for " + "treatment of severe pre-eclampsia/eclampsia", + ), + "ac_iv_anti_htn_treatment": Property( + Types.BOOL, + "Whether this woman has received intravenous antihypertensive " + "drugs for treatment of severe hypertension", + ), + "ac_admitted_for_immediate_delivery": Property( + Types.CATEGORICAL, + "Admission type for women needing urgent " + "delivery in the antenatal period", + categories=[ + "none", + "induction_now", + "induction_future", + "caesarean_now", + "caesarean_future", + "avd_now", + ], + default_category_value="none", + ), } def read_parameters(self, data_folder): @@ -180,24 +226,6 @@ def read_parameters(self, data_folder): sheet_name='parameter_values') self.load_parameters_from_dataframe(parameter_dataframe) - def initialise_population(self, population): - df = population.props - - df.loc[df.is_alive, 'ac_total_anc_visits_current_pregnancy'] = 0 - df.loc[df.is_alive, 'ac_date_next_contact'] = pd.NaT - df.loc[df.is_alive, 'ac_to_be_admitted'] = False - df.loc[df.is_alive, 'ac_receiving_iron_folic_acid'] = False - df.loc[df.is_alive, 'ac_receiving_bep_supplements'] = False - df.loc[df.is_alive, 'ac_receiving_calcium_supplements'] = False - df.loc[df.is_alive, 'ac_gest_htn_on_treatment'] = False - df.loc[df.is_alive, 'ac_gest_diab_on_treatment'] = 'none' - df.loc[df.is_alive, 'ac_ectopic_pregnancy_treated'] = False - df.loc[df.is_alive, 'ac_received_post_abortion_care'] = False - df.loc[df.is_alive, 'ac_received_abx_for_prom'] = False - df.loc[df.is_alive, 'ac_mag_sulph_treatment'] = False - df.loc[df.is_alive, 'ac_iv_anti_htn_treatment'] = False - df.loc[df.is_alive, 'ac_admitted_for_immediate_delivery'] = 'none' - def get_and_store_pregnancy_item_codes(self): """ This function defines the required consumables for each intervention delivered during this module and stores From 3bd4c61f4aeb604be0914891d6f3314bfebea389 Mon Sep 17 00:00:00 2001 From: willGraham01 Date: Thu, 18 Jul 2024 15:05:54 +0100 Subject: [PATCH 07/38] Refactor chronicsyndrome init pop method --- src/tlo/methods/chronicsyndrome.py | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/src/tlo/methods/chronicsyndrome.py b/src/tlo/methods/chronicsyndrome.py index 0ae6599939..c11e2baff1 100644 --- a/src/tlo/methods/chronicsyndrome.py +++ b/src/tlo/methods/chronicsyndrome.py @@ -81,13 +81,18 @@ class ChronicSyndrome(Module, GenericFirstAppointmentsMixin): } PROPERTIES = { - 'cs_has_cs': Property(Types.BOOL, 'Current status of mockitis'), - 'cs_status': Property( - Types.CATEGORICAL, 'Historical status: N=never; C=currently 2; P=previously', categories=['N', 'C', 'P'] + "cs_has_cs": Property(Types.BOOL, "Current status of mockitis"), + "cs_status": Property( + Types.CATEGORICAL, + "Historical status: N=never; C=currently 2; P=previously", + categories=["N", "C", "P"], + default_category_value="N", ), - 'cs_date_acquired': Property(Types.DATE, 'Date of latest infection'), - 'cs_scheduled_date_death': Property(Types.DATE, 'Date of scheduled death of infected individual'), - 'cs_date_cure': Property(Types.DATE, 'Date an infected individual was cured'), + "cs_date_acquired": Property(Types.DATE, "Date of latest infection"), + "cs_scheduled_date_death": Property( + Types.DATE, "Date of scheduled death of infected individual" + ), + "cs_date_cure": Property(Types.DATE, "Date an infected individual was cured"), } def __init__(self, name=None, resourcefilepath=None): @@ -136,15 +141,10 @@ def initialise_population(self, population): :param population: the population of individuals """ - df = population.props # a shortcut to the dataframe storing data for individiuals - p = self.parameters + super().initialise_population(population=population) - # Set default for properties - df.loc[df.is_alive, 'cs_has_cs'] = False # default: no individuals infected - df.loc[df.is_alive, 'cs_status'].values[:] = 'N' # default: never infected - df.loc[df.is_alive, 'cs_date_acquired'] = pd.NaT # default: not a time - df.loc[df.is_alive, 'cs_scheduled_date_death'] = pd.NaT # default: not a time - df.loc[df.is_alive, 'cs_date_cure'] = pd.NaT # default: not a time + df = population.props + p = self.parameters # randomly selected some individuals as infected num_alive = df.is_alive.sum() From 3be20a88ce3551493613aa9130e6054cb7ce5097 Mon Sep 17 00:00:00 2001 From: willGraham01 Date: Thu, 18 Jul 2024 15:09:39 +0100 Subject: [PATCH 08/38] Refactor contraception init pop method --- src/tlo/methods/contraception.py | 45 ++++++++++++++++++-------------- 1 file changed, 26 insertions(+), 19 deletions(-) diff --git a/src/tlo/methods/contraception.py b/src/tlo/methods/contraception.py index ab6c633f4c..3d8625132f 100644 --- a/src/tlo/methods/contraception.py +++ b/src/tlo/methods/contraception.py @@ -120,19 +120,30 @@ class Contraception(Module): # contraceptive or after using a method which is not in this category. PROPERTIES = { - 'co_contraception': Property(Types.CATEGORICAL, 'Current contraceptive method', - categories=sorted(all_contraception_states)), - 'is_pregnant': Property(Types.BOOL, 'Whether this individual is currently pregnant'), - 'date_of_last_pregnancy': Property(Types.DATE, 'Date that the most recent or current pregnancy began.'), - 'co_unintended_preg': Property(Types.BOOL, 'Whether the most recent or current pregnancy was unintended.'), - 'co_date_of_last_fp_appt': Property(Types.DATE, - 'The date of the most recent Family Planning appointment. This is used to ' - 'determine if a Family Planning appointment is needed to maintain the ' - 'person on their current contraceptive. If the person is to maintain use of' - ' the current contraceptive, they will have an HSI only if the days elapsed' - ' since this value exceeds the method-specific parameter ' - '`days_between_appts_for_maintenance`.' - ) + "co_contraception": Property( + Types.CATEGORICAL, + "Current contraceptive method", + categories=sorted(all_contraception_states), + default_category_value="not_using", + ), + "is_pregnant": Property( + Types.BOOL, "Whether this individual is currently pregnant" + ), + "date_of_last_pregnancy": Property( + Types.DATE, "Date that the most recent or current pregnancy began." + ), + "co_unintended_preg": Property( + Types.BOOL, "Whether the most recent or current pregnancy was unintended." + ), + "co_date_of_last_fp_appt": Property( + Types.DATE, + "The date of the most recent Family Planning appointment. This is used to " + "determine if a Family Planning appointment is needed to maintain the " + "person on their current contraceptive. If the person is to maintain use of" + " the current contraceptive, they will have an HSI only if the days elapsed" + " since this value exceeds the method-specific parameter " + "`days_between_appts_for_maintenance`.", + ), } def __init__(self, name=None, resourcefilepath=None, use_healthsystem=True, run_update_contraceptive=True): @@ -213,14 +224,10 @@ def pre_initialise_population(self): def initialise_population(self, population): """Set initial values for properties""" - # 1) Set default values for properties + super().initialise_population(population=population) + df = population.props - df.loc[df.is_alive, 'co_contraception'] = 'not_using' - df.loc[df.is_alive, 'is_pregnant'] = False - df.loc[df.is_alive, 'date_of_last_pregnancy'] = pd.NaT - df.loc[df.is_alive, 'co_unintended_preg'] = False - df.loc[df.is_alive, 'co_date_of_last_fp_appt'] = pd.NaT # 2) Assign contraception method # Select females aged 15-49 from population, for current year From 61a4888fbc977dbe9d0a0dc3c2e43c1236f5416b Mon Sep 17 00:00:00 2001 From: willGraham01 Date: Thu, 18 Jul 2024 15:12:13 +0100 Subject: [PATCH 09/38] Refactor CopD init pop method --- src/tlo/methods/copd.py | 26 +++++++++++++++----------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/src/tlo/methods/copd.py b/src/tlo/methods/copd.py index 53602505ae..9d1f5527dd 100644 --- a/src/tlo/methods/copd.py +++ b/src/tlo/methods/copd.py @@ -123,16 +123,20 @@ class Copd(Module, GenericFirstAppointmentsMixin): } PROPERTIES = { - 'ch_lungfunction': Property( - Types.CATEGORICAL, 'Lung function of the person.' - '0 for those under 15; on a 7-point scale for others, from 0 (Perfect) to 6 (End-Stage' - ' COPD).', categories=ch_lungfunction_cats, ordered=True, + "ch_lungfunction": Property( + Types.CATEGORICAL, + "Lung function of the person." + "0 for those under 15; on a 7-point scale for others, from 0 (Perfect) to 6 (End-Stage" + " COPD).", + categories=ch_lungfunction_cats, + ordered=True, ), - 'ch_will_die_this_episode': Property( - Types.BOOL, 'Whether this person will die during a current severe exacerbation' + "ch_will_die_this_episode": Property( + Types.BOOL, + "Whether this person will die during a current severe exacerbation", ), - 'ch_has_inhaler': Property( - Types.BOOL, 'Whether the person is currently using an inhaler' + "ch_has_inhaler": Property( + Types.BOOL, "Whether the person is currently using an inhaler" ), } @@ -154,11 +158,11 @@ def pre_initialise_population(self): self.models = CopdModels(self.parameters, self.rng) def initialise_population(self, population): - """ Set initial values of properties values for all individuals""" + """Set initial values of properties values for all individuals""" + super().initialise_population(population=population) + df = population.props df.loc[df.is_alive, 'ch_lungfunction'] = self.models.init_lung_function(df.loc[df.is_alive]) - df.loc[df.is_alive, 'ch_will_die_this_episode'] = False - df.loc[df.is_alive, 'ch_has_inhaler'] = False def initialise_simulation(self, sim): """ Get ready for simulation start: From 125f710ad0d6f2678a64a1aded19b8998df9286a Mon Sep 17 00:00:00 2001 From: willGraham01 Date: Thu, 18 Jul 2024 15:22:19 +0100 Subject: [PATCH 10/38] Refactor depression --- src/tlo/methods/depression.py | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/src/tlo/methods/depression.py b/src/tlo/methods/depression.py index 81ae29403e..feb6f31c25 100644 --- a/src/tlo/methods/depression.py +++ b/src/tlo/methods/depression.py @@ -390,20 +390,12 @@ def apply_linear_model(self, lm, df): return self.rng.random_sample(len(df)) < lm.predict(df) def initialise_population(self, population): + super().initialise_population(population=population) df = population.props - df['de_depr'] = False - df['de_ever_depr'] = False - df['de_date_init_most_rec_depr'] = pd.NaT - df['de_date_depr_resolved'] = pd.NaT - df['de_intrinsic_3mo_risk_of_depr_resolution'] = np.NaN - df['de_ever_diagnosed_depression'] = False - df['de_on_antidepr'] = False - df['de_ever_talk_ther'] = False - df['de_ever_non_fatal_self_harm_event'] = False + df['de_recently_pregnant'] = df['is_pregnant'] | ( df['date_of_last_pregnancy'] > (self.sim.date - DateOffset(years=1)) ) - df['de_cc'] = False # Assign initial 'current depression' status df.loc[df['is_alive'], 'de_depr'] = self.apply_linear_model( From 46bafd44d00c073700bd3102c6d62307c69cd222 Mon Sep 17 00:00:00 2001 From: willGraham01 Date: Thu, 18 Jul 2024 15:26:22 +0100 Subject: [PATCH 11/38] Refactor diarrhoea module init pop method --- src/tlo/methods/diarrhoea.py | 142 ++++++++++++++++++----------------- 1 file changed, 72 insertions(+), 70 deletions(-) diff --git a/src/tlo/methods/diarrhoea.py b/src/tlo/methods/diarrhoea.py index 06c8a37b18..002c1d2046 100644 --- a/src/tlo/methods/diarrhoea.py +++ b/src/tlo/methods/diarrhoea.py @@ -453,56 +453,79 @@ class Diarrhoea(Module, GenericFirstAppointmentsMixin): PROPERTIES = { # ---- Core Properties of Actual Status and Intrinsic Properties of A Current Episode ---- - 'gi_has_diarrhoea': Property(Types.BOOL, - 'Whether or not the person currently has an episode of diarrhoea.' - ), - 'gi_pathogen': Property(Types.CATEGORICAL, - 'The attributable pathogen for the current episode of diarrhoea ' - '(np.nan if the person does not currently have diarrhoea).', - categories=list(pathogens)), - 'gi_type': Property(Types.CATEGORICAL, - 'Type (watery or blood) of the current episode of diarrhoea ' - '(np.nan if the person does not currently have diarrhoea).', - categories=['watery', - 'bloody']), - 'gi_dehydration': Property(Types.CATEGORICAL, - 'Severity of dehydration for the current episode of diarrhoea ' - '(np.nan if the person does not currently have diarrhoea).', - categories=['none', - 'some', # <-- this level is not used currently. - 'severe' - ]), - 'gi_duration_longer_than_13days': Property(Types.BOOL, - 'Whether the duration of the current episode would last longer than ' - '13 days if untreated. (False if does not have current episode)'), - 'gi_number_of_episodes': Property(Types.INT, - "Number of episodes of diarrhoea caused by a pathogen"), - + "gi_has_diarrhoea": Property( + Types.BOOL, + "Whether or not the person currently has an episode of diarrhoea.", + ), + "gi_pathogen": Property( + Types.CATEGORICAL, + "The attributable pathogen for the current episode of diarrhoea " + "(np.nan if the person does not currently have diarrhoea).", + categories=list(pathogens), + default_category_value=np.nan, + ), + "gi_type": Property( + Types.CATEGORICAL, + "Type (watery or blood) of the current episode of diarrhoea " + "(np.nan if the person does not currently have diarrhoea).", + categories=["watery", "bloody"], + default_category_value=np.nan, + ), + "gi_dehydration": Property( + Types.CATEGORICAL, + "Severity of dehydration for the current episode of diarrhoea " + "(np.nan if the person does not currently have diarrhoea).", + categories=[ + "none", + "some", # <-- this level is not used currently. + "severe", + ], + default_category_value=np.nan, + ), + "gi_duration_longer_than_13days": Property( + Types.BOOL, + "Whether the duration of the current episode would last longer than " + "13 days if untreated. (False if does not have current episode)", + ), + "gi_number_of_episodes": Property( + Types.INT, "Number of episodes of diarrhoea caused by a pathogen" + ), # ---- Internal variables storing dates of scheduled events ---- - 'gi_date_of_onset': Property(Types.DATE, 'Date of onset of current episode of diarrhoea (pd.NaT if does not ' - 'have current episode of diarrhoea).'), - 'gi_scheduled_date_recovery': Property(Types.DATE, - 'Scheduled date of recovery from current episode of diarrhoea ' - '(pd.NaT if does not have current episode or current episode ' - 'is scheduled to result in death). This is scheduled when the ' - 'episode is onset and may be revised subsequently if the episode ' - 'is cured by a treatment'), - 'gi_scheduled_date_death': Property(Types.DATE, 'Scheduled date of death caused by current episode of diarrhoea' - ' (pd.NaT if does not have current episode or if current ' - 'episode will not result in death). This is scheduled when the ' - 'episode is onset and may be revised subsequently if the ' - 'episode is cured by a treatment.'), - 'gi_date_end_of_last_episode': Property(Types.DATE, - 'The date on which the last episode of diarrhoea is fully resolved, ' - 'including allowing for the possibility of HSI events (pd.NaT if has ' - 'never had an episode). This is used to determine when a new episode ' - 'can begin and stops successive episodes interfering with one another.' - 'This is notnull when the person has ever had an episode of diarrhoea.' - ), - 'gi_treatment_date': Property(Types.DATE, - 'The actual date on which treatment is first administered for the current episode' - ' (pd.NaT if does not have current episode or if no treatment has yet been ' - 'provided in the current episode).') + "gi_date_of_onset": Property( + Types.DATE, + "Date of onset of current episode of diarrhoea (pd.NaT if does not " + "have current episode of diarrhoea).", + ), + "gi_scheduled_date_recovery": Property( + Types.DATE, + "Scheduled date of recovery from current episode of diarrhoea " + "(pd.NaT if does not have current episode or current episode " + "is scheduled to result in death). This is scheduled when the " + "episode is onset and may be revised subsequently if the episode " + "is cured by a treatment", + ), + "gi_scheduled_date_death": Property( + Types.DATE, + "Scheduled date of death caused by current episode of diarrhoea" + " (pd.NaT if does not have current episode or if current " + "episode will not result in death). This is scheduled when the " + "episode is onset and may be revised subsequently if the " + "episode is cured by a treatment.", + ), + "gi_date_end_of_last_episode": Property( + Types.DATE, + "The date on which the last episode of diarrhoea is fully resolved, " + "including allowing for the possibility of HSI events (pd.NaT if has " + "never had an episode). This is used to determine when a new episode " + "can begin and stops successive episodes interfering with one another." + "This is notnull when the person has ever had an episode of diarrhoea.", + ), + "gi_treatment_date": Property( + Types.DATE, + "The actual date on which treatment is first administered for the current episode" + " (pd.NaT if does not have current episode or if no treatment has yet been " + "provided in the current episode).", + ), } def __init__(self, name=None, resourcefilepath=None, do_checks=False): @@ -532,27 +555,6 @@ def read_parameters(self, data_folder): param_type.python_type), f'Parameter "{param_name}" is not read in correctly from the ' \ f'resourcefile.' - def initialise_population(self, population): - """ - Sets that there is no one with diarrhoea at initiation. - """ - df = population.props # a shortcut to the data-frame storing data for individuals - - # ---- Key Current Status Classification Properties ---- - df.loc[df.is_alive, 'gi_has_diarrhoea'] = False - df.loc[df.is_alive, 'gi_pathogen'] = np.nan - df.loc[df.is_alive, 'gi_type'] = np.nan - df.loc[df.is_alive, 'gi_dehydration'] = np.nan - df.loc[df.is_alive, 'gi_duration_longer_than_13days'] = False - df.loc[df.is_alive, 'gi_number_of_episodes'] = 0 - - # ---- Internal values ---- - df.loc[df.is_alive, 'gi_date_of_onset'] = pd.NaT - df.loc[df.is_alive, 'gi_scheduled_date_recovery'] = pd.NaT - df.loc[df.is_alive, 'gi_scheduled_date_death'] = pd.NaT - df.loc[df.is_alive, 'gi_treatment_date'] = pd.NaT - df.loc[df.is_alive, 'gi_date_end_of_last_episode'] = pd.NaT - def initialise_simulation(self, sim): """Prepares for simulation: * Schedules the main polling event From 24f53bed6a638dc8d2b81e9348d500b08150400a Mon Sep 17 00:00:00 2001 From: willGraham01 Date: Thu, 18 Jul 2024 15:28:43 +0100 Subject: [PATCH 12/38] Refactor EPI init pop metho --- src/tlo/methods/epi.py | 32 ++------------------------------ 1 file changed, 2 insertions(+), 30 deletions(-) diff --git a/src/tlo/methods/epi.py b/src/tlo/methods/epi.py index 1cdf8a1612..88e3c110b0 100644 --- a/src/tlo/methods/epi.py +++ b/src/tlo/methods/epi.py @@ -96,38 +96,10 @@ def read_parameters(self, data_folder): }) def initialise_population(self, population): + super().initialise_population(population=population) + df = population.props p = self.parameters - - # Set default for properties - df.loc[df.is_alive, [ - "va_bcg", - "va_opv", - "va_dtp", - "va_hib", - "va_hep", - "va_pneumo", - "va_rota", - "va_measles", - "va_rubella", - "va_hpv", - "va_td"] - ] = 0 - - df.loc[df.is_alive, [ - "va_bcg_all_doses", - "va_opv_all_doses", - "va_dtp_all_doses", - "va_hib_all_doses", - "va_hep_all_doses", - "va_pneumo_all_doses", - "va_rota_all_doses", - "va_measles_all_doses", - "va_rubella_all_doses", - "va_hpv_all_doses", - "va_td_all_doses"] - ] = False - # BCG # from 1981-2009 average bcg coverage is 92% (WHO estimates) # use vaccine coverage estimates for each year prior to 2010 From 778dc2e1221ec3dc254d1ea97f9c2890f2f7856d Mon Sep 17 00:00:00 2001 From: willGraham01 Date: Thu, 18 Jul 2024 15:31:02 +0100 Subject: [PATCH 13/38] Refactor epilepsy init pop method. Also remove ep_unified_symptom_code property - was never referenced in the codebase --- src/tlo/methods/epilepsy.py | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/src/tlo/methods/epilepsy.py b/src/tlo/methods/epilepsy.py index a1650a3889..86cd2c90af 100644 --- a/src/tlo/methods/epilepsy.py +++ b/src/tlo/methods/epilepsy.py @@ -119,15 +119,17 @@ def __init__(self, name=None, resourcefilepath=None): # Properties of individuals 'owned' by this module PROPERTIES = { - 'ep_seiz_stat': Property( + "ep_seiz_stat": Property( Types.CATEGORICAL, - '(0 = never epilepsy, 1 = previous seizures none now, 2 = infrequent seizures, 3 = frequent seizures)', - categories=['0', '1', '2', '3'], + "(0 = never epilepsy, 1 = previous seizures none now, 2 = infrequent seizures, 3 = frequent seizures)", + categories=["0", "1", "2", "3"], + default_category_value="0", + ), + "ep_antiep": Property(Types.BOOL, "on antiepileptic"), + "ep_epi_death": Property(Types.BOOL, "epilepsy death this 3 month period"), + "ep_disability": Property( + Types.REAL, "disability weight for current 3 month period" ), - 'ep_antiep': Property(Types.BOOL, 'on antiepileptic'), - 'ep_epi_death': Property(Types.BOOL, 'epilepsy death this 3 month period'), - 'ep_unified_symptom_code': Property(Types.CATEGORICAL, '', categories=['0', '1', '2', '3']), - 'ep_disability': Property(Types.REAL, 'disability weight for current 3 month period'), } # Declaration of how we will refer to any treatments that are related to this disease. @@ -165,16 +167,12 @@ def initialise_population(self, population): responsible for assigning initial values, for every individual, of those properties 'owned' by this module, i.e. those declared in the PROPERTIES dictionary above. """ + super().initialise_population(population=population) df = population.props # a shortcut to the data-frame storing data for individuals p = self.parameters rng = self.rng - df.loc[df.is_alive, 'ep_seiz_stat'] = '0' - df.loc[df.is_alive, 'ep_antiep'] = False - df.loc[df.is_alive, 'ep_epi_death'] = False - df.loc[df.is_alive, 'ep_disability'] = 0 - # allocate initial ep_seiz_stat alive_idx = df.index[df.is_alive] df.loc[alive_idx, 'ep_seiz_stat'] = self.rng.choice(['0', '1', '2', '3'], size=len(alive_idx), From 6dc254481d5aa01d72e0056d60ea9f72ce09a19e Mon Sep 17 00:00:00 2001 From: willGraham01 Date: Fri, 19 Jul 2024 08:45:56 +0100 Subject: [PATCH 14/38] Revert "Refactor epilepsy init pop method. Also remove ep_unified_symptom_code property - was never referenced in the codebase" This reverts commit 778dc2e1221ec3dc254d1ea97f9c2890f2f7856d. --- src/tlo/methods/epilepsy.py | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/src/tlo/methods/epilepsy.py b/src/tlo/methods/epilepsy.py index 86cd2c90af..a1650a3889 100644 --- a/src/tlo/methods/epilepsy.py +++ b/src/tlo/methods/epilepsy.py @@ -119,17 +119,15 @@ def __init__(self, name=None, resourcefilepath=None): # Properties of individuals 'owned' by this module PROPERTIES = { - "ep_seiz_stat": Property( + 'ep_seiz_stat': Property( Types.CATEGORICAL, - "(0 = never epilepsy, 1 = previous seizures none now, 2 = infrequent seizures, 3 = frequent seizures)", - categories=["0", "1", "2", "3"], - default_category_value="0", - ), - "ep_antiep": Property(Types.BOOL, "on antiepileptic"), - "ep_epi_death": Property(Types.BOOL, "epilepsy death this 3 month period"), - "ep_disability": Property( - Types.REAL, "disability weight for current 3 month period" + '(0 = never epilepsy, 1 = previous seizures none now, 2 = infrequent seizures, 3 = frequent seizures)', + categories=['0', '1', '2', '3'], ), + 'ep_antiep': Property(Types.BOOL, 'on antiepileptic'), + 'ep_epi_death': Property(Types.BOOL, 'epilepsy death this 3 month period'), + 'ep_unified_symptom_code': Property(Types.CATEGORICAL, '', categories=['0', '1', '2', '3']), + 'ep_disability': Property(Types.REAL, 'disability weight for current 3 month period'), } # Declaration of how we will refer to any treatments that are related to this disease. @@ -167,12 +165,16 @@ def initialise_population(self, population): responsible for assigning initial values, for every individual, of those properties 'owned' by this module, i.e. those declared in the PROPERTIES dictionary above. """ - super().initialise_population(population=population) df = population.props # a shortcut to the data-frame storing data for individuals p = self.parameters rng = self.rng + df.loc[df.is_alive, 'ep_seiz_stat'] = '0' + df.loc[df.is_alive, 'ep_antiep'] = False + df.loc[df.is_alive, 'ep_epi_death'] = False + df.loc[df.is_alive, 'ep_disability'] = 0 + # allocate initial ep_seiz_stat alive_idx = df.index[df.is_alive] df.loc[alive_idx, 'ep_seiz_stat'] = self.rng.choice(['0', '1', '2', '3'], size=len(alive_idx), From 651a672470b51f26e5d8fe86db91af7d76478dab Mon Sep 17 00:00:00 2001 From: willGraham01 Date: Fri, 19 Jul 2024 09:26:44 +0100 Subject: [PATCH 15/38] Allow other Property Types to have a custom default value. Refactor epilepsy init pop --- src/tlo/core.py | 37 ++++++++++++------- src/tlo/methods/alri.py | 8 ++-- src/tlo/methods/bladder_cancer.py | 4 +- .../methods/care_of_women_during_pregnancy.py | 4 +- src/tlo/methods/chronicsyndrome.py | 2 +- src/tlo/methods/contraception.py | 2 +- src/tlo/methods/diarrhoea.py | 6 +-- src/tlo/methods/epilepsy.py | 24 ++++++------ 8 files changed, 48 insertions(+), 39 deletions(-) diff --git a/src/tlo/core.py b/src/tlo/core.py index 831f2a19b4..7d98ca14d4 100644 --- a/src/tlo/core.py +++ b/src/tlo/core.py @@ -136,9 +136,9 @@ class Property(Specifiable): object: float("nan"), np.uint32: 0, } - # Default value for categorical-properties, which needs to be set at instantiation - # for Properties defined by modules. Leave as None to be ignored. - _default_category_value: Any + # An overwrite for the default value map above, if a specific property needs + # to instantiate at a different default value. + _default_property_value: Any def __init__( self, @@ -147,7 +147,7 @@ def __init__( categories: Set[Any] = None, *, ordered: bool = False, - default_category_value: Optional[Any] = None, + default_property_value: Optional[Any] = None, ) -> None: """Create a new property specification. @@ -158,27 +158,36 @@ def __init__( ``Types.CATEGORICAL``. :param ordered: Whether categories are ordered if ``type_`` is ``Types.CATEGORICAL``. - :param default_category_value: The default category in the set of categories to - assign on instantiation (if ``type_`` is ``Types.CATEGORICAL``). Value must - be in the categories argument to take effect, otherwise this will not be set. + :param default_property_value: The default value to assign to elements in a series + of this ``Property``. If ``type_`` is ``Types.CATEGORICAL``, this value must + be one of the supplied categories, otherwise it must be of type ``type_``. """ if type_ in [Types.SERIES, Types.DATA_FRAME]: raise TypeError("Property cannot be of type SERIES or DATA_FRAME.") - + super().__init__(type_, description, categories) self.ordered = ordered - if self.type_ is Types.CATEGORICAL and default_category_value in categories: - self._default_category_value = default_category_value - else: - self._default_category_value = None + # Set supplied default value, if appropriate + self._default_property_value = ( + default_property_value + if default_property_value is not None + and ( + ( + self.type_ is Types.CATEGORICAL + and default_property_value in categories + ) + or isinstance(default_property_value, self.python_type) + ) + else None + ) @property def _default_value(self) -> Type[Any]: return ( self.PANDAS_TYPE_DEFAULT_VALUE_MAP[self.pandas_type] - if self._default_category_value is None - else self._default_category_value + if self._default_property_value is None + else self._default_property_value ) def create_series(self, name: str, size: int) -> pd.Series: diff --git a/src/tlo/methods/alri.py b/src/tlo/methods/alri.py index b295a93166..6cae30eb42 100644 --- a/src/tlo/methods/alri.py +++ b/src/tlo/methods/alri.py @@ -758,28 +758,28 @@ class Alri(Module, GenericFirstAppointmentsMixin): "If infected, what is the pathogen with which the person is currently infected. (np.nan if not " "infected)", categories=list(all_pathogens), - default_category_value=np.nan, + default_property_value=np.nan, ), # ---- The bacterial pathogen which is the attributed co-/secondary infection ---- "ri_secondary_bacterial_pathogen": Property( Types.CATEGORICAL, "If infected, is there a secondary bacterial pathogen (np.nan if none or not applicable)", categories=list(pathogens["bacterial"]), - default_category_value=np.nan, + default_property_value=np.nan, ), # ---- The underlying Alri condition ---- "ri_disease_type": Property( Types.CATEGORICAL, "If infected, what disease type is the person currently suffering from.", categories=disease_types, - default_category_value=np.nan, + default_property_value=np.nan, ), # ---- The peripheral oxygen saturation level ---- "ri_SpO2_level": Property( Types.CATEGORICAL, "Peripheral oxygen saturation level (Sp02), measure for hypoxaemia", categories=["<90%", "90-92%", ">=93%"], - default_category_value=">=93%", + default_property_value=">=93%", ), # ---- Treatment Status ---- "ri_on_treatment": Property( diff --git a/src/tlo/methods/bladder_cancer.py b/src/tlo/methods/bladder_cancer.py index 6903b5dc85..c89c50d168 100644 --- a/src/tlo/methods/bladder_cancer.py +++ b/src/tlo/methods/bladder_cancer.py @@ -178,7 +178,7 @@ def __init__(self, name=None, resourcefilepath=None): Types.CATEGORICAL, "Current status of the health condition, bladder cancer", categories=["none", "tis_t1", "t2p", "metastatic"], - default_category_value="none", + default_property_value="none", ), "bc_date_diagnosis": Property( Types.DATE, @@ -193,7 +193,7 @@ def __init__(self, name=None, resourcefilepath=None): "the cancer stage at which treatment is given (because the treatment only has an effect during the stage" "at which it is given ", categories=["none", "tis_t1", "t2p", "metastatic"], - default_category_value="none", + default_property_value="none", ), "bc_date_palliative_care": Property( Types.DATE, diff --git a/src/tlo/methods/care_of_women_during_pregnancy.py b/src/tlo/methods/care_of_women_during_pregnancy.py index 9927bc1b5d..149dc3772a 100644 --- a/src/tlo/methods/care_of_women_during_pregnancy.py +++ b/src/tlo/methods/care_of_women_during_pregnancy.py @@ -179,7 +179,7 @@ def __init__(self, name=None, resourcefilepath=None): Types.CATEGORICAL, "Treatment this woman is receiving for gestational " "diabetes", categories=["none", "diet_exercise", "orals", "insulin"], - default_category_value="none", + default_property_value="none", ), "ac_ectopic_pregnancy_treated": Property( Types.BOOL, @@ -217,7 +217,7 @@ def __init__(self, name=None, resourcefilepath=None): "caesarean_future", "avd_now", ], - default_category_value="none", + default_property_value="none", ), } diff --git a/src/tlo/methods/chronicsyndrome.py b/src/tlo/methods/chronicsyndrome.py index c11e2baff1..5fe5806362 100644 --- a/src/tlo/methods/chronicsyndrome.py +++ b/src/tlo/methods/chronicsyndrome.py @@ -86,7 +86,7 @@ class ChronicSyndrome(Module, GenericFirstAppointmentsMixin): Types.CATEGORICAL, "Historical status: N=never; C=currently 2; P=previously", categories=["N", "C", "P"], - default_category_value="N", + default_property_value="N", ), "cs_date_acquired": Property(Types.DATE, "Date of latest infection"), "cs_scheduled_date_death": Property( diff --git a/src/tlo/methods/contraception.py b/src/tlo/methods/contraception.py index 3d8625132f..8ca5f38614 100644 --- a/src/tlo/methods/contraception.py +++ b/src/tlo/methods/contraception.py @@ -124,7 +124,7 @@ class Contraception(Module): Types.CATEGORICAL, "Current contraceptive method", categories=sorted(all_contraception_states), - default_category_value="not_using", + default_property_value="not_using", ), "is_pregnant": Property( Types.BOOL, "Whether this individual is currently pregnant" diff --git a/src/tlo/methods/diarrhoea.py b/src/tlo/methods/diarrhoea.py index 002c1d2046..1949ef3741 100644 --- a/src/tlo/methods/diarrhoea.py +++ b/src/tlo/methods/diarrhoea.py @@ -462,14 +462,14 @@ class Diarrhoea(Module, GenericFirstAppointmentsMixin): "The attributable pathogen for the current episode of diarrhoea " "(np.nan if the person does not currently have diarrhoea).", categories=list(pathogens), - default_category_value=np.nan, + default_property_value=np.nan, ), "gi_type": Property( Types.CATEGORICAL, "Type (watery or blood) of the current episode of diarrhoea " "(np.nan if the person does not currently have diarrhoea).", categories=["watery", "bloody"], - default_category_value=np.nan, + default_property_value=np.nan, ), "gi_dehydration": Property( Types.CATEGORICAL, @@ -480,7 +480,7 @@ class Diarrhoea(Module, GenericFirstAppointmentsMixin): "some", # <-- this level is not used currently. "severe", ], - default_category_value=np.nan, + default_property_value=np.nan, ), "gi_duration_longer_than_13days": Property( Types.BOOL, diff --git a/src/tlo/methods/epilepsy.py b/src/tlo/methods/epilepsy.py index a1650a3889..47c92ae85d 100644 --- a/src/tlo/methods/epilepsy.py +++ b/src/tlo/methods/epilepsy.py @@ -119,15 +119,19 @@ def __init__(self, name=None, resourcefilepath=None): # Properties of individuals 'owned' by this module PROPERTIES = { - 'ep_seiz_stat': Property( + "ep_seiz_stat": Property( Types.CATEGORICAL, - '(0 = never epilepsy, 1 = previous seizures none now, 2 = infrequent seizures, 3 = frequent seizures)', - categories=['0', '1', '2', '3'], + "(0 = never epilepsy, 1 = previous seizures none now, 2 = infrequent seizures, 3 = frequent seizures)", + categories=["0", "1", "2", "3"], + default_property_value="0", + ), + "ep_antiep": Property(Types.BOOL, "on antiepileptic"), + "ep_epi_death": Property(Types.BOOL, "epilepsy death this 3 month period"), + "ep_disability": Property( + Types.REAL, + "disability weight for current 3 month period", + default_property_value=0.0, ), - 'ep_antiep': Property(Types.BOOL, 'on antiepileptic'), - 'ep_epi_death': Property(Types.BOOL, 'epilepsy death this 3 month period'), - 'ep_unified_symptom_code': Property(Types.CATEGORICAL, '', categories=['0', '1', '2', '3']), - 'ep_disability': Property(Types.REAL, 'disability weight for current 3 month period'), } # Declaration of how we will refer to any treatments that are related to this disease. @@ -165,16 +169,12 @@ def initialise_population(self, population): responsible for assigning initial values, for every individual, of those properties 'owned' by this module, i.e. those declared in the PROPERTIES dictionary above. """ + super().initialise_population(population=population) df = population.props # a shortcut to the data-frame storing data for individuals p = self.parameters rng = self.rng - df.loc[df.is_alive, 'ep_seiz_stat'] = '0' - df.loc[df.is_alive, 'ep_antiep'] = False - df.loc[df.is_alive, 'ep_epi_death'] = False - df.loc[df.is_alive, 'ep_disability'] = 0 - # allocate initial ep_seiz_stat alive_idx = df.index[df.is_alive] df.loc[alive_idx, 'ep_seiz_stat'] = self.rng.choice(['0', '1', '2', '3'], size=len(alive_idx), From 97dade00a407003363ad63f345b66ebcaef502cf Mon Sep 17 00:00:00 2001 From: willGraham01 Date: Fri, 19 Jul 2024 09:28:40 +0100 Subject: [PATCH 16/38] Refactor heatlhburden, healthseekingbehaviour, hiv_tb_calibration init pop. All these modules pass-ed this method. Since there are no properties defined by these modules, this is what the inherited method will do without need to redefine it in the module again. --- src/tlo/methods/healthburden.py | 3 --- src/tlo/methods/healthseekingbehaviour.py | 5 ----- src/tlo/methods/hiv_tb_calibration.py | 3 --- 3 files changed, 11 deletions(-) diff --git a/src/tlo/methods/healthburden.py b/src/tlo/methods/healthburden.py index ba9a9de836..0882cd14a2 100644 --- a/src/tlo/methods/healthburden.py +++ b/src/tlo/methods/healthburden.py @@ -72,9 +72,6 @@ def read_parameters(self, data_folder): p['gbd_causes_of_disability'] = set(pd.read_csv( Path(self.resourcefilepath) / 'gbd' / 'ResourceFile_CausesOfDALYS_GBD2019.csv', header=None)[0].values) - def initialise_population(self, population): - pass - def initialise_simulation(self, sim): """Do before simulation starts: 1) Prepare data storage structures diff --git a/src/tlo/methods/healthseekingbehaviour.py b/src/tlo/methods/healthseekingbehaviour.py index 22e628d166..83c42e923d 100644 --- a/src/tlo/methods/healthseekingbehaviour.py +++ b/src/tlo/methods/healthseekingbehaviour.py @@ -135,11 +135,6 @@ def read_parameters(self, data_folder): # `self.force_any_symptom_to_lead_to_healthcareseeking` without any further checking). assert isinstance(self.parameters['force_any_symptom_to_lead_to_healthcareseeking'], bool) - def initialise_population(self, population): - """Nothing to initialise in the population - """ - pass - def initialise_simulation(self, sim): """ * define the linear models that govern healthcare seeking diff --git a/src/tlo/methods/hiv_tb_calibration.py b/src/tlo/methods/hiv_tb_calibration.py index bd09f54d96..41ac6397ed 100644 --- a/src/tlo/methods/hiv_tb_calibration.py +++ b/src/tlo/methods/hiv_tb_calibration.py @@ -47,9 +47,6 @@ def __init__(self, name=None, resourcefilepath=None): def read_parameters(self, data_folder): pass - def initialise_population(self, population): - pass - def initialise_simulation(self, sim): pass From 6658420f60839de0b40c8f09152b6a307553731e Mon Sep 17 00:00:00 2001 From: willGraham01 Date: Fri, 19 Jul 2024 09:33:29 +0100 Subject: [PATCH 17/38] Refactor hiv init pop method --- src/tlo/methods/hiv.py | 21 +++------------------ 1 file changed, 3 insertions(+), 18 deletions(-) diff --git a/src/tlo/methods/hiv.py b/src/tlo/methods/hiv.py index 1ddafe4c47..d140c17c7a 100644 --- a/src/tlo/methods/hiv.py +++ b/src/tlo/methods/hiv.py @@ -111,6 +111,7 @@ def __init__(self, name=None, resourcefilepath=None, run_with_checks=False): Types.CATEGORICAL, "ART status of person, whether on ART or not; and whether viral load is suppressed or not if on ART.", categories=["not", "on_VL_suppressed", "on_not_VL_suppressed"], + default_property_value="not", ), "hv_on_cotrimoxazole": Property( Types.BOOL, @@ -610,24 +611,8 @@ def pre_initialise_population(self): ) def initialise_population(self, population): - """Set our property values for the initial population.""" - - df = population.props - - # --- Current status - df.loc[df.is_alive, "hv_inf"] = False - df.loc[df.is_alive, "hv_art"] = "not" - df.loc[df.is_alive, "hv_is_on_prep"] = False - df.loc[df.is_alive, "hv_behaviour_change"] = False - df.loc[df.is_alive, "hv_diagnosed"] = False - df.loc[df.is_alive, "hv_number_tests"] = 0 - - # --- Dates on which things have happened - df.loc[df.is_alive, "hv_date_inf"] = pd.NaT - df.loc[df.is_alive, "hv_last_test_date"] = pd.NaT - df.loc[df.is_alive, "hv_date_treated"] = pd.NaT - df.loc[df.is_alive, "hv_date_last_ART"] = pd.NaT - + super().initialise_population(population=population) + # Launch sub-routines for allocating the right number of people into each category self.initialise_baseline_prevalence(population) # allocate baseline prevalence From 72c40b8b8f9d9c1700a9d94068d5123801562199 Mon Sep 17 00:00:00 2001 From: willGraham01 Date: Fri, 19 Jul 2024 09:55:34 +0100 Subject: [PATCH 18/38] Refactor labour init pop --- src/tlo/methods/labour.py | 164 +++++++++++++++++++++++--------------- 1 file changed, 99 insertions(+), 65 deletions(-) diff --git a/src/tlo/methods/labour.py b/src/tlo/methods/labour.py index 695dbeb501..7375c695e5 100644 --- a/src/tlo/methods/labour.py +++ b/src/tlo/methods/labour.py @@ -578,44 +578,102 @@ def __init__(self, name=None, resourcefilepath=None): } PROPERTIES = { - 'la_due_date_current_pregnancy': Property(Types.DATE, 'The date on which a newly pregnant woman is scheduled to' - ' go into labour'), - 'la_currently_in_labour': Property(Types.BOOL, 'whether this woman is currently in labour'), - 'la_intrapartum_still_birth': Property(Types.BOOL, 'whether this womans most recent pregnancy has ended ' - 'in a stillbirth'), - 'la_parity': Property(Types.REAL, 'total number of previous deliveries'), - 'la_previous_cs_delivery': Property(Types.INT, 'total number of previous deliveries'), - 'la_obstructed_labour': Property(Types.BOOL, 'Whether this woman is experiencing obstructed labour'), - 'la_placental_abruption': Property(Types.BOOL, 'whether the woman has experienced placental abruption'), - 'la_antepartum_haem': Property(Types.CATEGORICAL, 'whether the woman has experienced an antepartum haemorrhage' - ' in this delivery and it severity', - categories=['none', 'mild_moderate', 'severe']), - - 'la_uterine_rupture': Property(Types.BOOL, 'whether the woman has experienced uterine rupture in this ' - 'delivery'), - 'la_uterine_rupture_treatment': Property(Types.BOOL, 'whether this womans uterine rupture has been treated'), - 'la_sepsis': Property(Types.BOOL, 'whether this woman has developed sepsis due to an intrapartum infection'), - 'la_sepsis_pp': Property(Types.BOOL, 'whether this woman has developed sepsis due to a postpartum infection'), - 'la_sepsis_treatment': Property(Types.BOOL, 'If this woman has received treatment for maternal sepsis'), - 'la_eclampsia_treatment': Property(Types.BOOL, 'whether this womans eclampsia has been treated'), - 'la_severe_pre_eclampsia_treatment': Property(Types.BOOL, 'whether this woman has been treated for severe ' - 'pre-eclampsia'), - 'la_maternal_hypertension_treatment': Property(Types.BOOL, 'whether this woman has been treated for maternal ' - 'hypertension'), - 'la_gest_htn_on_treatment': Property(Types.BOOL, 'whether this woman has is receiving regular ' - 'antihypertensives'), - 'la_postpartum_haem': Property(Types.BOOL, 'whether the woman has experienced an postpartum haemorrhage in this' - 'delivery'), - 'la_postpartum_haem_treatment': Property(Types.BITSET, ' Treatment for received for postpartum haemorrhage ' - '(bitset)'), - 'la_has_had_hysterectomy': Property(Types.BOOL, 'whether this woman has had a hysterectomy as treatment for a ' - 'complication of labour, and therefore is unable to conceive'), - 'la_date_most_recent_delivery': Property(Types.DATE, 'date of on which this mother last delivered'), - 'la_is_postpartum': Property(Types.BOOL, 'Whether a woman is in the postpartum period, from delivery until ' - 'day +42 (6 weeks)'), - 'la_pn_checks_maternal': Property(Types.INT, 'Number of postnatal checks this woman has received'), - 'la_iron_folic_acid_postnatal': Property(Types.BOOL, 'Whether a woman is receiving iron and folic acid during ' - 'the postnatal period'), + "la_due_date_current_pregnancy": Property( + Types.DATE, + "The date on which a newly pregnant woman is scheduled to" + " go into labour", + ), + "la_currently_in_labour": Property( + Types.BOOL, "whether this woman is currently in labour" + ), + "la_intrapartum_still_birth": Property( + Types.BOOL, + "whether this womans most recent pregnancy has ended " "in a stillbirth", + ), + "la_parity": Property( + Types.REAL, + "total number of previous deliveries", + default_property_value=0.0, + ), + "la_previous_cs_delivery": Property( + Types.INT, "total number of previous deliveries" + ), + "la_obstructed_labour": Property( + Types.BOOL, "Whether this woman is experiencing obstructed labour" + ), + "la_placental_abruption": Property( + Types.BOOL, "whether the woman has experienced placental abruption" + ), + "la_antepartum_haem": Property( + Types.CATEGORICAL, + "whether the woman has experienced an antepartum haemorrhage" + " in this delivery and it severity", + categories=["none", "mild_moderate", "severe"], + default_property_value="none", + ), + "la_uterine_rupture": Property( + Types.BOOL, + "whether the woman has experienced uterine rupture in this " "delivery", + ), + "la_uterine_rupture_treatment": Property( + Types.BOOL, "whether this womans uterine rupture has been treated" + ), + "la_sepsis": Property( + Types.BOOL, + "whether this woman has developed sepsis due to an intrapartum infection", + ), + "la_sepsis_pp": Property( + Types.BOOL, + "whether this woman has developed sepsis due to a postpartum infection", + ), + "la_sepsis_treatment": Property( + Types.BOOL, "If this woman has received treatment for maternal sepsis" + ), + "la_eclampsia_treatment": Property( + Types.BOOL, "whether this womans eclampsia has been treated" + ), + "la_severe_pre_eclampsia_treatment": Property( + Types.BOOL, + "whether this woman has been treated for severe " "pre-eclampsia", + ), + "la_maternal_hypertension_treatment": Property( + Types.BOOL, + "whether this woman has been treated for maternal " "hypertension", + ), + "la_gest_htn_on_treatment": Property( + Types.BOOL, + "whether this woman has is receiving regular " "antihypertensives", + ), + "la_postpartum_haem": Property( + Types.BOOL, + "whether the woman has experienced an postpartum haemorrhage in this" + "delivery", + ), + "la_postpartum_haem_treatment": Property( + Types.BITSET, + " Treatment for received for postpartum haemorrhage " "(bitset)", + ), + "la_has_had_hysterectomy": Property( + Types.BOOL, + "whether this woman has had a hysterectomy as treatment for a " + "complication of labour, and therefore is unable to conceive", + ), + "la_date_most_recent_delivery": Property( + Types.DATE, "date of on which this mother last delivered" + ), + "la_is_postpartum": Property( + Types.BOOL, + "Whether a woman is in the postpartum period, from delivery until " + "day +42 (6 weeks)", + ), + "la_pn_checks_maternal": Property( + Types.INT, "Number of postnatal checks this woman has received" + ), + "la_iron_folic_acid_postnatal": Property( + Types.BOOL, + "Whether a woman is receiving iron and folic acid during " + "the postnatal period", + ), } def read_parameters(self, data_folder): @@ -625,37 +683,13 @@ def read_parameters(self, data_folder): self.load_parameters_from_dataframe(parameter_dataframe) def initialise_population(self, population): - df = population.props - # For the first period (2010-2015) we use the first value in each list as a parameter pregnancy_helper_functions.update_current_parameter_dictionary(self, list_position=0) - params = self.current_parameters + super().initialise_population(population=population) - df.loc[df.is_alive, 'la_currently_in_labour'] = False - df.loc[df.is_alive, 'la_intrapartum_still_birth'] = False - df.loc[df.is_alive, 'la_parity'] = 0 - df.loc[df.is_alive, 'la_previous_cs_delivery'] = 0 - df.loc[df.is_alive, 'la_due_date_current_pregnancy'] = pd.NaT - df.loc[df.is_alive, 'la_obstructed_labour'] = False - df.loc[df.is_alive, 'la_placental_abruption'] = False - df.loc[df.is_alive, 'la_antepartum_haem'] = 'none' - df.loc[df.is_alive, 'la_uterine_rupture'] = False - df.loc[df.is_alive, 'la_uterine_rupture_treatment'] = False - df.loc[df.is_alive, 'la_sepsis'] = False - df.loc[df.is_alive, 'la_sepsis_pp'] = False - df.loc[df.is_alive, 'la_sepsis_treatment'] = False - df.loc[df.is_alive, 'la_eclampsia_treatment'] = False - df.loc[df.is_alive, 'la_severe_pre_eclampsia_treatment'] = False - df.loc[df.is_alive, 'la_maternal_hypertension_treatment'] = False - df.loc[df.is_alive, 'la_gest_htn_on_treatment'] = False - df.loc[df.is_alive, 'la_postpartum_haem'] = False - df.loc[df.is_alive, 'la_postpartum_haem_treatment'] = 0 - df.loc[df.is_alive, 'la_has_had_hysterectomy'] = False - df.loc[df.is_alive, 'la_date_most_recent_delivery'] = pd.NaT - df.loc[df.is_alive, 'la_is_postpartum'] = False - df.loc[df.is_alive, 'la_pn_checks_maternal'] = 0 - df.loc[df.is_alive, 'la_iron_folic_acid_postnatal'] = False + df = population.props + params = self.current_parameters # we store different potential treatments for postpartum haemorrhage via bistet self.pph_treatment = BitsetHandler(self.sim.population, 'la_postpartum_haem_treatment', From eee15d2b3747e4f5428d9ac8c6df083b3fbd5671 Mon Sep 17 00:00:00 2001 From: willGraham01 Date: Fri, 19 Jul 2024 10:00:26 +0100 Subject: [PATCH 19/38] Refactor malaria init pop method --- src/tlo/methods/malaria.py | 75 +++++++++++++++----------------------- 1 file changed, 30 insertions(+), 45 deletions(-) diff --git a/src/tlo/methods/malaria.py b/src/tlo/methods/malaria.py index f322783717..667e105a29 100644 --- a/src/tlo/methods/malaria.py +++ b/src/tlo/methods/malaria.py @@ -205,40 +205,45 @@ def __init__(self, name=None, resourcefilepath=None): } PROPERTIES = { - 'ma_is_infected': Property( - Types.BOOL, 'Current status of malaria, infected with malaria parasitaemia' + "ma_is_infected": Property( + Types.BOOL, "Current status of malaria, infected with malaria parasitaemia" ), - 'ma_date_infected': Property(Types.DATE, 'Date of latest infection'), - 'ma_date_symptoms': Property( - Types.DATE, 'Date of symptom start for clinical infection' + "ma_date_infected": Property(Types.DATE, "Date of latest infection"), + "ma_date_symptoms": Property( + Types.DATE, "Date of symptom start for clinical infection" ), - 'ma_date_death': Property(Types.DATE, 'Date of death due to malaria'), - 'ma_tx': Property(Types.CATEGORICAL, 'Type of anti-malarial treatment person is currently using', - categories=['none', 'uncomplicated', 'complicated']), - 'ma_date_tx': Property( - Types.DATE, 'Date treatment started for most recent malaria episode' - ), - 'ma_inf_type': Property( + "ma_date_death": Property(Types.DATE, "Date of death due to malaria"), + "ma_tx": Property( Types.CATEGORICAL, - 'specific symptoms with malaria infection', - categories=['none', 'asym', 'clinical', 'severe'], + "Type of anti-malarial treatment person is currently using", + categories=["none", "uncomplicated", "complicated"], + default_property_value="none", + ), + "ma_date_tx": Property( + Types.DATE, "Date treatment started for most recent malaria episode" ), - 'ma_age_edited': Property( - Types.REAL, 'age values redefined to match with malaria data' + "ma_inf_type": Property( + Types.CATEGORICAL, + "specific symptoms with malaria infection", + categories=["none", "asym", "clinical", "severe"], + default_property_value="none", ), - 'ma_clinical_counter': Property( - Types.INT, 'annual counter for malaria clinical episodes' + "ma_age_edited": Property( + Types.REAL, + "age values redefined to match with malaria data", + default_property_value=0.0, ), - 'ma_dx_counter': Property( - Types.INT, 'annual counter for malaria diagnoses' + "ma_clinical_counter": Property( + Types.INT, "annual counter for malaria clinical episodes" ), - 'ma_tx_counter': Property( - Types.INT, 'annual counter for malaria treatment episodes' + "ma_dx_counter": Property(Types.INT, "annual counter for malaria diagnoses"), + "ma_tx_counter": Property( + Types.INT, "annual counter for malaria treatment episodes" ), - 'ma_clinical_preg_counter': Property( - Types.INT, 'annual counter for malaria clinical episodes in pregnant women' + "ma_clinical_preg_counter": Property( + Types.INT, "annual counter for malaria clinical episodes in pregnant women" ), - 'ma_iptp': Property(Types.BOOL, 'if woman has IPTp in current pregnancy'), + "ma_iptp": Property(Types.BOOL, "if woman has IPTp in current pregnancy"), } def read_parameters(self, data_folder): @@ -377,26 +382,6 @@ def pre_initialise_population(self): self.lm["rr_of_severe_malaria"] = LinearModel.multiplicative( *(predictors + conditional_predictors)) - def initialise_population(self, population): - df = population.props - - # ----------------------------------- INITIALISE THE POPULATION----------------------------------- - # Set default for properties - df.loc[df.is_alive, 'ma_is_infected'] = False - df.loc[df.is_alive, 'ma_date_infected'] = pd.NaT - df.loc[df.is_alive, 'ma_date_symptoms'] = pd.NaT - df.loc[df.is_alive, 'ma_date_death'] = pd.NaT - df.loc[df.is_alive, 'ma_tx'] = 'none' - df.loc[df.is_alive, 'ma_date_tx'] = pd.NaT - df.loc[df.is_alive, 'ma_inf_type'] = 'none' - df.loc[df.is_alive, 'ma_age_edited'] = 0.0 - - df.loc[df.is_alive, 'ma_clinical_counter'] = 0 - df.loc[df.is_alive, 'ma_dx_counter'] = 0 - df.loc[df.is_alive, 'ma_tx_counter'] = 0 - df.loc[df.is_alive, 'ma_clinical_preg_counter'] = 0 - df.loc[df.is_alive, 'ma_iptp'] = False - def malaria_poll2(self, population): df = population.props p = self.parameters From 2c11a2f324e4d9d518519fcb7e53de191999275c Mon Sep 17 00:00:00 2001 From: willGraham01 Date: Fri, 19 Jul 2024 10:04:14 +0100 Subject: [PATCH 20/38] Refactor measles init pop method --- src/tlo/methods/measles.py | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/src/tlo/methods/measles.py b/src/tlo/methods/measles.py index b6955ff9d7..1698527a56 100644 --- a/src/tlo/methods/measles.py +++ b/src/tlo/methods/measles.py @@ -142,16 +142,6 @@ def read_parameters(self, data_folder): def pre_initialise_population(self): self.process_parameters() - def initialise_population(self, population): - """Set our property values for the initial population. - set whole population to measles-free for 1st jan - """ - df = population.props - - df.loc[df.is_alive, "me_has_measles"] = False # default: no individuals infected - df.loc[df.is_alive, "me_date_measles"] = pd.NaT - df.loc[df.is_alive, "me_on_treatment"] = False - def initialise_simulation(self, sim): """Schedule measles event to start straight away. Each month it will assign new infections""" sim.schedule_event(MeaslesEvent(self), sim.date) From c3b69a1fbff742cb213fe2cb7e18720b45414e47 Mon Sep 17 00:00:00 2001 From: willGraham01 Date: Fri, 19 Jul 2024 10:05:28 +0100 Subject: [PATCH 21/38] Refactor Mockitis init pop method --- src/tlo/methods/mockitis.py | 40 ++++++++++++------------------------- 1 file changed, 13 insertions(+), 27 deletions(-) diff --git a/src/tlo/methods/mockitis.py b/src/tlo/methods/mockitis.py index 6af33c5fc7..7a2b834a55 100644 --- a/src/tlo/methods/mockitis.py +++ b/src/tlo/methods/mockitis.py @@ -71,17 +71,18 @@ class Mockitis(Module, GenericFirstAppointmentsMixin): } PROPERTIES = { - 'mi_is_infected': Property( - Types.BOOL, 'Current status of mockitis'), - 'mi_status': Property( - Types.CATEGORICAL, 'Historical status: N=never; C=currently; P=previously', - categories=['N', 'C', 'P']), - 'mi_date_infected': Property( - Types.DATE, 'Date of latest infection'), - 'mi_scheduled_date_death': Property( - Types.DATE, 'Date of scheduled death of infected individual'), - 'mi_date_cure': Property( - Types.DATE, 'Date an infected individual was cured') + "mi_is_infected": Property(Types.BOOL, "Current status of mockitis"), + "mi_status": Property( + Types.CATEGORICAL, + "Historical status: N=never; C=currently; P=previously", + categories=["N", "C", "P"], + default_property_value="N", + ), + "mi_date_infected": Property(Types.DATE, "Date of latest infection"), + "mi_scheduled_date_death": Property( + Types.DATE, "Date of scheduled death of infected individual" + ), + "mi_date_cure": Property(Types.DATE, "Date an infected individual was cured"), } def __init__(self, name=None, resourcefilepath=None): @@ -125,24 +126,9 @@ def read_parameters(self, data_folder): ) def initialise_population(self, population): - """Set our property values for the initial population. - - This method is called by the simulation when creating the initial population, and is - responsible for assigning initial values, for every individual, of those properties - 'owned' by this module, i.e. those declared in the PROPERTIES dictionary above. - - :param population: the population of individuals - """ + super().initialise_population(population=population) df = population.props # a shortcut to the dataframe storing data for individiuals - - # Set default for properties - df.loc[df.is_alive, 'mi_is_infected'] = False # default: no individuals infected - df.loc[df.is_alive, 'mi_status'] = 'N' # default: never infected - df.loc[df.is_alive, 'mi_date_infected'] = pd.NaT # default: not a time - df.loc[df.is_alive, 'mi_scheduled_date_death'] = pd.NaT # default: not a time - df.loc[df.is_alive, 'mi_date_cure'] = pd.NaT # default: not a time - alive_count = df.is_alive.sum() # randomly selected some individuals as infected From eb5a854e615893a6c88b56f80c196dc4075fa685 Mon Sep 17 00:00:00 2001 From: willGraham01 Date: Fri, 19 Jul 2024 10:11:16 +0100 Subject: [PATCH 22/38] Refactor newborn outcomes init pop method --- src/tlo/methods/newborn_outcomes.py | 226 ++++++++++++++++++---------- 1 file changed, 147 insertions(+), 79 deletions(-) diff --git a/src/tlo/methods/newborn_outcomes.py b/src/tlo/methods/newborn_outcomes.py index 433b21ca88..a8bb042f27 100644 --- a/src/tlo/methods/newborn_outcomes.py +++ b/src/tlo/methods/newborn_outcomes.py @@ -256,57 +256,147 @@ def __init__(self, name=None, resourcefilepath=None): } PROPERTIES = { - 'nb_is_twin': Property(Types.BOOL, 'whether this is part of a twin pair'), - 'nb_twin_sibling_id': Property(Types.INT, 'id number of this twins sibling'), - 'nb_early_preterm': Property(Types.BOOL, 'whether this neonate has been born early preterm (24-33 weeks ' - 'gestation)'), - 'nb_late_preterm': Property(Types.BOOL, 'whether this neonate has been born late preterm (34-36 weeks ' - 'gestation)'), - 'nb_preterm_birth_disab': Property(Types.CATEGORICAL, 'Disability associated with preterm delivery', - categories=['none', 'mild_motor_and_cog', 'mild_motor', 'moderate_motor', - 'severe_motor']), - 'nb_congenital_anomaly': Property(Types.BITSET, 'Types of congenital anomaly of the newborn stored as bitset'), - 'nb_early_onset_neonatal_sepsis': Property(Types.BOOL, 'whether this neonate has developed neonatal sepsis' - ' following birth'), - 'nb_inj_abx_neonatal_sepsis': Property(Types.BOOL, 'If this neonate has injectable antibiotics as treatment ' - 'for neonatal sepsis'), - 'nb_supp_care_neonatal_sepsis': Property(Types.BOOL, 'If this neonate has received full supportive care for ' - 'neonatal sepsis (in hospital)'), - 'nb_neonatal_sepsis_disab': Property(Types.CATEGORICAL, 'Disability associated neonatal sepsis', - categories=['none', 'mild_motor_and_cog', 'mild_motor', - 'moderate_motor', 'severe_motor']), - 'nb_preterm_respiratory_distress': Property(Types.BOOL, 'whether this preterm newborn has respiratory ' - 'distress syndrome (RDS)'), - 'nb_not_breathing_at_birth': Property(Types.BOOL, 'whether this neonate has failed to transition to breathing ' - 'on their own following birth'), - 'nb_received_neonatal_resus': Property(Types.BOOL, 'If this neonate has received resuscitation'), - 'nb_encephalopathy': Property(Types.CATEGORICAL, 'None, mild encephalopathy, moderate encephalopathy, ' - 'severe encephalopathy', - categories=['none', 'mild_enceph', 'moderate_enceph', 'severe_enceph']), - 'nb_encephalopathy_disab': Property(Types.CATEGORICAL, 'Disability associated neonatal sepsis', - categories=['none', 'mild_motor_and_cog', 'mild_motor', - 'moderate_motor', 'severe_motor']), - 'nb_retinopathy_prem': Property(Types.CATEGORICAL, 'Level of visual disturbance due to retinopathy of' - ' prematurity: None, mild, moderate, severe, blindness', - categories=['none', 'mild', 'moderate', 'severe', 'blindness']), - 'nb_low_birth_weight_status': Property(Types.CATEGORICAL, 'extremely low birth weight (<1000g), ' - ' very low birth weight (<1500g), ' - 'low birth weight (<2500g),' - 'normal birth weight (>2500g), macrosomia (>4000g)', - categories=['extremely_low_birth_weight', 'very_low_birth_weight', - 'low_birth_weight', 'normal_birth_weight', 'macrosomia']), - 'nb_size_for_gestational_age': Property(Types.CATEGORICAL, 'size for gestational age categories', - categories=['small_for_gestational_age', 'average_for_gestational_age', - 'large_for_gestational_age']), - 'nb_early_init_breastfeeding': Property(Types.BOOL, 'whether this neonate initiated breastfeeding ' - 'within 1 hour of birth '), - 'nb_breastfeeding_status': Property(Types.CATEGORICAL, 'How this neonate is being breastfed', - categories=['none', 'non_exclusive', 'exclusive']), - 'nb_kangaroo_mother_care': Property(Types.BOOL, 'whether this neonate received kangaroo mother care following ' - 'birth'), - 'nb_clean_birth': Property(Types.BOOL, 'whether this neonate received clean birth practices at delivery'), - 'nb_death_after_birth': Property(Types.BOOL, 'whether this child has died following complications after birth'), - 'nb_pnc_check': Property(Types.INT, 'Number of postnatal checks received in the postnatal period'), + "nb_is_twin": Property(Types.BOOL, "whether this is part of a twin pair"), + "nb_twin_sibling_id": Property(Types.INT, "id number of this twins sibling"), + "nb_early_preterm": Property( + Types.BOOL, + "whether this neonate has been born early preterm (24-33 weeks " + "gestation)", + ), + "nb_late_preterm": Property( + Types.BOOL, + "whether this neonate has been born late preterm (34-36 weeks " + "gestation)", + ), + "nb_preterm_birth_disab": Property( + Types.CATEGORICAL, + "Disability associated with preterm delivery", + categories=[ + "none", + "mild_motor_and_cog", + "mild_motor", + "moderate_motor", + "severe_motor", + ], + default_property_value="none", + ), + "nb_congenital_anomaly": Property( + Types.BITSET, "Types of congenital anomaly of the newborn stored as bitset" + ), + "nb_early_onset_neonatal_sepsis": Property( + Types.BOOL, + "whether this neonate has developed neonatal sepsis" " following birth", + ), + "nb_inj_abx_neonatal_sepsis": Property( + Types.BOOL, + "If this neonate has injectable antibiotics as treatment " + "for neonatal sepsis", + ), + "nb_supp_care_neonatal_sepsis": Property( + Types.BOOL, + "If this neonate has received full supportive care for " + "neonatal sepsis (in hospital)", + ), + "nb_neonatal_sepsis_disab": Property( + Types.CATEGORICAL, + "Disability associated neonatal sepsis", + categories=[ + "none", + "mild_motor_and_cog", + "mild_motor", + "moderate_motor", + "severe_motor", + ], + default_property_value="none", + ), + "nb_preterm_respiratory_distress": Property( + Types.BOOL, + "whether this preterm newborn has respiratory " "distress syndrome (RDS)", + ), + "nb_not_breathing_at_birth": Property( + Types.BOOL, + "whether this neonate has failed to transition to breathing " + "on their own following birth", + ), + "nb_received_neonatal_resus": Property( + Types.BOOL, "If this neonate has received resuscitation" + ), + "nb_encephalopathy": Property( + Types.CATEGORICAL, + "None, mild encephalopathy, moderate encephalopathy, " + "severe encephalopathy", + categories=["none", "mild_enceph", "moderate_enceph", "severe_enceph"], + default_property_value="none", + ), + "nb_encephalopathy_disab": Property( + Types.CATEGORICAL, + "Disability associated neonatal sepsis", + categories=[ + "none", + "mild_motor_and_cog", + "mild_motor", + "moderate_motor", + "severe_motor", + ], + default_property_value="none", + ), + "nb_retinopathy_prem": Property( + Types.CATEGORICAL, + "Level of visual disturbance due to retinopathy of" + " prematurity: None, mild, moderate, severe, blindness", + categories=["none", "mild", "moderate", "severe", "blindness"], + default_property_value="none", + ), + "nb_low_birth_weight_status": Property( + Types.CATEGORICAL, + "extremely low birth weight (<1000g), " + " very low birth weight (<1500g), " + "low birth weight (<2500g)," + "normal birth weight (>2500g), macrosomia (>4000g)", + categories=[ + "extremely_low_birth_weight", + "very_low_birth_weight", + "low_birth_weight", + "normal_birth_weight", + "macrosomia", + ], + default_property_value="normal_birth_weight", + ), + "nb_size_for_gestational_age": Property( + Types.CATEGORICAL, + "size for gestational age categories", + categories=[ + "small_for_gestational_age", + "average_for_gestational_age", + "large_for_gestational_age", + ], + default_property_value="average_for_gestational_age", + ), + "nb_early_init_breastfeeding": Property( + Types.BOOL, + "whether this neonate initiated breastfeeding " "within 1 hour of birth ", + ), + "nb_breastfeeding_status": Property( + Types.CATEGORICAL, + "How this neonate is being breastfed", + categories=["none", "non_exclusive", "exclusive"], + default_property_value="none", + ), + "nb_kangaroo_mother_care": Property( + Types.BOOL, + "whether this neonate received kangaroo mother care following " "birth", + ), + "nb_clean_birth": Property( + Types.BOOL, + "whether this neonate received clean birth practices at delivery", + ), + "nb_death_after_birth": Property( + Types.BOOL, + "whether this child has died following complications after birth", + ), + "nb_pnc_check": Property( + Types.INT, "Number of postnatal checks received in the postnatal period" + ), } def read_parameters(self, data_folder): @@ -341,36 +431,14 @@ def read_parameters(self, data_folder): 'mild_motor_cognitive_sepsis': self.sim.modules['HealthBurden'].get_daly_weight(441)} def initialise_population(self, population): - df = population.props - - df.loc[df.is_alive, 'nb_is_twin'] = False - df.loc[df.is_alive, 'nb_twin_sibling_id'] = -1 - df.loc[df.is_alive, 'nb_early_preterm'] = False - df.loc[df.is_alive, 'nb_late_preterm'] = False - df.loc[df.is_alive, 'nb_preterm_birth_disab'] = 'none' - df.loc[df.is_alive, 'nb_congenital_anomaly'] = 0 - df.loc[df.is_alive, 'nb_early_onset_neonatal_sepsis'] = False - df.loc[df.is_alive, 'nb_inj_abx_neonatal_sepsis'] = False - df.loc[df.is_alive, 'nb_supp_care_neonatal_sepsis'] = False - df.loc[df.is_alive, 'nb_neonatal_sepsis_disab'] = 'none' - df.loc[df.is_alive, 'nb_preterm_respiratory_distress'] = False - df.loc[df.is_alive, 'nb_not_breathing_at_birth'] = False - df.loc[df.is_alive, 'nb_received_neonatal_resus'] = False - df.loc[df.is_alive, 'nb_encephalopathy'] = 'none' - df.loc[df.is_alive, 'nb_encephalopathy_disab'] = 'none' - df.loc[df.is_alive, 'nb_retinopathy_prem'] = 'none' - df.loc[df.is_alive, 'nb_low_birth_weight_status'] = 'normal_birth_weight' - df.loc[df.is_alive, 'nb_size_for_gestational_age'] = 'average_for_gestational_age' - df.loc[df.is_alive, 'nb_early_init_breastfeeding'] = False - df.loc[df.is_alive, 'nb_breastfeeding_status'] = 'none' - df.loc[df.is_alive, 'nb_kangaroo_mother_care'] = False - df.loc[df.is_alive, 'nb_clean_birth'] = False - df.loc[df.is_alive, 'nb_death_after_birth'] = False - df.loc[df.is_alive, 'nb_pnc_check'] = 0 + super().initialise_population(population=population) # We store congenital anomalies as bitset - self.congeintal_anomalies = BitsetHandler(self.sim.population, 'nb_congenital_anomaly', - ['heart', 'limb_musc_skeletal', 'urogenital', 'digestive', 'other']) + self.congeintal_anomalies = BitsetHandler( + population, + "nb_congenital_anomaly", + ["heart", "limb_musc_skeletal", "urogenital", "digestive", "other"], + ) def get_and_store_newborn_item_codes(self): """ From aeed2aa41b7357b85b40a1abd21612467ebfb33b Mon Sep 17 00:00:00 2001 From: willGraham01 Date: Fri, 19 Jul 2024 10:13:54 +0100 Subject: [PATCH 23/38] Refactor oesophageal cancer init pop method --- src/tlo/methods/oesophagealcancer.py | 44 ++++++++++++++++------------ 1 file changed, 26 insertions(+), 18 deletions(-) diff --git a/src/tlo/methods/oesophagealcancer.py b/src/tlo/methods/oesophagealcancer.py index 1961aa340e..ebe38d2655 100644 --- a/src/tlo/methods/oesophagealcancer.py +++ b/src/tlo/methods/oesophagealcancer.py @@ -187,29 +187,43 @@ def __init__(self, name=None, resourcefilepath=None): "oc_status": Property( Types.CATEGORICAL, "Current status of the health condition, oesophageal dysplasia", - categories=["none", "low_grade_dysplasia", "high_grade_dysplasia", "stage1", "stage2", "stage3", "stage4"], + categories=[ + "none", + "low_grade_dysplasia", + "high_grade_dysplasia", + "stage1", + "stage2", + "stage3", + "stage4", + ], + default_property_value="none", ), - "oc_date_diagnosis": Property( Types.DATE, - "the date of diagnsosis of the oes_cancer (pd.NaT if never diagnosed)" + "the date of diagnsosis of the oes_cancer (pd.NaT if never diagnosed)", ), - "oc_date_treatment": Property( Types.DATE, - "date of first receiving attempted curative treatment (pd.NaT if never started treatment)" + "date of first receiving attempted curative treatment (pd.NaT if never started treatment)", ), - "oc_stage_at_which_treatment_applied": Property( Types.CATEGORICAL, "the cancer stage at which treatment is applied (because the treatment only has an effect during the stage" "at which it is applied.", - categories=["none", "low_grade_dysplasia", "high_grade_dysplasia", "stage1", "stage2", "stage3", "stage4"], + categories=[ + "none", + "low_grade_dysplasia", + "high_grade_dysplasia", + "stage1", + "stage2", + "stage3", + "stage4", + ], + default_property_value="none", ), - "oc_date_palliative_care": Property( Types.DATE, - "date of first receiving palliative care (pd.NaT is never had palliative care)" + "date of first receiving palliative care (pd.NaT is never had palliative care)", ), } @@ -228,16 +242,10 @@ def read_parameters(self, data_folder): ) def initialise_population(self, population): - """Set property values for the initial population.""" - df = population.props # a shortcut to the data-frame - p = self.parameters + super().initialise_population(population=population) - # defaults - df.loc[df.is_alive, "oc_status"] = "none" - df.loc[df.is_alive, "oc_date_diagnosis"] = pd.NaT - df.loc[df.is_alive, "oc_date_treatment"] = pd.NaT - df.loc[df.is_alive, "oc_stage_at_which_treatment_applied"] = "none" - df.loc[df.is_alive, "oc_date_palliative_care"] = pd.NaT + df = population.props + p = self.parameters # -------------------- oc_status ----------- # Determine who has cancer at ANY cancer stage: From ca7a9a37de24b0bc98dc9c706e31a68811f51b62 Mon Sep 17 00:00:00 2001 From: willGraham01 Date: Fri, 19 Jul 2024 10:15:49 +0100 Subject: [PATCH 24/38] Refactor other adult cancers init pop method --- src/tlo/methods/other_adult_cancers.py | 29 ++++++++------------------ 1 file changed, 9 insertions(+), 20 deletions(-) diff --git a/src/tlo/methods/other_adult_cancers.py b/src/tlo/methods/other_adult_cancers.py index 5999792393..0052b4e0b8 100644 --- a/src/tlo/methods/other_adult_cancers.py +++ b/src/tlo/methods/other_adult_cancers.py @@ -184,32 +184,28 @@ def __init__(self, name=None, resourcefilepath=None): Types.CATEGORICAL, "Current status of the health condition, other_adult cancer", categories=["none", "site_confined", "local_ln", "metastatic"], + default_property_value="none", ), - "oac_date_diagnosis": Property( Types.DATE, - "the date of diagnosis of the other_adult_cancer (pd.NaT if never diagnosed)" + "the date of diagnosis of the other_adult_cancer (pd.NaT if never diagnosed)", ), - "oac_date_treatment": Property( Types.DATE, - "date of first receiving attempted curative treatment (pd.NaT if never started treatment)" + "date of first receiving attempted curative treatment (pd.NaT if never started treatment)", ), - "oac_stage_at_which_treatment_given": Property( Types.CATEGORICAL, "the cancer stage at which treatment is given (because the treatment only has an effect during the stage" "at which it is given.", categories=["none", "site_confined", "local_ln", "metastatic"], + default_property_value="none", ), "oac_date_palliative_care": Property( Types.DATE, - "date of first receiving palliative care (pd.NaT is never had palliative care)" + "date of first receiving palliative care (pd.NaT is never had palliative care)", ), - "oac_date_death": Property( - Types.DATE, - "date of oac death" - ) + "oac_date_death": Property(Types.DATE, "date of oac death"), } def read_parameters(self, data_folder): @@ -229,18 +225,11 @@ def read_parameters(self, data_folder): ) def initialise_population(self, population): - """Set property values for the initial population.""" - df = population.props # a shortcut to the data-frame + super().initialise_population(population=population) + + df = population.props p = self.parameters - # defaults - df.loc[df.is_alive, "oac_status"] = "none" - df.loc[df.is_alive, "oac_date_diagnosis"] = pd.NaT - df.loc[df.is_alive, "oac_date_treatment"] = pd.NaT - df.loc[df.is_alive, "oac_stage_at_which_treatment_given"] = "none" - df.loc[df.is_alive, "oac_date_palliative_care"] = pd.NaT - df.loc[df.is_alive, "oac_date_death"] = pd.NaT - # -------------------- oac_status ----------- # Determine who has cancer at ANY cancer stage: # check parameters are sensible: probability of having any cancer stage cannot exceed 1.0 From 700fd81fb4bb4131de8b098f8ff700c089a92d61 Mon Sep 17 00:00:00 2001 From: willGraham01 Date: Fri, 19 Jul 2024 10:22:19 +0100 Subject: [PATCH 25/38] REfactor postnatal supervisor init pop method --- src/tlo/methods/postnatal_supervisor.py | 85 +++++++++++++++---------- 1 file changed, 52 insertions(+), 33 deletions(-) diff --git a/src/tlo/methods/postnatal_supervisor.py b/src/tlo/methods/postnatal_supervisor.py index 25bce6013f..f7bbd5e58a 100644 --- a/src/tlo/methods/postnatal_supervisor.py +++ b/src/tlo/methods/postnatal_supervisor.py @@ -208,25 +208,58 @@ def __init__(self, name=None, resourcefilepath=None): } PROPERTIES = { - 'pn_postnatal_period_in_weeks': Property(Types.REAL, 'The number of weeks a woman is in the postnatal period ' - '(1-6)'), - 'pn_htn_disorders': Property(Types.CATEGORICAL, 'Hypertensive disorders of the postnatal period', - categories=['none', 'resolved', 'gest_htn', 'severe_gest_htn', 'mild_pre_eclamp', - 'severe_pre_eclamp', 'eclampsia']), - 'pn_postpartum_haem_secondary': Property(Types.BOOL, 'Whether this woman is experiencing a secondary ' - 'postpartum haemorrhage'), - 'pn_sepsis_late_postpartum': Property(Types.BOOL, 'Whether this woman is experiencing postnatal (day7+) ' - 'sepsis'), - 'pn_obstetric_fistula': Property(Types.CATEGORICAL, 'Type of fistula developed after birth', - categories=['none', 'vesicovaginal', 'rectovaginal']), - 'pn_sepsis_early_neonatal': Property(Types.BOOL, 'Whether this neonate has developed early onset neonatal' - ' sepsis during week one of life'), - 'pn_sepsis_late_neonatal': Property(Types.BOOL, 'Whether this neonate has developed late neonatal sepsis ' - 'following discharge'), - 'pn_anaemia_following_pregnancy': Property(Types.CATEGORICAL, 'severity of anaemia following pregnancy', - categories=['none', 'mild', 'moderate', 'severe']), - 'pn_emergency_event_mother': Property(Types.BOOL, 'Whether a mother is experiencing an emergency complication' - ' postnatally'), + "pn_postnatal_period_in_weeks": Property( + Types.REAL, + "The number of weeks a woman is in the postnatal period " "(1-6)", + default_property_value=0.0, + ), + "pn_htn_disorders": Property( + Types.CATEGORICAL, + "Hypertensive disorders of the postnatal period", + categories=[ + "none", + "resolved", + "gest_htn", + "severe_gest_htn", + "mild_pre_eclamp", + "severe_pre_eclamp", + "eclampsia", + ], + default_property_value="none", + ), + "pn_postpartum_haem_secondary": Property( + Types.BOOL, + "Whether this woman is experiencing a secondary " "postpartum haemorrhage", + ), + "pn_sepsis_late_postpartum": Property( + Types.BOOL, "Whether this woman is experiencing postnatal (day7+) " "sepsis" + ), + "pn_obstetric_fistula": Property( + Types.CATEGORICAL, + "Type of fistula developed after birth", + categories=["none", "vesicovaginal", "rectovaginal"], + default_property_value="none", + ), + "pn_sepsis_early_neonatal": Property( + Types.BOOL, + "Whether this neonate has developed early onset neonatal" + " sepsis during week one of life", + ), + "pn_sepsis_late_neonatal": Property( + Types.BOOL, + "Whether this neonate has developed late neonatal sepsis " + "following discharge", + ), + "pn_anaemia_following_pregnancy": Property( + Types.CATEGORICAL, + "severity of anaemia following pregnancy", + categories=["none", "mild", "moderate", "severe"], + default_property_value="none", + ), + "pn_emergency_event_mother": Property( + Types.BOOL, + "Whether a mother is experiencing an emergency complication" " postnatally", + ), } def read_parameters(self, data_folder): @@ -234,20 +267,6 @@ def read_parameters(self, data_folder): sheet_name='parameter_values') self.load_parameters_from_dataframe(parameter_dataframe) - def initialise_population(self, population): - df = population.props - - df.loc[df.is_alive, 'pn_postnatal_period_in_weeks'] = 0 - df.loc[df.is_alive, 'pn_htn_disorders'] = 'none' - df.loc[df.is_alive, 'pn_postpartum_haem_secondary'] = False - df.loc[df.is_alive, 'pn_sepsis_late_postpartum'] = False - df.loc[df.is_alive, 'pn_sepsis_early_neonatal'] = False - df.loc[df.is_alive, 'pn_sepsis_late_neonatal'] = False - df.loc[df.is_alive, 'pn_sepsis_late_neonatal'] = False - df.loc[df.is_alive, 'pn_anaemia_following_pregnancy'] = 'none' - df.loc[df.is_alive, 'pn_obstetric_fistula'] = 'none' - df.loc[df.is_alive, 'pn_emergency_event_mother'] = False - def initialise_simulation(self, sim): # For the first period (2010-2015) we use the first value in each list as a parameter pregnancy_helper_functions.update_current_parameter_dictionary(self, list_position=0) From 5aff268a9c2d334b67a5909ba777d156bd87f357 Mon Sep 17 00:00:00 2001 From: willGraham01 Date: Fri, 19 Jul 2024 10:30:24 +0100 Subject: [PATCH 26/38] Refactor pregnancy supervisor init pop method --- src/tlo/methods/pregnancy_supervisor.py | 168 +++++++++++++++--------- 1 file changed, 104 insertions(+), 64 deletions(-) diff --git a/src/tlo/methods/pregnancy_supervisor.py b/src/tlo/methods/pregnancy_supervisor.py index 7dd8819ab6..953dfb5138 100644 --- a/src/tlo/methods/pregnancy_supervisor.py +++ b/src/tlo/methods/pregnancy_supervisor.py @@ -388,48 +388,108 @@ def __init__(self, name=None, resourcefilepath=None): } PROPERTIES = { - 'ps_gestational_age_in_weeks': Property(Types.REAL, 'current gestational age, in weeks, of a woman ' - 'pregnancy'), - 'ps_date_of_anc1': Property(Types.DATE, 'Date first ANC visit is scheduled for'), - 'ps_ectopic_pregnancy': Property(Types.CATEGORICAL, 'Whether a woman is experiencing ectopic pregnancy and' - ' its current state', - categories=['none', 'not_ruptured', 'ruptured']), - 'ps_multiple_pregnancy': Property(Types.BOOL, 'Whether a woman is pregnant with multiple fetuses'), - 'ps_placenta_praevia': Property(Types.BOOL, 'Whether a woman pregnancy will be complicated by placenta' - 'praevia'), - 'ps_syphilis': Property(Types.BOOL, 'Whether a woman has syphilis during pregnancy'), - 'ps_anaemia_in_pregnancy': Property(Types.CATEGORICAL, 'Whether a woman has anaemia in pregnancy and its ' - 'severity', - categories=['none', 'mild', 'moderate', 'severe']), - - 'ps_anc4': Property(Types.BOOL, 'Whether this woman is predicted to attend 4 or more antenatal care visits ' - 'during her pregnancy'), - 'ps_abortion_complications': Property(Types.BITSET, 'Bitset column holding types of abortion complication'), - 'ps_prev_spont_abortion': Property(Types.BOOL, 'Whether this woman has had any previous pregnancies end in ' - 'spontaneous abortion'), - 'ps_prev_stillbirth': Property(Types.BOOL, 'Whether this woman has had any previous pregnancies end in ' - 'still birth'), - 'ps_htn_disorders': Property(Types.CATEGORICAL, 'if this woman suffers from a hypertensive disorder of ' - 'pregnancy', - categories=['none', 'gest_htn', 'severe_gest_htn', 'mild_pre_eclamp', - 'severe_pre_eclamp', 'eclampsia']), - 'ps_prev_pre_eclamp': Property(Types.BOOL, 'whether this woman has experienced pre-eclampsia in a previous ' - 'pregnancy'), - 'ps_gest_diab': Property(Types.CATEGORICAL, 'whether this woman is experiencing gestational diabetes', - categories=['none', 'uncontrolled', 'controlled']), - 'ps_prev_gest_diab': Property(Types.BOOL, 'whether this woman has ever suffered from gestational diabetes ' - 'during a previous pregnancy'), - 'ps_placental_abruption': Property(Types.BOOL, 'Whether this woman is experiencing placental abruption'), - 'ps_antepartum_haemorrhage': Property(Types.CATEGORICAL, 'severity of this womans antepartum haemorrhage', - categories=['none', 'mild_moderate', 'severe']), - 'ps_premature_rupture_of_membranes': Property(Types.BOOL, 'whether this woman has experience rupture of ' - 'membranes before the onset of labour. If this is ' - '<37 weeks from gestation the woman has preterm ' - 'premature rupture of membranes'), - 'ps_chorioamnionitis': Property(Types.BOOL, 'Whether a woman is experiencing chorioamnionitis'), - 'ps_emergency_event': Property(Types.BOOL, 'signifies a woman in undergoing an acute emergency event in her ' - 'pregnancy- used to consolidated care seeking in the instance of ' - 'multiple complications') + "ps_gestational_age_in_weeks": Property( + Types.REAL, + "current gestational age, in weeks, of a woman " "pregnancy", + default_property_value=0.0, + ), + "ps_date_of_anc1": Property( + Types.DATE, "Date first ANC visit is scheduled for" + ), + "ps_ectopic_pregnancy": Property( + Types.CATEGORICAL, + "Whether a woman is experiencing ectopic pregnancy and" + " its current state", + categories=["none", "not_ruptured", "ruptured"], + default_property_value="none", + ), + "ps_multiple_pregnancy": Property( + Types.BOOL, "Whether a woman is pregnant with multiple fetuses" + ), + "ps_placenta_praevia": Property( + Types.BOOL, + "Whether a woman pregnancy will be complicated by placenta" "praevia", + ), + "ps_syphilis": Property( + Types.BOOL, "Whether a woman has syphilis during pregnancy" + ), + "ps_anaemia_in_pregnancy": Property( + Types.CATEGORICAL, + "Whether a woman has anaemia in pregnancy and its " "severity", + categories=["none", "mild", "moderate", "severe"], + default_property_value="none", + ), + "ps_anc4": Property( + Types.BOOL, + "Whether this woman is predicted to attend 4 or more antenatal care visits " + "during her pregnancy", + ), + "ps_abortion_complications": Property( + Types.BITSET, "Bitset column holding types of abortion complication" + ), + "ps_prev_spont_abortion": Property( + Types.BOOL, + "Whether this woman has had any previous pregnancies end in " + "spontaneous abortion", + ), + "ps_prev_stillbirth": Property( + Types.BOOL, + "Whether this woman has had any previous pregnancies end in " "still birth", + ), + "ps_htn_disorders": Property( + Types.CATEGORICAL, + "if this woman suffers from a hypertensive disorder of " "pregnancy", + categories=[ + "none", + "gest_htn", + "severe_gest_htn", + "mild_pre_eclamp", + "severe_pre_eclamp", + "eclampsia", + ], + default_property_value="none", + ), + "ps_prev_pre_eclamp": Property( + Types.BOOL, + "whether this woman has experienced pre-eclampsia in a previous " + "pregnancy", + ), + "ps_gest_diab": Property( + Types.CATEGORICAL, + "whether this woman is experiencing gestational diabetes", + categories=["none", "uncontrolled", "controlled"], + default_property_value="none", + ), + "ps_prev_gest_diab": Property( + Types.BOOL, + "whether this woman has ever suffered from gestational diabetes " + "during a previous pregnancy", + ), + "ps_placental_abruption": Property( + Types.BOOL, "Whether this woman is experiencing placental abruption" + ), + "ps_antepartum_haemorrhage": Property( + Types.CATEGORICAL, + "severity of this womans antepartum haemorrhage", + categories=["none", "mild_moderate", "severe"], + default_property_value="none", + ), + "ps_premature_rupture_of_membranes": Property( + Types.BOOL, + "whether this woman has experience rupture of " + "membranes before the onset of labour. If this is " + "<37 weeks from gestation the woman has preterm " + "premature rupture of membranes", + ), + "ps_chorioamnionitis": Property( + Types.BOOL, "Whether a woman is experiencing chorioamnionitis" + ), + "ps_emergency_event": Property( + Types.BOOL, + "signifies a woman in undergoing an acute emergency event in her " + "pregnancy- used to consolidated care seeking in the instance of " + "multiple complications", + ), } def read_parameters(self, data_folder): @@ -470,29 +530,9 @@ def read_parameters(self, data_folder): } def initialise_population(self, population): - df = population.props - - df.loc[df.is_alive, 'ps_gestational_age_in_weeks'] = 0 - df.loc[df.is_alive, 'ps_date_of_anc1'] = pd.NaT - df.loc[df.is_alive, 'ps_ectopic_pregnancy'] = 'none' - df.loc[df.is_alive, 'ps_placenta_praevia'] = False - df.loc[df.is_alive, 'ps_multiple_pregnancy'] = False - df.loc[df.is_alive, 'ps_syphilis'] = False - df.loc[df.is_alive, 'ps_anaemia_in_pregnancy'] = 'none' - df.loc[df.is_alive, 'ps_anc4'] = False - df.loc[df.is_alive, 'ps_abortion_complications'] = 0 - df.loc[df.is_alive, 'ps_prev_spont_abortion'] = False - df.loc[df.is_alive, 'ps_prev_stillbirth'] = False - df.loc[df.is_alive, 'ps_htn_disorders'] = 'none' - df.loc[df.is_alive, 'ps_prev_pre_eclamp'] = False - df.loc[df.is_alive, 'ps_gest_diab'] = 'none' - df.loc[df.is_alive, 'ps_prev_gest_diab'] = False - df.loc[df.is_alive, 'ps_placental_abruption'] = False - df.loc[df.is_alive, 'ps_antepartum_haemorrhage'] = 'none' - df.loc[df.is_alive, 'ps_premature_rupture_of_membranes'] = False - df.loc[df.is_alive, 'ps_chorioamnionitis'] = False - df.loc[df.is_alive, 'ps_emergency_event'] = False + super().initialise_population(population=population) + df = population.props # This bitset property stores 'types' of complication that can occur after an abortion self.abortion_complications = BitsetHandler(self.sim.population, 'ps_abortion_complications', ['sepsis', 'haemorrhage', 'injury', 'other']) From 724210ca91a9026147d326df476f74420d790f08 Mon Sep 17 00:00:00 2001 From: willGraham01 Date: Fri, 19 Jul 2024 10:32:02 +0100 Subject: [PATCH 27/38] Refactor prostate cancer init pop method --- src/tlo/methods/prostate_cancer.py | 36 +++++++++--------------------- 1 file changed, 11 insertions(+), 25 deletions(-) diff --git a/src/tlo/methods/prostate_cancer.py b/src/tlo/methods/prostate_cancer.py index 8bb7fd82ef..3fa862ef6d 100644 --- a/src/tlo/methods/prostate_cancer.py +++ b/src/tlo/methods/prostate_cancer.py @@ -160,40 +160,35 @@ def __init__(self, name=None, resourcefilepath=None): Types.CATEGORICAL, "Current status of the health condition, prostate cancer", categories=["none", "prostate_confined", "local_ln", "metastatic"], + default_property_value="none", ), "pc_date_psa_test": Property( - Types.DATE, - "the date of psa test in response to symptoms" + Types.DATE, "the date of psa test in response to symptoms" ), "pc_date_biopsy": Property( Types.DATE, - "the date of biopsy in response to symptoms and positive psa test" + "the date of biopsy in response to symptoms and positive psa test", ), "pc_date_diagnosis": Property( Types.DATE, - "the date of diagnosis of the prostate cancer (pd.NaT if never diagnosed)" + "the date of diagnosis of the prostate cancer (pd.NaT if never diagnosed)", ), - "pc_date_treatment": Property( Types.DATE, - "date of first receiving attempted curative treatment (pd.NaT if never started treatment)" + "date of first receiving attempted curative treatment (pd.NaT if never started treatment)", ), - "pc_stage_at_which_treatment_given": Property( Types.CATEGORICAL, "the cancer stage at which treatment is given (because the treatment only has an effect during the stage" "at which it is given.", categories=["none", "prostate_confined", "local_ln", "metastatic"], + default_property_value="none", ), - "pc_date_palliative_care": Property( Types.DATE, - "date of first receiving palliative care (pd.NaT is never had palliative care)" + "date of first receiving palliative care (pd.NaT is never had palliative care)", ), - "pc_date_death": Property( - Types.DATE, - "date pc death" - ) + "pc_date_death": Property(Types.DATE, "date pc death"), } def read_parameters(self, data_folder): @@ -220,20 +215,11 @@ def read_parameters(self, data_folder): ) def initialise_population(self, population): - """Set property values for the initial population.""" - df = population.props # a shortcut to the data-frame + super().initialise_population(population=population) + + df = population.props p = self.parameters - # defaults - df.loc[df.is_alive, "pc_status"] = "none" - df.loc[df.is_alive, "pc_date_diagnosis"] = pd.NaT - df.loc[df.is_alive, "pc_date_treatment"] = pd.NaT - df.loc[df.is_alive, "pc_stage_at_which_treatment_given"] = "none" - df.loc[df.is_alive, "pc_date_palliative_care"] = pd.NaT - df.loc[df.is_alive, "pc_date_death"] = pd.NaT - df.loc[df.is_alive, "pc_date_psa_test"] = pd.NaT - df.loc[df.is_alive, "pc_date_biopsy"] = pd.NaT - # -------------------- pc_status ----------- # Determine who has cancer at ANY cancer stage: # check parameters are sensible: probability of having any cancer stage cannot exceed 1.0 From 82044a0500285e102766ce7b95198b820d3e9309 Mon Sep 17 00:00:00 2001 From: willGraham01 Date: Fri, 19 Jul 2024 10:46:31 +0100 Subject: [PATCH 28/38] Refactor rti init pop method --- src/tlo/methods/rti.py | 165 +++++++++++++++++++++++++---------------- 1 file changed, 101 insertions(+), 64 deletions(-) diff --git a/src/tlo/methods/rti.py b/src/tlo/methods/rti.py index 13ddee6a86..46d29368dc 100644 --- a/src/tlo/methods/rti.py +++ b/src/tlo/methods/rti.py @@ -1026,16 +1026,21 @@ def __init__(self, name=None, resourcefilepath=None): # Define the module's parameters PROPERTIES = { - 'rt_road_traffic_inc': Property(Types.BOOL, 'involved in a road traffic injury'), - 'rt_inj_severity': Property(Types.CATEGORICAL, - 'Injury status relating to road traffic injury: none, mild, severe', - categories=['none', 'mild', 'severe'], - ), + "rt_road_traffic_inc": Property( + Types.BOOL, "involved in a road traffic injury" + ), + "rt_inj_severity": Property( + Types.CATEGORICAL, + "Injury status relating to road traffic injury: none, mild, severe", + categories=["none", "mild", "severe"], + default_property_value="none", + ), **{ - f'rt_injury_{injury_index}': Property( + f"rt_injury_{injury_index}": Property( Types.CATEGORICAL, - f'Codes for injury {injury_index} from RTI', + f"Codes for injury {injury_index} from RTI", categories=categories, + default_property_value="none", ) # hacky solution to avoid issue that names defined in class scope are not # accessible in scope of comprehension expresions _except for_ outermost @@ -1045,44 +1050,95 @@ def __init__(self, name=None, resourcefilepath=None): ) }, **{ - f'rt_date_to_remove_daly_{injury_index}': Property( + f"rt_date_to_remove_daly_{injury_index}": Property( Types.DATE, - f'Date to remove the daly weight for injury {injury_index}', + f"Date to remove the daly weight for injury {injury_index}", ) for injury_index in INJURY_INDICES }, - 'rt_in_shock': Property(Types.BOOL, 'A property determining if this person is in shock'), - 'rt_death_from_shock': Property(Types.BOOL, 'whether this person died from shock'), - 'rt_injuries_to_cast': Property(Types.LIST, 'A list of injuries that are to be treated with casts'), - 'rt_injuries_for_minor_surgery': Property(Types.LIST, 'A list of injuries that are to be treated with a minor' - 'surgery'), - 'rt_injuries_for_major_surgery': Property(Types.LIST, 'A list of injuries that are to be treated with a minor' - 'surgery'), - 'rt_injuries_to_heal_with_time': Property(Types.LIST, 'A list of injuries that heal without further treatment'), - 'rt_injuries_for_open_fracture_treatment': Property(Types.LIST, 'A list of injuries that with open fracture ' - 'treatment'), - 'rt_ISS_score': Property(Types.INT, 'The ISS score associated with the injuries resulting from a road traffic' - 'accident'), - 'rt_perm_disability': Property(Types.BOOL, 'whether the injuries from an RTI result in permanent disability'), - 'rt_polytrauma': Property(Types.BOOL, 'polytrauma from RTI'), - 'rt_imm_death': Property(Types.BOOL, 'death at scene True/False'), - 'rt_diagnosed': Property(Types.BOOL, 'Person has had their injuries diagnosed'), - 'rt_post_med_death': Property(Types.BOOL, 'death in following month despite medical intervention True/False'), - 'rt_no_med_death': Property(Types.BOOL, 'death in following month without medical intervention True/False'), - 'rt_unavailable_med_death': Property(Types.BOOL, 'death in the following month without medical intervention ' - 'being able to be provided'), - 'rt_recovery_no_med': Property(Types.BOOL, 'recovery without medical intervention True/False'), - 'rt_disability': Property(Types.REAL, 'disability weight for current month'), - 'rt_date_inj': Property(Types.DATE, 'date of latest injury'), - 'rt_med_int': Property(Types.BOOL, 'whether this person is currently undergoing medical treatment'), - 'rt_in_icu_or_hdu': Property(Types.BOOL, 'whether this person is currently in ICU for RTI'), - 'rt_MAIS_military_score': Property(Types.INT, 'the maximum AIS-military score, used as a proxy to calculate the' - 'probability of mortality without medical intervention'), - 'rt_date_death_no_med': Property(Types.DATE, 'the date which the person has is scheduled to die without medical' - 'intervention'), - 'rt_debugging_DALY_wt': Property(Types.REAL, 'The true value of the DALY weight burden'), - 'rt_injuries_left_untreated': Property(Types.LIST, 'A list of injuries that have been left untreated due to a ' - 'blocked intervention') + "rt_in_shock": Property( + Types.BOOL, "A property determining if this person is in shock" + ), + "rt_death_from_shock": Property( + Types.BOOL, "whether this person died from shock" + ), + "rt_injuries_to_cast": Property( + Types.LIST, "A list of injuries that are to be treated with casts" + ), + "rt_injuries_for_minor_surgery": Property( + Types.LIST, + "A list of injuries that are to be treated with a minor" "surgery", + ), + "rt_injuries_for_major_surgery": Property( + Types.LIST, + "A list of injuries that are to be treated with a minor" "surgery", + ), + "rt_injuries_to_heal_with_time": Property( + Types.LIST, "A list of injuries that heal without further treatment" + ), + "rt_injuries_for_open_fracture_treatment": Property( + Types.LIST, "A list of injuries that with open fracture " "treatment" + ), + "rt_ISS_score": Property( + Types.INT, + "The ISS score associated with the injuries resulting from a road traffic" + "accident", + ), + "rt_perm_disability": Property( + Types.BOOL, + "whether the injuries from an RTI result in permanent disability", + ), + "rt_polytrauma": Property(Types.BOOL, "polytrauma from RTI"), + "rt_imm_death": Property(Types.BOOL, "death at scene True/False"), + "rt_diagnosed": Property(Types.BOOL, "Person has had their injuries diagnosed"), + "rt_post_med_death": Property( + Types.BOOL, + "death in following month despite medical intervention True/False", + ), + "rt_no_med_death": Property( + Types.BOOL, + "death in following month without medical intervention True/False", + ), + "rt_unavailable_med_death": Property( + Types.BOOL, + "death in the following month without medical intervention " + "being able to be provided", + ), + "rt_recovery_no_med": Property( + Types.BOOL, "recovery without medical intervention True/False" + ), + "rt_disability": Property( + Types.REAL, + "disability weight for current month", + default_property_value=0.0, + ), + "rt_date_inj": Property(Types.DATE, "date of latest injury"), + "rt_med_int": Property( + Types.BOOL, "whether this person is currently undergoing medical treatment" + ), + "rt_in_icu_or_hdu": Property( + Types.BOOL, "whether this person is currently in ICU for RTI" + ), + "rt_MAIS_military_score": Property( + Types.INT, + "the maximum AIS-military score, used as a proxy to calculate the" + "probability of mortality without medical intervention", + ), + "rt_date_death_no_med": Property( + Types.DATE, + "the date which the person has is scheduled to die without medical" + "intervention", + ), + "rt_debugging_DALY_wt": Property( + Types.REAL, + "The true value of the DALY weight burden", + default_property_value=0.0, + ), + "rt_injuries_left_untreated": Property( + Types.LIST, + "A list of injuries that have been left untreated due to a " + "blocked intervention", + ), } # Declare Metadata @@ -1474,31 +1530,12 @@ def initialise_population(self, population): """Sets up the default properties used in the RTI module and applies them to the dataframe. The default state for the RTI module is that people haven't been involved in a road traffic accident and are therefor alive and healthy.""" + super().initialise_population(population=population) + + # Set LIST-valued dataframe columns manually df = population.props - df.loc[df.is_alive, 'rt_road_traffic_inc'] = False - df.loc[df.is_alive, 'rt_inj_severity'] = "none" # default: no one has been injured in a RTI - for injury_index in RTI.INJURY_INDICES: - df.loc[df.is_alive, f'rt_injury_{injury_index}'] = "none" - df.loc[df.is_alive, f'rt_date_to_remove_daly_{injury_index}'] = pd.NaT - df.loc[df.is_alive, 'rt_in_shock'] = False - df.loc[df.is_alive, 'rt_death_from_shock'] = False - df.loc[df.is_alive, 'rt_polytrauma'] = False - df.loc[df.is_alive, 'rt_ISS_score'] = 0 - df.loc[df.is_alive, 'rt_perm_disability'] = False - df.loc[df.is_alive, 'rt_imm_death'] = False # default: no one is dead on scene of crash - df.loc[df.is_alive, 'rt_diagnosed'] = False - df.loc[df.is_alive, 'rt_recovery_no_med'] = False # default: no recovery without medical intervention - df.loc[df.is_alive, 'rt_post_med_death'] = False # default: no death after medical intervention - df.loc[df.is_alive, 'rt_no_med_death'] = False - df.loc[df.is_alive, 'rt_unavailable_med_death'] = False - df.loc[df.is_alive, 'rt_disability'] = 0 # default: no DALY - df.loc[df.is_alive, 'rt_date_inj'] = pd.NaT - df.loc[df.is_alive, 'rt_med_int'] = False - df.loc[df.is_alive, 'rt_in_icu_or_hdu'] = False - df.loc[df.is_alive, 'rt_MAIS_military_score'] = 0 - df.loc[df.is_alive, 'rt_date_death_no_med'] = pd.NaT - df.loc[df.is_alive, 'rt_debugging_DALY_wt'] = 0 alive_count = sum(df.is_alive) + df.loc[df.is_alive, 'rt_injuries_to_cast'] = pd.Series([[] for _ in range(alive_count)]) df.loc[df.is_alive, 'rt_injuries_for_minor_surgery'] = pd.Series([[] for _ in range(alive_count)]) df.loc[df.is_alive, 'rt_injuries_for_major_surgery'] = pd.Series([[] for _ in range(alive_count)]) From d5aef1791e7478dba56c95fc32cc2bb1a45e4de5 Mon Sep 17 00:00:00 2001 From: willGraham01 Date: Fri, 19 Jul 2024 10:47:12 +0100 Subject: [PATCH 29/38] Remove now-redundant init pop method from scenario-switcher --- src/tlo/methods/scenario_switcher.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/tlo/methods/scenario_switcher.py b/src/tlo/methods/scenario_switcher.py index 615660daaa..264ad7723f 100644 --- a/src/tlo/methods/scenario_switcher.py +++ b/src/tlo/methods/scenario_switcher.py @@ -94,9 +94,6 @@ def update_parameters(self): f"module={module}, name={name}.", ) - def initialise_population(self, population): - pass - def initialise_simulation(self, sim): """Schedule an event at which the parameters are changed.""" From 6952a2046ef30596c6c61e26cd380cb56bc3f103 Mon Sep 17 00:00:00 2001 From: willGraham01 Date: Fri, 19 Jul 2024 10:48:18 +0100 Subject: [PATCH 30/38] Refactor schisto init pop method --- src/tlo/methods/schisto.py | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/tlo/methods/schisto.py b/src/tlo/methods/schisto.py index 0e9735286a..839057b2b6 100644 --- a/src/tlo/methods/schisto.py +++ b/src/tlo/methods/schisto.py @@ -143,11 +143,8 @@ def pre_initialise_population(self): _spec.update_parameters_from_schisto_module() def initialise_population(self, population): - """Set the property values for the initial population.""" - - df = population.props - df.loc[df.is_alive, f'{self.module_prefix}_last_PZQ_date'] = pd.NaT - + super().initialise_population(population=population) + for _spec in self.species.values(): _spec.initialise_population(population) From 9ab6f64e7a24f6f3e236ac38cdf3f92736822bad Mon Sep 17 00:00:00 2001 From: willGraham01 Date: Fri, 19 Jul 2024 10:58:57 +0100 Subject: [PATCH 31/38] Refactor simplified births init pop method --- src/tlo/methods/simplified_births.py | 109 +++++++++++++++------------ 1 file changed, 62 insertions(+), 47 deletions(-) diff --git a/src/tlo/methods/simplified_births.py b/src/tlo/methods/simplified_births.py index 50408f21e9..c80a1ad882 100644 --- a/src/tlo/methods/simplified_births.py +++ b/src/tlo/methods/simplified_births.py @@ -5,6 +5,7 @@ import json from pathlib import Path +from typing import Dict import pandas as pd @@ -45,63 +46,82 @@ class SimplifiedBirths(Module): PROPERTIES = { # (Internal property) - 'si_date_of_last_delivery': Property(Types.DATE, - 'Date of delivery for the most recent pregnancy for this individual (if ' - 'has ever been pregnant). Maybe in the future if is currently pregnant.'), - + "si_date_of_last_delivery": Property( + Types.DATE, + "Date of delivery for the most recent pregnancy for this individual (if " + "has ever been pregnant). Maybe in the future if is currently pregnant.", + ), # (Internal property) - 'si_breastfeeding_status_6mo_to_23mo': Property(Types.CATEGORICAL, - 'How this neonate is breastfeed during ages 6mo to 23 months', - categories=['none', 'non_exclusive', 'exclusive']), - + "si_breastfeeding_status_6mo_to_23mo": Property( + Types.CATEGORICAL, + "How this neonate is breastfeed during ages 6mo to 23 months", + categories=["none", "non_exclusive", "exclusive"], + default_property_value="none", + ), # (Mocked property, usually handled by Contraception module) - 'is_pregnant': Property(Types.BOOL, - 'Whether this individual is currently pregnant'), - + "is_pregnant": Property( + Types.BOOL, "Whether this individual is currently pregnant" + ), # (Mocked property, usually handled by Contraception module) - 'date_of_last_pregnancy': Property(Types.DATE, - 'Date of the onset of the last pregnancy of this individual (if has ever ' - 'been pregnant).'), - + "date_of_last_pregnancy": Property( + Types.DATE, + "Date of the onset of the last pregnancy of this individual (if has ever " + "been pregnant).", + ), # (Mocked property, usually managed by Newborn_outcomes module) - 'nb_low_birth_weight_status': Property(Types.CATEGORICAL, 'temporary property', - categories=['extremely_low_birth_weight', 'very_low_birth_weight', - 'low_birth_weight', 'normal_birth_weight', 'macrosomia']), - + "nb_low_birth_weight_status": Property( + Types.CATEGORICAL, + "temporary property", + categories=[ + "extremely_low_birth_weight", + "very_low_birth_weight", + "low_birth_weight", + "normal_birth_weight", + "macrosomia", + ], + default_property_value="normal_birth_weight", + ), # (Mocked property, managed by Newborn_outcomes module) - 'nb_size_for_gestational_age': Property(Types.CATEGORICAL, 'temporary property', - categories=['small_for_gestational_age', 'average_for_gestational_age', - 'large_for_gestational_age']), - + "nb_size_for_gestational_age": Property( + Types.CATEGORICAL, + "temporary property", + categories=[ + "small_for_gestational_age", + "average_for_gestational_age", + "large_for_gestational_age", + ], + default_property_value="average_for_gestational_age", + ), # (Mocked property, usually managed by Newborn_outcomes module) - 'nb_late_preterm': Property(Types.BOOL, 'temporary property'), - + "nb_late_preterm": Property(Types.BOOL, "temporary property"), # (Mocked property, usually managed by Newborn_outcomes module) - 'nb_early_preterm': Property(Types.BOOL, 'temporary property'), - + "nb_early_preterm": Property(Types.BOOL, "temporary property"), # (Mocked property, usually managed by Newborn_outcomes module) - 'nb_breastfeeding_status': Property(Types.CATEGORICAL, 'temporary property', - categories=['none', 'non_exclusive', 'exclusive']), + "nb_breastfeeding_status": Property( + Types.CATEGORICAL, + "temporary property", + categories=["none", "non_exclusive", "exclusive"], + default_property_value="none", + ), } + @property + def default_properties(self) -> Dict[str, pd.NaT | str | bool]: + """ + Easy-access defaults for properties. + + This attribute was needed before the initialise_population refactor, + however it can now be defined as a property rather than dynamically. + """ + return { + p_name : p._default_value for p_name, p in self.PROPERTIES.items() + } + def __init__(self, name=None, resourcefilepath=None): super().__init__(name) self.resourcefilepath = resourcefilepath self.asfr = dict() - # Define defaults for properties: - self.default_properties = { - 'si_date_of_last_delivery': pd.NaT, - 'si_breastfeeding_status_6mo_to_23mo': 'none', - 'is_pregnant': False, - 'date_of_last_pregnancy': pd.NaT, - 'nb_low_birth_weight_status': 'normal_birth_weight', - 'nb_size_for_gestational_age': 'average_for_gestational_age', - 'nb_late_preterm': False, - 'nb_early_preterm': False, - 'nb_breastfeeding_status': 'none', - } - def read_parameters(self, data_folder): """Load parameters for probability of pregnancy/birth and breastfeeding status for newborns""" @@ -116,11 +136,6 @@ def read_parameters(self, data_folder): parameter = json.loads(param_as_string)[0] self.parameters['prob_breastfeeding_type'] = parameter - def initialise_population(self, population): - """Set property values to their defaults for the initial population.""" - df = population.props - df.loc[df.is_alive, self.default_properties.keys()] = self.default_properties.values() - def initialise_simulation(self, sim): """Schedule the SimplifiedBirthsPoll and the SimplifiedBirthEvent to occur every month.""" sim.schedule_event(SimplifiedBirthsPoll(self), sim.date) From b10d10c5114dea0a58d3a2c9e13ef0fc984bac1d Mon Sep 17 00:00:00 2001 From: willGraham01 Date: Fri, 19 Jul 2024 14:11:21 +0100 Subject: [PATCH 32/38] Refactor the Skeleton module init pop method. Include docstring explanation of what can now be handled automatically --- src/tlo/core.py | 5 +++++ src/tlo/methods/skeleton.py | 22 +++++++++++++++++++++- 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/src/tlo/core.py b/src/tlo/core.py index 7d98ca14d4..ae34b40ac2 100644 --- a/src/tlo/core.py +++ b/src/tlo/core.py @@ -372,6 +372,11 @@ def initialise_population(self, population: Population) -> None: By default, all ``Property``s in ``self.PROPERTIES`` will have their columns set to the default value for their dtype in the population dataframe. + Modules that inherit from this class do not have to redefine this method to obtain + this behaviour by default, however if you want to add additional steps or initialise + your properties in another way, you may need to define this method explicitly and + call super().initialise_population. See the template docstring in + ``tlo.methods.skeleton.initialise_population`` for more information. TODO: We probably need to declare somehow which properties we 'read' here, so the simulation knows what order to initialise modules in! diff --git a/src/tlo/methods/skeleton.py b/src/tlo/methods/skeleton.py index 3f21cc4fff..5ac521fb3b 100644 --- a/src/tlo/methods/skeleton.py +++ b/src/tlo/methods/skeleton.py @@ -110,9 +110,29 @@ def initialise_population(self, population): responsible for assigning initial values, for every individual, of those properties 'owned' by this module, i.e. those declared in the PROPERTIES dictionary above. + - If all you need to do at this stage is set the properties owned by this module to + their defaults, you don't need to define this method as this will happen automatically - + you can safely delete this method. + - If you want to do something in addition to setting the properties to their defaults + (EG sample a random amount of the initial population to infect with a disease) then you + should call super().initialise_population(population=population) right at the top of + this method, and then perform your additional steps underneath. This will ensure your + module's properties are still set for individuals you don't consider. + - If you want to handle the setting of the initial values entirely by yourself (which is + not recommended) then you will need to implement this here without calling + super().initialise_population. + :param population: the population of individuals """ - raise NotImplementedError + # The command below sets all the PROPERTIES defined above to their defaults. + # If you don't want your properties to be automatically set, delete the command + # below. + # If all you want to do is have your properties set to their defaults, + # you can just delete this entire function and its docstring. + super().initialise_population(population=population) + + # If you have additional tasks to perform after setting your properties, + # you should do them here after calling super(). def initialise_simulation(self, sim): """Get ready for simulation start. From c12c0565751b71203134bdcac6c827b6df4597cd Mon Sep 17 00:00:00 2001 From: willGraham01 Date: Fri, 19 Jul 2024 14:15:50 +0100 Subject: [PATCH 33/38] Refactor stunting init pop method --- src/tlo/methods/stunting.py | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/src/tlo/methods/stunting.py b/src/tlo/methods/stunting.py index 002d24bc31..5219539198 100644 --- a/src/tlo/methods/stunting.py +++ b/src/tlo/methods/stunting.py @@ -133,12 +133,15 @@ class Stunting(Module, GenericFirstAppointmentsMixin): } PROPERTIES = { - 'un_HAZ_category': Property(Types.CATEGORICAL, - 'Indicator of current stunting status - the height-for-age z-score category:' - '"HAZ>=-2" == No Stunting (within 2 standard deviations of mean); ' - '"-3<=HAZ<-2" == Non-Severe Stunting (2-3 standard deviations from mean); ' - '"HAZ<-3 == Severe Stunting (more than 3 standard deviations from mean)', - categories=['HAZ<-3', '-3<=HAZ<-2', 'HAZ>=-2']), + "un_HAZ_category": Property( + Types.CATEGORICAL, + "Indicator of current stunting status - the height-for-age z-score category:" + '"HAZ>=-2" == No Stunting (within 2 standard deviations of mean); ' + '"-3<=HAZ<-2" == Non-Severe Stunting (2-3 standard deviations from mean); ' + '"HAZ<-3 == Severe Stunting (more than 3 standard deviations from mean)', + categories=["HAZ<-3", "-3<=HAZ<-2", "HAZ>=-2"], + default_property_value="HAZ>=-2", + ), } def __init__(self, name=None, resourcefilepath=None): @@ -155,12 +158,11 @@ def read_parameters(self, data_folder): def initialise_population(self, population): """Set initial prevalence of stunting according to distributions provided in parameters""" + super().initialise_population(population=population) + df = population.props p = self.parameters - # Set default for property - df.loc[df.is_alive, 'un_HAZ_category'] = 'HAZ>=-2' - def get_probs_stunting(_agegp): """For the a given HAZ distribution (specified in the parameters by age-group), find the odds of a value <-2 (= 'stunted') and the odds of a value <-3 given a value <-2 (= 'severely stunted').""" From cda19c11099e54f3688ffc816f41d51f787ce016 Mon Sep 17 00:00:00 2001 From: willGraham01 Date: Fri, 19 Jul 2024 14:28:35 +0100 Subject: [PATCH 34/38] Fix typehint syntax error --- src/tlo/methods/simplified_births.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/tlo/methods/simplified_births.py b/src/tlo/methods/simplified_births.py index c80a1ad882..a4aee60137 100644 --- a/src/tlo/methods/simplified_births.py +++ b/src/tlo/methods/simplified_births.py @@ -5,7 +5,7 @@ import json from pathlib import Path -from typing import Dict +from typing import Dict, Union import pandas as pd @@ -106,7 +106,7 @@ class SimplifiedBirths(Module): } @property - def default_properties(self) -> Dict[str, pd.NaT | str | bool]: + def default_properties(self) -> Dict[str, Union[pd.NaT, str, bool]]: """ Easy-access defaults for properties. From 93c2835f9fec19f4d0f71e36ad1b53680ab4d441 Mon Sep 17 00:00:00 2001 From: willGraham01 Date: Fri, 19 Jul 2024 14:33:29 +0100 Subject: [PATCH 35/38] Refactor tb init pop method --- src/tlo/methods/tb.py | 30 ++++-------------------------- 1 file changed, 4 insertions(+), 26 deletions(-) diff --git a/src/tlo/methods/tb.py b/src/tlo/methods/tb.py index aa62f3ea8a..64d1dda281 100644 --- a/src/tlo/methods/tb.py +++ b/src/tlo/methods/tb.py @@ -88,6 +88,7 @@ def __init__(self, name=None, resourcefilepath=None, run_with_checks=False): "active", ], description="tb status", + default_property_value="uninfected", ), "tb_strain": Property( Types.CATEGORICAL, @@ -97,6 +98,7 @@ def __init__(self, name=None, resourcefilepath=None, run_with_checks=False): "mdr", ], description="tb strain: drug-susceptible (ds) or multi-drug resistant (mdr)", + default_property_value="none", ), "tb_date_latent": Property( Types.DATE, "Date acquired tb infection (latent stage)" @@ -134,6 +136,7 @@ def __init__(self, name=None, resourcefilepath=None, run_with_checks=False): "tb_mdrtx", ], description="current tb treatment regimen", + default_property_value="none", ), "tb_ever_treated": Property(Types.BOOL, "if ever treated for active tb"), "tb_treatment_failure": Property(Types.BOOL, "failed first line tb treatment"), @@ -789,10 +792,10 @@ def get_consumables_for_dx_and_tx(self): hs.get_item_code_from_item_name("Isoniazid/Rifapentine") def initialise_population(self, population): + super().initialise_population(population=population) df = population.props p = self.parameters - # if HIV is not registered, create a dummy property if "Hiv" not in self.sim.modules: population.make_test_property("hv_inf", Types.BOOL) @@ -803,31 +806,6 @@ def initialise_population(self, population): df["sy_aids_symptoms"] = 0 df["hv_art"] = "not" - # Set our property values for the initial population - df["tb_inf"].values[:] = "uninfected" - df["tb_strain"].values[:] = "none" - - df["tb_date_latent"] = pd.NaT - df["tb_scheduled_date_active"] = pd.NaT - df["tb_date_active"] = pd.NaT - df["tb_smear"] = False - - # ------------------ testing status ------------------ # - df["tb_date_tested"] = pd.NaT - df["tb_diagnosed"] = False - df["tb_date_diagnosed"] = pd.NaT - df["tb_diagnosed_mdr"] = False - - # ------------------ treatment status ------------------ # - df["tb_on_treatment"] = False - df["tb_date_treated"] = pd.NaT - df["tb_treatment_regimen"].values[:] = "none" - df["tb_ever_treated"] = False - df["tb_treatment_failure"] = False - - df["tb_on_ipt"] = False - df["tb_date_ipt"] = pd.NaT - # # ------------------ infection status ------------------ # # WHO estimates of active TB for 2010 to get infected initial population # don't need to scale or include treated proportion as no-one on treatment yet From 421ab2407ae6b10f6945639857a30eeada762240 Mon Sep 17 00:00:00 2001 From: willGraham01 Date: Fri, 19 Jul 2024 14:41:36 +0100 Subject: [PATCH 36/38] Refactor wasting init population method --- src/tlo/methods/wasting.py | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/src/tlo/methods/wasting.py b/src/tlo/methods/wasting.py index c8d3517ad5..59b02758b3 100644 --- a/src/tlo/methods/wasting.py +++ b/src/tlo/methods/wasting.py @@ -15,9 +15,13 @@ class Wasting(Module): INIT_DEPENDENCIES = {'Demography'} PROPERTIES = { - 'un_clinical_acute_malnutrition': Property(Types.CATEGORICAL, - 'temporary property', categories=['MAM', 'SAM', 'well']), - 'un_ever_wasted': Property(Types.BOOL, 'temporary property') + "un_clinical_acute_malnutrition": Property( + Types.CATEGORICAL, + "temporary property", + categories=["MAM", "SAM", "well"], + default_property_value="well", + ), + "un_ever_wasted": Property(Types.BOOL, "temporary property"), } def __init__(self, name=None, resourcefilepath=None): @@ -27,11 +31,6 @@ def __init__(self, name=None, resourcefilepath=None): def read_parameters(self, data_folder): pass - def initialise_population(self, population): - df = population.props - df.loc[df.is_alive, 'un_clinical_acute_malnutrition'] = 'well' - df.loc[df.is_alive, 'un_ever_wasted'] = False - def initialise_simulation(self, sim): pass From 876621c4e477924459e71a699fe2325af2ded9ed Mon Sep 17 00:00:00 2001 From: willGraham01 Date: Fri, 19 Jul 2024 16:46:07 +0100 Subject: [PATCH 37/38] Patch tests in the HIV module that rely on some CATEGORICAL df columns being unset to nan, which conflicts with our new default behaviour. --- tests/test_hiv.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/tests/test_hiv.py b/tests/test_hiv.py index 47ef0d2083..bde47cb1a5 100644 --- a/tests/test_hiv.py +++ b/tests/test_hiv.py @@ -376,6 +376,9 @@ def test_mtct_during_breastfeeding_if_mother_infected_already(seed): child_id = sim.population.do_birth() sim.modules['Demography'].on_birth(mother_id, child_id) + # We need to explicitly set the breastfeeding status of the + # newborn infant, since by default is is nan + sim.population.props.loc[child_id, "nb_breastfeeding_status"] = "exclusive" sim.modules['Hiv'].on_birth(mother_id, child_id) # Check child is not yet HIV-positive @@ -414,7 +417,10 @@ def test_mtct_during_breastfeeding_if_mother_infected_during_breastfeeding(seed) df.at[mother_id, 'date_of_last_pregnancy'] = sim.date child_id = sim.population.do_birth() - sim.modules['Demography'].on_birth(mother_id, child_id) + sim.modules["Demography"].on_birth(mother_id, child_id) + # We need to explicitly set the breastfeeding status of the + # newborn infant, since by default is is nan + sim.population.props.loc[child_id, "nb_breastfeeding_status"] = "exclusive" sim.modules['Hiv'].on_birth(mother_id, child_id) # Check child is not yet HIV-positive From 9e6c6516c82e82d824c9d03378b10fc6fea15940 Mon Sep 17 00:00:00 2001 From: willGraham01 Date: Fri, 19 Jul 2024 17:21:29 +0100 Subject: [PATCH 38/38] Linting pass --- src/tlo/core.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/tlo/core.py b/src/tlo/core.py index ae34b40ac2..98d1f3c7b5 100644 --- a/src/tlo/core.py +++ b/src/tlo/core.py @@ -15,13 +15,12 @@ if TYPE_CHECKING: from pathlib import Path - from typing import Optional - from tlo.simulation import Simulation - from tlo.population import Population from tlo.methods import Metadata from tlo.methods.causes import Cause + from tlo.population import Population + from tlo.simulation import Simulation class Types(Enum): """Possible types for parameters and properties.