Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
62 changes: 47 additions & 15 deletions src/tlo/methods/labour.py
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ def __init__(self, name=None):
# Finally define a dictionary which will hold the required consumables for each intervention
self.item_codes_lab_consumables = dict()


INIT_DEPENDENCIES = {'Demography'}

OPTIONAL_INIT_DEPENDENCIES = {'Stunting'}
Expand Down Expand Up @@ -1175,7 +1176,7 @@ def set_date_of_labour(self, individual_id):
# we determine if she will go into labour post term (42+ weeks)

if self.rng.random_sample() < self.la_linear_models['post_term_labour'].predict(
df.loc[[individual_id]])[individual_id]:
df.loc[[individual_id], ['li_bmi']])[individual_id]:

df.at[individual_id, 'la_due_date_current_pregnancy'] = \
(df.at[individual_id, 'date_of_last_pregnancy'] + pd.DateOffset(
Expand Down Expand Up @@ -1206,7 +1207,28 @@ def predict(self, eq, person_id):
"""
df = self.sim.population.props
mni = self.sim.modules['PregnancySupervisor'].mother_and_newborn_info
person = df.loc[[person_id]]

# we only need those properties required to evaluate the function
person_properties = eq.predict.person_properties

# if the simulation is running without stunting or cardio metabolic disorders modules
# then we need to remove the properties
if "Stunting" not in self.sim.modules and "un_HAZ_category" in person_properties:
person_properties = list(person_properties)
person_properties.remove("un_HAZ_category")

if "CardioMetabolicDisorders" not in self.sim.modules and "nc_hypertension" in person_properties:
person_properties = list(person_properties)
person_properties.remove("nc_hypertension")

if not person_properties:
# we do need to pass a valid dataframe, despite not actually needing any properties :(
person_properties = ['is_alive']

person = df.loc[
[person_id],
person_properties
]

# We define specific external variables used as predictors in the equations defined below
has_rbt = mni[person_id]['received_blood_transfusion']
Expand Down Expand Up @@ -1249,7 +1271,11 @@ def check_labour_can_proceed(self, individual_id):
:returns True/False if labour can proceed
"""
df = self.sim.population.props
person = df.loc[individual_id]
person = df.loc[
individual_id,
['is_alive', 'is_pregnant', 'la_currently_in_labour', 'la_due_date_current_pregnancy',
'ac_admitted_for_immediate_delivery', 'ps_gestational_age_in_weeks']
]

# If the mother has died OR has lost her pregnancy OR is already in labour then the labour events wont run
if not person.is_alive or not person.is_pregnant or person.la_currently_in_labour:
Expand All @@ -1259,8 +1285,7 @@ def check_labour_can_proceed(self, individual_id):
return False

# If she is alive, pregnant, not in labour AND her due date is today then the event will run
if person.is_alive and person.is_pregnant and (person.la_due_date_current_pregnancy == self.sim.date) \
and not person.la_currently_in_labour:
if person.la_due_date_current_pregnancy == self.sim.date:

# If the woman in not currently an inpatient then we assume this is her normal labour
if person.ac_admitted_for_immediate_delivery == 'none':
Expand All @@ -1278,11 +1303,9 @@ def check_labour_can_proceed(self, individual_id):
f'at gestation {person.ps_gestational_age_in_weeks}')
return True

# If she is alive, pregnant, not in labour BUT her due date is not today, however shes been admitted then we
# If she is alive, pregnant, not in labour BUT her due date is not today, however she's been admitted then we
# labour can progress as she requires early delivery
if person.is_alive and person.is_pregnant and not person.la_currently_in_labour and \
(person.la_due_date_current_pregnancy != self.sim.date) and (person.ac_admitted_for_immediate_delivery !=
'none'):
if person.ac_admitted_for_immediate_delivery != 'none':
logger.debug(key='message', data=f'person {individual_id} has just reached LabourOnsetEvent on '
f'{self.sim.date}- they have been admitted for delivery due to '
f'complications in the antenatal period and will now progress into the '
Expand Down Expand Up @@ -2454,12 +2477,16 @@ def apply(self, individual_id):
# been admitted antenatally for delivery will be delivering in hospital and that is scheduled accordingly

if df.at[individual_id, 'ac_admitted_for_immediate_delivery'] == 'none':
individual = df.loc[
[individual_id],
['age_years', 'li_urban', 'la_parity', 'li_ed_lev', 'li_wealth', 'li_mar_stat']
]

# Here we calculate this womans predicted risk of home birth and health centre birth
pred_hb_delivery = self.module.la_linear_models['probability_delivery_at_home'].predict(
df.loc[[individual_id]])[individual_id]
individual)[individual_id]
pred_hc_delivery = self.module.la_linear_models['probability_delivery_health_centre'].predict(
df.loc[[individual_id]])[individual_id]
individual)[individual_id]
pred_hp_delivery = params['probability_delivery_hospital']

