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

Simp vax #13

Merged
merged 11 commits into from
Oct 12, 2023
1 change: 0 additions & 1 deletion emodpy_typhoid/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,4 @@ def cleanup_for_2018_mode( config ):
config.parameters.Infectious_Period_Distribution = "FIXED_DURATION" # hack
config.parameters.Base_Incubation_Period = 1
config.parameters.Base_Infectious_Period = 1
config.parameters["Listed_Events"] = []

74 changes: 74 additions & 0 deletions emodpy_typhoid/interventions/typhoid_vaccine.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,37 @@ def new_intervention( camp, efficacy=0.82, mode="Shedding", constant_period=0, d
intervention.Changing_Effect.Decay_Time_Constant = decay_constant
return intervention

def new_vax( camp, efficacy=0.82, mode="Acquisition", constant_period=0, decay_constant=6935.0 ):
"""
Create a new 'SimpleVaccine' intervention with specified parameters. If you use this function directly, you'll need to distribute the intervention with a function like ScheduledCampaignEvent or TriggeredCampaignEvent from emod_api.interventions.common.

Args:
camp (Camp): The camp to which the intervention is applied.
efficacy (float, optional): The efficacy of the Typhoid vaccine. Default is 0.82.
mode (str, optional): The mode of the intervention. Default is "Acquisition" Can also be "Transmission" or "All".
constant_period (float, optional): The constant period of the waning effect in days. Default is 0.
decay_constant (float, optional): The decay time constant for the waning effect. Default is 6935.0.

Returns:
SimpleVaccine: A fully configured instance of the SimpleVaccine intervention with the specified parameters.
"""

intervention = s2c.get_class_with_defaults( "SimpleVaccine", camp.schema_path )
if mode == "Acquisition":
intervention.Vaccine_Type = "AcquisitionBlocking"
elif mode == "Transmission":
intervention.Vaccine_Type = "TransmissionBlocking"
elif mode == "All":
intervention.Vaccine_Type = "General"
else:
raise ValueError( f"mode {mode} not recognized. Options are: 'Acquisition', 'Transmission', or 'All'." )

intervention.Waning_Config = s2c.get_class_with_defaults( "WaningEffectBoxExponential" )
intervention.Waning_Config.Initial_Effect = efficacy
intervention.Waning_Config.Box_Duration = constant_period
intervention.Waning_Config.Decay_Time_Constant = decay_constant
return intervention

def new_triggered_intervention(
camp,
efficacy=0.82,
Expand Down Expand Up @@ -65,6 +96,49 @@ def new_triggered_intervention(

return event

def new_routine_immunization(
camp,
efficacy=0.82,
mode="Acquisition",
constant_period=0,
decay_constant=6935.0,
start_day=1,
child_age=9*30,
coverage=1.0,
node_ids=None,
property_restrictions_list=[],
co_event=None # expansion slot
):
"""
Create a new delayed, birth-triggered SimpleVaccine intervention based on specified parameters. Does not add to campaign.

Args:
camp (Camp): The camp to which the intervention is applied.
efficacy (float, optional): The efficacy of the Typhoid vaccine. Default is 0.82.
mode (str, optional): The mode of the intervention. Default is "Shedding".
constant_period (float, optional): The constant period of the waning effect in days. Default is 0.
decay_constant (float, optional): The decay time constant for the waning effect. Default is 6935.0.
start_day (int, optional): The day on which the intervention starts. Default is 1.
child_age (int, optional): The age of the person when they get the vaccine. Defaults to 9 months. Vaccines are actually distribute +/- 7 days.
coverage (float, optional): Demographic coverage of the intervention. Default is 1.0.
node_ids (list, optional): List of node IDs where the intervention is applied. Default is None.
property_restrictions_list (list, optional): List of property restrictions for the intervention. Default is an empty list.
co_event (None, optional): Expansion slot for future use.

Returns:
TriggeredCampaignEvent: An instance of a triggered campaign event with the TyphoidVaccine intervention.
"""
iv = new_vax( camp, efficacy=efficacy, mode=mode, constant_period=constant_period, decay_constant=decay_constant )
age_min = max(0,child_age-7)
delay = {
"Delay_Period_Min": age_min,
"Delay_Period_Max": child_age+7
}

event = common.triggered_campaign_delay_event( camp, start_day=start_day, trigger="Births", delay=delay, intervention=iv, ip_targeting=property_restrictions_list, coverage=coverage )

return event

def new_scheduled_intervention(
camp,
efficacy=0.82,
Expand Down
262 changes: 262 additions & 0 deletions examples/HINTy/example.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,262 @@
#!/usr/bin/env python

import pandas as pd
import numpy as np # just for linspace
import pathlib # for a join
from functools import partial

# idmtools ...
from idmtools.assets import Asset, AssetCollection #
from idmtools.builders import SimulationBuilder
from idmtools.core.platform_factory import Platform
from idmtools.entities.experiment import Experiment
from idmtools_platform_comps.utils.python_requirements_ac.requirements_to_asset_collection import RequirementsToAssetCollection
from idmtools_models.templated_script_task import get_script_wrapper_unix_task

# emodpy
from emodpy.emod_task import EMODTask
import emodpy.emod_task
#emodpy.emod_task.dev_mode = True
import emod_api.interventions.common as comm
#comm.old_adhoc_trigger_style = False

import manifest

BASE_YEAR=2010
SIMULATION_DURATION_IN_YEARS=12
CAMP_START_YEAR=2019

def update_sim_bic(simulation, value):
simulation.task.config.parameters.Base_Infectivity_Constant = value*0.1
return {"Base_Infectivity": value}

def update_sim_random_seed(simulation, value):
simulation.task.config.parameters.Run_Number = value
return {"Run_Number": value}

def year_to_days( year ):
return ( (year-BASE_YEAR)*365 )

def set_param_fn( config ):
config.parameters.Simulation_Type = "TYPHOID_SIM"
config.parameters.Simulation_Duration = SIMULATION_DURATION_IN_YEARS*365.0
config.parameters.Base_Individual_Sample_Rate = 0.2

#config.parameters.Enable_Birth = 0 # temporary
#config.parameters.Minimum_End_Time = 90
# cover up for default bugs in schema
config.parameters.Base_Year = BASE_YEAR
config.parameters.Inset_Chart_Reporting_Start_Year = 1900
config.parameters.Inset_Chart_Reporting_Stop_Year = 2050
config.parameters.Enable_Demographics_Reporting = 0
config.parameters.Enable_Property_Output = 1
config.parameters.Report_Event_Recorder_Events = [ "VaccineDistributed", "PropertyChange"]
config.parameters["Listed_Events"] = [ "VaccineDistributed" ] # old school
#config.parameters.Typhoid_Immunity_Memory = 36500
#config.parameters.Config_Name = "149_Typhoid"

config.parameters.Report_Typhoid_ByAgeAndGender_Start_Year = 2010
config.parameters.Report_Typhoid_ByAgeAndGender_Stop_Year = 2050
config.parameters.Typhoid_3year_Susceptible_Fraction = 0
config.parameters.Typhoid_6month_Susceptible_Fraction = 0
config.parameters.Typhoid_6year_Susceptible_Fraction = 0
config.parameters.Typhoid_Acute_Infectiousness = 13435
config.parameters.Typhoid_Carrier_Probability = 0.108
config.parameters.Typhoid_Carrier_Removal_Year = 2500
config.parameters.Typhoid_Chronic_Relative_Infectiousness = 0.241
config.parameters.Typhoid_Contact_Exposure_Rate = 0.06918859049226553
config.parameters.Typhoid_Environmental_Exposure_Rate = 0.06169346985005757
config.parameters.Typhoid_Environmental_Cutoff_Days = 157.20690133538764
config.parameters.Typhoid_Environmental_Peak_Start = 355.0579483941714
config.parameters.Typhoid_Environmental_Ramp_Down_Duration = 112.30224910440123
config.parameters.Typhoid_Environmental_Ramp_Up_Duration = 39.540475369174146
config.parameters.Typhoid_Exposure_Lambda = 7.0
config.parameters.Typhoid_Prepatent_Relative_Infectiousness = 0.5
config.parameters.Typhoid_Protection_Per_Infection = 0.98
config.parameters.Typhoid_Subclinical_Relative_Infectiousness = 1
config.parameters.Typhoid_Symptomatic_Fraction = 0.07

#config.parameters.x_Birth = 1.2

# when using 2018 binary
import emodpy_typhoid.config as config_utils
config_utils.cleanup_for_2018_mode( config )
return config


def build_camp( start_day_offset=1, vax_eff = 0.82 ):
"""
Build a campaign input file for the DTK using emod_api.
"""
import emod_api.campaign as camp
import emod_api.interventions.outbreak as ob

print(f"Telling emod-api to use {manifest.schema_file} as schema.")
camp.set_schema( manifest.schema_file )

for x in range( 10 ):
event = ob.new_intervention( camp, timestep=1+x, cases=1 )
camp.add( event )

import emodpy_typhoid.interventions.typhoid_vaccine as tv
import emod_api.interventions.common as comm
ria = tv.new_routine_immunization( camp,
efficacy=vax_eff,
start_day=year_to_days( CAMP_START_YEAR )+start_day_offset
)

notification_iv = comm.BroadcastEvent( camp, "VaccineDistributed" )
#event = comm.triggered_campaign_event_with_optional_delay( camp, start_day=1, intervention=[tv_iv,notification_iv], triggers=["Births"], delay=delay_dict )
camp.add( ria )

tv_iv = tv.new_vax( camp,
efficacy=vax_eff
)
one_time_campaign = comm.ScheduledCampaignEvent( camp,
Start_Day=year_to_days( CAMP_START_YEAR )+start_day_offset,
Intervention_List=[tv_iv,notification_iv],
Demographic_Coverage=0.72,
Target_Age_Min=0.75,
Target_Age_Max=15
)
camp.add( one_time_campaign )

def migrate():
"""
Use PropertyValueChanger to move some fraction between Rural and Urban over time.
"""

def two_step():
rural_to_urban_pvc = comm.PropertyValueChanger( camp,
Target_Property_Key="Region",
Target_Property_Value="Urban",
Maximum_Duration=30,
Revert=1,
)
#rural_to_urban_pvc = comm.PropertyValueChanger( camp, ... )
event = comm.ScheduledCampaignEvent( camp,
Start_Day=t,
Intervention_List=[rural_to_urban_pvc],
Demographic_Coverage=0.1,
Property_Restrictions = "Region:Rural"
#,Target_Age_Min=0.75,
#,Target_Age_Max=15
)
camp.add( event )
"""
# 1% Urban->Rural
comm.change_individual_property( camp,
target_property_name="Region",
target_property_value="Rural",
start_day=t, coverage=0.01,
ip_restrictions="Region:Urban" )
"""

def one_step():
# 1% Rural->Urban
comm.change_individual_property( camp,
target_property_name="Region",
target_property_value="Urban",
start_day=t, coverage=0.1,
ip_restrictions="Region:Rural" )

for t in np.linspace( 1, SIMULATION_DURATION_IN_YEARS*365, 20 ):
two_step()

#for t in np.linspace( 10*365, SIMULATION_DURATION_IN_YEARS*365, 3 ):

#migrate()
return camp

def build_demog():
"""
Build a demographics input file for the DTK using emod_api.
"""
import emodpy_typhoid.demographics.TyphoidDemographics as Demographics # OK to call into emod-api

demog = Demographics.from_template_node( lat=0, lon=0, pop=10000, name=1, forced_id=1 )
# We're getting all our demographics from a static file overlay.

"""
# This doesn't work right now but still want to leave in example of what we want to be able to do soon.
demog.AddAgeDependentTransmission(
Age_Bin_Edges_In_Years = [0, 5, 20, 60, -1],
TransmissionMatrix = [
[1.0, 1.0, 1.0, 1.0],
[1.0, 1.0, 1.0, 1.0],
[1.0, 1.0, 1.0, 1.0],
[1.0, 1.0, 1.0, 1.0]
]
)
"""
# 80% rural, 20% urban.
demog.AddIndividualPropertyAndHINT( Property="Region",
Values = [ "Rural", "Urban" ],
InitialDistribution = [ 0.8, 0.2 ],
TransmissionMatrix = [
[ 1, 0.1 ],
[ 0.1, 1 ]
],
EnviroTransmissionMatrix = [
[ 1, 0.1 ],
[ 0.1, 1 ]
]
)

return demog


def run_test():
# Create a platform
# Show how to dynamically set priority and node_group
platform = Platform("SLURM", node_group="idm_48cores", priority="Highest")

task = EMODTask.from_default2(config_path="config.json", eradication_path=manifest.eradication_path, campaign_builder=build_camp, demog_builder=build_demog, schema_path=manifest.schema_file, param_custom_cb=set_param_fn, ep4_custom_cb=None)
# normally we don't force-set parameters at this point
task.config.parameters.Demographics_Filenames = [ "demographics.json", "TestDemographics_pak_updated.json" ]
task.config.parameters.Death_Rate_Dependence = "NONDISEASE_MORTALITY_BY_YEAR_AND_AGE_FOR_EACH_GENDER"
task.config.parameters.Birth_Rate_Dependence = "INDIVIDUAL_PREGNANCIES_BY_AGE_AND_YEAR"
task.common_assets.add_directory(assets_directory=manifest.assets_input_dir)

task.set_sif( manifest.sif )

# Create simulation sweep with builder
builder = SimulationBuilder()
#builder.add_sweep_definition( update_sim_random_seed, range(1) )
def update_campaign_efficacy(simulation, value):
build_campaign_partial = partial(build_camp, vax_eff=value)
simulation.task.create_campaign_from_callback(build_campaign_partial)
return {"vax_efficacy": value}
def update_campaign_start(simulation, value):
build_campaign_partial = partial(build_camp, start_day=value)
simulation.task.create_campaign_from_callback(build_campaign_partial)
return {"campaign_start_day": value}

vax_effs = np.linspace(0,1.0,3) # 0.0, 0.5, 1.0
builder.add_sweep_definition( update_campaign_efficacy, vax_effs )
builder.add_sweep_definition( update_sim_random_seed, range(5) ) # keep at 1 for smoketesting
#start_day_offsets = np.linspace(0,60,7) # 1, 366, etc.
#builder.add_sweep_definition( update_campaign_start, start_day_offsets )

# create experiment from builder
experiment = Experiment.from_builder(builder, task, name="Typhoid Vax 101")
# The last step is to call run() on the ExperimentManager to run the simulations.
experiment.run(wait_until_done=True, platform=platform)

task.handle_experiment_completion( experiment )

# download and plot some stuff.
EMODTask.get_file_from_comps( experiment.uid, [ "InsetChart.json" ] )
task.cache_experiment_metadata_in_sql( experiment.uid )
import matplotlib
matplotlib.use( "TkAgg" )
import emod_api.channelreports.plot_icj_means as plotter
chan_data = plotter.collect( str( experiment.uid ), "Infected", tag="vax_efficacy=SWEEP" )
plotter.display( chan_data, False, "Infected", str( experiment.uid ) )


if __name__ == "__main__":
import emod_typhoid.bootstrap as dtk
dtk.setup( manifest.model_dl_dir )

run_test()
9 changes: 9 additions & 0 deletions examples/HINTy/manifest.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import os
requirements = "./requirements.txt"
model_dl_dir = "stash2"
schema_file=os.path.join(model_dl_dir, "schema.json")
eradication_path=os.path.join(model_dl_dir, "Eradication")
assets_input_dir="Assets"
Copy link
Collaborator

Choose a reason for hiding this comment

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

Can you check in Assets file under this directory?

reporters=model_dl_dir
sif="dtk_centos_2018.id"
world_bank_dataset="../world_bank_dataset.csv"
4 changes: 4 additions & 0 deletions examples/HINTy/requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
emodpy-typhoid==0.0.5.dev0
emodpy==1.22.0.dev3
emod-api==1.31.0.dev0
emod-typhoid==0.0.4.dev2
1 change: 1 addition & 0 deletions examples/vaccination/dtk_centos_2018.id
Copy link
Collaborator

Choose a reason for hiding this comment

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

Can we put this file under examples directory so we can share it within examples in different folders?

Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
79791913-ee50-ee11-aa0a-b88303911bc1::Asset Collection
Loading