vivarium-public-health 2.3.2__py3-none-any.whl → 3.0.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (48) hide show
  1. vivarium_public_health/_version.py +1 -1
  2. vivarium_public_health/disease/model.py +23 -21
  3. vivarium_public_health/disease/models.py +1 -0
  4. vivarium_public_health/disease/special_disease.py +40 -41
  5. vivarium_public_health/disease/state.py +42 -125
  6. vivarium_public_health/disease/transition.py +70 -27
  7. vivarium_public_health/mslt/delay.py +1 -0
  8. vivarium_public_health/mslt/disease.py +1 -0
  9. vivarium_public_health/mslt/intervention.py +1 -0
  10. vivarium_public_health/mslt/magic_wand_components.py +1 -0
  11. vivarium_public_health/mslt/observer.py +1 -0
  12. vivarium_public_health/mslt/population.py +1 -0
  13. vivarium_public_health/plugins/parser.py +61 -31
  14. vivarium_public_health/population/add_new_birth_cohorts.py +2 -3
  15. vivarium_public_health/population/base_population.py +2 -1
  16. vivarium_public_health/population/mortality.py +83 -80
  17. vivarium_public_health/{metrics → results}/__init__.py +2 -0
  18. vivarium_public_health/results/columns.py +22 -0
  19. vivarium_public_health/results/disability.py +187 -0
  20. vivarium_public_health/results/disease.py +222 -0
  21. vivarium_public_health/results/mortality.py +186 -0
  22. vivarium_public_health/results/observer.py +78 -0
  23. vivarium_public_health/results/risk.py +138 -0
  24. vivarium_public_health/results/simple_cause.py +18 -0
  25. vivarium_public_health/{metrics → results}/stratification.py +10 -8
  26. vivarium_public_health/risks/__init__.py +1 -2
  27. vivarium_public_health/risks/base_risk.py +134 -29
  28. vivarium_public_health/risks/data_transformations.py +65 -326
  29. vivarium_public_health/risks/distributions.py +315 -145
  30. vivarium_public_health/risks/effect.py +376 -75
  31. vivarium_public_health/risks/implementations/low_birth_weight_and_short_gestation.py +61 -89
  32. vivarium_public_health/treatment/magic_wand.py +1 -0
  33. vivarium_public_health/treatment/scale_up.py +1 -0
  34. vivarium_public_health/treatment/therapeutic_inertia.py +1 -0
  35. vivarium_public_health/utilities.py +17 -2
  36. {vivarium_public_health-2.3.2.dist-info → vivarium_public_health-3.0.0.dist-info}/METADATA +13 -3
  37. vivarium_public_health-3.0.0.dist-info/RECORD +49 -0
  38. {vivarium_public_health-2.3.2.dist-info → vivarium_public_health-3.0.0.dist-info}/WHEEL +1 -1
  39. vivarium_public_health/metrics/disability.py +0 -118
  40. vivarium_public_health/metrics/disease.py +0 -136
  41. vivarium_public_health/metrics/mortality.py +0 -144
  42. vivarium_public_health/metrics/risk.py +0 -110
  43. vivarium_public_health/testing/__init__.py +0 -0
  44. vivarium_public_health/testing/mock_artifact.py +0 -145
  45. vivarium_public_health/testing/utils.py +0 -71
  46. vivarium_public_health-2.3.2.dist-info/RECORD +0 -49
  47. {vivarium_public_health-2.3.2.dist-info → vivarium_public_health-3.0.0.dist-info}/LICENSE.txt +0 -0
  48. {vivarium_public_health-2.3.2.dist-info → vivarium_public_health-3.0.0.dist-info}/top_level.txt +0 -0
@@ -7,20 +7,26 @@ This module contains tools for modeling categorical and continuous risk
7
7
  exposure.
8
8
 
