Creating Demographics Files

Create a Demographics Files

The demographics file is a required input file for EMOD that specifies characteristics of the population in a simulation. This includes aspects like the population size, birth rates, non-malaria mortality rates, age structure, initial prevalence, and more. Full documentation on the demographics file and its parameters/structure are available in the malaria model documentation.

Parts of a demographics file

A demographics file is a JSON file organized into 4 main sections:

  1. Metadata
  2. NodeProperties
  3. Defaults
    • Parameters applied to all nodes in the simulation
  4. Nodes: each node is a simulated location. Transmission within a node is well-mixed, and nodes are connected by human and/or vector migration.
    • Allows node-specific parameters
    • Specified parameters override values in ‘Defaults’
# Structure of Demographics File for a simulation with 1 node
  {
     "Metadata": {
          "DateCreated": "dateTime",
          "Tool": "scriptUsedToGenerate",
          "Author": "author",
          "IdReference": "Gridded world grump2.5arcmin",
          "NodeCount": "1"
     },
     "NodeProperties": [
          {...}
     ],
     "Defaults": {
          "NodeAttributes": {
            ...
            "BirthRateSource": "World Bank",
            "CountryBirthRate": 31.047,
            "World Bank Year": "2016",
            ...
          },
          "IndividualAttributes": {...},
          "IndividualProperties": {...}
     },
     "Nodes": [{
          "NodeID": 1,
          "NodeAttributes": {
            "BirthRate": 0.1190,
            "InitialPopulation": 1400,
            "Village": "Obom"
          },
          "IndividualAttributes": {...},
          "IndividualProperties": {...}
     }]
  }

Single-node simulations

The emod-api package contains most of the major functionality to create a demographics file. It is supported by emodpy-malaria to add parameters that are more specific to the malaria workflow, imported as Demographics in the code chunk below. For single node, non-spatial simulations the from_template_node command is most commonly used; however, you may also choose to read in pre-made json files for these types of simulations. We include this command in our demographics builder with it’s basic parameters: - latitude - longitude - population size - site name - forced node ID (if desired) - initial prevalence value (if desired)

With this saved as the demog item, we can add additional complexity as needed. This may include things like setting equilibrium vital dynamics so birth and mortality rates are equal, producing a relatively stable population size, or an age distribution for our population. In this example, we pull the age distribution of all of Sub-Saharan Africa from the emod-api and then apply it to our demographics item. You may also add complexity through individual properties and other specific parameters as desired.

import emodpy_malaria.demographics.MalariaDemographics as Demographics
import emod_api.demographics.PreDefinedDistributions as Distributions

def build_demog():
    """
    This function builds a demographics input file for the DTK using emod_api.
    """

    demog = Demographics.from_template_node(lat=1.00, lon=1.00, pop=1000, name="Example_Site_Name", forced_id=1, init_prev=0.1)
    
    # Add equal birth and mortality rates
    demog.SetEquilibriumVitalDynamics()
    
    # Call and add age distribution
    age_distribution = Distributions.AgeDistribution_SSAfrica
    demog.SetAgeDistribution(age_distribution)

    return demog

Fixed birth rate and age equilibrium

The example above is based on the assumption that you set the population dynamic, controlled by Birth_Rate_Dependence to POPULATION_DEP_RATE (the default). However, in the situation where you want to use FIXED_BIRTH_RATE, then setting as above will cause the birth to be near zero, because birth rate in the POPULATION_DEP_RATE is read as probability of birth per person in the model per day. In the FIXED_BIRTH_RATE setting, birth rate is read as probability of birth per day.

As a result, it is recommended that you choose a crude birth rate that works for you (birth per 1000 population per year), and create your demographic this way:

import emodpy_malaria.demographics.MalariaDemographics as Demographics
from emod_api.demographics.DemographicsTemplates import CrudeRate

def build_demog():
    """
    This function builds a demographics input file for the DTK using emod_api.
    """
    
    pop = 1000
    crude_rate = 38.92

    demog = Demographics.from_template_node(lat=1.00, lon=1.00, pop=pop, name="Example_Site_Name", forced_id=1, init_prev=0.1)

    # Set Birth and Death Rate    
    demog.SetBirthRate(CrudeRate(crude_rate*pop))
    demog.SetMortalityRate(CrudeRate(crude_rate))
    
    # Set age distribution to equilibrium
    demog.SetEquilibriumAgeDistFromBirthAndMortRates(CrudeRate(crude_rate),
                                                     CrudeRate(crude_rate))

    return demog

Basically, the birth rate needs to be set differently to account for the difference between using FIXED_BIRTH_RATE and POPULATION_DEP_RATE. Note that in this example, the mortality rate is also set to the birth rate to ensure that the population is stable and at equilibrium. Finally, we use the SetEquilibriumAgeDistFromBirthAndMortRates to make sure the age distribution is already at equilibrium given the birth and death rates right from the beginning. You might notice that this means the age distribution in the model is not the same as the “real world”. The actual age distribution in the model can only be achieved if you supply the birth and death (by age) rates over the years of simulations. With constant birth rate and equilibrium vital dynamics, the age distribution will move into a fixed shape even if you start off with a different age distribution.