vivarium-public-health 3.0.3__py3-none-any.whl → 3.0.4__py3-none-any.whl

Sign up to get free protection for your applications and to get access to all the features.
Files changed (33) hide show
  1. vivarium_public_health/_version.py +1 -1
  2. vivarium_public_health/disease/state.py +24 -19
  3. vivarium_public_health/mslt/delay.py +13 -5
  4. vivarium_public_health/mslt/disease.py +35 -14
  5. vivarium_public_health/mslt/intervention.py +12 -9
  6. vivarium_public_health/mslt/observer.py +56 -17
  7. vivarium_public_health/mslt/population.py +7 -10
  8. vivarium_public_health/plugins/parser.py +29 -80
  9. vivarium_public_health/population/add_new_birth_cohorts.py +8 -9
  10. vivarium_public_health/population/base_population.py +0 -5
  11. vivarium_public_health/population/data_transformations.py +1 -8
  12. vivarium_public_health/population/mortality.py +3 -3
  13. vivarium_public_health/results/columns.py +1 -1
  14. vivarium_public_health/results/disability.py +85 -11
  15. vivarium_public_health/results/disease.py +125 -2
  16. vivarium_public_health/results/mortality.py +78 -2
  17. vivarium_public_health/results/observer.py +141 -6
  18. vivarium_public_health/results/risk.py +66 -5
  19. vivarium_public_health/results/simple_cause.py +8 -2
  20. vivarium_public_health/results/stratification.py +39 -14
  21. vivarium_public_health/risks/base_risk.py +14 -16
  22. vivarium_public_health/risks/data_transformations.py +3 -1
  23. vivarium_public_health/risks/distributions.py +0 -1
  24. vivarium_public_health/risks/effect.py +31 -29
  25. vivarium_public_health/risks/implementations/low_birth_weight_and_short_gestation.py +51 -30
  26. vivarium_public_health/treatment/scale_up.py +6 -10
  27. vivarium_public_health/treatment/therapeutic_inertia.py +3 -1
  28. {vivarium_public_health-3.0.3.dist-info → vivarium_public_health-3.0.4.dist-info}/METADATA +1 -1
  29. vivarium_public_health-3.0.4.dist-info/RECORD +49 -0
  30. {vivarium_public_health-3.0.3.dist-info → vivarium_public_health-3.0.4.dist-info}/WHEEL +1 -1
  31. vivarium_public_health-3.0.3.dist-info/RECORD +0 -49
  32. {vivarium_public_health-3.0.3.dist-info → vivarium_public_health-3.0.4.dist-info}/LICENSE.txt +0 -0
  33. {vivarium_public_health-3.0.3.dist-info → vivarium_public_health-3.0.4.dist-info}/top_level.txt +0 -0
@@ -40,6 +40,18 @@ class CategoricalRiskObserver(PublicHealthObserver):
40
40
  - "sex"
41
41
  include:
42
42
  - "sample_stratification"
43
+
44
+ Attributes
45
+ ----------
46
+ risk
47
+ The name of the risk factor.
48
+ exposure_pipeline_name
49
+ The name of the pipeline that produces the risk factor exposure.
50
+ step_size
51
+ The time step size of the simulation.
52
+ categories
53
+ The categories of the risk factor.
54
+
43
55
  """
44
56
 
45
57
  ##############
@@ -48,8 +60,7 @@ class CategoricalRiskObserver(PublicHealthObserver):
48
60
 
49
61
  @property
50
62
  def configuration_defaults(self) -> Dict[str, Any]:
51
- """
52
- A dictionary containing the defaults for any configurations managed by
63
+ """A dictionary containing the defaults for any configurations managed by
53
64
  this component.
54
65
  """
