Skip to content

demographics_utils

apply_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

Source code in emod_api/demographics/demographics_utils.py
def apply_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" in demog and "IndividualAttributes" in demog["Defaults"]:
        fn(demog["Defaults"], *args)
    else:
        for node in demog["Nodes"]:
            fn(node, *args)

set_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

1
2
3
4
5
6
7
# 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

Source code in emod_api/demographics/demographics_utils.py
def set_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
    """
    with open(filename, "r") as demogjson_file:
        demog = json.loads(demogjson_file.read())

    def set_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) in distributions:
        if distribution not in distribution_types.keys():
            raise Exception("Don't recognize distribution type %s" % distribution)

        apply_to_defaults_or_nodes(demog, set_attributes, dist_type, par1, par2)

    with open(filename, "w") as output_file:
        output_file.write(json.dumps(demog, sort_keys=True, indent=4))

set_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

Source code in emod_api/demographics/demographics_utils.py
def set_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")
    if len(demog_filenames) != 1:
        raise Exception("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")

    if use_existing:
        return

    with open(demog_filename, "r") as demogjson_file:
        demog = json.loads(demogjson_file.read())

    birthrate = 0.0001
    mod_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]],
    }

    def set_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)
    with open(output_file_path, "w") as output_file:
        output_file.write(json.dumps(demog, sort_keys=True, indent=4))

set_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

Source code in emod_api/demographics/demographics_utils.py
def set_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)])

set_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

Source code in emod_api/demographics/demographics_utils.py
def set_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)])

set_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

Source code in emod_api/demographics/demographics_utils.py
def set_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")
    if len(demog_filenames) != 1:
        raise Exception("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")

    if use_existing:
        return

    with open(demog_filename, "r") as demogjson_file:
        demog = json.loads(demogjson_file.read())

    birthrate = 0.12329
    exponential_age_param = 0.000118
    population_removal_rate = 45
    mod_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]],
    }

    def set_attributes(d):
        if "IndividualAttributes" not in d:
            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)
    with open(output_file_path, "w") as output_file:
        output_file.write(json.dumps(demog, sort_keys=True, indent=4))