From 3a818cf22eea4eefadcfbaf891c7a850d52ce6d0 Mon Sep 17 00:00:00 2001 From: Steve Bachmeier <23350991+stevebachmeier@users.noreply.github.com> Date: Mon, 22 May 2023 16:56:31 -0600 Subject: [PATCH 1/4] support python 3.8-3.11 (#313) --- .github/workflows/build.yml | 2 +- .github/workflows/deploy.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index c9bd3312a..7cdb6d3de 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -10,7 +10,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - python-version: ["3.7", "3.8", "3.9", "3.10"] + python-version: ["3.8", "3.9", "3.10", "3.11"] defaults: run: shell: bash -le {0} diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index e203571cf..ba3da927d 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -12,7 +12,7 @@ jobs: - name: Set up Python uses: actions/setup-python@v4 with: - python-version: '3.8' + python-version: '3.11' - name: Install dependencies run: | python --version From 5024101eba1944635a135ec73dcd48c46fbc9148 Mon Sep 17 00:00:00 2001 From: Matthew Kappel Date: Thu, 25 May 2023 13:48:52 -0700 Subject: [PATCH 2/4] Handle FutureWarning: Calling float on a single element Series (#315) - *Category*: bugfix - *JIRA issue*: [MIC-3599](https://jira.ihme.washington.edu/browse/MIC-3599) Changes and notes Follows suggestion from FutureWarning to get the single Series item via .iloc[0] Testing Tested with the Maternal IV Iron simulation. When the FutureWarning ignore filters are removed from vivarium, previously emitted FutureWarnings no longer appear with this change. --- .../population/data_transformations.py | 61 ++++++++++--------- 1 file changed, 33 insertions(+), 28 deletions(-) diff --git a/src/vivarium_public_health/population/data_transformations.py b/src/vivarium_public_health/population/data_transformations.py index a246aae39..467012c23 100644 --- a/src/vivarium_public_health/population/data_transformations.py +++ b/src/vivarium_public_health/population/data_transformations.py @@ -108,13 +108,13 @@ def rescale_binned_proportions( values are rescaled to reflect their smaller representation. """ col_order = pop_data.columns.copy() - if age_start > pop_data.age_end.max(): + if age_start > pop_data["age_end"].max(): raise ValueError( "Provided population data is insufficient to model the requested age range." ) - age_start = max(pop_data.age_start.min(), age_start) - age_end = min(pop_data.age_end.max(), age_end) - 1e-8 + age_start = max(pop_data["age_start"].min(), age_start) + age_end = min(pop_data["age_end"].max(), age_end) - 1e-8 pop_data = _add_edge_age_groups(pop_data.copy()) columns_to_scale = [ @@ -123,12 +123,13 @@ def rescale_binned_proportions( "value", ] for _, sub_pop in pop_data.groupby(["sex", "location"]): + min_bin = sub_pop[ + (sub_pop["age_start"] <= age_start) & (age_start < sub_pop["age_end"]) + ] + padding_bin = sub_pop[sub_pop["age_end"] == float(min_bin["age_start"].iloc[0])] - min_bin = sub_pop[(sub_pop.age_start <= age_start) & (age_start < sub_pop.age_end)] - padding_bin = sub_pop[sub_pop.age_end == float(min_bin.age_start)] - - min_scale = (float(min_bin.age_end) - age_start) / float( - min_bin.age_end - min_bin.age_start + min_scale = (float(min_bin["age_end"].iloc[0]) - age_start) / float( + min_bin["age_end"].iloc[0] - min_bin["age_start"].iloc[0] ) remainder = pop_data.loc[min_bin.index, columns_to_scale].values * (1 - min_scale) @@ -138,11 +139,11 @@ def rescale_binned_proportions( pop_data.loc[min_bin.index, "age_start"] = age_start pop_data.loc[padding_bin.index, "age_end"] = age_start - max_bin = sub_pop[(sub_pop.age_end > age_end) & (age_end >= sub_pop.age_start)] - padding_bin = sub_pop[sub_pop.age_start == float(max_bin.age_end)] + max_bin = sub_pop[(sub_pop["age_end"] > age_end) & (age_end >= sub_pop["age_start"])] + padding_bin = sub_pop[sub_pop["age_start"] == float(max_bin["age_end"].iloc[0])] - max_scale = (age_end - float(max_bin.age_start)) / float( - max_bin.age_end - max_bin.age_start + max_scale = (age_end - float(max_bin["age_start"].iloc[0])) / float( + max_bin["age_end"].iloc[0] - max_bin["age_start"].iloc[0] ) remainder = pop_data.loc[max_bin.index, columns_to_scale] * (1 - max_scale) @@ -239,10 +240,11 @@ def smooth_ages( """ simulants = simulants.copy() for (sex, location), sub_pop in population_data.groupby(["sex", "location"]): - - ages = sorted(sub_pop.age.unique()) - younger = [float(sub_pop.loc[sub_pop.age == ages[0], "age_start"])] + ages[:-1] - older = ages[1:] + [float(sub_pop.loc[sub_pop.age == ages[-1], "age_end"])] + ages = sorted(sub_pop["age"].unique()) + younger = [float(sub_pop.loc[sub_pop["age"] == ages[0], "age_start"].iloc[0])] + ages[ + :-1 + ] + older = ages[1:] + [float(sub_pop.loc[sub_pop["age"] == ages[-1], "age_end"].iloc[0])] uniform_all = randomness.get_draw(simulants.index) @@ -250,9 +252,9 @@ def smooth_ages( age = AgeValues(*age_set) has_correct_demography = ( - (simulants.age == age.current) - & (simulants.sex == sex) - & (simulants.location == location) + (simulants["age"] == age.current) + & (simulants["sex"] == sex) + & (simulants["location"] == location) ) affected = simulants[has_correct_demography] @@ -319,15 +321,15 @@ def _get_bins_and_proportions( ) """ - left = float(pop_data.loc[pop_data.age == age.current, "age_start"]) - right = float(pop_data.loc[pop_data.age == age.current, "age_end"]) + left = float(pop_data.loc[pop_data["age"] == age.current, "age_start"].iloc[0]) + right = float(pop_data.loc[pop_data["age"] == age.current, "age_end"].iloc[0]) - if not pop_data.loc[pop_data.age == age.young, "age_start"].empty: - lower_left = float(pop_data.loc[pop_data.age == age.young, "age_start"]) + if not pop_data.loc[pop_data["age"] == age.young, "age_start"].empty: + lower_left = float(pop_data.loc[pop_data["age"] == age.young, "age_start"].iloc[0]) else: lower_left = left - if not pop_data.loc[pop_data.age == age.old, "age_end"].empty: - upper_right = float(pop_data.loc[pop_data.age == age.old, "age_end"]) + if not pop_data.loc[pop_data["age"] == age.old, "age_end"].empty: + upper_right = float(pop_data.loc[pop_data["age"] == age.old, "age_end"].iloc[0]) else: upper_right = right @@ -338,18 +340,21 @@ def _get_bins_and_proportions( # in order to back out a point estimate for the probability density at the center # of the interval. This not the best assumption, but it'll do. p_age = float( - pop_data.loc[pop_data.age == age.current, proportion_column] / (right - left) + pop_data.loc[pop_data["age"] == age.current, proportion_column].iloc[0] + / (right - left) ) p_young = ( float( - pop_data.loc[pop_data.age == age.young, proportion_column] / (left - lower_left) + pop_data.loc[pop_data["age"] == age.young, proportion_column].iloc[0] + / (left - lower_left) ) if age.young != left else p_age ) p_old = ( float( - pop_data.loc[pop_data.age == age.old, proportion_column] / (upper_right - right) + pop_data.loc[pop_data["age"] == age.old, proportion_column].iloc[0] + / (upper_right - right) ) if age.old != right else 0 From ba12f039ffaaa7d148457586b9d20e736d559c99 Mon Sep 17 00:00:00 2001 From: Rajan Mudambi <11376379+rmudambi@users.noreply.github.com> Date: Fri, 26 May 2023 11:07:47 -0700 Subject: [PATCH 3/4] Refactor/transition names (#316) Category: refactor JIRA issue: MIC-4085 Changes and notes Define get_transition_names function on BaseDiseaseState Call this function when getting all transitions in a Disease Model This is a straight refactor with no logic changes. It's needed to support the change I made in the associated US CVD PR (ihmeuw/vivarium_nih_us_cvd#124) to allow the model to use the standard VPH disease observer A bunch of whitespcae changes got pulled in by the linter. Testing Ran an interactive sim for a few steps and verified that the metrics pipeline was counting transitions as expected. Currently running a parallel sim. --- setup.py | 1 - src/vivarium_public_health/disease/model.py | 4 +--- .../disease/special_disease.py | 1 - src/vivarium_public_health/disease/state.py | 14 +++++++++++++- src/vivarium_public_health/population/mortality.py | 1 - .../low_birth_weight_and_short_gestation.py | 3 --- tests/disease/test_disease.py | 1 - tests/metrics/test_stratification.py | 2 -- tests/population/test_add_new_birth_cohort.py | 1 - 9 files changed, 14 insertions(+), 14 deletions(-) diff --git a/setup.py b/setup.py index 11fe7dc35..f616a24c7 100644 --- a/setup.py +++ b/setup.py @@ -4,7 +4,6 @@ from setuptools import find_packages, setup if __name__ == "__main__": - base_dir = os.path.dirname(__file__) src_dir = os.path.join(base_dir, "src") diff --git a/src/vivarium_public_health/disease/model.py b/src/vivarium_public_health/disease/model.py index 2420fcde3..094a2678a 100644 --- a/src/vivarium_public_health/disease/model.py +++ b/src/vivarium_public_health/disease/model.py @@ -53,9 +53,7 @@ def transition_names(self) -> List[TransitionString]: states = {s.name.split(".")[1]: s for s in self.states} transitions = [] for state in states.values(): - for trans in state.transition_set.transitions: - _, _, init_state, _, end_state = trans.name.split(".") - transitions.append(TransitionString(f"{init_state}_TO_{end_state}")) + transitions += state.get_transition_names() return transitions def setup(self, builder): diff --git a/src/vivarium_public_health/disease/special_disease.py b/src/vivarium_public_health/disease/special_disease.py index 4d6063903..c8060d1fb 100644 --- a/src/vivarium_public_health/disease/special_disease.py +++ b/src/vivarium_public_health/disease/special_disease.py @@ -283,7 +283,6 @@ def with_condition(self, index): return with_condition def get_exposure_filter(self, distribution, exposure_pipeline, threshold): - if distribution in ["dichotomous", "ordered_polytomous", "unordered_polytomous"]: def categorical_filter(index): diff --git a/src/vivarium_public_health/disease/state.py b/src/vivarium_public_health/disease/state.py index 8cc25d718..615ab33fe 100644 --- a/src/vivarium_public_health/disease/state.py +++ b/src/vivarium_public_health/disease/state.py @@ -6,7 +6,7 @@ This module contains tools to manage standard disease states. """ -from typing import Callable, Dict +from typing import Callable, Dict, List import numpy as np import pandas as pd @@ -17,6 +17,7 @@ from vivarium_public_health.disease.transition import ( ProportionTransition, RateTransition, + TransitionString, ) from vivarium_public_health.utilities import is_non_zero @@ -94,6 +95,17 @@ def _transition_side_effect(self, index, event_time): if self.side_effect_function is not None: self.side_effect_function(index, event_time) + ################## + # Public methods # + ################## + + def get_transition_names(self) -> List[str]: + transitions = [] + for trans in self.transition_set.transitions: + _, _, init_state, _, end_state = trans.name.split(".") + transitions.append(TransitionString(f"{init_state}_TO_{end_state}")) + return transitions + def add_transition( self, output: State, diff --git a/src/vivarium_public_health/population/mortality.py b/src/vivarium_public_health/population/mortality.py index 1e589ce60..47e48aac8 100644 --- a/src/vivarium_public_health/population/mortality.py +++ b/src/vivarium_public_health/population/mortality.py @@ -56,7 +56,6 @@ class Mortality: - configuration_defaults = {"unmodeled_causes": []} def __init__(self): diff --git a/src/vivarium_public_health/risks/implementations/low_birth_weight_and_short_gestation.py b/src/vivarium_public_health/risks/implementations/low_birth_weight_and_short_gestation.py index 2198d76d2..5a7f68f71 100644 --- a/src/vivarium_public_health/risks/implementations/low_birth_weight_and_short_gestation.py +++ b/src/vivarium_public_health/risks/implementations/low_birth_weight_and_short_gestation.py @@ -31,7 +31,6 @@ class LBWSGDistribution(PolytomousDistribution): - configuration_defaults = { "lbwsg_distribution": { "age_column": "age", @@ -211,7 +210,6 @@ def _parse_description(axis: str, description: str) -> pd.Interval: class LBWSGRisk(Risk): - AXES = [BIRTH_WEIGHT, GESTATIONAL_AGE] def __init__(self): @@ -316,7 +314,6 @@ def _get_current_exposure(self, index: pd.Index) -> pd.DataFrame: class LBWSGRiskEffect(RiskEffect): - TMREL_BIRTH_WEIGHT_INTERVAL: pd.Interval = pd.Interval(3500.0, 4500.0) TMREL_GESTATIONAL_AGE_INTERVAL: pd.Interval = pd.Interval(38.0, 42.0) diff --git a/tests/disease/test_disease.py b/tests/disease/test_disease.py index 6a244bfce..76bb6450f 100644 --- a/tests/disease/test_disease.py +++ b/tests/disease/test_disease.py @@ -52,7 +52,6 @@ def get_test_prevalence(simulation, key): 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 diff --git a/tests/metrics/test_stratification.py b/tests/metrics/test_stratification.py index 8e0169ab4..ff5f5c5b2 100644 --- a/tests/metrics/test_stratification.py +++ b/tests/metrics/test_stratification.py @@ -15,7 +15,6 @@ class FavoriteColor: - OPTIONS = ["red", "green", "orange"] @property @@ -34,7 +33,6 @@ def setup(self, builder: Builder): class FavoriteNumber: - OPTIONS = [7, 42, 14312] @property diff --git a/tests/population/test_add_new_birth_cohort.py b/tests/population/test_add_new_birth_cohort.py index 295ecdc08..6c077f63d 100644 --- a/tests/population/test_add_new_birth_cohort.py +++ b/tests/population/test_add_new_birth_cohort.py @@ -16,7 +16,6 @@ @pytest.fixture() def config(base_config): - base_config.update( { "population": { From 11ea0f202a1d0f09d37b26ad33e6f4598e50ee5b Mon Sep 17 00:00:00 2001 From: Steve Bachmeier <23350991+stevebachmeier@users.noreply.github.com> Date: Thu, 1 Jun 2023 13:38:21 -0600 Subject: [PATCH 4/4] Release/v0.11.0 (#319) --- CHANGELOG.rst | 7 +++++++ setup.py | 2 +- src/vivarium_public_health/__about__.py | 2 +- 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 46cb6b91c..a674f9032 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -1,3 +1,10 @@ +**0.11.0 - 06/01/23** + + - Support Python 3.8-3.11 + - Update vivarium pin + - Handle FutureWarning + - Refactor to create a 'get_transition_names' function + **0.10.24 - 05/11/23** - Standardize builder, cause argument order in state get data functions diff --git a/setup.py b/setup.py index f616a24c7..480a92143 100644 --- a/setup.py +++ b/setup.py @@ -15,7 +15,7 @@ long_description = f.read() install_requirements = [ - "vivarium>=1.1.0", + "vivarium>=1.2.0", "numpy", "pandas", "scipy", diff --git a/src/vivarium_public_health/__about__.py b/src/vivarium_public_health/__about__.py index 5faa3ab6d..5426e2004 100644 --- a/src/vivarium_public_health/__about__.py +++ b/src/vivarium_public_health/__about__.py @@ -13,7 +13,7 @@ __summary__ = "Components for modelling diseases, risks, and interventions with ``vivarium``" __uri__ = "https://github.com/ihmeuw/vivarium_public_health" -__version__ = "0.10.24" +__version__ = "0.11.0" __author__ = "The vivarium_public_health developers" __email__ = "vivarium.dev@gmail.com"