Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

equipment pkgs #1378

Merged
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
Git LFS file not shown
Git LFS file not shown
Original file line number Diff line number Diff line change
Expand Up @@ -322,6 +322,12 @@
.drop_duplicates() \
.pipe(lambda x: x.set_index(x['Item_code'].astype(int)))['Category'] \
.to_dict()
# Manually declare the price category for equipment items added manually
# 402: Endoscope: 'Cost >= $1000'
equipment_price_category_mapper[402] = 'Cost >= $1000'
# 403: Electrocardiogram: 'Cost >= $1000'
equipment_price_category_mapper[403] = 'Cost >= $1000'

equipment_price_category = final_equipment_availability_export_full.index.get_level_values('Item_Code') \
.map(equipment_price_category_mapper)
final_equipment_availability_export_full = final_equipment_availability_export_full.groupby(
Expand Down
4 changes: 1 addition & 3 deletions src/tlo/methods/bladder_cancer.py
Original file line number Diff line number Diff line change
Expand Up @@ -897,9 +897,7 @@ def apply(self, person_id, squeeze_factor):

if cons_avail:
# If consumables are available and the treatment will go ahead - update the equipment
# TODO: DISCUSSED - replace with package and call here
self.add_equipment({'Infusion pump', 'Drip stand', 'Laparotomy Set',
'Blood pressure machine', 'Pulse oximeter'})
self.add_equipment(self.healthcare_system.equipment.from_pkg_names('Major Surgery'))

# Record date and stage of starting treatment
df.at[person_id, "bc_date_treatment"] = self.sim.date
Expand Down
4 changes: 1 addition & 3 deletions src/tlo/methods/breast_cancer.py
Original file line number Diff line number Diff line change
Expand Up @@ -796,9 +796,7 @@ def apply(self, person_id, squeeze_factor):

if cons_available:
# If consumables are available and the treatment will go ahead - add the used equipment
# TODO: DISCUSSED - link to new surgical pacakge
self.add_equipment({'Infusion pump', 'Drip stand', 'Laparotomy Set',
'Blood pressure machine', 'Pulse oximeter'})
self.add_equipment(self.healthcare_system.equipment.from_pkg_names('Major Surgery'))

# Log the use of adjuvant chemotherapy
self.get_consumables(
Expand Down
8 changes: 1 addition & 7 deletions src/tlo/methods/cardio_metabolic_disorders.py
Original file line number Diff line number Diff line change
Expand Up @@ -1799,13 +1799,7 @@ def apply(self, person_id, squeeze_factor):
data=('This is HSI_CardioMetabolicDisorders_SeeksEmergencyCareAndGetsTreatment: '
f'The squeeze-factor is {squeeze_factor}.'),
)
# to do @eva/joe - DISCUSSED, make ICU package and use here
self.add_equipment({'Analyser, Combined Chemistry and Electrolytes',
'Analyser, Haematology',
'Patient monitor', 'Drip stand',
'Infusion pump', 'Blood pressure machine',
'Pulse oximeter', 'Trolley, emergency', 'Stethoscope',
'Oxygen cylinder, with regulator'})
self.add_equipment(self.healthcare_system.equipment.from_pkg_names('ICU'))

for _ev in self.events_to_investigate:
self.do_for_each_event_to_be_investigated(_ev)
Expand Down
25 changes: 11 additions & 14 deletions src/tlo/methods/care_of_women_during_pregnancy.py
Original file line number Diff line number Diff line change
Expand Up @@ -1440,8 +1440,9 @@ def apply(self, person_id, squeeze_factor):

# =================================== INTERVENTIONS ====================================================
# Add equipment used during first ANC visit not directly related to interventions
self.add_equipment(self.healthcare_system.equipment.from_pkg_names('ANC'))
self.add_equipment(
{'Weighing scale', 'Height Pole (Stadiometer)', 'MUAC tape', 'Measuring tapes',
{'Height Pole (Stadiometer)', 'MUAC tape',
'Ultrasound, combined 2/4 pole interferential with vacuum and dual frequency 1-3MHZ'})

# First all women, regardless of ANC contact or gestation, undergo urine and blood pressure measurement
Expand Down Expand Up @@ -1529,9 +1530,9 @@ def apply(self, person_id, squeeze_factor):

# =================================== INTERVENTIONS ====================================================
# Add equipment used during ANC visit not directly related to interventions
self.add_equipment(self.healthcare_system.equipment.from_pkg_names('ANC'))
self.add_equipment(
{'Weighing scale', 'Measuring tapes', 'Stethoscope, foetal, monaural, Pinard, plastic'
'Ultrasound, combined 2/4 pole interferential with vacuum and dual frequency 1-3MHZ'})
{'Ultrasound, combined 2/4 pole interferential with vacuum and dual frequency 1-3MHZ'})

# First we administer the interventions all women will receive at this contact regardless of
# gestational age
Expand Down Expand Up @@ -1617,8 +1618,7 @@ def apply(self, person_id, squeeze_factor):
df.at[person_id, 'ac_total_anc_visits_current_pregnancy'] += 1

# =================================== INTERVENTIONS ====================================================
self.add_equipment({'Weighing scale', 'Measuring tapes',
'Stethoscope, foetal, monaural, Pinard, plastic'})
self.add_equipment(self.healthcare_system.equipment.from_pkg_names('ANC'))

gest_age_next_contact = self.module.determine_gestational_age_for_next_contact(person_id)
self.module.interventions_delivered_each_visit_from_anc2(hsi_event=self)
Expand Down Expand Up @@ -1692,8 +1692,7 @@ def apply(self, person_id, squeeze_factor):
df.at[person_id, 'ac_total_anc_visits_current_pregnancy'] += 1

# =================================== INTERVENTIONS ====================================================
self.add_equipment({'Weighing scale', 'Measuring tapes',
'Stethoscope, foetal, monaural, Pinard, plastic'})
self.add_equipment(self.healthcare_system.equipment.from_pkg_names('ANC'))

gest_age_next_contact = self.module.determine_gestational_age_for_next_contact(person_id)
self.module.interventions_delivered_each_visit_from_anc2(hsi_event=self)
Expand Down Expand Up @@ -1762,10 +1761,10 @@ def apply(self, person_id, squeeze_factor):
self.module.anc_counter[5] += 1
df.at[person_id, 'ac_total_anc_visits_current_pregnancy'] += 1

# =================================== INTERVENTIONS ====================================================
# =================================== INTERVENTIONS ===================================================
self.add_equipment(self.healthcare_system.equipment.from_pkg_names('ANC'))
self.add_equipment(
{'Weighing scale', 'Measuring tapes', 'Stethoscope, foetal, monaural, Pinard, plastic'
'Ultrasound, combined 2/4 pole interferential with vacuum and dual frequency 1-3MHZ'})
{'Ultrasound, combined 2/4 pole interferential with vacuum and dual frequency 1-3MHZ'})

