Skip to content

Commit

Permalink
Update consumables in cancer modules (#1353)
Browse files Browse the repository at this point in the history
  • Loading branch information
tbhallett authored May 16, 2024
1 parent 8b0698d commit 4f561a5
Show file tree
Hide file tree
Showing 7 changed files with 622 additions and 363 deletions.
2 changes: 1 addition & 1 deletion resources/ResourceFile_Bladder_Cancer.xlsx
Git LFS file not shown
256 changes: 148 additions & 108 deletions src/tlo/methods/bladder_cancer.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
Bladder Cancer Disease Module
Limitations to note:
* Needs to represent the the DxTest 'cytoscopy_blood_urine_bladder_cancer' requires use of a cytoscope
* Needs to represent the DxTest 'cystoscopy_blood_urine_bladder_cancer' requires use of a cystoscope
* Footprints of HSI -- pending input from expert on resources required.
"""
from __future__ import annotations
Expand All @@ -17,6 +17,7 @@
from tlo.events import IndividualScopeEventMixin, PopulationScopeEventMixin, RegularEvent
from tlo.lm import LinearModel, LinearModelType, Predictor
from tlo.methods import Metadata
from tlo.methods.cancer_consumables import get_consumable_item_codes_cancers
from tlo.methods.causes import Cause
from tlo.methods.demography import InstantaneousDeath
from tlo.methods.dxmanager import DxTest
Expand All @@ -40,6 +41,7 @@ def __init__(self, name=None, resourcefilepath=None):
self.lm_onset_blood_urine = None
self.lm_onset_pelvic_pain = None
self.daly_wts = dict()
self.item_codes_bladder_can = dict()

INIT_DEPENDENCIES = {'Demography', 'Lifestyle', 'HealthSystem', 'SymptomManager'}

Expand Down Expand Up @@ -162,11 +164,11 @@ def __init__(self, name=None, resourcefilepath=None):
"rp_bladder_cancer_schisto_h": Parameter(
Types.REAL, "relative prevalence at baseline of bladder cancer if schisto_h"
),
"sensitivity_of_cytoscopy_for_bladder_cancer_blood_urine": Parameter(
Types.REAL, "sensitivity of cytoscopy_for diagnosis of bladder cancer given blood urine"
"sensitivity_of_cystoscopy_for_bladder_cancer_blood_urine": Parameter(
Types.REAL, "sensitivity of cystoscopy_for diagnosis of bladder cancer given blood urine"
),
"sensitivity_of_cytoscopy_for_bladder_cancer_pelvic_pain": Parameter(
Types.REAL, "sensitivity of cytoscopy_for diagnosis of bladder cancer given pelvic pain"
"sensitivity_of_cystoscopy_for_bladder_cancer_pelvic_pain": Parameter(
Types.REAL, "sensitivity of cystoscopy_for diagnosis of bladder cancer given pelvic pain"
)
}

Expand Down Expand Up @@ -374,6 +376,9 @@ def initialise_simulation(self, sim):
* Define the Disability-weights
* Schedule the palliative care appointments for those that are on palliative care at initiation
"""
# We call the following function to store the required consumables for the simulation run within the appropriate
# dictionary
self.item_codes_bladder_can = get_consumable_item_codes_cancers(self)

# ----- SCHEDULE LOGGING EVENTS -----
# Schedule logging event to happen immediately
Expand Down Expand Up @@ -464,17 +469,17 @@ def initialise_simulation(self, sim):
# This properties of conditional on the test being done only to persons with the Symptom, 'blood_urine'.

self.sim.modules['HealthSystem'].dx_manager.register_dx_test(
cytoscopy_for_bladder_cancer_given_blood_urine=DxTest(
cystoscopy_for_bladder_cancer_given_blood_urine=DxTest(
property='bc_status',
sensitivity=self.parameters['sensitivity_of_cytoscopy_for_bladder_cancer_blood_urine'],
sensitivity=self.parameters['sensitivity_of_cystoscopy_for_bladder_cancer_blood_urine'],
target_categories=["tis_t1", "t2p", "metastatic"]
)
)

self.sim.modules['HealthSystem'].dx_manager.register_dx_test(
cytoscopy_for_bladder_cancer_given_pelvic_pain=DxTest(
cystoscopy_for_bladder_cancer_given_pelvic_pain=DxTest(
property='bc_status',
sensitivity=self.parameters['sensitivity_of_cytoscopy_for_bladder_cancer_pelvic_pain'],
sensitivity=self.parameters['sensitivity_of_cystoscopy_for_bladder_cancer_pelvic_pain'],
target_categories=["tis_t1", "t2p", "metastatic"]
)
)
Expand Down Expand Up @@ -705,43 +710,53 @@ def apply(self, person_id, squeeze_factor):
if not pd.isnull(df.at[person_id, "bc_date_diagnosis"]):
return hs.get_blank_appt_footprint()

# Use a cytoscope to diagnose whether the person has bladder Cancer:
dx_result = hs.dx_manager.run_dx_test(
dx_tests_to_run='cytoscopy_for_bladder_cancer_given_blood_urine',
hsi_event=self
)
# Check consumables are available
# TODO: replace with cystoscope
cons_avail = self.get_consumables(item_codes=self.module.item_codes_bladder_can['screening_biopsy_core'],
optional_item_codes=
self.module.item_codes_bladder_can['screening_biopsy_optional'])

if dx_result:
# record date of diagnosis:
df.at[person_id, 'bc_date_diagnosis'] = self.sim.date

# Check if is in metastatic:
in_metastatic = df.at[person_id, 'bc_status'] == 'metastatic'

# If diagnosis detects cancer, we assume classification as metastatic is accurate
if not in_metastatic:
# start treatment:
hs.schedule_hsi_event(
hsi_event=HSI_BladderCancer_StartTreatment(
module=self.module,
person_id=person_id
),
priority=0,
topen=self.sim.date,
tclose=None
)
if cons_avail:
# Use a biopsy to diagnose whether the person has bladder Cancer
# If consumables are available, run the dx_test representing the biopsy

else:
# start palliative care:
hs.schedule_hsi_event(
hsi_event=HSI_BladderCancer_PalliativeCare(
module=self.module,
person_id=person_id
),
priority=0,
topen=self.sim.date,
tclose=None
)
# Use a cystoscope to diagnose whether the person has bladder Cancer:
dx_result = hs.dx_manager.run_dx_test(
dx_tests_to_run='cystoscopy_for_bladder_cancer_given_blood_urine',
hsi_event=self
)

if dx_result:
# record date of diagnosis:
df.at[person_id, 'bc_date_diagnosis'] = self.sim.date

# Check if is in metastatic:
in_metastatic = df.at[person_id, 'bc_status'] == 'metastatic'

# If diagnosis detects cancer, we assume classification as metastatic is accurate
if not in_metastatic:
# start treatment:
hs.schedule_hsi_event(
hsi_event=HSI_BladderCancer_StartTreatment(
module=self.module,
person_id=person_id
),
priority=0,
topen=self.sim.date,
tclose=None
)

else:
# start palliative care:
hs.schedule_hsi_event(
hsi_event=HSI_BladderCancer_PalliativeCare(
module=self.module,
person_id=person_id
),
priority=0,
topen=self.sim.date,
tclose=None
)


class HSI_BladderCancer_Investigation_Following_pelvic_pain(HSI_Event, IndividualScopeEventMixin):
Expand All @@ -768,49 +783,59 @@ def apply(self, person_id, squeeze_factor):
if not pd.isnull(df.at[person_id, "bc_date_diagnosis"]):
return hs.get_blank_appt_footprint()

# Use a cytoscope to diagnose whether the person has bladder Cancer:
dx_result = hs.dx_manager.run_dx_test(
dx_tests_to_run='cytoscopy_for_bladder_cancer_given_pelvic_pain',
hsi_event=self
)
# Check consumables are available
# TODO: replace with cystoscope
cons_avail = self.get_consumables(item_codes=self.module.item_codes_bladder_can['screening_biopsy_core'],
optional_item_codes=self.module.item_codes_bladder_can[
'screening_biopsy_optional'])

if dx_result:
# record date of diagnosis:
df.at[person_id, 'bc_date_diagnosis'] = self.sim.date

# Check if is in metastatic:
in_metastatic = df.at[person_id, 'bc_status'] == 'metastatic'

# If diagnosis detects cancer, we assume classification as metastatic is accurate
if not in_metastatic:
# start treatment:
hs.schedule_hsi_event(
hsi_event=HSI_BladderCancer_StartTreatment(
module=self.module,
person_id=person_id
),
priority=0,
topen=self.sim.date,
tclose=None
)
if cons_avail:
# Use a biopsy to diagnose whether the person has bladder Cancer
# If consumables are available, run the dx_test representing the biopsy

else:
# start palliative care:
hs.schedule_hsi_event(
hsi_event=HSI_BladderCancer_PalliativeCare(
module=self.module,
person_id=person_id
),
priority=0,
topen=self.sim.date,
tclose=None
)
# Use a cystoscope to diagnose whether the person has bladder Cancer:
dx_result = hs.dx_manager.run_dx_test(
dx_tests_to_run='cystoscopy_for_bladder_cancer_given_pelvic_pain',
hsi_event=self
)

if dx_result:
# record date of diagnosis:
df.at[person_id, 'bc_date_diagnosis'] = self.sim.date

# Check if is in metastatic:
in_metastatic = df.at[person_id, 'bc_status'] == 'metastatic'

# If diagnosis detects cancer, we assume classification as metastatic is accurate
if not in_metastatic:
# start treatment:
hs.schedule_hsi_event(
hsi_event=HSI_BladderCancer_StartTreatment(
module=self.module,
person_id=person_id
),
priority=0,
topen=self.sim.date,
tclose=None
)

else:
# start palliative care:
hs.schedule_hsi_event(
hsi_event=HSI_BladderCancer_PalliativeCare(
module=self.module,
person_id=person_id
),
priority=0,
topen=self.sim.date,
tclose=None
)


class HSI_BladderCancer_StartTreatment(HSI_Event, IndividualScopeEventMixin):
"""
Scheduled by HSI_bladderCancer_Investigation_Following_blood_urine or pelvic pain following a
diagnosis of bladder Cancer using cytoscopy. It initiates the treatment of bladder Cancer.
diagnosis of bladder Cancer using cystoscopy. It initiates the treatment of bladder Cancer.
It is only for persons with a cancer that is not in metastatic and who have been diagnosed.
"""
def __init__(self, module, person_id):
Expand Down Expand Up @@ -849,20 +874,28 @@ def apply(self, person_id, squeeze_factor):
assert not pd.isnull(df.at[person_id, "bc_date_diagnosis"])
assert pd.isnull(df.at[person_id, "bc_date_treatment"])

# Record date and stage of starting treatment
df.at[person_id, "bc_date_treatment"] = self.sim.date
df.at[person_id, "bc_stage_at_which_treatment_given"] = df.at[person_id, "bc_status"]

# Schedule a post-treatment check for 12 months:
hs.schedule_hsi_event(
hsi_event=HSI_BladderCancer_PostTreatmentCheck(
module=self.module,
person_id=person_id,
),
topen=self.sim.date + DateOffset(years=12),
tclose=None,
priority=0
)
# Check consumables are available
cons_avail = self.get_consumables(item_codes=self.module.item_codes_bladder_can['treatment_surgery_core'],
optional_item_codes=
self.module.item_codes_bladder_can['treatment_surgery_optional'])

if cons_avail:
# If consumables are available and the treatment will go ahead

# Record date and stage of starting treatment
df.at[person_id, "bc_date_treatment"] = self.sim.date
df.at[person_id, "bc_stage_at_which_treatment_given"] = df.at[person_id, "bc_status"]

# Schedule a post-treatment check for 12 months:
hs.schedule_hsi_event(
hsi_event=HSI_BladderCancer_PostTreatmentCheck(
module=self.module,
person_id=person_id,
),
topen=self.sim.date + DateOffset(years=12),
tclose=None,
priority=0
)


class HSI_BladderCancer_PostTreatmentCheck(HSI_Event, IndividualScopeEventMixin):
Expand Down Expand Up @@ -946,20 +979,27 @@ def apply(self, person_id, squeeze_factor):
# Check that the person is in metastatic
assert df.at[person_id, "bc_status"] == 'metastatic'

# Record the start of palliative care if this is first appointment
if pd.isnull(df.at[person_id, "bc_date_palliative_care"]):
df.at[person_id, "bc_date_palliative_care"] = self.sim.date

# Schedule another instance of the event for one month
hs.schedule_hsi_event(
hsi_event=HSI_BladderCancer_PalliativeCare(
module=self.module,
person_id=person_id
),
topen=self.sim.date + DateOffset(months=1),
tclose=None,
priority=0
)
# Check consumables are available
cons_available = self.get_consumables(
item_codes=self.module.item_codes_bladder_can['palliation'])

if cons_available:
# If consumables are available and the treatment will go ahead

# Record the start of palliative care if this is first appointment
if pd.isnull(df.at[person_id, "bc_date_palliative_care"]):
df.at[person_id, "bc_date_palliative_care"] = self.sim.date

# Schedule another instance of the event for one month
hs.schedule_hsi_event(
hsi_event=HSI_BladderCancer_PalliativeCare(
module=self.module,
person_id=person_id
),
topen=self.sim.date + DateOffset(months=1),
tclose=None,
priority=0
)


# ---------------------------------------------------------------------------------------------------------
Expand Down
Loading

0 comments on commit 4f561a5

Please sign in to comment.