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

Let the Scale-up of HIV, TB, Malaria services go to "MAXIMAL" levels (as well as target levels) #1441

Closed
wants to merge 20 commits into from
Closed
Show file tree
Hide file tree
Changes from 14 commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
d5ea448
create new scenario file for testing HTM max scale-up
tdm32 Jul 29, 2024
ecb7e9b
change parameter do_sacleup to categorical in hiv, tb and malaria mod…
tdm32 Jul 29, 2024
3457f93
add type_of_scaleup with default value=none to htm resourcefiles
tdm32 Jul 29, 2024
0e0d0b4
choose scale-up values from resourcefile using parameter type_of_scaleup
tdm32 Jul 29, 2024
d0f0c17
set up scenarios to test max scale-up works as expected
tdm32 Jul 29, 2024
82cf195
set up scenarios to test max scale-up works as expected
tdm32 Jul 29, 2024
76e7c7b
edit figures
tdm32 Jul 29, 2024
afd94bb
switch type_of_scaleup to string
tdm32 Jul 29, 2024
97a0b80
update test_htm_scaleup.py
tdm32 Jul 29, 2024
591c5e3
enhanced_lifestly.py update np.timedelta64 as ValueError: Unit M is n…
tdm32 Jul 29, 2024
96b7577
switch scale-up parameter selection (target vs max) to update_paramet…
tdm32 Jul 29, 2024
ee32ab2
comment out plots in analysis_maxHTM_scenario.py
tdm32 Jul 29, 2024
c8acbb1
tidy up script
tdm32 Jul 29, 2024
a2821c6
move import statements used for plotting
tdm32 Jul 29, 2024
2cab7fc
remove unneeded columns from scale-up_parameters sheet in resourcefiles
tdm32 Jul 29, 2024
8637cc7
Merge branch 'master' into tara_max_HTMscenarios_setup_29Jul
tbhallett Jul 29, 2024
3706fdf
switch to using maximum scale-up
tbhallett Jul 29, 2024
a2d5b00
update from master
tdm32 Jul 29, 2024
57a4f87
roll back change in enhanced_lifestyle.py
tbhallett Jul 29, 2024
83512a2
Merge remote-tracking branch 'origin/tara_max_HTMscenarios_setup_29Ju…
tdm32 Jul 29, 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
4 changes: 2 additions & 2 deletions resources/ResourceFile_HIV.xlsx
tbhallett marked this conversation as resolved.
Show resolved Hide resolved
Git LFS file not shown
4 changes: 2 additions & 2 deletions resources/ResourceFile_TB.xlsx
Git LFS file not shown
4 changes: 2 additions & 2 deletions resources/malaria/ResourceFile_malaria.xlsx
Git LFS file not shown
Original file line number Diff line number Diff line change
@@ -0,0 +1,229 @@
"""
This scenario file sets up the scenarios for simulating the effects of scaling up programs

The scenarios are:
*0 baseline mode 1
*1 scale-up HIV program
*2 scale-up TB program
*3 scale-up malaria program
*4 scale-up HIV and Tb and malaria programs

scale-up occurs on the default scale-up start date (01/01/2025: in parameters list of resourcefiles)

For all scenarios, keep all default health system settings

check the batch configuration gets generated without error:
tlo scenario-run --draw-only src/scripts/comparison_of_horizontal_and_vertical_programs/analysis_maxHTM_scenario.py

Run on the batch system using:
tlo batch-submit src/scripts/comparison_of_horizontal_and_vertical_programs/analysis_maxHTM_scenario.py

or locally using:
tlo scenario-run src/scripts/comparison_of_horizontal_and_vertical_programs/analysis_maxHTM_scenario.py

or execute a single run:
tlo scenario-run src/scripts/comparison_of_horizontal_and_vertical_programs/analysis_maxHTM_scenario.py --draw 1 0

"""

import datetime
from pathlib import Path

from tlo import Date, logging
from tlo.methods import (
demography,
enhanced_lifestyle,
epi,
healthburden,
healthseekingbehaviour,
healthsystem,
hiv,
malaria,
simplified_births,
symptommanager,
tb,
)
from tlo.scenario import BaseScenario

resourcefilepath = Path("./resources")
datestamp = datetime.date.today().strftime("__%Y_%m_%d")

outputspath = Path("./outputs")
scaleup_start_year = 2012
end_date = Date(2015, 1, 1)


class EffectOfProgrammes(BaseScenario):
def __init__(self):
super().__init__()
self.seed = 0
self.start_date = Date(2010, 1, 1)
self.end_date = end_date
self.pop_size = 1_000
self.number_of_draws = 5
self.runs_per_draw = 1