# The denominator is calculated
Expand Down Expand Up @@ -2707,7 +2734,7 @@ def __init__(self, module, mother_id):

def apply(self, mother_id):
df = self.sim.population.props
person = df.loc[mother_id]
person = df.loc[mother_id, ['is_alive', 'la_intrapartum_still_birth', 'ps_multiple_pregnancy', 'is_pregnant']]
mni = self.sim.modules['PregnancySupervisor'].mother_and_newborn_info
params = self.module.current_parameters

Expand Down Expand Up @@ -2747,6 +2774,7 @@ def apply(self, mother_id):
else:
self.sim.do_birth(mother_id)

# refresh the reference to the dataframe as the do_birth function might have changed the underlying object
df = self.sim.population.props

# If the mother survived labour but experienced a stillbirth we reset all the relevant pregnancy variables now
Expand Down Expand Up @@ -2786,10 +2814,14 @@ def apply(self, mother_id):

else:
# We use a linear model to determine if women without complications will receive any postnatal care
mother = df.loc[
[mother_id],
['age_years', 'li_urban', 'li_wealth', 'la_parity', 'ac_total_anc_visits_current_pregnancy']
]
prob_pnc = self.module.la_linear_models['postnatal_check'].predict(
df.loc[[mother_id]],
mode_of_delivery=pd.Series(mni[mother_id]['mode_of_delivery'], index=df.loc[[mother_id]].index),
delivery_setting=pd.Series(mni[mother_id]['delivery_setting'], index=df.loc[[mother_id]].index)
mother,
mode_of_delivery=pd.Series(mni[mother_id]['mode_of_delivery'], index=mother.index),
delivery_setting=pd.Series(mni[mother_id]['delivery_setting'], index=mother.index)
)[mother_id]
has_comps = False

Expand Down
35 changes: 35 additions & 0 deletions src/tlo/methods/labour_lm.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,16 @@ def predict_for_dataframe(self, df, rng=None, **externals):
import pandas as pd


def person_properties(keys):
"""Decorator to specify the person's properties needed to evaluate the function"""
keys_t = tuple(keys)
def decorator(func):
func.person_properties = keys_t
return func
return decorator


