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

Editing units of consumable required for each HSI #1298

Merged
merged 67 commits into from
Jun 6, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
67 commits
Select commit Hold shift + click to select a range
c2c6949
add latest version of costing resource file
Mar 13, 2024
dbcf1fb
add latest version of costing resource file
Mar 24, 2024
1d21999
update Gentamycin (units)
Mar 24, 2024
ba0f658
update item quantities for HIV prep and infant prep
tdm32 Mar 25, 2024
ae1dc16
update 1g to 1mg for Albendazole (Item code 52)
Mar 26, 2024
fcee467
update units for gloves from 1 glove to "1 pair of gloves"
Mar 26, 2024
c352bee
update item quantities for TB drugs
tdm32 Mar 27, 2024
7d67c5c
add conditions for each IPT recommendation
tdm32 Mar 27, 2024
ae0d18f
add prices for ARVs
Mar 28, 2024
c666e50
add Isoniazid/Rifapentine to `ResourceFile_Consumables_Items_and_Pack…
Mar 28, 2024
2667397
add Isoniazid/Rifapentine to all relevant RFs
Apr 3, 2024
ab7328a
Update to the functionality for requesting consumables across the MNH…
joehcollins Apr 5, 2024
0126a6b
fixes to failing tests
joehcollins Apr 5, 2024
ebd9495
linting
joehcollins Apr 5, 2024
ccdab82
linting
joehcollins Apr 5, 2024
ef2d344
change cotrimoxazole units to mg
tdm32 Apr 10, 2024
d357192
Merge branch 'consumables/editing_units_required' into consumables/ed…
tdm32 Apr 10, 2024
2f11f24
merge in updated unit costs
tdm32 Apr 10, 2024
48104b0
added dosage for amitriptyline antidepressant treatment
joehcollins Apr 11, 2024
c11b707
added dosage for epilepsy treatment
joehcollins Apr 11, 2024
0ac40bb
fix error in postnatal_supervisor.py leading to failing test
joehcollins Apr 11, 2024
3535a58
units added for care_of_women_during_pregnancy.py
joehcollins Apr 11, 2024
ff4e29a
units added for care_of_women_during_pregnancy.py
joehcollins Apr 11, 2024
26a7025
units added for labour.py
joehcollins Apr 11, 2024
789bf21
fix failing test. initial doses for newborn outcomes/postnatal superv…
joehcollins Apr 11, 2024
1e77564
fix failing test. initial doses for newborn outcomes/postnatal superv…
joehcollins Apr 17, 2024
4762314
Merge remote-tracking branch 'origin/consumables/editing_units_requir…
Apr 18, 2024
06cec42
delete temporary ~ file created
Apr 18, 2024
9821cfc
update units of safety box to "1 disposed syringe (100 syringes per b…
Apr 18, 2024
0a63924
fix failing test. initial doses for newborn outcomes/postnatal superv…
joehcollins Apr 17, 2024
82ec04e
fixed error in labour. COPD consumable unites
joehcollins May 14, 2024
ae8615d
remove consumable packages from diarrhoea.py
joehcollins May 14, 2024
a967850
diarrhoea.py consumable units
joehcollins May 14, 2024
a80e389
cmd.py consumable units
joehcollins May 15, 2024
08cfa42
rti.py consumable units
joehcollins May 15, 2024
e456975
Merge branch 'refs/heads/master' into consumables/editing_units_required
tbhallett May 16, 2024
6bdf8c6
alri.py consumable units plus fixed error in diarrhoea.py
joehcollins May 17, 2024
7625c77
co: get item codes of consumables from item names and define number o…
EvaJanouskova May 20, 2024
dc0b8ac
Add cystoscope, endoscope and prostate specific antigen test
May 21, 2024
3b14bfa
Merge remote-tracking branch 'origin/consumables/editing_units_requir…
May 21, 2024
4600b19
co: alternative consumables chosen by probs
Mar 5, 2024
48401d8
co: 21 tablets per packet for both types of pills (informed by Emi)
EvaJanouskova May 29, 2024
534b9d8
co: update TODOs
EvaJanouskova May 29, 2024
275dc45
cancer_cons: consumables updated and required units per case defined …
EvaJanouskova May 29, 2024
4b721a7
[no ci] cancer_cons: rm outdated TODOs
EvaJanouskova May 30, 2024
e20b794
[no ci] co: rm resolved TODOs
EvaJanouskova May 30, 2024
9bf704e
Merge remote-tracking branch 'origin/consumables/editing_units_requir…
EvaJanouskova May 30, 2024
b7f61b8
co: rm TODOs as opened an issue to resolve them (#1384)
EvaJanouskova May 30, 2024
5e3d5c0
cancers: missing arguments added
EvaJanouskova May 30, 2024
108dd72
add availability data cancer consumables
May 30, 2024
85516ea
Merge remote-tracking branch 'origin/consumables/editing_units_requir…
May 30, 2024
2a6dac4
Revert "cancers: missing arguments added"
EvaJanouskova May 30, 2024
4a1a4c2
cancer_cons: rm get_consumable_item_codes_cancers() argument
EvaJanouskova May 30, 2024
46ab68d
cancer_cons: names corrections -- item & consumables set
EvaJanouskova May 30, 2024
af82463
Merge branch 'refs/heads/master' into consumables/editing_units_required
tbhallett May 31, 2024
b6a9c94
add depn to health system to copd
tbhallett May 31, 2024
db6ef66
remove packing with dict
tbhallett May 31, 2024
9aeff85
refactoring and adding todo
tbhallett May 31, 2024
4228adf
fix misnamed tb consumable
tbhallett May 31, 2024
a63e731
roll back file added by accident
tbhallett May 31, 2024
55b5e7d
test_co & co: alternatives rolled back
EvaJanouskova May 31, 2024
e7e7686
roll back second output
tbhallett May 31, 2024
991c376
Merge branch 'refs/heads/master' into consumables/editing_units_required
tbhallett Jun 3, 2024
cf015e9
simplify _get_cons_group as no longer changing dose by age
tbhallett Jun 3, 2024
e729e84
remove todo, now resolved
tbhallett Jun 3, 2024
c31c118
linting and removed completed todo
tbhallett Jun 3, 2024
98bcc01
linting
tbhallett Jun 3, 2024
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
3 changes: 3 additions & 0 deletions resources/costing/ResourceFile_Costing.xlsx
Git LFS file not shown
Git LFS file not shown
Git LFS file not shown
Git LFS file not shown
Original file line number Diff line number Diff line change
Expand Up @@ -277,14 +277,10 @@ def custom_agg(x):
return _collapsed_df

# Hold out the dataframe with no naming inconsistencies
list_of_items_with_inconsistent_names_zipped = list(
zip(inconsistent_item_names_mapping.keys(), inconsistent_item_names_mapping.values()))
list_of_items_with_inconsistent_names = [
item for sublist in list_of_items_with_inconsistent_names_zipped for item in sublist]
df_with_consistent_item_names = lmis_df_wide_flat[~lmis_df_wide_flat[('item',)].isin(
list_of_items_with_inconsistent_names)]
df_without_consistent_item_names = lmis_df_wide_flat[lmis_df_wide_flat[('item',)].isin(
list_of_items_with_inconsistent_names)]
list_of_items_with_inconsistent_names_zipped = set(zip(inconsistent_item_names_mapping.keys(), inconsistent_item_names_mapping.values()))
list_of_items_with_inconsistent_names = [item for sublist in list_of_items_with_inconsistent_names_zipped for item in sublist]
df_with_consistent_item_names = lmis_df_wide_flat[~lmis_df_wide_flat[('item',)].isin(list_of_items_with_inconsistent_names)]
df_without_consistent_item_names = lmis_df_wide_flat[lmis_df_wide_flat[('item',)].isin(list_of_items_with_inconsistent_names)]
Comment on lines +280 to +283
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

check these were the changes Sakshi intended.

# Make inconsistently named drugs uniform across the dataframe
df_without_consistent_item_names_corrected = rename_items_to_address_inconsistentencies(
df_without_consistent_item_names, inconsistent_item_names_mapping)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,8 @@

# Set local Dropbox source
path_to_dropbox = Path( # <-- point to the TLO dropbox locally
'/Users/tbh03/Dropbox (SPH Imperial College)/Thanzi la Onse Theme 1 SHARE')
# '/Users/tbh03/Dropbox (SPH Imperial College)/Thanzi la Onse Theme 1 SHARE'
'/Users/sm2511/Dropbox/Thanzi La Onse')

resourcefilepath = Path("./resources")
path_for_new_resourcefiles = resourcefilepath / "healthsystem/consumables"
Expand Down Expand Up @@ -245,7 +246,7 @@

def add_record(df: pd.DataFrame, record: Dict):
"""Add a row to the bottom of the dataframe, where the row is specified by a dict keyed by the target columns."""
assert list(df.columns) == list(record.keys())
assert set(df.columns) == set(record.keys())
return pd.concat([df, pd.DataFrame.from_records([record])], ignore_index=True)


Expand Down Expand Up @@ -328,6 +329,54 @@ def add_record(df: pd.DataFrame, record: Dict):
},
)

cons = add_record(
cons,
{
'Intervention_Cat': "Added by SM (Recommended by TM)",
'Intervention_Pkg': "Isoniazid preventative therapy for HIV+ no TB",
'Intervention_Pkg_Code': 82,
'Items': "Isoniazid/Rifapentine",
'Item_Code': 2678,
'Expected_Units_Per_Case': 1.0,
'Unit_Cost': 1.0
},
)

cons = add_record(
cons,
{
'Intervention_Cat': "Added by SM (Recommended by EJ)",
'Intervention_Pkg': "Misc",
'Intervention_Pkg_Code': -99,
'Items': "Cystoscope",
'Item_Code': 285,
'Expected_Units_Per_Case': 1.0,
'Unit_Cost': np.nan},
)

cons = add_record(
cons,{
'Intervention_Cat': "Added by SM (Recommended by EJ)",
'Intervention_Pkg': "Misc",
'Intervention_Pkg_Code': -99,
'Items': "Endoscope",
'Item_Code': 280,
'Expected_Units_Per_Case': 1.0,
'Unit_Cost': np.nan},
)

cons = add_record(
cons,{
'Intervention_Cat': "Added by SM (Recommended by EJ)",
'Intervention_Pkg': "Misc",
'Intervention_Pkg_Code': -99,
'Items': "Prostate specific antigen test",
'Item_Code': 281,
'Expected_Units_Per_Case': 1.0,
'Unit_Cost': np.nan},
)


# --------------
# --------------
# --------------
Expand Down
139 changes: 36 additions & 103 deletions src/tlo/methods/alri.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@
"""
from __future__ import annotations

import types
from collections import defaultdict
from itertools import chain
from pathlib import Path
Expand Down Expand Up @@ -1014,139 +1013,85 @@ def look_up_consumables(self):

get_item_code = self.sim.modules['HealthSystem'].get_item_code_from_item_name

def get_dosage_for_age_in_months(age_in_whole_months: float, doses_by_age_in_months: Dict[int, float]):
"""Returns the dose corresponding to age, using the lookup provided in `doses`. The format of `doses` is:
{<higher_age_boundary_of_age_group_in_months>: <dose>}."""

for upper_age_bound_in_months, _dose in sorted(doses_by_age_in_months.items()):
if age_in_whole_months < upper_age_bound_in_months:
return _dose
return _dose

# # # # # # Dosages by age # # # # # #
# # # # # # Dosages by weight # # # # # #
# Assuming average weight of 0-5 is 12kg (abstraction). Doses sourced for WHO Pocket book of hospital care for
# children: Second edition 2014

# Antibiotic therapy -------------------
# Antibiotics for non-severe pneumonia - oral amoxicillin for 5 days
# Antibiotics for non-severe pneumonia - oral amoxicillin for 5 days (40mg/kg BD - ((12*40)*2)*5 =4800mg)
self.consumables_used_in_hsi['Amoxicillin_tablet_or_suspension_5days'] = {
get_item_code(item='Amoxycillin 250mg_1000_CMST'):
lambda _age: get_dosage_for_age_in_months(int(_age * 12.0),
{2: 0, 12: 0.006, 36: 0.012, np.inf: 0.018}
),
get_item_code(item='Amoxycillin 125mg/5ml suspension, PFR_0.025_CMST'):
lambda _age: get_dosage_for_age_in_months(int(_age * 12.0),
{2: 0, 12: 1, 36: 2, np.inf: 3}
),
}
get_item_code(item='Amoxycillin 250mg_1000_CMST'): 4800,
get_item_code(item='Amoxycillin 125mg/5ml suspension, PFR_0.025_CMST'): 192} # 25mg/ml - 4800/25

# Antibiotics for non-severe pneumonia - oral amoxicillin for 3 days
# Antibiotics for non-severe pneumonia - oral amoxicillin for 3 days (40mg/kg BD - ((12*40)*2)*3 =2880mg)
self.consumables_used_in_hsi['Amoxicillin_tablet_or_suspension_3days'] = {
get_item_code(item='Amoxycillin 250mg_1000_CMST'):
lambda _age: get_dosage_for_age_in_months(int(_age * 12.0),
{2: 0, 12: 0.01, 36: 0.02, np.inf: 0.03}
),
get_item_code(item='Amoxycillin 125mg/5ml suspension, PFR_0.025_CMST'):
lambda _age: get_dosage_for_age_in_months(int(_age * 12.0),
{2: 0, 12: 1, 36: 2, np.inf: 3}
),
}
get_item_code(item='Amoxycillin 250mg_1000_CMST'): 2880,
get_item_code(item='Amoxycillin 125mg/5ml suspension, PFR_0.025_CMST'): 115} # 25mg/ml - 2880/25

# Antibiotics for non-severe pneumonia - oral amoxicillin for 7 days for young infants only
# Antibiotics for non-severe pneumonia - oral amoxicillin for 7 days for young infants only (40mg/kg BD -
# ((12*40)*2)*7 =6720mg)
self.consumables_used_in_hsi['Amoxicillin_tablet_or_suspension_7days'] = {
get_item_code(item='Amoxycillin 250mg_1000_CMST'):
lambda _age: get_dosage_for_age_in_months(int(_age * 12.0),
{1: 0.004, 2: 0.006, np.inf: 0.01}
),
get_item_code(item='Amoxycillin 125mg/5ml suspension, PFR_0.025_CMST'):
lambda _age: get_dosage_for_age_in_months(int(_age * 12.0),
{1: 0.4, 2: 0.5, np.inf: 1}
),
}
get_item_code(item='Amoxycillin 250mg_1000_CMST'): 6720,
get_item_code(item='Amoxycillin 125mg/5ml suspension, PFR_0.025_CMST'): 269} # 25mg/ml - 6720/25

# Antibiotic therapy for severe pneumonia - ampicillin package
# Amp. dose - 50mg/KG QDS 5 days = (50*12)*4)*5 = 12_000mg
# Gent. dose -7.5mg/kg per day 5 days = (7.5*12)*5 = 450mg
self.consumables_used_in_hsi['1st_line_IV_antibiotics'] = {
get_item_code(item='Ampicillin injection 500mg, PFR_each_CMST'):
lambda _age: get_dosage_for_age_in_months(int(_age * 12.0),
{1: 3.73, 2: 5.6, 4: 8, 12: 16, 36: 24, np.inf: 40}
),
get_item_code(item='Gentamicin Sulphate 40mg/ml, 2ml_each_CMST'):
lambda _age: get_dosage_for_age_in_months(int(_age * 12.0),
{1: 0.7, 2: 1.4, 4: 2.81, 12: 4.69, 36: 7.03, np.inf: 9.37}
),
get_item_code(item='Ampicillin injection 500mg, PFR_each_CMST'): 24, # 500mg vial -12_000/500
get_item_code(item='Gentamicin Sulphate 40mg/ml, 2ml_each_CMST'): 6, # 80mg/2ml = 450/8
get_item_code(item='Cannula iv (winged with injection pot) 16_each_CMST'): 1,
get_item_code(item='Syringe, Autodisable SoloShot IX '): 1
}

# # Antibiotic therapy for severe pneumonia - benzylpenicillin package when ampicillin is not available
# Benpen dose - 50_000IU/KG QDS 5 days = (50_000*12)*4)*5 = 12_000_000IU = 8g (approx)
# Gent. dose -7.5mg/kg per day 5 days = (7.5*12)*5 = 450mg
self.consumables_used_in_hsi['Benzylpenicillin_gentamicin_therapy_for_severe_pneumonia'] = {
get_item_code(item='Benzylpenicillin 3g (5MU), PFR_each_CMST'):
lambda _age: get_dosage_for_age_in_months(int(_age * 12.0),
{1: 2, 2: 5, 4: 8, 12: 15, 36: 24, np.inf: 34}
),
get_item_code(item='Gentamicin Sulphate 40mg/ml, 2ml_each_CMST'):
lambda _age: get_dosage_for_age_in_months(int(_age * 12.0),
{1: 0.7, 2: 1.4, 4: 2.81, 12: 4.69, 36: 7.03, np.inf: 9.37}
),
get_item_code(item='Benzylpenicillin 3g (5MU), PFR_each_CMST'): 8,
get_item_code(item='Gentamicin Sulphate 40mg/ml, 2ml_each_CMST'): 6, # 80mg/2ml = 450/8
get_item_code(item='Cannula iv (winged with injection pot) 16_each_CMST'): 1,
get_item_code(item='Syringe, Autodisable SoloShot IX '): 1
}

# Second line of antibiotics for severe pneumonia, if Staph not suspected
# Ceft. dose = 80mg/kg per day 5 days = (80*12)*5 = 4800mg
self.consumables_used_in_hsi['Ceftriaxone_therapy_for_severe_pneumonia'] = {
get_item_code(item='Ceftriaxone 1g, PFR_each_CMST'):
lambda _age: get_dosage_for_age_in_months(int(_age * 12.0),
{4: 1.5, 12: 3, 36: 5, np.inf: 7}
),
get_item_code(item='Ceftriaxone 1g, PFR_each_CMST'): 1, # smallest unit is 1g
get_item_code(item='Cannula iv (winged with injection pot) 16_each_CMST'): 1,
get_item_code(item='Syringe, Autodisable SoloShot IX '): 1
}

# Second line of antibiotics for severe pneumonia, if Staph is suspected
# Flucox. dose = 50mg/kg QDS 7 days = ((50*12)*4)*7 = 16_800mg
# Oral flucox dose. = same
self.consumables_used_in_hsi['2nd_line_Antibiotic_therapy_for_severe_staph_pneumonia'] = {
get_item_code(item='Flucloxacillin 250mg, vial, PFR_each_CMST'):
lambda _age: get_dosage_for_age_in_months(int(_age * 12.0),
{2: 21, 4: 22.4, 12: 37.3, 36: 67.2, 60: 93.3, np.inf: 140}
),
get_item_code(item='Gentamicin Sulphate 40mg/ml, 2ml_each_CMST'):
lambda _age: get_dosage_for_age_in_months(int(_age * 12.0),
{4: 2.81, 12: 4.69, 36: 7.03, 60: 9.37, np.inf: 13.6}
),
get_item_code(item='Flucloxacillin 250mg, vial, PFR_each_CMST'): 16_800,
get_item_code(item='Gentamicin Sulphate 40mg/ml, 2ml_each_CMST'): 6, # 80mg/2ml = 450/8
get_item_code(item='Cannula iv (winged with injection pot) 16_each_CMST'): 1,
get_item_code(item='Syringe, Autodisable SoloShot IX '): 1,
get_item_code(item='Flucloxacillin 250mg_100_CMST'):
lambda _age: get_dosage_for_age_in_months(int(_age * 12.0),
{4: 0.42, 36: 0.84, 60: 1.68, np.inf: 1.68}
),
}
get_item_code(item='Flucloxacillin 250mg_100_CMST'): 16_800}

# First dose of antibiotic before referral -------------------

# single dose of 7.5mg gent and 50mg/g amp. given
# Referral process in iCCM for severe pneumonia, and at health centres for HIV exposed/infected
self.consumables_used_in_hsi['First_dose_oral_amoxicillin_for_referral'] = {
get_item_code(item='Amoxycillin 250mg_1000_CMST'):
lambda _age: get_dosage_for_age_in_months(int(_age * 12.0),
{12: 0.001, 36: 0.002, np.inf: 0.003}
),
get_item_code(item='Amoxycillin 250mg_1000_CMST'): 250,
}

# Referral process at health centres for severe cases
self.consumables_used_in_hsi['First_dose_IM_antibiotics_for_referral'] = {
get_item_code(item='Ampicillin injection 500mg, PFR_each_CMST'):
lambda _age: get_dosage_for_age_in_months(int(_age * 12.0),
{4: 0.4, 12: 0.8, 36: 1.4, np.inf: 2}
),
get_item_code(item='Gentamicin Sulphate 40mg/ml, 2ml_each_CMST'):
lambda _age: get_dosage_for_age_in_months(int(_age * 12.0),
{4: 0.56, 12: 0.94, 36: 1.41, np.inf: 1.87}
),
get_item_code(item='Ampicillin injection 500mg, PFR_each_CMST'): 2, # 2 x 500mg vial
get_item_code(item='Gentamicin Sulphate 40mg/ml, 2ml_each_CMST'): 2, # assuming single dose at referral
get_item_code(item='Cannula iv (winged with injection pot) 16_each_CMST'): 1,
get_item_code(item='Syringe, Autodisable SoloShot IX '): 1
}

# Oxygen, pulse oximetry and x-ray -------------------

# Oxygen for hypoxaemia
# Oxygen for hypoxaemia - 5/l per min (Approx) for 3 days ((24*60)*5)*3
self.consumables_used_in_hsi['Oxygen_Therapy'] = {
get_item_code(item='Oxygen, 1000 liters, primarily with oxygen cylinders'): 1,
get_item_code(item='Oxygen, 1000 liters, primarily with oxygen cylinders'): 21_600,
}

# Pulse oximetry
Expand All @@ -1162,10 +1107,7 @@ def get_dosage_for_age_in_months(age_in_whole_months: float, doses_by_age_in_mon
# Optional consumables -------------------
# Paracetamol
self.consumables_used_in_hsi['Paracetamol_tablet'] = {
get_item_code(item='Paracetamol, tablet, 100 mg'):
lambda _age: get_dosage_for_age_in_months(int(_age * 12.0),
{36: 12, np.inf: 18}
),
get_item_code(item='Paracetamol, tablet, 100 mg'): 240, # 20mg/kg
}

# Maintenance of fluids via nasograstric tube
Expand All @@ -1178,11 +1120,6 @@ def get_dosage_for_age_in_months(age_in_whole_months: float, doses_by_age_in_mon
get_item_code(item='Salbutamol sulphate 1mg/ml, 5ml_each_CMST'): 2
}

# Bronchodilator - oral
self.consumables_used_in_hsi['Oral_Brochodilator'] = {
get_item_code(item='Salbutamol, syrup, 2 mg/5 ml'): 1,
get_item_code(item='Salbutamol, tablet, 4 mg'): 1
}

def end_episode(self, person_id):
"""End the episode infection for a person (i.e. reset all properties to show no current infection or
Expand Down Expand Up @@ -2420,11 +2357,7 @@ def _get_cons(self, _arg: Union[str, Tuple[str]]) -> bool:
def _get_cons_group(self, item_group_str: str) -> bool:
"""True if _all_ of a group of consumables (identified by a string) is available."""
if item_group_str is not None:
return self.get_consumables(
item_codes={
k: v(self._age_exact_years) if isinstance(v, types.LambdaType) else v
for k, v in self.module.consumables_used_in_hsi[item_group_str].items()
})
return self.get_consumables(self.module.consumables_used_in_hsi[item_group_str])
else:
raise ValueError('String for the group of consumables not provided')

Expand Down
Loading