def log_configuration(self):
return {
'filename': 'scaleup_tests',
'directory': Path('./outputs'), # <- (specified only for local running)
'custom_levels': {
'*': logging.WARNING,
'tlo.methods.hiv': logging.INFO,
'tlo.methods.tb': logging.INFO,
'tlo.methods.malaria': logging.INFO,
'tlo.methods.demography': logging.INFO,
}
}

def modules(self):
return [
demography.Demography(resourcefilepath=self.resources),
simplified_births.SimplifiedBirths(resourcefilepath=self.resources),
enhanced_lifestyle.Lifestyle(resourcefilepath=self.resources),
healthsystem.HealthSystem(resourcefilepath=self.resources),
symptommanager.SymptomManager(resourcefilepath=self.resources),
healthseekingbehaviour.HealthSeekingBehaviour(resourcefilepath=self.resources),
healthburden.HealthBurden(resourcefilepath=self.resources),
epi.Epi(resourcefilepath=self.resources),
hiv.Hiv(resourcefilepath=self.resources),
tb.Tb(resourcefilepath=self.resources),
malaria.Malaria(resourcefilepath=self.resources),
]

def draw_parameters(self, draw_number, rng):

return {
'Hiv': {
'type_of_scaleup': ['none', 'max', 'none', 'none', 'max'][draw_number],
'scaleup_start_year': scaleup_start_year,
},
'Tb': {
'type_of_scaleup': ['none', 'none', 'max', 'none', 'max'][draw_number],
'scaleup_start_year': scaleup_start_year,
},
'Malaria': {
'type_of_scaleup': ['none', 'none', 'none', 'max', 'max'][draw_number],
'scaleup_start_year': scaleup_start_year,
},
}


if __name__ == '__main__':
from tlo.cli import scenario_run

scenario_run([__file__])



# %% Produce some figures and summary info
tbhallett marked this conversation as resolved.
Show resolved Hide resolved

# import pandas as pd
# import matplotlib.pyplot as plt

# # Find results_folder associated with a given batch_file (and get most recent [-1])
# results_folder = get_scenario_outputs("scaleup_tests-", outputspath)[-1]
#
# # get basic information about the results
# info = get_scenario_info(results_folder)
#
# # 1) Extract the parameters that have varied over the set of simulations
# params = extract_params(results_folder)
#
#
# # DEATHS
#
#
# def get_num_deaths_by_cause_label(_df):
# """Return total number of Deaths by label within the TARGET_PERIOD
# values are summed for all ages
# df returned: rows=COD, columns=draw
# """
# return _df \
# .loc[pd.to_datetime(_df.date).between(*TARGET_PERIOD)] \
# .groupby(_df['label']) \
# .size()
#
#
# TARGET_PERIOD = (Date(scaleup_start_year, 1, 1), end_date)
#
# # produce df of total deaths over scale-up period
# num_deaths_by_cause_label = extract_results(
# results_folder,
# module='tlo.methods.demography',
# key='death',
# custom_generate_series=get_num_deaths_by_cause_label,
# do_scaling=True
# )
#
#
# def summarise_deaths_for_one_cause(results_folder, label):
# """ returns mean deaths for each year of the simulation
# values are aggregated across the runs of each draw
# for the specified cause
# """
#
# results_deaths = extract_results(
# results_folder,
# module="tlo.methods.demography",
# key="death",
# custom_generate_series=(
# lambda df: df.assign(year=df["date"].dt.year).groupby(
# ["year", "label"])["person_id"].count()
# ),
# do_scaling=True,
# )
# # removes multi-index
# results_deaths = results_deaths.reset_index()
#
# # select only cause specified
# tmp = results_deaths.loc[
# (results_deaths.label == label)
# ]
#
# # group deaths by year
# tmp = pd.DataFrame(tmp.groupby(["year"]).sum())
#
# # get mean for each draw
# mean_deaths = pd.concat({'mean': tmp.iloc[:, 1:].groupby(level=0, axis=1).mean()}, axis=1).swaplevel(axis=1)
#
# return mean_deaths
#
#
# aids_deaths = summarise_deaths_for_one_cause(results_folder, 'AIDS')
# tb_deaths = summarise_deaths_for_one_cause(results_folder, 'TB (non-AIDS)')
# malaria_deaths = summarise_deaths_for_one_cause(results_folder, 'Malaria')
#
#
# draw_labels = ['No scale-up', 'HIV scale-up', 'TB scale-up', 'Malaria scale-up', 'HTM scale-up']
# colours = ['blue', 'green', 'red', 'purple', 'orange']
#
# # Create subplots
# fig, axs = plt.subplots(3, 1, figsize=(10, 10))
# # Plot for df1
# for i, col in enumerate(aids_deaths.columns):
# axs[0].plot(aids_deaths.index, aids_deaths[col], label=draw_labels[i],
# color=colours[i])
# axs[0].set_title('HIV/AIDS')
# axs[0].legend(loc='center left', bbox_to_anchor=(1, 0.5)) # Legend to the right of the plot
# axs[0].axvline(x=scaleup_start_year, color='gray', linestyle='--')
#
# # Plot for df2
# for i, col in enumerate(tb_deaths.columns):
# axs[1].plot(tb_deaths.index, tb_deaths[col], color=colours[i])
# axs[1].set_title('TB')
# axs[1].axvline(x=scaleup_start_year, color='gray', linestyle='--')
#
# # Plot for df3
# for i, col in enumerate(malaria_deaths.columns):
# axs[2].plot(malaria_deaths.index, malaria_deaths[col], color=colours[i])
# axs[2].set_title('Malaria')
# axs[2].axvline(x=scaleup_start_year, color='gray', linestyle='--')
#
# for ax in axs:
# ax.set_xlabel('Years')
# ax.set_ylabel('Number deaths')
#
# plt.tight_layout(rect=[0, 0, 0.85, 1]) # Adjust layout to make space for legend
# plt.show()
#
4 changes: 2 additions & 2 deletions src/tlo/methods/enhanced_lifestyle.py
Copy link
Collaborator