gest_age_next_contact = self.module.determine_gestational_age_for_next_contact(person_id)
self.module.interventions_delivered_each_visit_from_anc2(hsi_event=self)
Expand Down Expand Up @@ -1896,8 +1895,7 @@ def apply(self, person_id, squeeze_factor):
df.at[person_id, 'ac_total_anc_visits_current_pregnancy'] += 1

# =================================== INTERVENTIONS ====================================================
self.add_equipment({'Weighing scale', 'Measuring tapes',
'Stethoscope, foetal, monaural, Pinard, plastic'})
self.add_equipment(self.healthcare_system.equipment.from_pkg_names('ANC'))

gest_age_next_contact = self.module.determine_gestational_age_for_next_contact(person_id)
self.module.interventions_delivered_each_visit_from_anc2(hsi_event=self)
Expand Down Expand Up @@ -1952,8 +1950,7 @@ def apply(self, person_id, squeeze_factor):
self.module.anc_counter[8] += 1
df.at[person_id, 'ac_total_anc_visits_current_pregnancy'] += 1

self.add_equipment({'Weighing scale', 'Measuring tapes',
'Stethoscope, foetal, monaural, Pinard, plastic'})
self.add_equipment(self.healthcare_system.equipment.from_pkg_names('ANC'))

self.module.interventions_delivered_each_visit_from_anc2(hsi_event=self)

