Source code for emod_api.demographics.demographics_utils
importjsonparams={"Demographics_Filenames":[],"Population_Scale_Type":"FIXED_SCALING","x_Base_Population":1,"Enable_Aging":1,"Age_Initialization_Distribution_Type":"DISTRIBUTION_SIMPLE","Enable_Demographics_Birth":1,"Enable_Demographics_Initial":1,"Enable_Demographics_Other":0,"Enable_Demographics_Reporting":0,"Enable_Demographics_Builtin":0,"Enable_Demographics_Risk":0,"Enable_Immunity_Initialization_Distribution":0,# compatibility with EMOD v2.0 and earlier"Susceptibility_Initialization_Distribution_Type":"DISTRIBUTION_OFF","Enable_Initial_Prevalence":1,"Enable_Vital_Dynamics":1,"Death_Rate_Dependence":"NONDISEASE_MORTALITY_BY_AGE_AND_GENDER","Enable_Birth":1,"Birth_Rate_Dependence":"POPULATION_DEP_RATE","Birth_Rate_Time_Dependence":"NONE","x_Birth":1,"Enable_Disease_Mortality":0,"Base_Mortality":0,"Mortality_Time_Course":"DAILY_MORTALITY","x_Other_Mortality":1,"Enable_Natural_Mortality":1,"Individual_Sampling_Type":"TRACK_ALL","Base_Individual_Sample_Rate":1,# all parameters below are unused without sampling"Max_Node_Population_Samples":40,"Sample_Rate_0_18mo":1,"Sample_Rate_10_14":1,"Sample_Rate_15_19":1,"Sample_Rate_18mo_4yr":1,"Sample_Rate_20_Plus":1,"Sample_Rate_5_9":1,"Sample_Rate_Birth":2,}distribution_types={"CONSTANT_DISTRIBUTION":0,"UNIFORM_DISTRIBUTION":1,"GAUSSIAN_DISTRIBUTION":2,"EXPONENTIAL_DISTRIBUTION":3,"POISSON_DISTRIBUTION":4,"LOG_NORMAL":5,"BIMODAL_DISTRIBUTION":6,}
[docs]defset_risk_mod(filename,distribution,par1,par2):""" Set the ``RiskDistributionFlag``, ``RiskDistribution1`` and ``RiskDistribution2`` in a demographics file. :param filename: The demographics file location :param distribution: The selected distribution (need to come from ``distribution_types``) :param par1: Parameter 1 of the distribution :param par2: Parameter 2 of the distribution (may be unused depending on the selected distribution) :return: Nothing """set_demog_distributions(filename,[("Risk",distribution,par1,par2)])
[docs]defset_immune_mod(filename,distribution,par1,par2):""" Set the ``ImmunityDistributionFlag``, ``ImmunityDistribution1`` and ``ImmunityDistribution2`` in a demographics file. :param filename: The demographics file location :param distribution: The selected distribution (need to come from `distribution_types`) :param par1: Parameter 1 of the distribution :param par2: Parameter 2 of the distribution (may be unused depending on the selected distribution) :return: Nothing """set_demog_distributions(filename,[("Immunity",distribution,par1,par2)])
[docs]defapply_to_defaults_or_nodes(demog,fn,*args):""" Apply the ``fn`` function either to the ``Defaults`` dictionary or to each of the nodes depending if the ``IndividualAttributes`` parameter is present in the ``Defaults`` or not. .. todo:: This function should be refactored to look at both the ``Defaults`` and each individual nodes. It will make sure that if a node override the default ``IndividualAttributes`` the change will still be effective. :param demog: The demographic file represented as a dictionary :param fn: The function to apply the ``Defaults`` or individual nodes :param args: Argument list needed by ``fn`` :return: Nothing """if"Defaults"indemogand"IndividualAttributes"indemog["Defaults"]:fn(demog["Defaults"],*args)else:fornodeindemog["Nodes"]:fn(node,*args)
[docs]defset_demog_distributions(filename,distributions):""" Apply distributions to a given demographics file. The distributions needs to be formatted as a list of (name, distribution, par1, par2) with: * **name:** Immunity, Risk, Age, Prevalence or MigrationHeterogeneity * **distribution:** One distribution contained in ``distribution_types`` * **par1, par2:** the values for the distribution parameters .. code-block:: python # Set the PrevalenceDistribution to a uniform distribution with 0.1 and 0.2 # and the ImmunityDistributionFlag to a constant distribution with 1 demog = json.load(open("demographics.json","r")) distributions = list() distributions.add(("Prevalence","UNIFORM_DISTRIBUTION",0.1,0.2)) distributions.add(("Immunity","CONSTANT_DISTRIBUTION",1,0)) set_demog_distribution(demog, distributions) :param filename: the demographics file as json :param distributions: the different distributions to set contained in a list :return: Nothing """withopen(filename,"r")asdemogjson_file:demog=json.loads(demogjson_file.read())defset_attributes(d,dist_type,par1,par2):d["IndividualAttributes"].update({dist_type+"DistributionFlag":distribution_types[distribution],dist_type+"Distribution1":par1,dist_type+"Distribution2":par2,})for(dist_type,distribution,par1,par2)indistributions:ifdistributionnotindistribution_types.keys():raiseException("Don't recognize distribution type %s"%distribution)apply_to_defaults_or_nodes(demog,set_attributes,dist_type,par1,par2)withopen(filename,"w")asoutput_file:output_file.write(json.dumps(demog,sort_keys=True,indent=4))
# the following two methods need a refactor# we can have a single demographics file object and adjust attribute depending on usage
[docs]defset_static_demographics(cb,use_existing=False):""" Create a static demographics based on the demographics file specified in the config file of the :py:class:`DTKConfigBuilder` object passed to the function. This function takes the current demographics file and adjust the birth rate/death rate to get a static population (the deaths are always compensated by new births). .. todo:: Make sure that the population is 1000 individuals. For now rely on the fact that the base demographics file will be 1000 Initial Population. :param cb: The config builder object :param use_existing: If ``True`` will only take the demographics file name and add the .static to it. If ``False`` will create a static demographics file based on the specified demographics file. :return: Nothing """demog_filenames=cb.get_param("Demographics_Filenames")iflen(demog_filenames)!=1:raiseException("Expecting only one demographics filename.")demog_filename=demog_filenames[0]static_demog_filename=demog_filename.replace("compiled.","").replace(".json",".static.json",1)cb.set_param("Demographics_Filenames",[static_demog_filename])cb.set_param("Birth_Rate_Dependence","FIXED_BIRTH_RATE")ifuse_existing:returnwithopen(demog_filename,"r")asdemogjson_file:demog=json.loads(demogjson_file.read())birthrate=0.12329exponential_age_param=0.000118population_removal_rate=45mod_mortality={"NumDistributionAxes":2,"AxisNames":["gender","age"],"AxisUnits":["male=0,female=1","years"],"AxisScaleFactors":[1,365],"NumPopulationGroups":[2,1],"PopulationGroups":[[0,1],[0]],"ResultUnits":"annual deaths per 1000 individuals","ResultScaleFactor":2.74e-06,"ResultValues":[[population_removal_rate],[population_removal_rate]],}defset_attributes(d):ifnot"IndividualAttributes"ind:d["IndividualAttributes"]={}d["IndividualAttributes"].update({"MortalityDistribution":mod_mortality,"AgeDistributionFlag":distribution_types["EXPONENTIAL_DISTRIBUTION"],"AgeDistribution1":exponential_age_param,})d["NodeAttributes"].update({"BirthRate":birthrate})apply_to_defaults_or_nodes(demog,set_attributes)output_file_path=demog_filename.replace(".json",".static.json",1)withopen(output_file_path,"w")asoutput_file:output_file.write(json.dumps(demog,sort_keys=True,indent=4))
[docs]defset_growing_demographics(cb,use_existing=False):""" This function creates a growing population. It works the same way as the :any:`set_static_demographics` but with a birth rate more important than the death rate which leads to a growing population. .. todo:: Make sure that the population is 1000 individuals. For now rely on the fact that the base demographics file will be 1000 Initial Population. :param cb: The :py:class:`DTKConfigBuilder <dtk.utils.core.DTKConfigBuilder>` object :param use_existing: If ``True`` will only take the demographics file name and add the .growing to it. If ``False`` will create a growing demographics file based on the specified demographics file. :return: Nothing """demog_filenames=cb.get_param("Demographics_Filenames")iflen(demog_filenames)!=1:raiseException("Expecting only one demographics filename.")demog_filename=demog_filenames[0]growing_demog_filename=demog_filename.replace("compiled.","").replace(".json",".growing.json",1)cb.set_param("Demographics_Filenames",[growing_demog_filename])cb.set_param("Birth_Rate_Dependence","POPULATION_DEP_RATE")ifuse_existing:returnwithopen(demog_filename,"r")asdemogjson_file:demog=json.loads(demogjson_file.read())birthrate=0.0001mod_mortality={"NumDistributionAxes":2,"AxisNames":["gender","age"],"AxisUnits":["male=0,female=1","years"],"AxisScaleFactors":[1,365],"NumPopulationGroups":[2,5],"PopulationGroups":[[0,1],[0,2,10,100,2000]],"ResultUnits":"annual deaths per 1000 individuals","ResultScaleFactor":2.74e-06,"ResultValues":[[60,8,2,20,400],[60,8,2,20,400]],}defset_attributes(d):d["IndividualAttributes"].update({"MortalityDistribution":mod_mortality})d["NodeAttributes"].update({"BirthRate":birthrate})apply_to_defaults_or_nodes(demog,set_attributes)output_file_path=demog_filename.replace(".json",".growing.json",1)withopen(output_file_path,"w")asoutput_file:output_file.write(json.dumps(demog,sort_keys=True,indent=4))