9
9
  """
10
+
10
11
  from typing import Any, Dict, List
11
12
 
12
13
  import pandas as pd
13
14
  from vivarium import Component
14
15
  from vivarium.framework.engine import Builder
16
+ from vivarium.framework.event import Event
15
17
  from vivarium.framework.population import SimulantData
16
18
  from vivarium.framework.randomness import RandomnessStream
17
19
  from vivarium.framework.values import Pipeline
18
20
 
19
- from vivarium_public_health.risks.data_transformations import (
20
- get_exposure_post_processor,
21
+ from vivarium_public_health.risks.data_transformations import get_exposure_post_processor
22
+ from vivarium_public_health.risks.distributions import (
23
+ ContinuousDistribution,
24
+ DichotomousDistribution,
25
+ EnsembleDistribution,
26
+ PolytomousDistribution,
27
+ RiskExposureDistribution,
21
28
  )
22
- from vivarium_public_health.risks.distributions import SimulationDistribution
23
- from vivarium_public_health.utilities import EntityString
29
+ from vivarium_public_health.utilities import EntityString, get_lookup_columns
24
30
 
25
31
 
26
32
  class Risk(Component):
@@ -81,25 +87,42 @@ class Risk(Component):
81
87
 
82
88
  """
83
89
 
84
- CONFIGURATION_DEFAULTS = {
85
- "risk": {
86
- "exposure": "data",
87
- "rebinned_exposed": [],
88
- "category_thresholds": [],
89
- }
90
+ exposure_distributions = {
91
+ "dichotomous": DichotomousDistribution,
92
+ "ordered_polytomous": PolytomousDistribution,
93
+ "unordered_polytomous": PolytomousDistribution,
94
+ "normal": ContinuousDistribution,
95
+ "lognormal": ContinuousDistribution,
96
+ "ensemble": EnsembleDistribution,
90
97
  }
91
98
 
92
99
  ##############
93
100
  # Properties #
94
101
  ##############
95
102
 
103
+ @property
104
+ def name(self) -> str:
105
+ return self.risk
106
+
96
107
  @property
97
108
  def configuration_defaults(self) -> Dict[str, Any]:
98
- return {self.risk.name: self.CONFIGURATION_DEFAULTS["risk"]}
109
+ return {
110
+ self.name: {
111
+ "data_sources": {
112
+ "exposure": f"{self.risk}.exposure",
113
+ "ensemble_distribution_weights": f"{self.risk}.exposure_distribution_weights",
114
+ "exposure_standard_deviation": f"{self.risk}.exposure_standard_deviation",
115
+ },
116
+ "distribution_type": f"{self.risk}.distribution",
117
+ # rebinned_exposed only used for DichotomousDistribution
118
+ "rebinned_exposed": [],
119
+ "category_thresholds": [],
120
+ }
121
+ }
99
122
 
100
123
  @property
101
124
  def columns_created(self) -> List[str]:
102
- return [self.propensity_column_name]
125
+ return [self.propensity_column_name, self.exposure_column_name]
103
126
 
104
127
  @property
105
128
  def initialization_requirements(self) -> Dict[str, List[str]]:
@@ -122,30 +145,98 @@ class Risk(Component):
122
145
  """
123
146
  super().__init__()
124
147
  self.risk = EntityString(risk)
125
- self.exposure_distribution = self.get_exposure_distribution()
126
- self._sub_components = [self.exposure_distribution]
148
+ self.distribution_type = None
127
149
 
128
150
  self.randomness_stream_name = f"initial_{self.risk.name}_propensity"
129
151
  self.propensity_column_name = f"{self.risk.name}_propensity"
130
152
  self.propensity_pipeline_name = f"{self.risk.name}.propensity"
131
153
  self.exposure_pipeline_name = f"{self.risk.name}.exposure"
154
+ self.exposure_column_name = f"{self.risk.name}_exposure"
155
+
156
+ #################
157
+ # Setup methods #
158
+ #################
159
+
160
+ def build_all_lookup_tables(self, builder: "Builder") -> None:
161
+ # All lookup tables are built in the exposure distribution
162
+ pass
132
163
 
133
164
  # noinspection PyAttributeOutsideInit
134
165
  def setup(self, builder: Builder) -> None:
166
+ self.distribution_type = self.get_distribution_type(builder)
167
+ self.exposure_distribution = self.get_exposure_distribution(builder)
168
+
135
169
  self.randomness = self.get_randomness_stream(builder)
136
170
  self.propensity = self.get_propensity_pipeline(builder)
137
171
  self.exposure = self.get_exposure_pipeline(builder)
138
172
 
139
- ##########################
140
- # Initialization methods #
141
- ##########################
173
+ def get_distribution_type(self, builder: Builder) -> str:
174
+ """
175
+ Get the distribution type for the risk from the configuration.
142
176
 
143
- def get_exposure_distribution(self) -> SimulationDistribution:
144
- return SimulationDistribution(self.risk)
177
+ If the configured distribution type is not one of the supported types,
178
+ it is assumed to be a data source and the data is retrieved using the
179
+ get_data method.
145
180
 
146
- #################
147
- # Setup methods #
148
- #################
181
+ Parameters
182
+ ----------
183
+ builder : Builder
184
+ the builder object
185
+
186
+ Returns
187
+ -------
188
+ str
189
+ the distribution type
190
+ """
191
+ if self.configuration is None:
192
+ self.configuration = self.get_configuration(builder)
193
+
194
+ distribution_type = self.configuration["distribution_type"]
195
+ if distribution_type not in self.exposure_distributions.keys():
196
+ # todo deal with incorrect typing
197
+ distribution_type = self.get_data(builder, distribution_type)
198
+
199
+ if self.configuration["rebinned_exposed"]:
200
+ if distribution_type != "dichotomous" or "polytomous" not in distribution_type:
201
+ raise ValueError(
202
+ f"Unsupported risk distribution type '{distribution_type}' "
203
+ f"for {self.name}. Rebinned exposed categories are only "
204
+ "supported for dichotomous and polytomous distributions."
205
+ )
206
+ distribution_type = "dichotomous"
207
+ return distribution_type
208
+
209
+ def get_exposure_distribution(self, builder: Builder) -> RiskExposureDistribution:
210
+ """
211
+ Creates and sets up the exposure distribution component for the Risk
212
+ based on its distribution type.
213
+
214
+ Parameters
215
+ ----------
216
+ builder : Builder
217
+ the builder object
218
+
219
+ Returns
220
+ -------
221
+ RiskExposureDistribution
222
+ the exposure distribution
223
+
224
+ Raises
225
+ ------
226
+ NotImplementedError
227
+ if the distribution type is not supported
228
+ """
229
+ try:
230
+ exposure_distribution = self.exposure_distributions[self.distribution_type](
231
+ self.risk, self.distribution_type
232
+ )
233
+ except KeyError:
234
+ raise NotImplementedError(
235
+ f"Distribution type {self.distribution_type} is not supported."
236
+ )
237
+
238
+ exposure_distribution.setup_component(builder)
239
+ return exposure_distribution
149
240
 
150
241
  def get_randomness_stream(self, builder: Builder) -> RandomnessStream:
151
242
  return builder.randomness.get_stream(self.randomness_stream_name)
@@ -162,12 +253,18 @@ class Risk(Component):
162
253
  )
163
254
 
164
255
  def get_exposure_pipeline(self, builder: Builder) -> Pipeline:
256
+ required_columns = get_lookup_columns(
257
+ self.exposure_distribution.lookup_tables.values()
258
+ )
165
259
  return builder.value.register_value_producer(
166
260
  self.exposure_pipeline_name,
167
261
  source=self.get_current_exposure,
168
- requires_columns=["age", "sex"],
169
- requires_values=[self.propensity_pipeline_name],
170
- preferred_post_processor=get_exposure_post_processor(builder, self.risk),
262
+ requires_columns=required_columns,
263
+ requires_values=[
264
+ self.propensity_pipeline_name,
265
+ self.exposure_distribution.parameters_pipeline_name,
266
+ ],
267
+ preferred_post_processor=get_exposure_post_processor(builder, self.name),
171
268
  )
172
269
 
173
270
  ########################
@@ -175,11 +272,19 @@ class Risk(Component):
175
272
  ########################
176
273
 
177
274
  def on_initialize_simulants(self, pop_data: SimulantData) -> None:
178
- self.population_view.update(
179
- pd.Series(
180
- self.randomness.get_draw(pop_data.index), name=self.propensity_column_name
181
- )
275
+ propensity_values = self.randomness.get_draw(pop_data.index)
276
+ df = pd.DataFrame(
277
+ {
278
+ self.propensity_column_name: self.randomness.get_draw(pop_data.index),
279
+ self.exposure_column_name: self.exposure_distribution.ppf(propensity_values),
280
+ }
182
281
  )
282
+ self.population_view.update(df)
283
+
284
+ def on_time_step_prepare(self, event: Event) -> None:
285
+ exposure_values = self.exposure(event.index)
286
+ exposure_col = pd.Series(exposure_values, name=self.exposure_column_name)
287
+ self.population_view.update(exposure_col)
183
288
 
184
289
  ##################################
185
290
  # Pipeline sources and modifiers #