Expand Down
2 changes: 1 addition & 1 deletion src/tlo/methods/contraception.py
Original file line number Diff line number Diff line change
Expand Up @@ -1206,7 +1206,7 @@ def apply(self, person_id, squeeze_factor):
self.add_equipment({
'Cusco’s/ bivalved Speculum (small, medium, large)', 'Lamp, Anglepoise'
})
# TO DO: @Eva - DISCUSSED add equip for minor surgery
self.add_equipment(self.healthcare_system.equipment.from_pkg_names('Minor Surgery'))
elif _new_contraceptive == 'IUD':
self.add_equipment({
'Cusco’s/ bivalved Speculum (small, medium, large)', 'Sponge Holding Forceps'
Expand Down
47 changes: 36 additions & 11 deletions src/tlo/methods/equipment.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import warnings
from collections import defaultdict
from typing import Counter, Iterable, Literal, Set, Union
from typing import Counter, Dict, Iterable, Literal, Set, Union

import numpy as np
import pandas as pd
Expand Down Expand Up @@ -77,6 +77,7 @@ def __init__(

# - Data structures for quick look-ups for items and descriptors
self._item_code_lookup = self.catalogue.set_index('Item_Description')['Item_Code'].to_dict()
self._pkg_lookup = self._create_pkg_lookup()
self._all_item_descriptors = set(self._item_code_lookup.keys())
self._all_item_codes = set(self._item_code_lookup.values())
self._all_fac_ids = self.master_facilities_list['Facility_ID'].unique()
Expand Down Expand Up @@ -134,11 +135,11 @@ def parse_items(self, items: Union[int, str, Iterable[int], Iterable[str]]) -> S

def check_item_codes_recognised(item_codes: set[int]):
if not item_codes.issubset(self._all_item_codes):
warnings.warn(f'Item code(s) "{item_codes}" not recognised.')
warnings.warn(f'At least one item code was unrecognised: "{item_codes}".')

def check_item_descriptors_recognised(item_descriptors: set[str]):
if not item_descriptors.issubset(self._all_item_descriptors):
warnings.warn(f'Item descriptor(s) "{item_descriptors}" not recognised.')
warnings.warn(f'At least one item descriptor was unrecognised "{item_descriptors}".')

# Make into a set if it is not one already
if isinstance(items, (str, int)):
Expand Down Expand Up @@ -248,13 +249,37 @@ def set_of_keys_or_empty_set(x: Union[set, dict]):
data=row.to_dict(),
)

def lookup_item_codes_from_pkg_name(self, pkg_name: str) -> Set[int]:
"""Convenience function to find the set of item_codes that are grouped under a package name in the catalogue.
It is expected that this is used by the disease module once and then the resulting equipment item_codes are
saved on the module."""
df = self.catalogue
def from_pkg_names(self, pkg_names: Union[str, Iterable[str]]) -> Set[int]:
"""Convenience function to find the set of item_codes that are grouped under requested package name(s) in the
catalogue."""
# Make into a set if it is not one already
if isinstance(pkg_names, (str, int)):
pkg_names = set([pkg_names])
else:
pkg_names = set(pkg_names)

if pkg_name not in df['Pkg_Name'].unique():
raise ValueError(f'That Pkg_Name is not in the catalogue: {pkg_name=}')
item_codes = set()
for pkg_name in pkg_names:
if pkg_name in self._pkg_lookup.keys():
item_codes.update(self._pkg_lookup[pkg_name])
else:
raise ValueError(f'That Pkg_Name is not in the catalogue: {pkg_name=}')

return item_codes

return set(df.loc[df['Pkg_Name'] == pkg_name, 'Item_Code'].values)
def _create_pkg_lookup(self) -> Dict[str, Set[int]]:
df = self.catalogue
pkg_lookup = dict()

pkg_names_raw = set(df['Pkg_Name'].unique()[~pd.isnull(df['Pkg_Name'].unique())])
all_multiple_pkg_names = set(name for name in pkg_names_raw if ", " in name)
all_pkg_names = pkg_names_raw - all_multiple_pkg_names
for pkg_name in all_pkg_names:
pkg_lookup[pkg_name] = set(df.loc[df['Pkg_Name'] == pkg_name, 'Item_Code'].values)
for multiple_pkg_name in all_multiple_pkg_names:
for pkg_name in multiple_pkg_name.split(", "):
if pkg_name not in all_pkg_names:
pkg_lookup[pkg_name] = set()
all_pkg_names.update({pkg_name})
pkg_lookup[pkg_name].update(set(df.loc[df['Pkg_Name'] == multiple_pkg_name, 'Item_Code'].values))
return pkg_lookup
8 changes: 2 additions & 6 deletions src/tlo/methods/labour.py
Original file line number Diff line number Diff line change
Expand Up @@ -2128,9 +2128,7 @@ def surgical_management_of_pph(self, hsi_event):
if avail and sf_check:

# Add used equipment
# Todo: DISCUSSED - @eva surgical package
hsi_event.add_equipment(
{'Infusion pump', 'Drip stand', 'Laparotomy Set', 'Blood pressure machine', 'Pulse oximeter'})
hsi_event.add_equipment(self.healthcare_system.equipment.from_pkg_names('Major Surgery'))

# determine if uterine preserving surgery will be successful
treatment_success_pph = params['success_rate_pph_surgery'] > self.rng.random_sample()
Expand Down Expand Up @@ -3236,9 +3234,7 @@ def apply(self, person_id, squeeze_factor):
elif (avail and sf_check) or (mni[person_id]['cs_indication'] == 'other'):

# If intervention is delivered - add used equipment
# todo: DISCUSSED @Eva link to surgical equipment package when that exsists
self.add_equipment(
{'Infusion pump', 'Drip stand', 'Laparotomy Set', 'Blood pressure machine', 'Pulse oximeter'})
self.add_equipment(self.healthcare_system.equipment.from_pkg_names('Major Surgery'))

person = df.loc[person_id]
logger.info(key='caesarean_delivery', data=person.to_dict())
Expand Down
4 changes: 1 addition & 3 deletions src/tlo/methods/oesophagealcancer.py
Original file line number Diff line number Diff line change
Expand Up @@ -784,9 +784,7 @@ def apply(self, person_id, squeeze_factor):

if cons_avail:
# If consumables are available and the treatment will go ahead - update the equipment
# TODO: DISCUSSED - add surgery package
self.add_equipment({'Infusion pump', 'Drip stand', 'Laparotomy Set',
'Blood pressure machine', 'Pulse oximeter'})
self.add_equipment(self.healthcare_system.equipment.from_pkg_names('Major Surgery'))

# Log chemotherapy consumables
self.get_consumables(
Expand Down
4 changes: 1 addition & 3 deletions src/tlo/methods/other_adult_cancers.py
Original file line number Diff line number Diff line change
Expand Up @@ -786,9 +786,7 @@ def apply(self, person_id, squeeze_factor):

if cons_available:
# If consumables are available and the treatment will go ahead - update the equipment
# TODO: DISCUSSED - link to surgical equipment package when that exists
self.add_equipment({'Infusion pump', 'Drip stand', 'Laparotomy Set',
'Blood pressure machine', 'Pulse oximeter'})
self.add_equipment(self.healthcare_system.equipment.from_pkg_names('Major Surgery'))

# Record date and stage of starting treatment
df.at[person_id, "oac_date_treatment"] = self.sim.date
Expand Down
4 changes: 1 addition & 3 deletions src/tlo/methods/prostate_cancer.py
Original file line number Diff line number Diff line change
Expand Up @@ -918,9 +918,7 @@ def apply(self, person_id, squeeze_factor):

if cons_available:
# If consumables are available and the treatment will go ahead - update the equipment
# TODO: DISCUSSED -link to surgical equipment package when that exists
self.add_equipment({'Infusion pump', 'Drip stand', 'Laparotomy Set',
'Blood pressure machine', 'Pulse oximeter'})
self.add_equipment(self.healthcare_system.equipment.from_pkg_names('Major Surgery'))

# Record date and stage of starting treatment
df.at[person_id, "pc_date_treatment"] = self.sim.date
Expand Down
25 changes: 9 additions & 16 deletions src/tlo/methods/rti.py
Original file line number Diff line number Diff line change
Expand Up @@ -3205,8 +3205,7 @@ def apply(self, person_id, squeeze_factor):
road_traffic_injuries.rti_injury_diagnosis(person_id, self.EXPECTED_APPT_FOOTPRINT)

if 'DiagRadio' in list(self.EXPECTED_APPT_FOOTPRINT.keys()):
# TODO: @Eva - DISCUSSED use xray package when available
self.add_equipment({'X-ray machine', 'X-ray viewer'})
self.add_equipment(self.healthcare_system.equipment.from_pkg_names('X-ray'))

elif 'Tomography' in list(self.EXPECTED_APPT_FOOTPRINT.keys()):
self.ACCEPTED_FACILITY_LEVEL = '3'
Expand Down Expand Up @@ -3513,13 +3512,7 @@ def apply(self, person_id, squeeze_factor):

if df.loc[person_id, 'rt_ISS_score'] > self.hdu_cut_off_iss_score:

# to do @eva/joe - DISCUSSED, make ICU package and use here
self.add_equipment({'Analyser, Combined Chemistry and Electrolytes',
'Analyser, Haematology',
'Patient monitor', 'Drip stand',
'Infusion pump', 'Blood pressure machine',
'Pulse oximeter', 'Trolley, emergency', 'Stethoscope',
'Oxygen cylinder, with regulator'})
self.add_equipment(self.healthcare_system.equipment.from_pkg_names('ICU'))

mean_icu_days = p['mean_icu_days']
sd_icu_days = p['sd_icu_days']
Expand Down Expand Up @@ -4099,9 +4092,7 @@ def apply(self, person_id, squeeze_factor):
data=f"Fracture casts available for person {person_id} {open_fracture_counts} open fractures"
)

# Todo: DISCUSSED @Eva link to surgical equipment package when that exsists
self.add_equipment(
{'Infusion pump', 'Drip stand', 'Laparotomy Set', 'Blood pressure machine', 'Pulse oximeter'})
self.add_equipment(self.healthcare_system.equipment.from_pkg_names('Major Surgery'))

person = df.loc[person_id]
# update the dataframe to show this person is recieving treatment
Expand Down Expand Up @@ -4823,8 +4814,9 @@ def apply(self, person_id, squeeze_factor):
assert df.loc[person_id, 'rt_diagnosed'], 'This person has not been through a and e'
assert df.loc[person_id, 'rt_med_int'], 'This person has not been through rti med int'

# TODO: @eva - DISCUSSED @eva add surgical package
self.add_equipment({'Laparotomy Set', 'Infusion pump', 'Drip stand'})
# TODO: @Joe to confirm major surgery pkg should be used here (as the original set of equipment here was not
# the full pkg)
self.add_equipment(self.healthcare_system.equipment.from_pkg_names('Major Surgery'))

# ------------------------ Track permanent disabilities with treatment -------------------------------------
# --------------------------------- Perm disability from TBI -----------------------------------------------
Expand Down Expand Up @@ -5141,8 +5133,9 @@ def apply(self, person_id, squeeze_factor):
# todo: think about consequences of certain consumables not being available for minor surgery and model health
# outcomes
if request_outcome:
# TODO: DISCUSSED @Eva link to surgical equipment package when that exists
self.add_equipment({'Laparotomy Set', 'Infusion pump', 'Drip stand'})
# TODO: @Joe to confirm major surgery pkg should be used here (as the original set of equipment here was not
# the full pkg)
self.add_equipment(self.healthcare_system.equipment.from_pkg_names('Major Surgery'))

# create a dictionary to store the recovery times for each injury in days
minor_surg_recov_time_days = {
Expand Down
Loading
Loading