55
66
  return {
@@ -62,6 +73,7 @@ class CategoricalRiskObserver(PublicHealthObserver):
62
73
 
63
74
  @property
64
75
  def columns_required(self) -> Optional[List[str]]:
76
+ """The columns required by this observer."""
65
77
  return ["alive"]
66
78
 
67
79
  #####################
@@ -69,11 +81,12 @@ class CategoricalRiskObserver(PublicHealthObserver):
69
81
  #####################
70
82
 
71
83
  def __init__(self, risk: str) -> None:
72
- """
84
+ """Constructor for this observer.
85
+
73
86
  Parameters
74
87
  ----------
75
- risk: name of a risk
76
-
88
+ risk
89
+ The name of the risk being observed
77
90
  """
78
91
  super().__init__()
79
92
  self.risk = risk
@@ -84,13 +97,37 @@ class CategoricalRiskObserver(PublicHealthObserver):
84
97
  #################
85
98
 
86
99
  def setup(self, builder: Builder) -> None:
100
+ """Set up the observer."""
87
101
  self.step_size = builder.time.step_size()
88
102
  self.categories = builder.data.load(f"risk_factor.{self.risk}.categories")
89
103
 
90
104
  def get_configuration(self, builder: Builder) -> LayeredConfigTree:
105
+ """Get the stratification configuration for this observer.
106
+
107
+ Parameters
108
+ ----------
109
+ builder
110
+ The builder object for the simulation.
111
+
112
+ Returns
113
+ -------
114
+ The stratification configuration for this observer.
115
+ """
91
116
  return builder.configuration.stratification[self.risk]
92
117
 
93
118
  def register_observations(self, builder: Builder) -> None:
119
+ """Register a stratification and observation.
120
+
121
+ Notes
122
+ -----
123
+ While it's typical for all stratification registrations to be encapsulated
124
+ in a single class (i.e. the
125
+ :class:ResultsStratifier <vivarium_public_health.results.stratification.ResultsStratifier),
126
+ this observer registers an additional one. While it could be registered
127
+ in the ``ResultsStratifier`` as well, it is specific to this observer and
128
+ so it is registered here while we have easy access to the required categories
129
+ and value names.
130
+ """
94
131
  builder.results.register_stratification(
95
132
  f"{self.risk}",
96
133
  list(self.categories.keys()),
@@ -113,6 +150,7 @@ class CategoricalRiskObserver(PublicHealthObserver):
113
150
  ###############
114
151
 
115
152
  def aggregate_risk_category_person_time(self, x: pd.DataFrame) -> float:
153
+ """Aggregate the person time for this time step."""
116
154
  return len(x) * to_years(self.step_size())
117
155
 
118
156
  ##############################
@@ -120,19 +158,42 @@ class CategoricalRiskObserver(PublicHealthObserver):
120
158
  ##############################
121
159
 
122
160
  def format(self, measure: str, results: pd.DataFrame) -> pd.DataFrame:
161
+ """Rename the appropriate column to 'sub_entity'.
162
+
163
+ The primary thing this method does is rename the risk column
164
+ to 'sub_entity'. We do this here instead of the 'get_sub_entity_column'
165
+ method simply because we do not want the risk column at all. If we keep
166
+ it here and then return it as the sub-entity column later, the final
167
+ results would have both.
168
+
169
+ Parameters
170
+ ----------
171
+ measure
172
+ The measure.
173
+ results
174
+ The results to format.
175
+
176
+ Returns
177
+ -------
178
+ The formatted results.
179
+ """
123
180
  results = results.reset_index()
124
181
  results.rename(columns={self.risk: COLUMNS.SUB_ENTITY}, inplace=True)
125
182
  return results
126
183
 
127
184
  def get_measure_column(self, measure: str, results: pd.DataFrame) -> pd.Series:
185
+ """Get the 'measure' column values."""
128
186
  return pd.Series("person_time", index=results.index)
129
187
 
130
188
  def get_entity_type_column(self, measure: str, results: pd.DataFrame) -> pd.Series:
189
+ """Get the 'entity_type' column values."""
131
190
  return pd.Series("rei", index=results.index)
132
191
 
133
192
  def get_entity_column(self, measure: str, results: pd.DataFrame) -> pd.Series:
193
+ """Get the 'entity' column values."""
134
194
  return pd.Series(self.risk, index=results.index)
135
195
 
136
196
  def get_sub_entity_column(self, measure: str, results: pd.DataFrame) -> pd.Series:
197
+ """Get the 'sub_entity' column values."""
137
198
  # The sub-entity col was created in the 'format' method
138
199
  return results[COLUMNS.SUB_ENTITY]
@@ -4,15 +4,21 @@ from dataclasses import dataclass
4
4
  @dataclass
5
5
  class SimpleCause:
6
6
  """A simple dataclass to represent the bare minimum information needed
7
- for observers, e.g. 'all_causes' as a cause of disability. It also
8
- includes a class method to convert a provided disease state into a
7
+ for observers, e.g. 'all_causes' as a cause of disability.
8
+
9
+ It also includes a class method to convert a provided disease state into a
9
10
  ``SimpleCause`` instance.
11
+
10
12
  """
11
13
 
12
14
  state_id: str
15
+ """The state_id of the cause."""
13
16
  model: str
17
+ """The model of the cause."""
14
18
  cause_type: str
19
+ """The cause type of the cause."""
15
20
 
16
21
  @classmethod
17
22
  def create_from_disease_state(cls, disease_state: type) -> "SimpleCause":
23
+ """Create a SimpleCause instance from a"""
18
24
  return cls(disease_state.state_id, disease_state.model, disease_state.cause_type)
@@ -5,9 +5,8 @@ Results Stratifier
5
5
 
6
6
  This module contains tools for stratifying observed quantities
7
7
  by specified characteristics through the vivarium results interface.
8
- """
9
8
 
10
- from __future__ import annotations
9
+ """
11
10
 
12
11
  import pandas as pd
13
12
  from vivarium import Component
@@ -15,6 +14,22 @@ from vivarium.framework.engine import Builder
15
14
 
16
15
 
17
16
  class ResultsStratifier(Component):
17
+ """A component for registering common public health stratifications.
18
+
19
+ The purpose of this component is to encapsulate all common public health
20
+ stratification registrations in one place. This is not enforced, however,
21
+ and stratification registrations can be done in any component.
22
+
23
+ Attributes
24
+ ----------
25
+ age_bins
26
+ The age bins for stratifying by age.
27
+ start_year
28
+ The start year of the simulation.
29
+ end_year
30
+ The end year of the simulation.
31
+ """
32
+
18
33
  #####################
19
34
  # Lifecycle methods #
20
35
  #####################
@@ -32,6 +47,7 @@ class ResultsStratifier(Component):
32
47
  #################
33
48
 
34
49
  def register_stratifications(self, builder: Builder) -> None:
50
+ """Register stratifications for the simulation."""
35
51
  builder.results.register_stratification(
36
52
  "age_group",
37
53
  self.age_bins["age_group_name"].to_list(),
@@ -80,18 +96,17 @@ class ResultsStratifier(Component):
80
96
  # Mappers #
81
97
  ###########
82
98
 
83
- def map_age_groups(self, pop: pd.DataFrame) -> pd.Series[str]:
84
- """Map age with age group name strings
99
+ def map_age_groups(self, pop: pd.DataFrame) -> pd.Series:
100
+ """Map age with age group name strings.
85
101
 
86
102
  Parameters
87
103
  ----------
88
104
  pop
89
- A pd.DataFrame with one column, an age to be mapped to an age group name string
105
+ A table with one column, an age to be mapped to an age group name string.
90
106
 
91
107
  Returns
92
- ------
93
- pandas.Series
94
- A pd.Series with age group name string corresponding to the pop passed into the function
108
+ -------
109
+ The age group name strings corresponding to the pop passed into the function.
95
110
  """
96
111
  bins = self.age_bins["age_start"].to_list() + [self.age_bins["age_end"].iloc[-1]]
97
112
  labels = self.age_bins["age_group_name"].to_list()
@@ -99,23 +114,33 @@ class ResultsStratifier(Component):
99
114
  return age_group
100
115
 
101
116
  @staticmethod
102
- def map_year(pop: pd.DataFrame) -> pd.Series[str]:
103
- """Map datetime with year
117
+ def map_year(pop: pd.DataFrame) -> pd.Series:
118
+ """Map datetime with year.
104
119
 
105
120
  Parameters
106
121
  ----------
107
122
  pop
108
- A pd.DataFrame with one column, a datetime to be mapped to year
123
+ A table with one column, a datetime to be mapped to year.
109
124
 
110
125
  Returns
111
- ------
112
- pandas.Series
113
- A pd.Series with years corresponding to the pop passed into the function
126
+ -------
127
+ The years corresponding to the pop passed into the function.
114
128
  """
115
129
  return pop.squeeze(axis=1).dt.year.apply(str)
116
130
 
117
131
  @staticmethod
118
132
  def get_age_bins(builder: Builder) -> pd.DataFrame:
133
+ """Get the age bins for stratifying by age.
134
+
135
+ Parameters
136
+ ----------
137
+ builder
138
+ The builder object for the simulation.
139
+
140
+ Returns
141
+ -------
142
+ The age bins for stratifying by age.
143
+ """
119
144
  raw_age_bins = builder.data.load("population.age_bins")
120
145
  age_start = builder.configuration.population.initialization_age_min
121
146
  exit_age = builder.configuration.population.untracking_age
@@ -30,8 +30,9 @@ from vivarium_public_health.utilities import EntityString, get_lookup_columns
30
30
 
31
31
 
32
32
  class Risk(Component):
33
- """A model for a risk factor defined by either a continuous or a categorical
34
- value. For example,
33
+ """A model for a risk factor defined by either a continuous or a categorical value.
34
+
35
+ For example,
35
36
 
36
37
  #. high systolic blood pressure as a risk where the SBP is not dichotomized
37
38
  into hypotension and normal but is treated as the actual SBP
@@ -138,9 +139,10 @@ class Risk(Component):
138
139
 
139
140
  def __init__(self, risk: str):
140
141
  """
142
+
141
143
  Parameters
142
144
  ----------
143
- risk :
145
+ risk
144
146
  the type and name of a risk, specified as "type.name". Type is singular.
145
147
  """
146
148
  super().__init__()
@@ -171,8 +173,7 @@ class Risk(Component):
171
173
  self.exposure = self.get_exposure_pipeline(builder)
172
174
 
173
175
  def get_distribution_type(self, builder: Builder) -> str:
174
- """
175
- Get the distribution type for the risk from the configuration.
176
+ """Get the distribution type for the risk from the configuration.
176
177
 
177
178
  If the configured distribution type is not one of the supported types,
178
179
  it is assumed to be a data source and the data is retrieved using the
@@ -180,13 +181,12 @@ class Risk(Component):
180
181
 
181
182
  Parameters
182
183
  ----------
183
- builder : Builder
184
- the builder object
184
+ builder
185
+ The builder object.
185
186
 
186
187
  Returns
187
188
  -------
188
- str
189
- the distribution type
189
+ The distribution type.
190
190
  """
191
191
  if self.configuration is None:
192
192
  self.configuration = self.get_configuration(builder)
@@ -207,24 +207,22 @@ class Risk(Component):
207
207
  return distribution_type
208
208
 
209
209
  def get_exposure_distribution(self, builder: Builder) -> RiskExposureDistribution:
210
- """
211
- Creates and sets up the exposure distribution component for the Risk
210
+ """Creates and sets up the exposure distribution component for the Risk
212
211
  based on its distribution type.
213
212
 
214
213
  Parameters
215
214
  ----------
216
- builder : Builder
217
- the builder object
215
+ builder
216
+ The builder object.
218
217
 
219
218
  Returns
220
219
  -------
221
- RiskExposureDistribution
222
- the exposure distribution
220
+ The exposure distribution.
223
221
 
224
222
  Raises
225
223
  ------
226
224
  NotImplementedError
227
- if the distribution type is not supported
225
+ If the distribution type is not supported.
228
226
  """
229
227
  try:
230
228
  exposure_distribution = self.exposure_distributions[self.distribution_type](
@@ -78,7 +78,9 @@ def load_exposure_data(builder: Builder, risk: EntityString) -> pd.DataFrame:
78
78
  def rebin_relative_risk_data(
79
79
  builder, risk: EntityString, relative_risk_data: pd.DataFrame
80
80
  ) -> pd.DataFrame:
81
- """When the polytomous risk is rebinned, matching relative risk needs to be rebinned.
81
+ """Rebin relative risk data if necessary.
82
+
83
+ When the polytomous risk is rebinned, matching relative risk needs to be rebinned.
82
84
  After rebinning, rr for both exposed and unexposed categories should be the weighted sum of relative risk
83
85
  of the component categories where weights are relative proportions of exposure of those categories.
84
86
  For example, if cat1, cat2, cat3 are exposed categories and cat4 is unexposed with exposure [0.1,0.2,0.3,0.4],
@@ -461,7 +461,6 @@ def clip(q):
461
461
  This is bound up in the GBD risk factor PAF calculation process.
462
462
  We'll clip the distribution tails so we don't get NaNs back from the
463
463
  distribution calls
464
-
465
464
  """
466
465
  Q_LOWER_BOUND = 0.0011
467
466
  Q_UPPER_BOUND = 0.998
@@ -17,8 +17,6 @@ import scipy
17
17
  from layered_config_tree import ConfigurationError
18
18
  from vivarium import Component
19
19
  from vivarium.framework.engine import Builder
20
- from vivarium.framework.event import Event
21
- from vivarium.framework.population import SimulantData
22
20
 
23
21
  from vivarium_public_health.risks import Risk
24
22
  from vivarium_public_health.risks.data_transformations import (
@@ -30,10 +28,12 @@ from vivarium_public_health.utilities import EntityString, TargetString, get_loo
30
28
 
31
29
 
32
30
  class RiskEffect(Component):
33
- """A component to model the impact of a risk factor on the target rate of
34
- some affected entity. This component can source data either from
35
- builder.data or from parameters supplied in the configuration.
36
- For a risk named 'risk' that affects 'affected_risk' and 'affected_cause',
31
+ """A component to model the effect of a risk factor on an affected entity's target rate.
32
+
33
+ This component can source data either from builder.data or from parameters
34
+ supplied in the configuration.
35
+
36
+ For a risk named 'risk' that affects 'affected_risk' and 'affected_cause',
37
37
  the configuration would look like:
38
38
 
39
39
  .. code-block:: yaml
@@ -59,10 +59,7 @@ class RiskEffect(Component):
59
59
 
60
60
  @property
61
61
  def configuration_defaults(self) -> Dict[str, Any]:
62
- """
63
- A dictionary containing the defaults for any configurations managed by
64
- this component.
65
- """
62
+ """Default values for any configurations managed by this component."""
66
63
  return {
67
64
  self.name: {
68
65
  "data_sources": {
@@ -89,13 +86,14 @@ class RiskEffect(Component):
89
86
 
90
87
  def __init__(self, risk: str, target: str):
91
88
  """
89
+
92
90
  Parameters
93
91
  ----------
94
- risk :
92
+ risk
95
93
  Type and name of risk factor, supplied in the form
96
94
  "risk_type.risk_name" where risk_type should be singular (e.g.,
97
95
  risk_factor instead of risk_factors).
98
- target :
96
+ target
99
97
  Type, name, and target rate of entity to be affected by risk factor,
100
98
  supplied in the form "entity_type.entity_name.measure"
101
99
  where entity_type should be singular (e.g., cause instead of causes).
@@ -210,7 +208,9 @@ class RiskEffect(Component):
210
208
  def rebin_relative_risk_data(
211
209
  self, builder, relative_risk_data: pd.DataFrame
212
210
  ) -> pd.DataFrame:
213
- """When the polytomous risk is rebinned, matching relative risk needs to be rebinned.
211
+ """Rebin relative risk data.
212
+
213
+ When the polytomous risk is rebinned, matching relative risk needs to be rebinned.
214
214
  After rebinning, rr for both exposed and unexposed categories should be the weighted sum of relative risk
215
215
  of the component categories where weights are relative proportions of exposure of those categories.
216
216
  For example, if cat1, cat2, cat3 are exposed categories and cat4 is unexposed with exposure [0.1,0.2,0.3,0.4],
@@ -319,18 +319,22 @@ class RiskEffect(Component):
319
319
 
320
320
 
321
321
  class NonLogLinearRiskEffect(RiskEffect):
322
- """A component to model the impact of an exposure-parametrized risk factor on
323
- the target rate of some affected entity. This component will
324
-
325
- 1) read TMRED data from the artifact and define the TMREL
326
- 2) calculate the relative risk at TMREL by linearly interpolating over
327
- relative risk data defined in the configuration
328
- 3) divide relative risk data from configuration by RR at TMREL
329
- and clip to be greater than 1
330
- 4) build a LookupTable which returns the exposure and RR of the left and right edges
331
- of the RR bin containing a simulant's exposure
332
- 5) use this LookupTable to modify the target pipeline by linearly interpolating
333
- a simulant's RR value and multiplying it by the intended target rate
322
+ """A component to model the exposure-parametrized effect of a risk factor.
323
+
324
+ More specifically, this models the effect of the risk factor on the target rate of
325
+ some affected entity.
326
+
327
+ This component:
328
+ 1) reads TMRED data from the artifact and define the TMREL
329
+ 2) calculates the relative risk at TMREL by linearly interpolating over
330
+ relative risk data defined in the configuration
331
+ 3) divides relative risk data from configuration by RR at TMREL
332
+ and clip to be greater than 1
333
+ 4) builds a LookupTable which returns the exposure and RR of the left and right edges
334
+ of the RR bin containing a simulant's exposure
335
+ 5) uses this LookupTable to modify the target pipeline by linearly interpolating
336
+ a simulant's RR value and multiplying it by the intended target rate
337
+
334
338
  """
