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

Sign up to get free protection for your applications and to get access to all the features.
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 #