Source code for fpsim.defaults

"""
Define defaults for use throughout FPsim
"""

# Imports
import numpy as np
import sciris as sc
import starsim as ss
import fpsim
import fpsim.arrays as fpa


#%% Global defaults
useSI          = True
mpy            = 12   # Months per year, to avoid magic numbers
eps            = 1e-9 # To avoid divide-by-zero
min_age        = 15   # Minimum age to be considered eligible to use contraceptive methods
max_age        = 99   # Maximum age (inclusive)
max_age_preg   = 50   # Maximum age to become pregnant
max_parity     = 20   # Maximum number of children to track - also applies to abortions, miscarriages, stillbirths
max_parity_spline = 20   # Used for parity splines
location_registry = {}  # Registry for external custom locations
valid_country_locs = ['senegal', 'kenya', 'ethiopia', 'cotedivoire', 'niger', 'nigeria_kano', 'nigeria_kaduna', 'nigeria_lagos', 'pakistan_sindh']
valid_region_locs = {
    'ethiopia': ['addis_ababa', 'afar', 'amhara', 'benishangul_gumuz', 'dire_dawa', 'gambela', 'harari', 'oromia', 'snnpr', 'somali', 'tigray']
}


# Parse locations
[docs] def get_location(location, printmsg=False): if not location: print("No location specified. Available locations are: ") print(", ".join(valid_country_locs)) print("To use model defaults, set test=True.") print(("To use a custom location, you can construct the sim by passing in a dataloader with a path to where you are keeping your data.\n" "Example:\n" " import fpsim as fp\n" " # Load your own data\n" " my_data = fp.DataLoader(data_path='path-to-my-data')" " sim = fp.Sim(dataloader=my_data)")) raise ValueError('Location must be specified. To use model defaults, set test=True.') location = location.lower() # Ensure it's lowercase # External locations override internal ones if location in location_registry: return location # Define valid locations if location not in valid_country_locs and not any(location in v for v in valid_region_locs.values()): errormsg = f'Location "{location}" is not currently supported' raise NotImplementedError(errormsg) return location
[docs] def get_dataloader(location, printwarn=True): """ Return the data loader module """ from . import locations as fplocs location = get_location(location) if hasattr(fplocs, location): dataloader = getattr(fplocs, location).dataloader() else: raise NotImplementedError(f'Could not find dataloader for {location}') return dataloader
[docs] def get_calib_pars(location, verbose=1): """ Return the calibration parameters """ from . import locations as fplocs if location is None: return location = get_location(location) if hasattr(fplocs, location): calib_pars = getattr(fplocs, location).make_calib_pars() else: sc.printv(f'No calibration parameters found for {location}', thisverbose=0, verbose=verbose) return None return calib_pars
[docs] def get_test_defaults(): """ Return the test defaults """ defaults = { 'n_agents': 500, 'start': 2000, 'stop': 2005, 'location': 'senegal', } return defaults
# Defaults states and values of any new(born) agent unless initialized with data or other strategy # or updated during the course of a simulation. fpmod_states = [ # Contraception ss.BoolState('on_contra', default=False), # whether she's on contraception ss.IntArr('method', default=0), # Which method to use. 0 used for those on no method ss.FloatArr('ti_contra', default=0), # time point at which to set method ss.FloatArr('barrier', default=0), ss.BoolState('ever_used_contra', default=False), # Ever been on contraception. 0 for never having used ss.FloatArr('rel_sus', default=0), # Relative susceptibility to pregnancy, set to 1 for active fecund women # Sexual and reproductive states, all False by default and set during simulation ss.BoolState('lam'), ss.BoolState('pregnant'), ss.BoolState('fertile'), ss.BoolState('sexually_active'), ss.BoolState('sexual_debut'), ss.BoolState('lactating'), ss.BoolState('postpartum'), # Ages of key events ss.FloatArr('sexual_debut_age', default=-1), ss.FloatArr('fated_debut', default=-1), ss.FloatArr('first_birth_age', default=-1), # Counts of events ss.FloatArr('parity', default=0), # Number of births including stillbirths ss.FloatArr('n_births', default=0), # Number of live births ss.FloatArr('n_stillbirths', default=0), # Number of stillbirths ss.FloatArr('n_miscarriages', default=0), # Number of miscarriages ss.FloatArr('n_abortions', default=0), # Number of abortions ss.FloatArr('n_pregnancies', default=0), # Number of pregnancies, including miscarriages, stillbirths, abortions ss.FloatArr('months_inactive', default=0), # TODO, what does this store? ss.FloatArr('short_interval', default=0), # TODO, what does this store? # Durations and counters ss.FloatArr('gestation', default=0), # TODO, remove? ss.FloatArr('remainder_months', default=0), # TODO, remove? ss.FloatArr('dur_pregnancy', default=0), ss.FloatArr('dur_postpartum', default=0), ss.FloatArr('dur_breastfeed', default=0), ss.FloatArr('dur_breastfeed_total', default=0), # Timesteps of significant events ss.FloatArr('ti_conceived'), ss.FloatArr('ti_pregnant'), ss.FloatArr('ti_delivery'), ss.FloatArr('ti_last_delivery'), ss.FloatArr('ti_live_birth'), ss.FloatArr('ti_stillbirth'), ss.FloatArr('ti_postpartum'), ss.FloatArr('ti_miscarriage'), ss.FloatArr('ti_abortion'), ss.FloatArr('ti_stop_postpartum'), ss.FloatArr('ti_stop_breastfeeding'), ss.FloatArr('ti_debut'), ss.FloatArr('ti_dead'), # Fecundity ss.FloatArr('personal_fecundity', default=0), # Add these states to the people object. They are not tracked by timestep in the way other states are, so they # need to be added manually. Eventually these will become part of a separate module tracking pregnancies and # pregnancy outcomes. fpa.TwoDimensionalArr('birth_ages', ncols=max_parity), # Ages at time of live births fpa.TwoDimensionalArr('stillborn_ages', ncols=max_parity), # Ages at time of stillbirths fpa.TwoDimensionalArr('miscarriage_ages', ncols=max_parity), # Ages at time of miscarriages fpa.TwoDimensionalArr('abortion_ages', ncols=max_parity), # Ages at time of abortions ss.BoolState('partnered', default=False), # Will remain at these values if use_partnership is False ss.FloatArr('partnership_age', default=-1), # Will remain at these values if use_partnership is False # ss.State('urban', default=True), # Urban/rural # ss.FloatArr('wealthquintile', default=3), # Wealth quintile ] # Postpartum keys to months postpartum_map = { 'pp0to5': [0, 6], 'pp6to11': [6, 12], 'pp12to23': [12, 24] } # Age bins for tracking age-specific fertility rate age_bin_map = { '10-14': [10, 15], '15-19': [15, 20], '20-24': [20, 25], '25-29': [25, 30], '30-34': [30, 35], '35-39': [35, 40], '40-44': [40, 45], '45-49': [45, 50] } # Age and parity splines spline_ages = np.arange(max_age + 1) spline_preg_ages = np.arange(max_age_preg + 1) spline_parities = np.arange(max_parity_spline + 1) # Define allowable keys to select all (all ages, all methods, etc) none_all_keys = [None, 'all', ':', [None], ['all'], [':']] # Age bins for different method switching matrices -- can be overwritten by locations method_age_map = { '<18': [ 0, 18], '18-20': [18, 20], '20-25': [20, 25], '25-35': [25, 35], '>35': [35, max_age+1], # +1 since we're using < rather than <= } immutable_method_age_map = { '<18': [ 0, 18], '18-20': [18, 20], '20-25': [20, 25], '25-30': [25, 30], '30-35': [30, 35], '>35': [35, max_age+1], # +1 since we're using < rather than <= } method_youth_age_map = { '<16': [10, 16], '16-17': [16, 18], '18-19': [18, 20], '20-22': [20, 23], '23-25': [23, 26], '>25': [26, max_age+1] } # Counts - we compute number of new events each timestep, plus number of cumulative events event_counts = sc.autolist( 'births', 'stillbirths', 'miscarriages', 'abortions', 'short_intervals', 'secondary_births', 'pregnancies', 'total_births', 'maternal_deaths', 'infant_deaths', 'method_failures', ) people_counts = sc.autolist( 'contra_access', 'new_users', 'ever_used_contra', 'switchers', 'n_fecund', 'pp0to5', 'pp6to11', 'pp12to23', 'parity0to1', 'parity2to3', 'parity4to5', 'parity6plus', 'nonpostpartum', ) sim_results = sc.autolist( 'n_urban', 'n_wq1', 'n_wq2', 'n_wq3', 'n_wq4', 'n_wq5', ) # Rates and other results that aren't scaled rate_results = sc.autolist( 'tfr', 'mmr', 'imr', 'p_short_interval', )