omop-constructs 0.3.0__tar.gz → 0.3.2__tar.gz

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 (51) hide show
  1. {omop_constructs-0.3.0 → omop_constructs-0.3.2}/PKG-INFO +1 -1
  2. {omop_constructs-0.3.0 → omop_constructs-0.3.2}/pyproject.toml +1 -1
  3. {omop_constructs-0.3.0 → omop_constructs-0.3.2}/src/omop_constructs/alchemy/episodes/__init__.py +4 -1
  4. {omop_constructs-0.3.0 → omop_constructs-0.3.2}/src/omop_constructs/alchemy/episodes/condition_episode_mv.py +21 -2
  5. {omop_constructs-0.3.0 → omop_constructs-0.3.2}/src/omop_constructs/alchemy/episodes/episode_factories.py +31 -3
  6. {omop_constructs-0.3.0 → omop_constructs-0.3.2}/src/omop_constructs/alchemy/episodes/episode_joins.py +4 -2
  7. omop_constructs-0.3.2/src/omop_constructs/alchemy/episodes/surgical_joins.py +131 -0
  8. omop_constructs-0.3.2/src/omop_constructs/alchemy/episodes/surgical_procedure_mv.py +57 -0
  9. omop_constructs-0.3.2/src/omop_constructs/alchemy/episodes/treatment_summary_joins.py +25 -0
  10. {omop_constructs-0.3.0 → omop_constructs-0.3.2}/src/omop_constructs/alchemy/modifiers/__init__.py +3 -2
  11. {omop_constructs-0.3.0 → omop_constructs-0.3.2}/src/omop_constructs/alchemy/modifiers/condition_modifier_join.py +6 -4
  12. {omop_constructs-0.3.0 → omop_constructs-0.3.2}/src/omop_constructs/alchemy/modifiers/modifier_mappers.py +1 -1
  13. {omop_constructs-0.3.0 → omop_constructs-0.3.2}/README.md +0 -0
  14. {omop_constructs-0.3.0 → omop_constructs-0.3.2}/src/omop_constructs/__init__.py +0 -0
  15. {omop_constructs-0.3.0 → omop_constructs-0.3.2}/src/omop_constructs/alchemy/__init__.py +0 -0
  16. {omop_constructs-0.3.0 → omop_constructs-0.3.2}/src/omop_constructs/alchemy/adapters.py +0 -0
  17. {omop_constructs-0.3.0 → omop_constructs-0.3.2}/src/omop_constructs/alchemy/concepts/__init__.py +0 -0
  18. {omop_constructs-0.3.0 → omop_constructs-0.3.2}/src/omop_constructs/alchemy/concepts/concept_mappers.py +0 -0
  19. {omop_constructs-0.3.0 → omop_constructs-0.3.2}/src/omop_constructs/alchemy/concepts/concept_standardisation.py +0 -0
  20. {omop_constructs-0.3.0 → omop_constructs-0.3.2}/src/omop_constructs/alchemy/conditions/__init__.py +0 -0
  21. {omop_constructs-0.3.0 → omop_constructs-0.3.2}/src/omop_constructs/alchemy/conditions/condition_joins.py +0 -0
  22. {omop_constructs-0.3.0 → omop_constructs-0.3.2}/src/omop_constructs/alchemy/conditions/condition_mappers.py +0 -0
  23. {omop_constructs-0.3.0 → omop_constructs-0.3.2}/src/omop_constructs/alchemy/demography/__init__.py +0 -0
  24. {omop_constructs-0.3.0 → omop_constructs-0.3.2}/src/omop_constructs/alchemy/demography/demography_matview.py +0 -0
  25. {omop_constructs-0.3.0 → omop_constructs-0.3.2}/src/omop_constructs/alchemy/demography/demography_queries.py +0 -0
  26. {omop_constructs-0.3.0 → omop_constructs-0.3.2}/src/omop_constructs/alchemy/episodes/condition_episode_objects.py +0 -0
  27. {omop_constructs-0.3.0 → omop_constructs-0.3.2}/src/omop_constructs/alchemy/events/__init__.py +0 -0
  28. {omop_constructs-0.3.0 → omop_constructs-0.3.2}/src/omop_constructs/alchemy/events/dx_linked_event_mv.py +0 -0
  29. {omop_constructs-0.3.0 → omop_constructs-0.3.2}/src/omop_constructs/alchemy/events/event_factories.py +0 -0
  30. {omop_constructs-0.3.0 → omop_constructs-0.3.2}/src/omop_constructs/alchemy/events/event_queries.py +0 -0
  31. {omop_constructs-0.3.0 → omop_constructs-0.3.2}/src/omop_constructs/alchemy/modifiers/condition_modifier_mv.py +0 -0
  32. {omop_constructs-0.3.0 → omop_constructs-0.3.2}/src/omop_constructs/alchemy/modifiers/modifier_factories.py +0 -0
  33. {omop_constructs-0.3.0 → omop_constructs-0.3.2}/src/omop_constructs/alchemy/modifiers/modifier_joins.py +0 -0
  34. {omop_constructs-0.3.0 → omop_constructs-0.3.2}/src/omop_constructs/alchemy/source_factories.py +0 -0
  35. {omop_constructs-0.3.0 → omop_constructs-0.3.2}/src/omop_constructs/core/__init__.py +0 -0
  36. {omop_constructs-0.3.0 → omop_constructs-0.3.2}/src/omop_constructs/core/base.py +0 -0
  37. {omop_constructs-0.3.0 → omop_constructs-0.3.2}/src/omop_constructs/core/constructs.py +0 -0
  38. {omop_constructs-0.3.0 → omop_constructs-0.3.2}/src/omop_constructs/core/ddl.py +0 -0
  39. {omop_constructs-0.3.0 → omop_constructs-0.3.2}/src/omop_constructs/core/errors.py +0 -0
  40. {omop_constructs-0.3.0 → omop_constructs-0.3.2}/src/omop_constructs/core/materialized.py +0 -0
  41. {omop_constructs-0.3.0 → omop_constructs-0.3.2}/src/omop_constructs/core/plan.py +0 -0
  42. {omop_constructs-0.3.0 → omop_constructs-0.3.2}/src/omop_constructs/core/registry.py +0 -0
  43. {omop_constructs-0.3.0 → omop_constructs-0.3.2}/src/omop_constructs/py.typed +0 -0
  44. {omop_constructs-0.3.0 → omop_constructs-0.3.2}/src/omop_constructs/semantics/__init__.py +0 -0
  45. {omop_constructs-0.3.0 → omop_constructs-0.3.2}/src/omop_constructs/semantics/adapters.py +0 -0
  46. {omop_constructs-0.3.0 → omop_constructs-0.3.2}/src/omop_constructs/semantics/lookups.py +0 -0
  47. {omop_constructs-0.3.0 → omop_constructs-0.3.2}/src/omop_constructs/semantics/runtime_lookups.py +0 -0
  48. {omop_constructs-0.3.0 → omop_constructs-0.3.2}/src/omop_constructs/services/__init__.py +0 -0
  49. {omop_constructs-0.3.0 → omop_constructs-0.3.2}/src/omop_constructs/services/concept.py +0 -0
  50. {omop_constructs-0.3.0 → omop_constructs-0.3.2}/src/omop_constructs/services/person.py +0 -0
  51. {omop_constructs-0.3.0 → omop_constructs-0.3.2}/src/omop_constructs/typing.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: omop-constructs