Choose a reason for hiding this comment

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

these changes from lifestyle coming in again!? Very weird! I'll have to roll back for the version to merge

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

it won't run locally with np.timedelta64 value="M" for me:
enhanced_lifestly.py np.timedelta64 as ValueError: Unit M is not supported. Only unambiguous timedelta values durations are supported. Allowed units are 'W', 'D', 'h', 'm', 's', 'ms', 'us', 'ns'

Copy link
Collaborator

Choose a reason for hiding this comment

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

This is very weird. Matt/Asif would know better but I guess it's to do with perhaps your setup not being quite the same the specification? (In which case delete it and start again with the conda environment setup...?)

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

oh no...

Original file line number Diff line number Diff line change
Expand Up @@ -661,13 +661,13 @@ def update_all_properties(self, df):
:param df: The population dataframe """
# get months since last poll
now = self.module.sim.date
months_since_last_poll = round((now - self.date_last_run) / np.timedelta64(1, "M"))
days_since_last_poll = round((now - self.date_last_run) / np.timedelta64(1, "D"))
# loop through linear models dictionary and initialise each property in the population dataframe
for _property_name, _model in self._models.items():
if _model['update'] is not None:
df.loc[df.is_alive, _property_name] = _model['update'].predict(
df.loc[df.is_alive], rng=self.rng, other=self.module.sim.date,
months_since_last_poll=months_since_last_poll)
months_since_last_poll=days_since_last_poll / 30.5)
# update date last event run
self.date_last_run = now

Expand Down
20 changes: 13 additions & 7 deletions src/tlo/methods/hiv.py
Original file line number Diff line number Diff line change
Expand Up @@ -398,16 +398,16 @@ def __init__(self, name=None, resourcefilepath=None, run_with_checks=False):
" high-bound-exclusive]",
),
# ------------------ scale-up parameters for scenario analysis ------------------ #
"do_scaleup": Parameter(
Types.BOOL,
"argument to determine whether scale-up of program will be implemented"
"type_of_scaleup": Parameter(
Types.STRING, "argument to determine type scale-up of program which will be implemented, "
"can be 'none', 'target' or 'max'",
),
"scaleup_start_year": Parameter(
Types.INT,
"the year when the scale-up starts (it will occur on 1st January of that year)"
),
"scaleup_parameters": Parameter(
Types.DICT,
Types.DATA_FRAME,
"the parameters and values changed in scenario analysis"
),
}
Expand Down Expand Up @@ -448,7 +448,7 @@ def read_parameters(self, data_folder):
p["treatment_cascade"] = workbook["spectrum_treatment_cascade"]

# load parameters for scale-up projections
p["scaleup_parameters"] = workbook["scaleup_parameters"].set_index('parameter')['scaleup_value'].to_dict()
p['scaleup_parameters'] = workbook["scaleup_parameters"]

# DALY weights
# get the DALY weight that this module will use from the weight database (these codes are just random!)
Expand Down Expand Up @@ -914,7 +914,7 @@ def initialise_simulation(self, sim):
sim.schedule_event(HivLoggingEvent(self), sim.date + DateOffset(years=1))

# Optional: Schedule the scale-up of programs
if self.parameters["do_scaleup"]:
if self.parameters["type_of_scaleup"] != 'none':
scaleup_start_date = Date(self.parameters["scaleup_start_year"], 1, 1)
assert scaleup_start_date >= self.sim.start_date, f"Date {scaleup_start_date} is before simulation starts."
sim.schedule_event(HivScaleUpEvent(self), scaleup_start_date)
Expand Down Expand Up @@ -1102,8 +1102,14 @@ def initialise_simulation(self, sim):
)

def update_parameters_for_program_scaleup(self):
""" options for program scale-up are 'target' or 'max' """
p = self.parameters
scaled_params = p["scaleup_parameters"]
scaled_params_workbook = p["scaleup_parameters"]

if p['type_of_scaleup'] == 'target':
scaled_params = scaled_params_workbook.set_index('parameter')['target_value'].to_dict()
else:
scaled_params = scaled_params_workbook.set_index('parameter')['max_value'].to_dict()

# scale-up HIV program
# reduce risk of HIV - applies to whole adult population
Expand Down
23 changes: 14 additions & 9 deletions src/tlo/methods/malaria.py
Original file line number Diff line number Diff line change
Expand Up @@ -189,17 +189,16 @@ def __init__(self, name=None, resourcefilepath=None):
Types.REAL,
'probability that treatment will clear malaria symptoms'
),
# ------------------ scale-up parameters for scenario analysis ------------------ #
"do_scaleup": Parameter(
Types.BOOL,
"argument to determine whether scale-up of program will be implemented"
"type_of_scaleup": Parameter(
Types.STRING, "argument to determine type scale-up of program which will be implemented, "
"can be 'none', 'target' or 'max'",
),
"scaleup_start_year": Parameter(
Types.INT,
"the year when the scale-up starts (it will occur on 1st January of that year)"
),
"scaleup_parameters": Parameter(
Types.DICT,
Types.DATA_FRAME,
"the parameters and values changed in scenario analysis"
)
}
Expand Down Expand Up @@ -261,7 +260,7 @@ def read_parameters(self, data_folder):
p['sev_inc'] = pd.read_csv(self.resourcefilepath / 'malaria' / 'ResourceFile_malaria_SevInc_expanded.csv')

# load parameters for scale-up projections
p["scaleup_parameters"] = workbook["scaleup_parameters"].set_index('parameter')['scaleup_value'].to_dict()
p['scaleup_parameters'] = workbook["scaleup_parameters"]

# check itn projected values are <=0.7 and rounded to 1dp for matching to incidence tables
p['itn'] = round(p['itn'], 1)
Expand Down Expand Up @@ -602,7 +601,7 @@ def initialise_simulation(self, sim):
sim.schedule_event(MalariaPrevDistrictLoggingEvent(self), sim.date + DateOffset(months=1))

# Optional: Schedule the scale-up of programs
if self.parameters["do_scaleup"]:
if self.parameters["type_of_scaleup"] != 'none':
scaleup_start_date = Date(self.parameters["scaleup_start_year"], 1, 1)
assert scaleup_start_date >= self.sim.start_date, f"Date {scaleup_start_date} is before simulation starts."
sim.schedule_event(MalariaScaleUpEvent(self), scaleup_start_date)
Expand Down Expand Up @@ -659,8 +658,14 @@ def initialise_simulation(self, sim):
)

def update_parameters_for_program_scaleup(self):
""" options for program scale-up are 'target' or 'max' """
p = self.parameters
scaled_params = p["scaleup_parameters"]
scaled_params_workbook = p["scaleup_parameters"]

if p['type_of_scaleup'] == 'target':
scaled_params = scaled_params_workbook.set_index('parameter')['target_value'].to_dict()
else:
scaled_params = scaled_params_workbook.set_index('parameter')['max_value'].to_dict()

# scale-up malaria program
# increase testing
Expand Down Expand Up @@ -1164,7 +1169,7 @@ def apply(self, person_id, squeeze_factor):
facility_level=self.ACCEPTED_FACILITY_LEVEL,
treatment_id=self.TREATMENT_ID,
)

logger.info(key='rdt_log', data=person_details_for_test)

# if positive, refer for a confirmatory test at level 1a
Expand Down
Loading
Loading