Skip to content

Commit f5251b6

Browse files
authored
Equipment: Integration into modules (#1341)
1 parent 802c364 commit f5251b6

27 files changed

+330
-104
lines changed
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
version https://git-lfs.github.com/spec/v1
2-
oid sha256:3e151e16f7eea2ae61d2fa637c26449aa533ddc6a7f0d83aff495f5f6c9d1f8d
3-
size 33201
2+
oid sha256:ec5f619816df6150ae92839152607296a5f2289024c92ce6b5ba621d38db20b7
3+
size 33517
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
version https://git-lfs.github.com/spec/v1
2-
oid sha256:e31936377f6b90779ad66480c4bc477cdca9322e86f2e00d202bbb91eebf6d57
3-
size 1306170
2+
oid sha256:2785365d20a4da4c147ba6a5df9e0259c9076df0fec556086aea0f2a068c9c53
3+
size 1313098

src/scripts/data_file_processing/healthsystem/equipment/equipment_availability_estimation.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -322,6 +322,12 @@
322322
.drop_duplicates() \
323323
.pipe(lambda x: x.set_index(x['Item_code'].astype(int)))['Category'] \
324324
.to_dict()
325+
# Manually declare the price category for equipment items added manually
326+
# 402: Endoscope: 'Cost >= $1000'
327+
equipment_price_category_mapper[402] = 'Cost >= $1000'
328+
# 403: Electrocardiogram: 'Cost >= $1000'
329+
equipment_price_category_mapper[403] = 'Cost >= $1000'
330+
325331
equipment_price_category = final_equipment_availability_export_full.index.get_level_values('Item_Code') \
326332
.map(equipment_price_category_mapper)
327333
final_equipment_availability_export_full = final_equipment_availability_export_full.groupby(

src/tlo/methods/alri.py

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2551,6 +2551,8 @@ def _get_disease_classification_for_treatment_decision(self,
25512551
'chest_indrawing_pneumonia', (symptoms-based assessment)
25522552
'cough_or_cold' (symptoms-based assessment)
25532553
}."""
2554+
if use_oximeter:
2555+
self.add_equipment({'Pulse oximeter'})
25542556

25552557
child_is_younger_than_2_months = age_exact_years < (2.0 / 12.0)
25562558

@@ -2606,6 +2608,15 @@ def _try_treatment(antibiotic_indicated: Tuple[str], oxygen_indicated: bool) ->
26062608
oxygen_available = self._get_cons('Oxygen_Therapy')
26072609
oxygen_provided = (oxygen_available and oxygen_indicated)
26082610

2611+
# If individual is provided with oxygen, add used equipment
2612+
if oxygen_provided:
2613+
self.add_equipment({'Oxygen cylinder, with regulator', 'Nasal Prongs'})
2614+
2615+
# If individual is provided with intravenous antibiotics, add used equipment
2616+
if antibiotic_provided in ('1st_line_IV_antibiotics',
2617+
'Benzylpenicillin_gentamicin_therapy_for_severe_pneumonia'):
2618+
self.add_equipment({'Infusion pump', 'Drip stand'})
2619+
26092620
all_things_needed_available = antibiotic_available and (
26102621
(oxygen_available and oxygen_indicated) or (not oxygen_indicated)
26112622
)
@@ -2687,16 +2698,20 @@ def _provide_bronchodilator_if_wheeze(self, facility_level, symptoms):
26872698
if facility_level == '1a':
26882699
_ = self._get_cons('Inhaled_Brochodilator')
26892700
else:
2701+
# n.b. this is never called, see issue 1172
26902702
_ = self._get_cons('Brochodilator_and_Steroids')
26912703

26922704
def do_on_follow_up_following_treatment_failure(self):
26932705
"""Things to do for a patient who is having this HSI following a failure of an earlier treatment.
26942706
A further drug will be used but this will have no effect on the chance of the person dying."""
26952707

26962708
if self._has_staph_aureus():
2697-
_ = self._get_cons('2nd_line_Antibiotic_therapy_for_severe_staph_pneumonia')
2709+
cons_avail = self._get_cons('2nd_line_Antibiotic_therapy_for_severe_staph_pneumonia')
26982710
else:
2699-
_ = self._get_cons('Ceftriaxone_therapy_for_severe_pneumonia')
2711+
cons_avail = self._get_cons('Ceftriaxone_therapy_for_severe_pneumonia')
2712+
2713+
if cons_avail:
2714+
self.add_equipment({'Infusion pump', 'Drip stand'})
27002715

27012716
def apply(self, person_id, squeeze_factor):
27022717
"""Assess and attempt to treat the person."""

src/tlo/methods/bladder_cancer.py

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -725,14 +725,14 @@ def apply(self, person_id, squeeze_factor):
725725
return hs.get_blank_appt_footprint()
726726

727727
# Check consumables are available
728-
# TODO: replace with cystoscope
729-
cons_avail = self.get_consumables(item_codes=self.module.item_codes_bladder_can['screening_biopsy_core'],
730-
optional_item_codes=
731-
self.module.item_codes_bladder_can['screening_biopsy_optional'])
728+
cons_avail = self.get_consumables(item_codes=self.module.item_codes_bladder_can['screening_cystoscopy_core'],
729+
optional_item_codes=self.module.item_codes_bladder_can[
730+
'screening_biopsy_endoscopy_cystoscopy_optional'])
732731

733732
if cons_avail:
734733
# Use a biopsy to diagnose whether the person has bladder Cancer
735-
# If consumables are available, run the dx_test representing the biopsy
734+
# If consumables are available update the use of equipment and run the dx_test representing the biopsy
735+
self.add_equipment({'Cystoscope', 'Ordinary Microscope', 'Ultrasound scanning machine'})
736736

737737
# Use a cystoscope to diagnose whether the person has bladder Cancer:
738738
dx_result = hs.dx_manager.run_dx_test(
@@ -798,14 +798,14 @@ def apply(self, person_id, squeeze_factor):
798798
return hs.get_blank_appt_footprint()
799799

800800
# Check consumables are available
801-
# TODO: replace with cystoscope
802-
cons_avail = self.get_consumables(item_codes=self.module.item_codes_bladder_can['screening_biopsy_core'],
801+
cons_avail = self.get_consumables(item_codes=self.module.item_codes_bladder_can['screening_cystoscopy_core'],
803802
optional_item_codes=self.module.item_codes_bladder_can[
804-
'screening_biopsy_optional'])
803+
'screening_biopsy_endoscopy_cystoscopy_optional'])
805804

806805
if cons_avail:
807806
# Use a biopsy to diagnose whether the person has bladder Cancer
808-
# If consumables are available, run the dx_test representing the biopsy
807+
# If consumables are available log the use of equipment and run the dx_test representing the biopsy
808+
self.add_equipment({'Cystoscope', 'Ordinary Microscope', 'Ultrasound scanning machine'})
809809

810810
# Use a cystoscope to diagnose whether the person has bladder Cancer:
811811
dx_result = hs.dx_manager.run_dx_test(
@@ -894,7 +894,8 @@ def apply(self, person_id, squeeze_factor):
894894
self.module.item_codes_bladder_can['treatment_surgery_optional'])
895895

896896
if cons_avail:
897-
# If consumables are available and the treatment will go ahead
897+
# If consumables are available and the treatment will go ahead - update the equipment
898+
self.add_equipment(self.healthcare_system.equipment.from_pkg_names('Major Surgery'))
898899

899900
# Record date and stage of starting treatment
900901
df.at[person_id, "bc_date_treatment"] = self.sim.date
@@ -998,7 +999,8 @@ def apply(self, person_id, squeeze_factor):
998999
item_codes=self.module.item_codes_bladder_can['palliation'])
9991000

10001001
if cons_available:
1001-
# If consumables are available and the treatment will go ahead
1002+
# If consumables are available and the treatment will go ahead - update the equipment
1003+
self.add_equipment({'Infusion pump', 'Drip stand'})
10021004

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

src/tlo/methods/breast_cancer.py

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -696,11 +696,13 @@ def apply(self, person_id, squeeze_factor):
696696
# Check consumables to undertake biopsy are available
697697
cons_avail = self.get_consumables(item_codes=self.module.item_codes_breast_can['screening_biopsy_core'],
698698
optional_item_codes=
699-
self.module.item_codes_breast_can['screening_biopsy_optional'])
699+
self.module.item_codes_breast_can[
700+
'screening_biopsy_endoscopy_cystoscopy_optional'])
700701

701702
if cons_avail:
702703
# Use a biopsy to diagnose whether the person has breast Cancer
703-
# If consumables are available, run the dx_test representing the biopsy
704+
# If consumables are available, add the used equipment and run the dx_test representing the biopsy
705+
self.add_equipment({'Ultrasound scanning machine', 'Ordinary Microscope'})
704706

705707
dx_result = hs.dx_manager.run_dx_test(
706708
dx_tests_to_run='biopsy_for_breast_cancer_given_breast_lump_discernible',
@@ -764,8 +766,6 @@ def apply(self, person_id, squeeze_factor):
764766
df = self.sim.population.props
765767
hs = self.sim.modules["HealthSystem"]
766768

767-
# todo: request consumables needed for this
768-
769769
if not df.at[person_id, 'is_alive']:
770770
return hs.get_blank_appt_footprint()
771771

@@ -798,7 +798,9 @@ def apply(self, person_id, squeeze_factor):
798798
)
799799

800800
if cons_available:
801-
# If consumables, treatment will go ahead
801+
# If consumables are available and the treatment will go ahead - add the used equipment
802+
self.add_equipment(self.healthcare_system.equipment.from_pkg_names('Major Surgery'))
803+
802804
# Log the use of adjuvant chemotherapy
803805
self.get_consumables(
804806
item_codes=self.module.item_codes_breast_can['treatment_chemotherapy'],
@@ -906,7 +908,8 @@ def apply(self, person_id, squeeze_factor):
906908
item_codes=self.module.item_codes_breast_can['palliation'])
907909

908910
if cons_available:
909-
# If consumables are available and the treatment will go ahead
911+
# If consumables are available and the treatment will go ahead - add the used equipment
912+
self.add_equipment({'Infusion pump', 'Drip stand'})
910913

911914
# Record the start of palliative care if this is first appointment
912915
if pd.isnull(df.at[person_id, "brc_date_palliative_care"]):

src/tlo/methods/cancer_consumables.py

Lines changed: 5 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -15,16 +15,16 @@ def get_consumable_item_codes_cancers(self) -> Dict[str, int]:
1515
cons_dict = dict()
1616

1717
# Add items that are needed for all cancer modules
18-
cons_dict['screening_biopsy_core'] = \
19-
{get_item_code("Biopsy needle"): 1}
20-
21-
cons_dict['screening_biopsy_optional'] = \
18+
cons_dict['screening_biopsy_endoscopy_cystoscopy_optional'] = \
2219
{get_item_code("Specimen container"): 1,
2320
get_item_code("Lidocaine HCl (in dextrose 7.5%), ampoule 2 ml"): 1,
2421
get_item_code("Gauze, absorbent 90cm x 40m_each_CMST"): 30,
2522
get_item_code("Disposables gloves, powder free, 100 pieces per box"): 1,
2623
get_item_code("Syringe, needle + swab"): 1}
2724

25+
cons_dict['screening_biopsy_core'] = \
26+
{get_item_code("Biopsy needle"): 1}
27+
2828
cons_dict['treatment_surgery_core'] = \
2929
{get_item_code("Halothane (fluothane)_250ml_CMST"): 100,
3030
get_item_code("Scalpel blade size 22 (individually wrapped)_100_CMST"): 1}
@@ -69,23 +69,9 @@ def get_consumable_item_codes_cancers(self) -> Dict[str, int]:
6969
cons_dict['screening_cystoscopy_core'] = \
7070
{get_item_code("Cystoscope"): 1}
7171

72-
cons_dict['screening_cystoscope_optional'] = \
73-
{get_item_code("Specimen container"): 1,
74-
get_item_code("Lidocaine HCl (in dextrose 7.5%), ampoule 2 ml"): 1,
75-
get_item_code("Gauze, absorbent 90cm x 40m_each_CMST"): 30,
76-
get_item_code("Disposables gloves, powder free, 100 pieces per box"): 1,
77-
get_item_code("Syringe, needle + swab"): 1}
78-
7972
elif 'OesophagealCancer' == self.name:
8073

81-
cons_dict['screening_endoscope_core'] = \
74+
cons_dict['screening_endoscopy_core'] = \
8275
{get_item_code("Endoscope"): 1}
8376

84-
cons_dict['screening_endoscope_optional'] = \
85-
{get_item_code("Specimen container"): 1,
86-
get_item_code("Gauze, absorbent 90cm x 40m_each_CMST"): 30,
87-
get_item_code("Lidocaine HCl (in dextrose 7.5%), ampoule 2 ml"): 1,
88-
get_item_code("Disposables gloves, powder free, 100 pieces per box"): 1,
89-
get_item_code("Syringe, needle + swab"): 1}
90-
9177
return cons_dict

src/tlo/methods/cardio_metabolic_disorders.py

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1435,6 +1435,7 @@ def apply(self, person_id, squeeze_factor):
14351435
return hs.get_blank_appt_footprint()
14361436

14371437
# Run a test to diagnose whether the person has condition:
1438+
self.add_equipment({'Blood pressure machine'})
14381439
dx_result = hs.dx_manager.run_dx_test(
14391440
dx_tests_to_run='assess_hypertension',
14401441
hsi_event=self
@@ -1487,6 +1488,9 @@ def do_for_each_condition(self, _c) -> bool:
14871488
if df.at[person_id, f'nc_{_c}_ever_diagnosed']:
14881489
return
14891490

1491+
if _c == 'chronic_ischemic_heart_disease':
1492+
self.add_equipment({'Electrocardiogram', 'Stethoscope'})
1493+
14901494
# Run a test to diagnose whether the person has condition:
14911495
dx_result = hs.dx_manager.run_dx_test(
14921496
dx_tests_to_run=f'assess_{_c}',
@@ -1519,6 +1523,11 @@ def apply(self, person_id, squeeze_factor):
15191523
return hs.get_blank_appt_footprint()
15201524

15211525
# Do test and trigger treatment (if necessary) for each condition:
1526+
if set(self.conditions_to_investigate).intersection(
1527+
['diabetes', 'chronic_kidney_disease', 'chronic_ischemic_hd']
1528+
):
1529+
self.add_equipment({'Analyser, Haematology', 'Analyser, Combined Chemistry and Electrolytes'})
1530+
15221531
hsi_scheduled = [self.do_for_each_condition(_c) for _c in self.conditions_to_investigate]
15231532

15241533
# If no follow-up treatment scheduled but the person has at least 2 risk factors, start weight loss treatment
@@ -1542,6 +1551,7 @@ def apply(self, person_id, squeeze_factor):
15421551
and (self.module.rng.rand() < self.module.parameters['hypertension_hsi']['pr_assessed_other_symptoms'])
15431552
):
15441553
# Run a test to diagnose whether the person has condition:
1554+
self.add_equipment({'Blood pressure machine'})
15451555
dx_result = hs.dx_manager.run_dx_test(
15461556
dx_tests_to_run='assess_hypertension',
15471557
hsi_event=self
@@ -1589,6 +1599,8 @@ def apply(self, person_id, squeeze_factor):
15891599

15901600
# Don't advise those with CKD to lose weight, but do so for all other conditions if BMI is higher than normal
15911601
if self.condition != 'chronic_kidney_disease' and (df.at[person_id, 'li_bmi'] > 2):
1602+
self.add_equipment({'Weighing scale'})
1603+
15921604
self.sim.population.props.at[person_id, 'nc_ever_weight_loss_treatment'] = True
15931605
# Schedule a post-weight loss event for individual to potentially lose weight in next 6-12 months:
15941606
self.sim.schedule_event(CardioMetabolicDisordersWeightLossEvent(m, person_id),
@@ -1749,6 +1761,12 @@ def do_for_each_event_to_be_investigated(self, _ev):
17491761
df = self.sim.population.props
17501762

17511763
# Run a test to diagnose whether the person has condition:
1764+
if _ev == 'ever_stroke':
1765+
self.add_equipment({'Computed Tomography (CT machine)', 'CT scanner accessories'})
1766+
1767+
if _ev == 'ever_heart_attack':
1768+
self.add_equipment({'Electrocardiogram'})
1769+
17521770
dx_result = self.sim.modules['HealthSystem'].dx_manager.run_dx_test(
17531771
dx_tests_to_run=f'assess_{_ev}',
17541772
hsi_event=self
@@ -1808,6 +1826,7 @@ def apply(self, person_id, squeeze_factor):
18081826
data=('This is HSI_CardioMetabolicDisorders_SeeksEmergencyCareAndGetsTreatment: '
18091827
f'The squeeze-factor is {squeeze_factor}.'),
18101828
)
1829+
self.add_equipment(self.healthcare_system.equipment.from_pkg_names('ICU'))
18111830

18121831
for _ev in self.events_to_investigate:
18131832
self.do_for_each_event_to_be_investigated(_ev)

0 commit comments

Comments
 (0)