def test_acmr(): sim = InteractiveContext( 'src/vivarium_conic_lsff/model_specifications/india.yaml') sim.step() # make sure everything is setup pop = sim.get_population() age_groups = pd.cut(pop.age, bins=[0, 7 / 365, 28 / 365, 1, 5], right=False) mr_pipeline = sim.get_value('mortality_rate') acmr_orig = mr_pipeline.source(pop.index).sum(axis=1) acmr_w_risk = mr_pipeline( pop.index).sum(axis=1) * 365 # convert back to "per person-year" # confirm that they are *not* identical at the individual level assert not np.allclose( acmr_orig, acmr_w_risk, rtol=.05), 'expect acmr to be quite different for some individuals' # but close at pop level assert np.allclose( acmr_orig.groupby(age_groups).median(), acmr_w_risk.groupby(age_groups).median(), rtol=.1 ), 'expect acmr to be within 10% of original at population level'
def test_incidence(base_config, base_plugins, disease): year_start = base_config.time.start.year year_end = base_config.time.end.year time_step = pd.Timedelta(days=base_config.time.step_size) healthy = BaseDiseaseState('healthy') sick = BaseDiseaseState('sick') key = f"sequela.acute_myocardial_infarction_first_2_days.incidence_rate" transition = RateTransition(input_state=healthy, output_state=sick, get_data_functions={ 'incidence_rate': lambda _, builder: builder.data.load(key) }) healthy.transition_set.append(transition) model = DiseaseModel(disease, initial_state=healthy, states=[healthy, sick]) simulation = InteractiveContext(components=[TestPopulation(), model], configuration=base_config, plugin_configuration=base_plugins, setup=False) simulation._data.write(key, 0.7) simulation.setup() incidence_rate = simulation._values.get_value('sick.incidence_rate') simulation.step() assert np.allclose(from_yearly(0.7, time_step), incidence_rate(simulation.get_population().index), atol=0.00001)
def test_risk_deletion(base_config, base_plugins, disease): time_step = base_config.time.step_size time_step = pd.Timedelta(days=time_step) year_start = base_config.time.start.year year_end = base_config.time.end.year base_rate = 0.7 paf = 0.1 healthy = BaseDiseaseState('healthy') sick = BaseDiseaseState('sick') key = "sequela.acute_myocardial_infarction_first_2_days.incidence_rate" transition = RateTransition(input_state=healthy, output_state=sick, get_data_functions={ 'incidence_rate': lambda _, builder: builder.data.load(key) }) healthy.transition_set.append(transition) model = DiseaseModel(disease, initial_state=healthy, states=[healthy, sick]) class PafModifier: @property def name(self): return 'paf_modifier' def setup(self, builder): builder.value.register_value_modifier( 'sick.incidence_rate.paf', modifier=simulation._tables.build_table( build_table(paf, year_start, year_end), key_columns=('sex', ), parameter_columns=['age', 'year'], value_columns=None)) simulation = InteractiveContext( components=[TestPopulation(), model, PafModifier()], configuration=base_config, plugin_configuration=base_plugins, setup=False) simulation._data.write(key, base_rate) simulation.setup() incidence_rate = simulation._values.get_value('sick.incidence_rate') simulation.step() expected_rate = base_rate * (1 - paf) assert np.allclose(from_yearly(expected_rate, time_step), incidence_rate(simulation.get_population().index), atol=0.00001)
def test_mortality_rate(base_config, base_plugins, disease): year_start = base_config.time.start.year year_end = base_config.time.end.year time_step = pd.Timedelta(days=base_config.time.step_size) healthy = BaseDiseaseState('healthy') mort_get_data_funcs = { 'dwell_time': lambda _, __: pd.Timedelta(days=0), 'disability_weight': lambda _, __: 0.0, 'prevalence': lambda _, __: build_table(0.000001, year_start - 1, year_end, ['age', 'year', 'sex', 'value']), 'excess_mortality_rate': lambda _, __: build_table(0.7, year_start - 1, year_end), } mortality_state = DiseaseState('sick', get_data_functions=mort_get_data_funcs) healthy.add_transition(mortality_state) model = DiseaseModel(disease, initial_state=healthy, states=[healthy, mortality_state]) simulation = InteractiveContext( components=[TestPopulation(), model, Mortality()], configuration=base_config, plugin_configuration=base_plugins) mortality_rate = simulation._values.get_value('mortality_rate') simulation.step() # Folks instantly transition to sick so now our mortality rate should be much higher assert np.allclose( from_yearly(0.7, time_step), mortality_rate(simulation.get_population().index)['sick'])
def test_dwell_time(assign_cause_mock, base_config, base_plugins, disease, base_data): time_step = 10 assign_cause_mock.side_effect = lambda population, *args: pd.DataFrame( {'condition_state': 'healthy'}, index=population.index) base_config.update( { 'time': { 'step_size': time_step }, 'population': { 'population_size': 10 } }, **metadata(__file__)) healthy_state = BaseDiseaseState('healthy') data_function = base_data(0) data_function['dwell_time'] = lambda _, __: pd.Timedelta(days=28) data_function['disability_weight'] = lambda _, __: 0.0 event_state = DiseaseState('event', get_data_functions=data_function) done_state = BaseDiseaseState('sick') healthy_state.add_transition(event_state) event_state.add_transition(done_state) model = DiseaseModel(disease, initial_state=healthy_state, states=[healthy_state, event_state, done_state]) simulation = InteractiveContext(components=[TestPopulation(), model], configuration=base_config, plugin_configuration=base_plugins) # Move everyone into the event state simulation.step() event_time = simulation._clock.time assert np.all(simulation.get_population()[disease] == 'event') simulation.step() simulation.step() # Not enough time has passed for people to move out of the event state, so they should all still be there assert np.all(simulation.get_population()[disease] == 'event') simulation.step() # Now enough time has passed so people should transition away assert np.all(simulation.get_population()[disease] == 'sick') assert np.all(simulation.get_population().event_event_time == pd.to_datetime(event_time)) assert np.all(simulation.get_population().event_event_count == 1)
def test_dwell_time_with_mortality(base_config, base_plugins, disease): year_start = base_config.time.start.year year_end = base_config.time.end.year time_step = 10 pop_size = 100 base_config.update( { 'time': { 'step_size': time_step }, 'population': { 'population_size': pop_size } }, **metadata(__file__)) healthy_state = BaseDiseaseState('healthy') mort_get_data_funcs = { 'dwell_time': lambda _, __: pd.Timedelta(days=14), 'excess_mortality_rate': lambda _, __: build_table(0.7, year_start - 1, year_end), 'disability_weight': lambda _, __: 0.0 } mortality_state = DiseaseState('event', get_data_functions=mort_get_data_funcs) done_state = BaseDiseaseState('sick') healthy_state.add_transition(mortality_state) mortality_state.add_transition(done_state) model = DiseaseModel(disease, initial_state=healthy_state, states=[healthy_state, mortality_state, done_state]) mortality = Mortality() simulation = InteractiveContext( components=[TestPopulation(), model, mortality], configuration=base_config, plugin_configuration=base_plugins) # Move everyone into the event state simulation.step() assert np.all(simulation.get_population()[disease] == 'event') simulation.step() # Not enough time has passed for people to move out of the event state, so they should all still be there assert np.all(simulation.get_population()[disease] == 'event') simulation.step() # Make sure some people have died and remained in event state assert (simulation.get_population()['alive'] == 'alive').sum() < pop_size assert ((simulation.get_population()['alive'] == 'dead').sum() == ( simulation.get_population()[disease] == 'event').sum()) # enough time has passed so living people should transition away to sick assert ((simulation.get_population()['alive'] == 'alive').sum() == ( simulation.get_population()[disease] == 'sick').sum())