3
- Version: 0.3.0
3
+ Version: 0.3.2
4
4
  Summary: For building complex constructs on top of the omop-alchemy library.
5
5
  Author: Georgie Kennedy
6
6
  Author-email: Georgie Kennedy <georgina.kennedy@unsw.edu.au>
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "omop-constructs"
3
- version = "0.3.0"
3
+ version = "0.3.2"
4
4
  description = "For building complex constructs on top of the omop-alchemy library."
5
5
  readme = "README.md"
6
6
  authors = [
@@ -1,9 +1,12 @@
1
- from .condition_episode_mv import OverarchingDiseaseEpisodeMV, TreatmentRegimenCycleMV, ConditionEpisodeMV
1
+ from .condition_episode_mv import OverarchingDiseaseEpisodeMV, TreatmentRegimenCycleMV, ConditionEpisodeMV, DxTreatStartMV
2
2
  from .condition_episode_objects import ConditionEpisodeObject
3
+ from .surgical_procedure_mv import SurgicalProcedureMV
3
4
 
4
5
  __all__ = [
5
6
  "OverarchingDiseaseEpisodeMV",
6
7
  "TreatmentRegimenCycleMV",
7
8
  "ConditionEpisodeMV",
8
9
  "ConditionEpisodeObject",
10
+ "SurgicalProcedureMV",
11
+ "DxTreatStartMV",
9
12
  ]
@@ -3,7 +3,7 @@ import sqlalchemy.orm as so
3
3
  from orm_loader.helpers import Base
4
4
  from datetime import date
5
5
  from typing import Optional
6
- from .episode_joins import overarching_disease_episode, treatment_regimen_with_cycles, condition_episode_select
6
+ from .episode_joins import overarching_disease_episode, treatment_regimen_with_cycles, condition_episode_select, dx_window_select
7
7
  from ...core.materialized import MaterializedViewMixin
8
8
  from ...core.constructs import register_construct
9
9
 
@@ -116,6 +116,8 @@ class TreatmentRegimenCycleMV(
116
116
  episode_start_date: so.Mapped[date] = so.mapped_column(sa.Date)
117
117
  episode_end_date: so.Mapped[Optional[date]] = so.mapped_column(sa.Date, nullable=True)
118
118
 
119
+ episode_parent_id: so.Mapped[Optional[int]] = so.mapped_column(sa.Integer, nullable=True)
120
+
119
121
  cycle_episode_id: so.Mapped[Optional[int]] = so.mapped_column(sa.Integer, nullable=True)
120
122
  cycle_episode_concept_id: so.Mapped[Optional[int]] = so.mapped_column(sa.Integer, nullable=True)
121
123
  cycle_episode_label: so.Mapped[Optional[str]] = so.mapped_column(sa.String, nullable=True)
@@ -143,4 +145,21 @@ class TreatmentRegimenCycleMV(
143
145
  def cycle_interval(self):
144
146
  if self.cycle_episode_id is None:
145
147
  return None
146
- return (self.cycle_episode_start_date, self.cycle_episode_end_date)
148
+ return (self.cycle_episode_start_date, self.cycle_episode_end_date)
149
+
150
+
151
+ @register_construct
152
+ class DxTreatStartMV(MaterializedViewMixin, Base):
153
+ __mv_name__ = "dx_treat_start_mv"
154
+ __mv_select__ = dx_window_select.select()
155
+ __mv_index__ = "dx_episode_id"
156
+ __deps__ = (ConditionEpisodeMV.__mv_name__, TreatmentRegimenCycleMV.__mv_name__,)
157
+ __tablename__ = __mv_name__
158
+
159
+ dx_episode_id: so.Mapped[int] = so.mapped_column(primary_key=True)
160
+ person_id: so.Mapped[int] = so.mapped_column(sa.Integer)
161
+ dx_start_date: so.Mapped[date] = so.mapped_column(sa.Date)
162
+
163
+ treatment_start: so.Mapped[Optional[date]] = so.mapped_column(sa.Date)
164
+ treatment_end: so.Mapped[Optional[date]] = so.mapped_column(sa.Date)
165
+ treatment_regimen_count: so.Mapped[Optional[int]] = so.mapped_column(sa.Integer)
@@ -6,8 +6,9 @@ from omop_alchemy.cdm.model import (
6
6
  Concept
7
7
  )
8
8
 
9
- episode_concept = so.aliased(Concept, name="episode_concept")
9
+ from omop_semantics.runtime.default_valuesets import runtime # type: ignore
10
10
 
11
+ episode_concept = so.aliased(Concept, name="episode_concept")
11
12
 
12
13
  def get_episode_query(
13
14
  episode_concept_ids: Iterable[int],
@@ -26,8 +27,6 @@ def get_episode_query(
26
27
  Episode.episode_end_date,
27
28
  Episode.episode_end_datetime,
28
29
  Episode.episode_concept_id,
29
- Episode.episode_end_datetime,
30
- Episode.episode_concept_id,
31
30
  episode_concept.concept_name.label(f"episode_label"),
32
31
  Episode.episode_object_concept_id,
33
32
  Episode.episode_type_concept_id,
@@ -74,4 +73,33 @@ def get_episode_hierarchy_query(
74
73
  isouter=True,
75
74
  )
76
75
  .subquery(name=name)
76
+ )
77
+
78
+ def dx_treatment_window(name="dx_treat_window"):
79
+ Diagnosis = Episode
80
+ Regimen = so.aliased(Episode, name="regimen")
81
+
82
+ return (
83
+ sa.select(
84
+ Diagnosis.episode_id.label("dx_episode_id"),
85
+ Diagnosis.person_id,
86
+ Diagnosis.episode_start_date.label("dx_start_date"),
87
+ sa.func.min(Regimen.episode_start_date).label("treatment_start"),
88
+ sa.func.max(Regimen.episode_end_date).label("treatment_end"),
89
+ sa.func.count(sa.distinct(Regimen.episode_id)).label("treatment_regimen_count"),
90
+ )
91
+ .join(
92
+ Regimen,
93
+ Regimen.episode_parent_id == Diagnosis.episode_id,
94
+ )
95
+ .where(
96
+ Diagnosis.episode_concept_id.in_(runtime.types.disease_episode_types.ids),
97
+ Regimen.episode_concept_id.in_(runtime.types.treatment_episode_types.ids),
98
+ )
99
+ .group_by(
100
+ Diagnosis.episode_id,
101
+ Diagnosis.person_id,
102
+ Diagnosis.episode_start_date,
103
+ )
104
+ .subquery(name)
77
105
  )
@@ -1,5 +1,5 @@
1
1
  from omop_semantics.runtime.default_valuesets import runtime # type: ignore
2
- from .episode_factories import get_episode_query, get_episode_hierarchy_query
2
+ from .episode_factories import get_episode_query, get_episode_hierarchy_query, dx_treatment_window
3
3
 
4
4
  episode_of_care_select = get_episode_query(
5
5
  [runtime.types.disease_episode_types.episode_of_care], # type: ignore
@@ -37,4 +37,6 @@ treatment_regimen_with_cycles = get_episode_hierarchy_query(
37
37
  child_episode_subq=treatment_cycle_select,
38
38
  name="treatment_regimen_with_cycles",
39
39
  child_label="cycle_episode"
40
- )
40
+ )
41
+
42
+ dx_window_select = dx_treatment_window()
@@ -0,0 +1,131 @@
1
+ import sqlalchemy as sa
2
+ import sqlalchemy.orm as so
3
+ from typing import Optional
4
+ from omop_alchemy.cdm.model import Concept, Concept_Ancestor, Procedure_Occurrence, Observation
5
+ from omop_semantics.runtime.default_valuesets import runtime # type: ignore
6
+ from .condition_episode_mv import ConditionEpisodeMV
7
+
8
+ rth_ca = so.aliased(Concept_Ancestor, name="rth_ca")
9
+ srg_ca = so.aliased(Concept_Ancestor, name="srg_ca")
10
+
11
+ surgical_concepts = (
12
+ sa.select(
13
+ Concept.concept_id,
14
+ Concept.concept_name,
15
+ Concept.concept_code,
16
+ )
17
+ .join(srg_ca, Concept.concept_id == srg_ca.descendant_concept_id)
18
+ .where(srg_ca.ancestor_concept_id == runtime.cancer_procedures.cancer_procedure_types.surgical_procedure)
19
+ )
20
+
21
+ radiotherapy_concepts = (
22
+ sa.select(
23
+ Concept.concept_id,
24
+ Concept.concept_name,
25
+ Concept.concept_code,
26
+ )
27
+ .join(rth_ca, Concept.concept_id == rth_ca.descendant_concept_id)
28
+ .where(rth_ca.ancestor_concept_id == runtime.cancer_procedures.cancer_procedure_types.rt_procedure)
29
+ )
30
+
31
+ radioisotope_concepts = (
32
+ sa.select(
33
+ Concept.concept_id,
34
+ Concept.concept_name,
35
+ Concept.concept_code,
36
+ )
37
+ .join(rth_ca, Concept.concept_id == rth_ca.descendant_concept_id)
38
+ .where(rth_ca.ancestor_concept_id == runtime.cancer_procedures.cancer_procedure_types.rn_procedure)
39
+ )
40
+
41
+ surg_only = surgical_concepts.except_all(
42
+ radiotherapy_concepts.union_all(radioisotope_concepts)
43
+ ).subquery(name="surg_only")
44
+
45
+ radioisotopes_only = radioisotope_concepts.subquery(name="radioisotopes_only")
46
+
47
+ surg_obs_concept = so.aliased(Concept, name="surg_obs_concept")
48
+
49
+ surgical_procedure_events = (
50
+ sa.select(
51
+ Procedure_Occurrence.person_id,
52
+ Procedure_Occurrence.procedure_occurrence_id.label("surgery_occurrence_id"),
53
+ Procedure_Occurrence.procedure_concept_id.label("surgery_concept_id"),
54
+ Procedure_Occurrence.procedure_datetime.label("surgery_datetime"),
55
+ surg_only.c.concept_name.label("surgery_name"),
56
+ surg_only.c.concept_code.label("surgery_concept_code"),
57
+ sa.literal("procedure").label("surgery_source"),
58
+ )
59
+ .join(surg_only, surg_only.c.concept_id == Procedure_Occurrence.procedure_concept_id)
60
+ )
61
+
62
+ historical_surgical_events = (
63
+ sa.select(
64
+ Observation.person_id,
65
+ Observation.observation_id.label("surgery_occurrence_id"),
66
+ Observation.value_as_concept_id.label("surgery_concept_id"),
67
+ Observation.observation_datetime.label("surgery_datetime"),
68
+ surg_obs_concept.concept_name.label("surgery_name"),
69
+ surg_obs_concept.concept_code.label("surgery_concept_code"),
70
+ sa.literal("observation").label("surgery_source"),
71
+ )
72
+ .join(surg_obs_concept, surg_obs_concept.concept_id == Observation.value_as_concept_id)
73
+ .where(Observation.observation_concept_id == runtime.cancer_procedures.cancer_procedure_types.historical_procedure)
74
+ )
75
+
76
+ all_cancer_relevant_surg = (
77
+ sa.union_all(surgical_procedure_events, historical_surgical_events)
78
+ .subquery(name="all_cancer_relevant_surg")
79
+ )
80
+
81
+
82
+ cancer_relevant_surg_select = (
83
+ sa.select(
84
+ sa.func.row_number().over().label("mv_id"),
85
+ ConditionEpisodeMV.person_id,
86
+ ConditionEpisodeMV.episode_id.label("condition_episode_id"),
87
+ ConditionEpisodeMV.episode_start_date.label("condition_start_date"),
88
+
89
+ all_cancer_relevant_surg.c.surgery_occurrence_id,
90
+ all_cancer_relevant_surg.c.surgery_concept_id,
91
+ all_cancer_relevant_surg.c.surgery_datetime,
92
+ all_cancer_relevant_surg.c.surgery_concept_code,
93
+ all_cancer_relevant_surg.c.surgery_name,
94
+ all_cancer_relevant_surg.c.surgery_source,
95
+ )
96
+ # still person-level until windowing is added
97
+ .join(
98
+ all_cancer_relevant_surg,
99
+ all_cancer_relevant_surg.c.person_id == ConditionEpisodeMV.person_id,
100
+ isouter=True,
101
+ )
102
+ .subquery(name="cancer_relevant_surg")
103
+ )
104
+
105
+ radioisotope_select = (
106
+ sa.select(
107
+ sa.func.row_number().over().label("mv_id"),
108
+ ConditionEpisodeMV.person_id,
109
+ ConditionEpisodeMV.episode_id.label("condition_episode_id"),
110
+ ConditionEpisodeMV.episode_start_date.label("condition_start_date"),
111
+
112
+ Procedure_Occurrence.procedure_occurrence_id.label("ri_occurrence_id"),
113
+ Procedure_Occurrence.procedure_concept_id.label("ri_concept_id"),
114
+ Procedure_Occurrence.procedure_datetime.label("ri_datetime"),
115
+ radioisotopes_only.c.concept_name.label("ri_name"),
116
+ radioisotopes_only.c.concept_code.label("ri_concept_code"),
117
+ sa.literal("radioisotope_procedure").label("ri_source"),
118
+ )
119
+ .join(
120
+ Procedure_Occurrence,
121
+ Procedure_Occurrence.person_id == ConditionEpisodeMV.person_id,
122
+ isouter=True,
123
+ )
124
+ .join(
125
+ radioisotopes_only,
126
+ radioisotopes_only.c.concept_id == Procedure_Occurrence.procedure_concept_id,
127
+ isouter=True,
128
+ )
129
+ .subquery(name="radioisotope_procedure")
130
+ )
131
+
@@ -0,0 +1,57 @@
1
+ import sqlalchemy as sa
2
+ import sqlalchemy.orm as so
3
+ from datetime import date
4
+ from typing import Optional
5
+ from orm_loader.helpers import Base
6
+ from ...core.materialized import MaterializedViewMixin
7
+ from ...core.constructs import register_construct
8
+ from .surgical_joins import all_cancer_relevant_surg, cancer_relevant_surg_select, radioisotope_select
9
+ from .condition_episode_mv import ConditionEpisodeMV
10
+
11
+
12
+ @register_construct
13
+ class SurgicalProcedureMV(MaterializedViewMixin, Base):
14
+ __mv_name__ = "surgical_procedure_mv"
15
+ __mv_select__ = cancer_relevant_surg_select.select()
16
+ __mv_index__ = "mv_id"
17
+ __deps__ = (ConditionEpisodeMV.__mv_name__,)
18
+ __tablename__ = __mv_name__
19
+ __table_args__ = {"extend_existing": True}
20
+
21
+ mv_id: so.Mapped[int] = so.mapped_column(primary_key=True)
22
+
23
+ person_id: so.Mapped[int] = so.mapped_column(sa.Integer)
24
+ condition_episode_id: so.Mapped[int] = so.mapped_column(sa.Integer)
25
+ condition_start_date: so.Mapped[date] = so.mapped_column(sa.Date)
26
+
27
+ surgery_occurrence_id: so.Mapped[int] = so.mapped_column(sa.Integer)
28
+ surgery_concept_id: so.Mapped[int] = so.mapped_column(sa.Integer)
29
+ surgery_datetime: so.Mapped[Optional[date]] = so.mapped_column(sa.DateTime)
30
+
31
+ surgery_name: so.Mapped[str] = so.mapped_column(sa.String)
32
+ surgery_concept_code: so.Mapped[str] = so.mapped_column(sa.String)
33
+ surgery_source: so.Mapped[str] = so.mapped_column(sa.String)
34
+
35
+
36
+ @register_construct
37
+ class RadioisotopeMV(MaterializedViewMixin, Base):
38
+ __mv_name__ = "radioisotope_mv"
39
+ __mv_select__ = radioisotope_select.select()
40
+ __mv_index__ = "mv_id"
41
+ __deps__ = (ConditionEpisodeMV.__mv_name__,)
42
+ __tablename__ = __mv_name__
43
+ __table_args__ = {"extend_existing": True}
44
+
45
+ mv_id: so.Mapped[int] = so.mapped_column(primary_key=True)
46
+
47
+ person_id: so.Mapped[int] = so.mapped_column(sa.Integer)
48
+ condition_episode_id: so.Mapped[int] = so.mapped_column(sa.Integer)
49
+ condition_start_date: so.Mapped[date] = so.mapped_column(sa.Date)
50
+
51
+ ri_occurrence_id: so.Mapped[int] = so.mapped_column(sa.Integer)
52
+ ri_concept_id: so.Mapped[int] = so.mapped_column(sa.Integer)
53
+ ri_datetime: so.Mapped[Optional[date]] = so.mapped_column(sa.DateTime)
54
+
55
+ ri_name: so.Mapped[str] = so.mapped_column(sa.String)
56
+ ri_concept_code: so.Mapped[str] = so.mapped_column(sa.String)
57
+ ri_source: so.Mapped[str] = so.mapped_column(sa.String)
@@ -0,0 +1,25 @@
1
+ import sqlalchemy as sa
2
+ from omop_semantics.runtime.default_valuesets import runtime
3
+ from .condition_episode_mv import TreatmentRegimenCycleMV
4
+
5
+ treatment_summary = (
6
+ sa.select(
7
+ TreatmentRegimenCycleMV.person_id,
8
+ TreatmentRegimenCycleMV.episode_parent_id.label("condition_episode_id"),
9
+ TreatmentRegimenCycleMV.episode_concept_id,
10
+ TreatmentRegimenCycleMV.episode_label,
11
+
12
+ sa.func.min(TreatmentRegimenCycleMV.episode_start_date).label("treatment_start_date"),
13
+ sa.func.max(TreatmentRegimenCycleMV.episode_end_date).label("treatment_end_date"),
14
+
15
+ sa.func.count(sa.distinct(TreatmentRegimenCycleMV.episode_id)).label("regimen_count"),
16
+ sa.func.count(sa.distinct(TreatmentRegimenCycleMV.cycle_episode_id)).label("cycle_count"),
17
+ )
18
+ .group_by(
19
+ TreatmentRegimenCycleMV.person_id,
20
+ TreatmentRegimenCycleMV.episode_parent_id,
21
+ TreatmentRegimenCycleMV.episode_concept_id,
22
+ TreatmentRegimenCycleMV.episode_label,
23
+ )
24
+ .subquery("treatment_summary")
25
+ )
@@ -9,7 +9,7 @@ from .modifier_mappers import (
9
9
  MetastaticDiseaseModifierMV,
10
10
  AllStageModifierMV
11
11
  )
12
- from .condition_modifier_mv import ModifiedCondition
12
+ from .condition_modifier_mv import ModifiedCondition, StageModifier
13
13
 
14
14
  __all__ = [
15
15
  "TStageMV",
@@ -21,5 +21,6 @@ __all__ = [
21
21
  "SizeModifierMV",
22
22
  "ModifiedCondition",
23
23
  "MetastaticDiseaseModifierMV",
24
- "AllStageModifierMV"
24
+ "AllStageModifierMV",
25
+ "StageModifier"
25
26
  ]
@@ -18,6 +18,7 @@ from .modifier_mappers import (
18
18
  )
19
19
 
20
20
  condition_concept = so.aliased(Concept, name='condition_concept')
21
+ stage_concept = so.aliased(Concept, name='stage_concept')
21
22
 
22
23
  modified_conditions_join = (
23
24
  sa.select(
@@ -147,10 +148,10 @@ all_stage_join = (
147
148
  Condition_Occurrence.condition_concept_id,
148
149
  condition_concept.concept_name.label('condition_concept'),
149
150
  Episode_Event.episode_id.label('condition_episode'),
150
- AllStageModifierMV.stage_id.label('stage_id'),
151
- AllStageModifierMV.stage_date.label('stage_date'),
152
- AllStageModifierMV.stage_concept_id.label('stage_concept_id'),
153
- AllStageModifierMV.stage_label.label('stage_label'),
151
+ AllStageModifierMV.measurement_id.label('stage_id'),
152
+ AllStageModifierMV.measurement_date.label('stage_date'),
153
+ AllStageModifierMV.measurement_concept_id.label('stage_concept_id'),
154
+ stage_concept.concept_name.label('stage_label'),
154
155
  )
155
156
  .join(
156
157
  Episode_Event,
@@ -169,4 +170,5 @@ all_stage_join = (
169
170
  isouter=True
170
171
  )
171
172
  .join(condition_concept, condition_concept.concept_id==Condition_Occurrence.condition_concept_id)
173
+ .join(stage_concept, stage_concept.concept_id==AllStageModifierMV.measurement_concept_id)
172
174
  )
@@ -116,7 +116,7 @@ class MetastaticDiseaseModifierMV(MeasModCols, MaterializedViewMixin, Base):
116
116
  measurement_concept_id = sa.Column(sa.Integer)
117
117
 
118
118
  @register_construct
119
- class AllStageModifierMV(StageColumns, MaterializedViewMixin, Base):
119
+ class AllStageModifierMV(MeasModCols, MaterializedViewMixin, Base):
120
120
  __mv_name__ = "all_stage_modifier_mv"
121
121
  __mv_select__ = all_stage_select.select()
122
122
  __mv_index__ = "measurement_event_id"