335
339
 
336
340
  ##############
@@ -339,10 +343,7 @@ class NonLogLinearRiskEffect(RiskEffect):
339
343
 
340
344
  @property
341
345
  def configuration_defaults(self) -> Dict[str, Any]:
342
- """
343
- A dictionary containing the defaults for any configurations managed by
344
- this component.
345
- """
346
+ """Default values for any configurations managed by this component."""
346
347
  return {
347
348
  self.name: {
348
349
  "data_sources": {
@@ -485,6 +486,7 @@ class NonLogLinearRiskEffect(RiskEffect):
485
486
  ##############
486
487
 
487
488
  def validate_rr_data(self, rr_data: pd.DataFrame) -> None:
489
+ """Validate the relative risk data."""
488
490
  # check that rr_data has numeric parameter data
489
491
  parameter_data_is_numeric = rr_data["parameter"].dtype.kind in "biufc"
490
492
  if not parameter_data_is_numeric:
@@ -5,6 +5,7 @@ Low Birth Weight and Short Gestation
5
5
 
6
6
  Low birth weight and short gestation (LBWSG) is a non-standard risk
7
7
  implementation that has been used in several public health models.
8
+
8
9
  """
9
10
 
10
11
  import pickle
@@ -39,12 +40,16 @@ class LBWSGDistribution(PolytomousDistribution):
39
40
  self.category_intervals = self.get_category_intervals(builder)
40
41
 
41
42
  def get_category_intervals(self, builder: Builder) -> Dict[str, Dict[str, pd.Interval]]:
42
- """
43
- Gets the intervals for each category. It is a dictionary from the string
44
- "birth_weight" or "gestational_age" to a dictionary from the category
45
- name to the interval
46
- :param builder:
47
- :return:
43
+ """Gets the intervals for each category.
44
+
45
+ Parameters
46
+ ----------
47
+ builder
48
+ The builder object.
49
+
50
+ Returns
51
+ -------
52
+ The intervals for each category.
48
53
  """
49
54
  categories: Dict[str, str] = builder.data.load(f"{self.risk}.categories")
50
55
  category_intervals = {
@@ -61,16 +66,19 @@ class LBWSGDistribution(PolytomousDistribution):
61
66
  ##################
62
67
 
63
68
  def ppf(self, propensities: pd.DataFrame) -> pd.DataFrame:
64
- """
65
- Takes a DataFrame with three columns: 'categorical.propensity',
66
- 'birth_weight.propensity', and 'gestational_age.propensity' which
67
- contain each of those propensities for each simulant.
68
-
69
- Returns a DataFrame with two columns for birth-weight and gestational
70
- age exposures.
71
-
72
- :param propensities:
73
- :return:
69
+ """Calculate continuous exposures from propensities.
70
+
71
+ Parameters
72
+ ----------
73
+ propensities
74
+ Propensities DataFrame for each simulant with three columns:
75
+ 'categorical.propensity', 'birth_weight.propensity', and
76
+ 'gestational_age.propensity'.
77
+
78
+ Returns
79
+ -------
80
+ A DataFrame with two columns for birth-weight and gestational age
81
+ exposures.
74
82
  """
75
83
 
76
84
  categorical_exposure = super().ppf(propensities[f"{CATEGORICAL}_propensity"])
@@ -88,10 +96,11 @@ class LBWSGDistribution(PolytomousDistribution):
88
96
  self,
89
97
  axis: str,
90
98
  propensity: pd.Series,
91
- categorical_propensity: pd.Series = None,
92
- categorical_exposure: pd.Series = None,
99
+ categorical_propensity: Optional[pd.Series] = None,
100
+ categorical_exposure: Optional[pd.Series] = None,
93
101
  ) -> pd.Series:
94
- """
102
+ """Calculate continuous exposures from propensities for a single axis.
103
+
95
104
  Takes an axis (either 'birth_weight' or 'gestational_age'), a propensity
96
105
  and either a categorical propensity or a categorical exposure and
97
106
  returns continuous exposures for that axis.
@@ -101,11 +110,27 @@ class LBWSGDistribution(PolytomousDistribution):
101
110
  categorical exposure parameters pipeline
102
111
  ("risk_factor.low_birth_weight_and_short_gestation.exposure_parameters").
103
112
 
104
- :param axis:
105
- :param propensity:
106
- :param categorical_propensity:
107
- :param categorical_exposure:
108
- :return:
113
+ Parameters
114
+ ----------
115
+ axis
116
+ The axis for which to calculate continuous exposures ('birth_weight'
117
+ or 'gestational_age').
118
+ propensity
119
+ The propensity for the axis.
120
+ categorical_propensity
121
+ The categorical propensity for the axis.
122
+ categorical_exposure
123
+ The categorical exposure for the axis.
124
+
125
+ Returns
126
+ -------
127
+ The continuous exposures for the axis.
128
+
129
+ Raises
130
+ ------
131
+ ValueError
132
+ If neither categorical propensity nor categorical exposure is provided
133
+ or both are provided.
109
134
  """
110
135
 
111
136
  if (categorical_propensity is None) == (categorical_exposure is None):
@@ -133,19 +158,15 @@ class LBWSGDistribution(PolytomousDistribution):
133
158
 
134
159
  @staticmethod
135
160
  def _parse_description(axis: str, description: str) -> pd.Interval:
136
- """
137
- Parses a string corresponding to a low birth weight and short gestation
161
+ """Parses a string corresponding to a low birth weight and short gestation
138
162
  category to an Interval.
163
+
139
164
  An example of a standard description:
140
165
  'Neonatal preterm and LBWSG (estimation years) - [0, 24) wks, [0, 500) g'
141
166
  An example of an edge case for gestational age:
142
167
  'Neonatal preterm and LBWSG (estimation years) - [40, 42+] wks, [2000, 2500) g'
143
168
  An example of an edge case of birth weight:
144
169
  'Neonatal preterm and LBWSG (estimation years) - [36, 37) wks, [4000, 9999] g'
145
-
146
- :param axis:
147
- :param description:
148
- :return:
149
170
  """
150
171
  endpoints = {
151
172
  BIRTH_WEIGHT: [