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
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
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
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
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
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
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
65
66
67
68
69
70
71
72
73
74
75
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
52
53
54
55
56
57
58
59
60
61
62
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
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
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))