@person_properties(['li_bmi'])
def predict_post_term_labour(self, df, rng=None, **externals):
"""
Individual level linear model which predicts an individuals probability of post term labour. Risk is increased in
Expand All @@ -40,6 +50,7 @@ def predict_post_term_labour(self, df, rng=None, **externals):
return pd.Series(data=[result], index=df.index)


@person_properties(['age_years', 'li_mar_stat', 'li_wealth', 'li_ed_lev', 'li_urban'])
def predict_parity(self, df, rng=None, **externals):
"""
Population level linear model (additive) which returns a df containing the predicted parity (previous number of
Expand Down Expand Up @@ -70,6 +81,7 @@ def predict_parity(self, df, rng=None, **externals):
return result


@person_properties(['un_HAZ_category'])
def predict_obstruction_cpd_ip(self, df, rng=None, **externals):
"""
Individual level linear model which predicts an individuals probability of developing obstructed labour
Expand All @@ -91,6 +103,7 @@ def predict_obstruction_cpd_ip(self, df, rng=None, **externals):
return pd.Series(data=[result], index=df.index)


@person_properties(['ps_premature_rupture_of_membranes', 'ac_received_abx_for_prom'])
def predict_sepsis_chorioamnionitis_ip(self, df, rng=None, **externals):
"""
Individual level linear model which predicts an individuals probability of developing sepsis secondary
Expand All @@ -111,6 +124,7 @@ def predict_sepsis_chorioamnionitis_ip(self, df, rng=None, **externals):
return pd.Series(data=[result], index=df.index)


@person_properties([])
def predict_sepsis_endometritis_pp(self, df, rng=None, **externals):
"""
Individual level linear model which predicts an individuals probability of developing sepsis secondary
Expand All @@ -128,6 +142,7 @@ def predict_sepsis_endometritis_pp(self, df, rng=None, **externals):
return pd.Series(data=[result], index=df.index)


@person_properties([])
def predict_sepsis_skin_soft_tissue_pp(self, df, rng=None, **externals):
"""
Individual level linear model which predicts an individuals probability of developing sepsis secondary
Expand All @@ -145,6 +160,7 @@ def predict_sepsis_skin_soft_tissue_pp(self, df, rng=None, **externals):
return pd.Series(data=[result], index=df.index)


@person_properties([])
def predict_sepsis_urinary_tract_pp(self, df, rng=None, **externals):
"""
Individual level linear model which predicts an individuals probability of developing sepsis secondary
Expand All @@ -160,6 +176,7 @@ def predict_sepsis_urinary_tract_pp(self, df, rng=None, **externals):
return pd.Series(data=[result], index=df.index)


@person_properties(['la_sepsis_treatment'])
def predict_sepsis_death(self, df, rng=None, **externals):
"""
Individual level linear model which predicts an individuals probability of death due to postpartum sepsis.
Expand All @@ -175,6 +192,8 @@ def predict_sepsis_death(self, df, rng=None, **externals):
return pd.Series(data=[result], index=df.index)


@person_properties(['la_eclampsia_treatment', 'ac_mag_sulph_treatment', 'la_maternal_hypertension_treatment',
'ac_iv_anti_htn_treatment'])
def predict_eclampsia_death(self, df, rng=None, **externals):
"""
This is an individual level linear model which predicts an individuals probability of death due to eclampsia.
Expand All @@ -195,6 +214,7 @@ def predict_eclampsia_death(self, df, rng=None, **externals):
return pd.Series(data=[result], index=df.index)


@person_properties(['la_maternal_hypertension_treatment', 'ac_iv_anti_htn_treatment'])
def predict_severe_pre_eclamp_death(self, df, rng=None, **externals):
"""
Individual level linear model which predicts an individuals probability of death due to severe
Expand All @@ -211,6 +231,7 @@ def predict_severe_pre_eclamp_death(self, df, rng=None, **externals):
return pd.Series(data=[result], index=df.index)


@person_properties(['la_previous_cs_delivery', 'ps_htn_disorders'])
def predict_placental_abruption_ip(self, df, rng=None, **externals):
"""
Individual level linear model which predicts an individuals probability of developing placental
Expand All @@ -230,6 +251,7 @@ def predict_placental_abruption_ip(self, df, rng=None, **externals):
return pd.Series(data=[result], index=df.index)


@person_properties(['ps_placenta_praevia', 'ps_placental_abruption', 'la_placental_abruption'])
def predict_antepartum_haem_ip(self, df, rng=None, **externals):
"""
Individual level linear model which predicts an individuals probability of developing an antepartum
Expand All @@ -249,6 +271,7 @@ def predict_antepartum_haem_ip(self, df, rng=None, **externals):
return pd.Series(data=[result], index=df.index)


@person_properties([])
def predict_antepartum_haem_death(self, df, rng=None, **externals):
"""
Individual level linear model which predicts an individuals probability of death due to antepartum
Expand All @@ -268,6 +291,8 @@ def predict_antepartum_haem_death(self, df, rng=None, **externals):
return pd.Series(data=[result], index=df.index)


@person_properties(['pn_htn_disorders', 'nc_hypertension', 'ps_multiple_pregnancy', 'la_placental_abruption',
'ps_placental_abruption'])
def predict_pph_uterine_atony_pp(self, df, rng=None, **externals):
"""
Individual level linear model which predicts an individuals probability of developing a postpartum haemorrhage due
Expand Down Expand Up @@ -298,6 +323,7 @@ def predict_pph_uterine_atony_pp(self, df, rng=None, **externals):
return pd.Series(data=[result], index=df.index)


@person_properties([])
def predict_pph_retained_placenta_pp(self, df, rng=None, **externals):
"""
Individual level linear model which predicts an individuals probability of developing a postpartum
Expand All @@ -313,6 +339,7 @@ def predict_pph_retained_placenta_pp(self, df, rng=None, **externals):
return pd.Series(data=[result], index=df.index)


@person_properties(['la_postpartum_haem_treatment'])
def predict_postpartum_haem_pp_death(self, df, rng=None, **externals):
"""
Individual level linear model which predicts an individuals probability of death following a postpartum
Expand All @@ -333,6 +360,7 @@ def predict_postpartum_haem_pp_death(self, df, rng=None, **externals):
return pd.Series(data=[result], index=df.index)


@person_properties(['la_parity', 'la_previous_cs_delivery', 'la_obstructed_labour'])
def predict_uterine_rupture_ip(self, df, rng=None, **externals):
"""
Population level linear model to allow for the model to be scaled at initialisation of the simulation. The model
Expand All @@ -352,6 +380,7 @@ def predict_uterine_rupture_ip(self, df, rng=None, **externals):
return result


@person_properties(['la_uterine_rupture_treatment', 'la_has_had_hysterectomy'])
def predict_uterine_rupture_death(self, df, rng=None, **externals):
"""
Individual level linear model which predicts an individuals probability of death following a uterine
Expand All @@ -371,6 +400,9 @@ def predict_uterine_rupture_death(self, df, rng=None, **externals):
return pd.Series(data=[result], index=df.index)


@person_properties(['is_alive', 'la_uterine_rupture', 'la_obstructed_labour', 'la_antepartum_haem',
'ps_antepartum_haemorrhage', 'ps_htn_disorders', 'la_sepsis', 'ps_chorioamnionitis',
'ps_multiple_pregnancy'])
def predict_intrapartum_still_birth(self, df, rng=None, **externals):
"""
Individual level linear model which predicts an individuals probability of experiencing an intrapartum
Expand Down Expand Up @@ -410,6 +442,7 @@ def predict_intrapartum_still_birth(self, df, rng=None, **externals):
return pd.Series(data=[result], index=df.index)


@person_properties(['age_years', 'li_wealth', 'la_parity', 'li_mar_stat', 'li_urban'])
def predict_probability_delivery_health_centre(self, df, rng=None, **externals):
"""
Population level to allow for scaling at the initialisation of the simulation. This model predicts an
Expand Down Expand Up @@ -444,6 +477,7 @@ def predict_probability_delivery_health_centre(self, df, rng=None, **externals):
return result


@person_properties(['age_years', 'li_urban', 'la_parity', 'li_ed_lev', 'li_wealth', 'li_mar_stat'])
def predict_probability_delivery_at_home(self, df, rng=None, **externals):
"""
Population level to allow for scaling at the initialisation of the simulation. This model predicts an
Expand Down Expand Up @@ -481,6 +515,7 @@ def predict_probability_delivery_at_home(self, df, rng=None, **externals):
return result


@person_properties(['age_years', 'li_urban', 'la_parity', 'li_wealth', 'ac_total_anc_visits_current_pregnancy'])
def predict_postnatal_check(self, df, rng=None, **externals):
"""
Population level to allow for scaling at the initialisation of the simulation. This model predicts an
Expand Down