omop-constructs 0.3.6__tar.gz → 0.3.7__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 (67) hide show
  1. {omop_constructs-0.3.6 → omop_constructs-0.3.7}/PKG-INFO +1 -1
  2. {omop_constructs-0.3.6 → omop_constructs-0.3.7}/pyproject.toml +1 -1
  3. {omop_constructs-0.3.6 → omop_constructs-0.3.7}/src/omop_constructs/alchemy/episodes/__init__.py +10 -0
  4. omop_constructs-0.3.7/src/omop_constructs/alchemy/episodes/course_joins.py +56 -0
  5. omop_constructs-0.3.7/src/omop_constructs/alchemy/episodes/course_mv.py +40 -0
  6. omop_constructs-0.3.7/src/omop_constructs/alchemy/episodes/cycle_join.py +38 -0
  7. omop_constructs-0.3.7/src/omop_constructs/alchemy/episodes/cycle_mv.py +34 -0
  8. omop_constructs-0.3.7/src/omop_constructs/alchemy/episodes/fraction_joins.py +37 -0
  9. omop_constructs-0.3.7/src/omop_constructs/alchemy/episodes/fraction_mv.py +33 -0
  10. omop_constructs-0.3.7/src/omop_constructs/alchemy/episodes/systemic_treatment_joins.py +53 -0
  11. omop_constructs-0.3.7/src/omop_constructs/alchemy/episodes/systemic_treatment_mv.py +40 -0
  12. omop_constructs-0.3.7/src/omop_constructs/alchemy/episodes/treatment_summary_joins.py +68 -0
  13. omop_constructs-0.3.7/src/omop_constructs/alchemy/episodes/treatment_summary_mv.py +47 -0
  14. {omop_constructs-0.3.6 → omop_constructs-0.3.7}/src/omop_constructs/alchemy/modifiers/__init__.py +5 -1
  15. omop_constructs-0.3.7/src/omop_constructs/alchemy/modifiers/procedure_modifier_joins.py +37 -0
  16. omop_constructs-0.3.7/src/omop_constructs/alchemy/modifiers/procedure_modifier_mv.py +30 -0
  17. {omop_constructs-0.3.6 → omop_constructs-0.3.7}/src/omop_constructs/semantics/runtime_lookups.py +8 -0
  18. omop_constructs-0.3.6/src/omop_constructs/alchemy/episodes/treatment_summary_joins.py +0 -25
  19. {omop_constructs-0.3.6 → omop_constructs-0.3.7}/README.md +0 -0
  20. {omop_constructs-0.3.6 → omop_constructs-0.3.7}/src/omop_constructs/__init__.py +0 -0
  21. {omop_constructs-0.3.6 → omop_constructs-0.3.7}/src/omop_constructs/alchemy/__init__.py +0 -0
  22. {omop_constructs-0.3.6 → omop_constructs-0.3.7}/src/omop_constructs/alchemy/adapters.py +0 -0
  23. {omop_constructs-0.3.6 → omop_constructs-0.3.7}/src/omop_constructs/alchemy/concepts/__init__.py +0 -0
  24. {omop_constructs-0.3.6 → omop_constructs-0.3.7}/src/omop_constructs/alchemy/concepts/concept_mappers.py +0 -0
  25. {omop_constructs-0.3.6 → omop_constructs-0.3.7}/src/omop_constructs/alchemy/concepts/concept_standardisation.py +0 -0
  26. {omop_constructs-0.3.6 → omop_constructs-0.3.7}/src/omop_constructs/alchemy/conditions/__init__.py +0 -0
  27. {omop_constructs-0.3.6 → omop_constructs-0.3.7}/src/omop_constructs/alchemy/conditions/condition_joins.py +0 -0
  28. {omop_constructs-0.3.6 → omop_constructs-0.3.7}/src/omop_constructs/alchemy/conditions/condition_mappers.py +0 -0
  29. {omop_constructs-0.3.6 → omop_constructs-0.3.7}/src/omop_constructs/alchemy/demography/__init__.py +0 -0
  30. {omop_constructs-0.3.6 → omop_constructs-0.3.7}/src/omop_constructs/alchemy/demography/demography_matview.py +0 -0
  31. {omop_constructs-0.3.6 → omop_constructs-0.3.7}/src/omop_constructs/alchemy/demography/demography_queries.py +0 -0
  32. {omop_constructs-0.3.6 → omop_constructs-0.3.7}/src/omop_constructs/alchemy/episodes/condition_episode_mv.py +0 -0
  33. {omop_constructs-0.3.6 → omop_constructs-0.3.7}/src/omop_constructs/alchemy/episodes/condition_episode_objects.py +0 -0
  34. {omop_constructs-0.3.6 → omop_constructs-0.3.7}/src/omop_constructs/alchemy/episodes/episode_factories.py +0 -0
  35. {omop_constructs-0.3.6 → omop_constructs-0.3.7}/src/omop_constructs/alchemy/episodes/episode_joins.py +0 -0
  36. {omop_constructs-0.3.6 → omop_constructs-0.3.7}/src/omop_constructs/alchemy/episodes/surgical_joins.py +0 -0
  37. {omop_constructs-0.3.6 → omop_constructs-0.3.7}/src/omop_constructs/alchemy/episodes/surgical_procedure_mv.py +0 -0
  38. {omop_constructs-0.3.6 → omop_constructs-0.3.7}/src/omop_constructs/alchemy/events/__init__.py +0 -0
  39. {omop_constructs-0.3.6 → omop_constructs-0.3.7}/src/omop_constructs/alchemy/events/dx_linked_event_mv.py +0 -0
  40. {omop_constructs-0.3.6 → omop_constructs-0.3.7}/src/omop_constructs/alchemy/events/dx_linked_obs_mv.py +0 -0
  41. {omop_constructs-0.3.6 → omop_constructs-0.3.7}/src/omop_constructs/alchemy/events/dx_linked_procedure_mv.py +0 -0
  42. {omop_constructs-0.3.6 → omop_constructs-0.3.7}/src/omop_constructs/alchemy/events/event_factories.py +0 -0
  43. {omop_constructs-0.3.6 → omop_constructs-0.3.7}/src/omop_constructs/alchemy/events/event_queries.py +0 -0
  44. {omop_constructs-0.3.6 → omop_constructs-0.3.7}/src/omop_constructs/alchemy/events/observation_queries.py +0 -0
  45. {omop_constructs-0.3.6 → omop_constructs-0.3.7}/src/omop_constructs/alchemy/events/procedure_queries.py +0 -0
  46. {omop_constructs-0.3.6 → omop_constructs-0.3.7}/src/omop_constructs/alchemy/modifiers/condition_modifier_join.py +0 -0
  47. {omop_constructs-0.3.6 → omop_constructs-0.3.7}/src/omop_constructs/alchemy/modifiers/condition_modifier_mv.py +0 -0
  48. {omop_constructs-0.3.6 → omop_constructs-0.3.7}/src/omop_constructs/alchemy/modifiers/modifier_factories.py +0 -0
  49. {omop_constructs-0.3.6 → omop_constructs-0.3.7}/src/omop_constructs/alchemy/modifiers/modifier_joins.py +0 -0
  50. {omop_constructs-0.3.6 → omop_constructs-0.3.7}/src/omop_constructs/alchemy/modifiers/modifier_mappers.py +0 -0
  51. {omop_constructs-0.3.6 → omop_constructs-0.3.7}/src/omop_constructs/alchemy/source_factories.py +0 -0
  52. {omop_constructs-0.3.6 → omop_constructs-0.3.7}/src/omop_constructs/core/__init__.py +0 -0
  53. {omop_constructs-0.3.6 → omop_constructs-0.3.7}/src/omop_constructs/core/base.py +0 -0
  54. {omop_constructs-0.3.6 → omop_constructs-0.3.7}/src/omop_constructs/core/constructs.py +0 -0
  55. {omop_constructs-0.3.6 → omop_constructs-0.3.7}/src/omop_constructs/core/ddl.py +0 -0
  56. {omop_constructs-0.3.6 → omop_constructs-0.3.7}/src/omop_constructs/core/errors.py +0 -0
  57. {omop_constructs-0.3.6 → omop_constructs-0.3.7}/src/omop_constructs/core/materialized.py +0 -0
  58. {omop_constructs-0.3.6 → omop_constructs-0.3.7}/src/omop_constructs/core/plan.py +0 -0
  59. {omop_constructs-0.3.6 → omop_constructs-0.3.7}/src/omop_constructs/core/registry.py +0 -0
  60. {omop_constructs-0.3.6 → omop_constructs-0.3.7}/src/omop_constructs/py.typed +0 -0
  61. {omop_constructs-0.3.6 → omop_constructs-0.3.7}/src/omop_constructs/semantics/__init__.py +0 -0
  62. {omop_constructs-0.3.6 → omop_constructs-0.3.7}/src/omop_constructs/semantics/adapters.py +0 -0
  63. {omop_constructs-0.3.6 → omop_constructs-0.3.7}/src/omop_constructs/semantics/lookups.py +0 -0
  64. {omop_constructs-0.3.6 → omop_constructs-0.3.7}/src/omop_constructs/services/__init__.py +0 -0
  65. {omop_constructs-0.3.6 → omop_constructs-0.3.7}/src/omop_constructs/services/concept.py +0 -0
  66. {omop_constructs-0.3.6 → omop_constructs-0.3.7}/src/omop_constructs/services/person.py +0 -0
  67. {omop_constructs-0.3.6 → omop_constructs-0.3.7}/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.6
3
+ Version: 0.3.7
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.6"
3
+ version = "0.3.7"
4
4
  description = "For building complex constructs on top of the omop-alchemy library."
5
5
  readme = "README.md"
6
6
  authors = [
@@ -1,6 +1,11 @@
1
1
  from .condition_episode_mv import OverarchingDiseaseEpisodeMV, TreatmentRegimenCycleMV, ConditionEpisodeMV, DxTreatStartMV
2
2
  from .condition_episode_objects import ConditionEpisodeObject
3
3
  from .surgical_procedure_mv import SurgicalProcedureMV
4
+ from .systemic_treatment_mv import SACTRegimenMV
5
+ from .cycle_mv import CycleMV
6
+ from .course_mv import RTCourseMV
7
+ from .fraction_mv import FractionMV
8
+ from .treatment_summary_mv import ConditionTreatmentEpisode
4
9
 
5
10
  __all__ = [
6
11
  "OverarchingDiseaseEpisodeMV",
@@ -9,4 +14,9 @@ __all__ = [
9
14
  "ConditionEpisodeObject",
10
15
  "SurgicalProcedureMV",
11
16
  "DxTreatStartMV",
17
+ "SACTRegimenMV",
18
+ "CycleMV",
19
+ "RTCourseMV",
20
+ "FractionMV",
21
+ "ConditionTreatmentEpisode",
12
22
  ]
@@ -0,0 +1,56 @@
1
+ import sqlalchemy as sa
2
+ import sqlalchemy.orm as so
3
+ from omop_alchemy.cdm.model import Episode, Episode_Event, Concept
4
+ from omop_semantics.runtime.default_valuesets import runtime
5
+ from ..modifiers import ModifiedProcedure
6
+ from .fraction_mv import FractionMV
7
+
8
+
9
+ course_concept = so.aliased(Concept, name='course_concept')
10
+
11
+ frac_summary_join = (
12
+ sa.select(
13
+ FractionMV.person_id,
14
+ FractionMV.fraction_id,
15
+ FractionMV.fraction_number,
16
+ FractionMV.course_id,
17
+ FractionMV.fraction_name,
18
+ sa.func.min(FractionMV.procedure_datetime).label('first_exposure_date'),
19
+ sa.func.max(FractionMV.procedure_datetime).label('last_exposure_date'),
20
+ sa.func.count(FractionMV.procedure_occurrence_id).label('fraction_count'),
21
+ )
22
+ .group_by(FractionMV.person_id, FractionMV.fraction_id, FractionMV.fraction_number, FractionMV.course_id, FractionMV.fraction_name)
23
+ .subquery()
24
+ )
25
+
26
+ course_join = (
27
+ sa.select(
28
+ *frac_summary_join.c,
29
+ sa.func.row_number().over().label('mv_id'),
30
+ Episode.episode_number.label('course_number'),
31
+ Episode.episode_parent_id.label('condition_episode_id'),
32
+ ModifiedProcedure.procedure_occurrence_id.label('course_prescription_id'),
33
+ ModifiedProcedure.procedure_concept_id.label('course_concept_id'),
34
+ ModifiedProcedure.procedure_concept.label('course_concept'),
35
+ ModifiedProcedure.intent_concept,
36
+ ModifiedProcedure.intent_concept_id,
37
+ ModifiedProcedure.intent_datetime
38
+ )
39
+ .join(
40
+ Episode,
41
+ sa.and_(
42
+ Episode.episode_id == frac_summary_join.c.course_id,
43
+ Episode.episode_concept_id==runtime.types.treatment_episode_types.treatment_regimen
44
+ ),
45
+ isouter=True
46
+ )
47
+ .join(
48
+ Episode_Event,
49
+ sa.and_(
50
+ Episode_Event.episode_id == Episode.episode_id,
51
+ Episode_Event.episode_event_field_concept_id == runtime.modifiers.modifier_fields.procedure_occurrence_id
52
+ ),
53
+ isouter=True
54
+ )
55
+ .join(ModifiedProcedure, ModifiedProcedure.procedure_occurrence_id==Episode_Event.event_id, isouter=True)
56
+ )
@@ -0,0 +1,40 @@
1
+ import sqlalchemy as sa
2
+ import sqlalchemy.orm as so
3
+ from orm_loader.helpers import Base
4
+ from datetime import date
5
+ from typing import Optional
6
+ from .course_joins import course_join
7
+ from .fraction_mv import FractionMV
8
+ from ...core.materialized import MaterializedViewMixin
9
+ from ...core.constructs import register_construct
10
+
11
+ @register_construct
12
+ class RTCourseMV(
13
+ MaterializedViewMixin,
14
+ Base,
15
+ ):
16
+ __mv_name__ = "rt_course_mv"
17
+ __mv_select__ = course_join.select()
18
+ __mv_index__ = "course_id"
19
+ __deps__ = (FractionMV.__mv_name__,)
20
+ __tablename__ = __mv_name__
21
+ __table_args__ = {"extend_existing": True}
22
+
23
+ mv_id: so.Mapped[int] = so.mapped_column(sa.Integer, primary_key=True)
24
+ person_id: so.Mapped[int] = so.mapped_column(sa.Integer)
25
+ fraction_id: so.Mapped[int] = so.mapped_column(sa.Integer)
26
+ fraction_number: so.Mapped[int] = so.mapped_column(sa.Integer)
27
+ fraction_count: so.Mapped[int] = so.mapped_column(sa.Integer)
28
+ fraction_name: so.Mapped[str] = so.mapped_column(sa.String)
29
+ first_exposure_date: so.Mapped[date] = so.mapped_column(sa.Date)
30
+ last_exposure_date: so.Mapped[date] = so.mapped_column(sa.Date)
31
+ course_id: so.Mapped[int] = so.mapped_column(sa.Integer)
32
+ course_number: so.Mapped[int] = so.mapped_column(sa.Integer)
33
+ condition_episode_id: so.Mapped[int] = so.mapped_column(sa.Integer)
34
+ course_prescription_id: so.Mapped[int] = so.mapped_column(sa.Integer)
35
+ course_concept_id: so.Mapped[int] = so.mapped_column(sa.Integer)
36
+ course_concept: so.Mapped[str] = so.mapped_column(sa.String)
37
+ intent_datetime: so.Mapped[Optional[date]] = so.mapped_column(sa.DateTime, nullable=True)
38
+ intent_concept_id: so.Mapped[Optional[int]] = so.mapped_column(sa.Integer, nullable=True)
39
+ intent_concept: so.Mapped[Optional[str]] = so.mapped_column(sa.String, nullable=True)
40
+
@@ -0,0 +1,38 @@
1
+ import sqlalchemy as sa
2
+ from omop_semantics.runtime.default_valuesets import runtime
3
+ import sqlalchemy.orm as so
4
+ from omop_alchemy.cdm.model import Concept, Drug_Exposure, Episode, Episode_Event
5
+
6
+ drug_concept = so.aliased(Concept, name='drug_concept')
7
+ route_concept = so.aliased(Concept, name='route_concept')
8
+ cycle_concept = so.aliased(Concept, name='cycle_concept')
9
+
10
+ cycle_join = (
11
+ sa.select(
12
+ sa.func.row_number().over().label('mv_id'),
13
+ Drug_Exposure.person_id,
14
+ Drug_Exposure.drug_exposure_start_date,
15
+ Drug_Exposure.drug_exposure_end_date,
16
+ Drug_Exposure.drug_exposure_id,
17
+ Drug_Exposure.quantity,
18
+ Drug_Exposure.drug_concept_id,
19
+ Drug_Exposure.dose_unit_source_value,
20
+ drug_concept.concept_name.label('drug_name'),
21
+ route_concept.concept_name.label('route'),
22
+ Episode.episode_id.label('cycle_id'),
23
+ Episode.episode_number.label('cycle_number'),
24
+ Episode.episode_parent_id.label('regimen_id'),
25
+ cycle_concept.concept_name.label('cycle_concept')
26
+ )
27
+ .join(drug_concept, drug_concept.concept_id==Drug_Exposure.drug_concept_id)
28
+ .join(route_concept, route_concept.concept_id==Drug_Exposure.route_concept_id)
29
+ .join(
30
+ Episode_Event,
31
+ sa.and_(
32
+ Episode_Event.event_id==Drug_Exposure.drug_exposure_id,
33
+ Episode_Event.episode_event_field_concept_id==runtime.modifiers.modifier_fields.drug_exposure_id
34
+ )
35
+ )
36
+ .join(Episode, Episode.episode_id==Episode_Event.episode_id)
37
+ .join(cycle_concept, cycle_concept.concept_id==Episode.episode_concept_id)
38
+ )
@@ -0,0 +1,34 @@
1
+ import sqlalchemy as sa
2
+ import sqlalchemy.orm as so
3
+ from orm_loader.helpers import Base
4
+ from datetime import date
5
+ from .cycle_join import cycle_join
6
+ from ...core.materialized import MaterializedViewMixin
7
+ from ...core.constructs import register_construct
8
+
9
+ @register_construct
10
+ class CycleMV(
11
+ MaterializedViewMixin,
12
+ Base,
13
+ ):
14
+ __mv_name__ = "cycle_mv"
15
+ __mv_select__ = cycle_join.select()
16
+ __mv_index__ = "cycle_id"
17
+ __deps__ = ()
18
+ __tablename__ = __mv_name__
19
+ __table_args__ = {"extend_existing": True}
20
+
21
+ mv_id: so.Mapped[int] = so.mapped_column(sa.Integer, primary_key=True)
22
+ person_id: so.Mapped[int] = so.mapped_column(sa.Integer)
23
+ drug_exposure_id: so.Mapped[int] = so.mapped_column(sa.Integer)
24
+ drug_exposure_start_date: so.Mapped[date] = so.mapped_column(sa.Date)
25
+ drug_exposure_end_date: so.Mapped[date] = so.mapped_column(sa.Date)
26
+ quantity: so.Mapped[float] = so.mapped_column(sa.Numeric)
27
+ drug_concept_id: so.Mapped[int] = so.mapped_column(sa.Integer)
28
+ dose_unit_source_value: so.Mapped[str] = so.mapped_column(sa.String)
29
+ drug_name: so.Mapped[str] = so.mapped_column(sa.String)
30
+ route: so.Mapped[str] = so.mapped_column(sa.String)
31
+ cycle_id: so.Mapped[int] = so.mapped_column(sa.Integer)
32
+ cycle_number: so.Mapped[int] = so.mapped_column(sa.Integer)
33
+ cycle_concept: so.Mapped[int] = so.mapped_column(sa.Integer)
34
+ regimen_id: so.Mapped[int] = so.mapped_column(sa.Integer)
@@ -0,0 +1,37 @@
1
+ import sqlalchemy as sa
2
+ import sqlalchemy.orm as so
3
+ from omop_alchemy.cdm.model import Episode, Episode_Event, Concept
4
+ from omop_semantics.runtime.default_valuesets import runtime
5
+ from ..modifiers import ModifiedProcedure
6
+ from ...semantics import registry
7
+
8
+ rt_proc_concept = so.aliased(Concept, name='rt_proc_concept')
9
+ fraction_concept = so.aliased(Concept, name='fraction_concept')
10
+
11
+ fraction_join = (
12
+ sa.select(
13
+ sa.func.row_number().over().label('mv_id'),
14
+ ModifiedProcedure.person_id,
15
+ ModifiedProcedure.procedure_datetime,
16
+ ModifiedProcedure.procedure_occurrence_id,
17
+ ModifiedProcedure.procedure_concept_id,
18
+ ModifiedProcedure.procedure_concept,
19
+ ModifiedProcedure.intent_concept,
20
+ ModifiedProcedure.intent_concept_id,
21
+ ModifiedProcedure.intent_datetime,
22
+ Episode.episode_id.label('fraction_id'),
23
+ Episode.episode_number.label('fraction_number'),
24
+ Episode.episode_parent_id.label('course_id'),
25
+ fraction_concept.concept_name.label('fraction_name')
26
+ )
27
+ .join(
28
+ Episode_Event,
29
+ sa.and_(
30
+ Episode_Event.event_id==ModifiedProcedure.procedure_occurrence_id,
31
+ Episode_Event.episode_event_field_concept_id==runtime.modifiers.modifier_fields.procedure_occurrence_id
32
+ )
33
+ )
34
+ .join(Episode, Episode.episode_id==Episode_Event.episode_id)
35
+ .join(fraction_concept, fraction_concept.concept_id==Episode.episode_object_concept_id)
36
+ .filter(ModifiedProcedure.procedure_concept_id.in_(list(registry['metastatic_disease'].all_concepts)))
37
+ )
@@ -0,0 +1,33 @@
1
+ import sqlalchemy as sa
2
+ import sqlalchemy.orm as so
3
+ from orm_loader.helpers import Base
4
+ from datetime import date
5
+ from .fraction_joins import fraction_join
6
+ from ...core.materialized import MaterializedViewMixin
7
+ from ...core.constructs import register_construct
8
+
9
+ @register_construct
10
+ class FractionMV(
11
+ MaterializedViewMixin,
12
+ Base,
13
+ ):
14
+ __mv_name__ = "fraction_mv"
15
+ __mv_select__ = fraction_join.select()
16
+ __mv_index__ = "fraction_id"
17
+ __deps__ = ()
18
+ __tablename__ = __mv_name__
19
+ __table_args__ = {"extend_existing": True}
20
+
21
+ mv_id: so.Mapped[int] = so.mapped_column(sa.Integer, primary_key=True)
22
+ person_id: so.Mapped[int] = so.mapped_column(sa.Integer)
23
+ procedure_occurrence_id: so.Mapped[int] = so.mapped_column(sa.Integer)
24
+ procedure_datetime: so.Mapped[date] = so.mapped_column(sa.DateTime)
25
+ procedure_concept_id: so.Mapped[int] = so.mapped_column(sa.Integer)
26
+ procedure_concept: so.Mapped[str] = so.mapped_column(sa.String)
27
+ intent_datetime: so.Mapped[date] = so.mapped_column(sa.DateTime)
28
+ intent_concept_id: so.Mapped[int] = so.mapped_column(sa.Integer)
29
+ intent_concept: so.Mapped[str] = so.mapped_column(sa.String)
30
+ fraction_id: so.Mapped[int] = so.mapped_column(sa.Integer)
31
+ fraction_number: so.Mapped[int] = so.mapped_column(sa.Integer)
32
+ course_id: so.Mapped[int] = so.mapped_column(sa.Integer)
33
+ fraction_name: so.Mapped[str] = so.mapped_column(sa.String)
@@ -0,0 +1,53 @@
1
+ import sqlalchemy as sa
2
+ from omop_alchemy.cdm.model import Episode, Episode_Event
3
+ from omop_semantics.runtime.default_valuesets import runtime
4
+ from ..modifiers import ModifiedProcedure
5
+ from .cycle_mv import CycleMV
6
+
7
+
8
+ cycle_summary_join = (
9
+ sa.select(
10
+ CycleMV.person_id,
11
+ CycleMV.cycle_id,
12
+ CycleMV.cycle_number,
13
+ CycleMV.regimen_id,
14
+ CycleMV.cycle_concept,
15
+ sa.func.min(CycleMV.drug_exposure_start_date).label('first_exposure_date'),
16
+ sa.func.max(CycleMV.drug_exposure_end_date).label('last_exposure_date'),
17
+ sa.func.count(CycleMV.drug_exposure_id).label('exposure_count'),
18
+ )
19
+ .group_by(CycleMV.person_id, CycleMV.cycle_id, CycleMV.cycle_number, CycleMV.regimen_id, CycleMV.cycle_concept)
20
+ .subquery()
21
+ )
22
+
23
+ regimen_join = (
24
+ sa.select(
25
+ *cycle_summary_join.c,
26
+ sa.func.row_number().over().label('mv_id'),
27
+ Episode.episode_number.label('regimen_number'),
28
+ Episode.episode_parent_id.label('condition_episode_id'),
29
+ ModifiedProcedure.procedure_occurrence_id.label('regimen_prescription_id'),
30
+ ModifiedProcedure.procedure_concept_id.label('regimen_concept_id'),
31
+ ModifiedProcedure.procedure_concept.label('regimen_concept'),
32
+ ModifiedProcedure.intent_concept,
33
+ ModifiedProcedure.intent_concept_id,
34
+ ModifiedProcedure.intent_datetime,
35
+ )
36
+ .join(
37
+ Episode,
38
+ sa.and_(
39
+ Episode.episode_id == cycle_summary_join.c.regimen_id,
40
+ Episode.episode_concept_id==runtime.types.treatment_episode_types.treatment_regimen
41
+ ),
42
+ isouter=True
43
+ )
44
+ .join(
45
+ Episode_Event,
46
+ sa.and_(
47
+ Episode_Event.episode_id==Episode.episode_id,
48
+ Episode_Event.episode_event_field_concept_id==runtime.modifiers.modifier_fields.procedure_occurrence_id
49
+ ),
50
+ isouter=True
51
+ )
52
+ .join(ModifiedProcedure, ModifiedProcedure.procedure_occurrence_id==Episode_Event.event_id, isouter=True)
53
+ )
@@ -0,0 +1,40 @@
1
+ import sqlalchemy as sa
2
+ import sqlalchemy.orm as so
3
+ from orm_loader.helpers import Base
4
+ from datetime import date
5
+ from typing import Optional
6
+ from .systemic_treatment_joins import regimen_join
7
+ from .cycle_mv import CycleMV
8
+ from ...core.materialized import MaterializedViewMixin
9
+ from ...core.constructs import register_construct
10
+
11
+ @register_construct
12
+ class SACTRegimenMV(
13
+ MaterializedViewMixin,
14
+ Base,
15
+ ):
16
+ __mv_name__ = "sact_treatment_mv"
17
+ __mv_select__ = regimen_join.select()
18
+ __mv_index__ = "regimen_id"
19
+ __deps__ = (CycleMV.__mv_name__,)
20
+ __tablename__ = __mv_name__
21
+ __table_args__ = {"extend_existing": True}
22
+
23
+ mv_id: so.Mapped[int] = so.mapped_column(sa.Integer, primary_key=True)
24
+ person_id: so.Mapped[int] = so.mapped_column(sa.Integer)
25
+ cycle_id: so.Mapped[int] = so.mapped_column(sa.Integer)
26
+ cycle_number: so.Mapped[int] = so.mapped_column(sa.Integer)
27
+ cycle_concept: so.Mapped[int] = so.mapped_column(sa.Integer)
28
+ exposure_count: so.Mapped[int] = so.mapped_column(sa.Integer)
29
+ first_exposure_date: so.Mapped[date] = so.mapped_column(sa.Date)
30
+ last_exposure_date: so.Mapped[date] = so.mapped_column(sa.Date)
31
+ regimen_id: so.Mapped[int] = so.mapped_column(sa.Integer)
32
+ regimen_number: so.Mapped[int] = so.mapped_column(sa.Integer)
33
+ condition_episode_id: so.Mapped[int] = so.mapped_column(sa.Integer)
34
+ regimen_prescription_id: so.Mapped[int] = so.mapped_column(sa.Integer)
35
+ regimen_concept_id: so.Mapped[int] = so.mapped_column(sa.Integer)
36
+ regimen_concept: so.Mapped[str] = so.mapped_column(sa.String)
37
+ intent_datetime: so.Mapped[Optional[date]] = so.mapped_column(sa.DateTime, nullable=True)
38
+ intent_concept_id: so.Mapped[Optional[int]] = so.mapped_column(sa.Integer, nullable=True)
39
+ intent_concept: so.Mapped[Optional[str]] = so.mapped_column(sa.String, nullable=True)
40
+
@@ -0,0 +1,68 @@
1
+ import sqlalchemy as sa
2
+ import sqlalchemy.orm as so
3
+ from .systemic_treatment_mv import SACTRegimenMV
4
+ from .course_mv import RTCourseMV
5
+ from omop_alchemy.cdm.model import Episode_Event, Condition_Occurrence, Concept
6
+ from omop_semantics.runtime.default_valuesets import runtime
7
+
8
+ condition_concept = so.aliased(Concept, name='condition_concept')
9
+
10
+ regimen_summary_join = (
11
+ sa.select(
12
+ SACTRegimenMV.person_id,
13
+ SACTRegimenMV.regimen_concept,
14
+ SACTRegimenMV.regimen_id,
15
+ SACTRegimenMV.regimen_number,
16
+ SACTRegimenMV.condition_episode_id,
17
+ SACTRegimenMV.intent_concept_id.label('sact_intent_concept_id'),
18
+ SACTRegimenMV.intent_concept.label('sact_intent_concept'),
19
+ sa.func.min(SACTRegimenMV.first_exposure_date).label('regimen_start_date'),
20
+ sa.func.max(SACTRegimenMV.last_exposure_date).label('regimen_end_date'),
21
+ sa.func.sum(SACTRegimenMV.exposure_count).label('exposure_count'),
22
+ sa.func.count(SACTRegimenMV.regimen_id).label('regimen_count'),
23
+ )
24
+ .group_by(SACTRegimenMV.person_id, SACTRegimenMV.regimen_concept, SACTRegimenMV.regimen_id, SACTRegimenMV.regimen_number, SACTRegimenMV.condition_episode_id, SACTRegimenMV.intent_concept_id, SACTRegimenMV.intent_concept)
25
+ .subquery()
26
+ )
27
+
28
+ course_summary_join = (
29
+ sa.select(
30
+ RTCourseMV.person_id,
31
+ RTCourseMV.course_concept,
32
+ RTCourseMV.course_id,
33
+ RTCourseMV.course_number,
34
+ RTCourseMV.condition_episode_id,
35
+ RTCourseMV.intent_concept_id.label('rt_intent_concept_id'),
36
+ RTCourseMV.intent_concept.label('rt_intent_concept'),
37
+ sa.func.min(RTCourseMV.first_exposure_date).label('course_start_date'),
38
+ sa.func.max(RTCourseMV.last_exposure_date).label('course_end_date'),
39
+ sa.func.sum(RTCourseMV.fraction_count).label('fraction_count'),
40
+ sa.func.count(RTCourseMV.course_id).label('course_count'),
41
+ )
42
+ .group_by(RTCourseMV.person_id, RTCourseMV.course_concept, RTCourseMV.course_id, RTCourseMV.course_number, RTCourseMV.condition_episode_id, RTCourseMV.intent_concept_id, RTCourseMV.intent_concept)
43
+ .subquery()
44
+ )
45
+
46
+ condition_treatment_join = (
47
+ sa.select(
48
+ sa.func.row_number().over().label('mv_id'),
49
+ Condition_Occurrence.person_id,
50
+ Condition_Occurrence.condition_occurrence_id,
51
+ Condition_Occurrence.condition_start_date,
52
+ Condition_Occurrence.condition_end_date,
53
+ Episode_Event.episode_id.label('condition_episode_id'),
54
+ *regimen_summary_join.c,
55
+ *course_summary_join.c,
56
+ )
57
+ .join(
58
+ Episode_Event,
59
+ sa.and_(
60
+ Episode_Event.event_id==Condition_Occurrence.condition_occurrence_id,
61
+ Episode_Event.episode_event_field_concept_id==runtime.modifiers.modifier_fields.condition_occurrence_id
62
+ ),
63
+ isouter=True
64
+ )
65
+ .join(regimen_summary_join, regimen_summary_join.c.condition_episode_id==Episode_Event.episode_id, isouter=True)
66
+ .join(course_summary_join, course_summary_join.c.condition_episode_id==Episode_Event.episode_id, isouter=True)
67
+ .subquery()
68
+ )
@@ -0,0 +1,47 @@
1
+ import sqlalchemy as sa
2
+ import sqlalchemy.orm as so
3
+ from orm_loader.helpers import Base
4
+ from datetime import date
5
+ from typing import Optional
6
+ from .treatment_summary_joins import condition_treatment_join
7
+ from .course_mv import RTCourseMV
8
+ from .systemic_treatment_mv import SACTRegimenMV
9
+ from ...core.materialized import MaterializedViewMixin
10
+ from ...core.constructs import register_construct
11
+
12
+ @register_construct
13
+ class ConditionTreatmentEpisode(
14
+ MaterializedViewMixin,
15
+ Base,
16
+ ):
17
+ __mv_name__ = "condition_treatment_episode_mv"
18
+ __mv_select__ = condition_treatment_join.select()
19
+ __mv_index__ = "condition_episode_id"
20
+ __deps__ = (RTCourseMV.__mv_name__, SACTRegimenMV.__mv_name__)
21
+ __tablename__ = __mv_name__
22
+ __table_args__ = {"extend_existing": True}
23
+
24
+ mv_id: so.Mapped[int] = so.mapped_column(sa.Integer, primary_key=True)
25
+ person_id: so.Mapped[int] = so.mapped_column(sa.Integer)
26
+ condition_episode_id: so.Mapped[int] = so.mapped_column(sa.Integer)
27
+ condition_occurrence_id: so.Mapped[int] = so.mapped_column(sa.Integer)
28
+ condition_start_date: so.Mapped[date] = so.mapped_column(sa.Date)
29
+ condition_end_date: so.Mapped[date] = so.mapped_column(sa.Date)
30
+ course_concept: so.Mapped[str] = so.mapped_column(sa.String)
31
+ course_id: so.Mapped[int] = so.mapped_column(sa.Integer)
32
+ course_number: so.Mapped[int] = so.mapped_column(sa.Integer)
33
+ course_start_date: so.Mapped[date] = so.mapped_column(sa.Date)
34
+ course_end_date: so.Mapped[date] = so.mapped_column(sa.Date)
35
+ rt_intent_concept_id: so.Mapped[int] = so.mapped_column(sa.Integer)
36
+ rt_intent_concept: so.Mapped[int] = so.mapped_column(sa.Integer)
37
+ fraction_count: so.Mapped[int] = so.mapped_column(sa.Integer)
38
+ course_count: so.Mapped[int] = so.mapped_column(sa.Integer)
39
+ regimen_concept: so.Mapped[str] = so.mapped_column(sa.String)
40
+ regimen_id: so.Mapped[int] = so.mapped_column(sa.Integer)
41
+ regimen_number: so.Mapped[int] = so.mapped_column(sa.Integer)
42
+ regimen_start_date: so.Mapped[date] = so.mapped_column(sa.Date)
43
+ regimen_end_date: so.Mapped[date] = so.mapped_column(sa.Date)
44
+ sact_intent_concept_id: so.Mapped[int] = so.mapped_column(sa.Integer)
45
+ sact_intent_concept: so.Mapped[int] = so.mapped_column(sa.Integer)
46
+ exposure_count: so.Mapped[int] = so.mapped_column(sa.Integer)
47
+ regimen_count: so.Mapped[int] = so.mapped_column(sa.Integer)
@@ -10,6 +10,9 @@ from .modifier_mappers import (
10
10
  AllStageModifierMV
11
11
  )
12
12
  from .condition_modifier_mv import ModifiedCondition, StageModifier
13
+ from .procedure_modifier_mv import (
14
+ ModifiedProcedure,
15
+ )
13
16
 
14
17
  __all__ = [
15
18
  "TStageMV",
@@ -22,5 +25,6 @@ __all__ = [
22
25
  "ModifiedCondition",
23
26
  "MetastaticDiseaseModifierMV",
24
27
  "AllStageModifierMV",
25
- "StageModifier"
28
+ "StageModifier",
29
+ "ModifiedProcedure"
26
30
  ]
@@ -0,0 +1,37 @@
1
+ from datetime import datetime
2
+ import sqlalchemy as sa
3
+ import sqlalchemy.orm as so
4
+ from omop_alchemy.cdm.model import Concept, Procedure_Occurrence, Measurement
5
+ from omop_semantics.runtime.default_valuesets import runtime
6
+
7
+
8
+ modifier_concept = so.aliased(Concept, name='modifier_concept')
9
+ procedure_concept = so.aliased(Concept, name='procedure_concept')
10
+
11
+ modified_procedure_join = (
12
+ sa.select(
13
+ Procedure_Occurrence.person_id,
14
+ Procedure_Occurrence.procedure_datetime,
15
+ Procedure_Occurrence.procedure_occurrence_id,
16
+ Procedure_Occurrence.procedure_source_value,
17
+ Procedure_Occurrence.procedure_concept_id,
18
+ procedure_concept.concept_name.label('procedure_concept'),
19
+ Measurement.measurement_id.label('intent_id'),
20
+ Measurement.measurement_datetime.label('intent_datetime'),
21
+ Measurement.measurement_concept_id.label('intent_concept_id'),
22
+ modifier_concept.concept_name.label('intent_concept'),
23
+ sa.func.row_number().over().label('mv_id')
24
+ )
25
+ .join(
26
+ Measurement,
27
+ sa.and_(
28
+ Measurement.modifier_of_field_concept_id==runtime.modifiers.modifier_fields.procedure_occurrence_id,
29
+ Procedure_Occurrence.procedure_occurrence_id==Measurement.modifier_of_event_id,
30
+ Measurement.measurement_concept_id.in_(runtime.treatment_modifiers.treatment_intent.ids)
31
+ ),
32
+ isouter=True
33
+ )
34
+ .join(procedure_concept, procedure_concept.concept_id==Procedure_Occurrence.procedure_concept_id)
35
+ .join(modifier_concept, modifier_concept.concept_id==Measurement.measurement_concept_id, isouter=True)
36
+ )
37
+
@@ -0,0 +1,30 @@
1
+ import sqlalchemy as sa
2
+ from orm_loader.helpers import Base
3
+ from ...core.materialized import MaterializedViewMixin
4
+ from ...core.constructs import register_construct
5
+ from .procedure_modifier_joins import modified_procedure_join
6
+
7
+ @register_construct
8
+ class ModifiedProcedure(MaterializedViewMixin, Base):
9
+ """
10
+ this class contains all stage modifier records no matter the sub-type, nor does it preference
11
+ clin / path stage etc - just a dump of all, along with the identifier to link to condition ep
12
+ """
13
+ __mv_name__ = 'modified_procedure_mv'
14
+ __mv_select__ = modified_procedure_join.select()
15
+ __mv_pk__ = ["mv_id"]
16
+ __table_args__ = {"extend_existing": True}
17
+ __tablename__ = __mv_name__
18
+ __deps__ = ()
19
+ mv_id = sa.Column(sa.Integer,primary_key=True)
20
+ person_id = sa.Column(sa.Integer)
21
+ procedure_datetime = sa.Column(sa.Date)
22
+ procedure_occurrence_id = sa.Column(sa.Integer)
23
+ procedure_source_value = sa.Column(sa.String)
24
+ procedure_concept_id = sa.Column(sa.Integer)
25
+ procedure_concept = sa.Column(sa.String)
26
+ intent_id = sa.Column(sa.Integer)
27
+ intent_datetime = sa.Column(sa.Date)
28
+ intent_concept_id = sa.Column(sa.Integer)
29
+ intent_concept = sa.Column(sa.String)
30
+ stage_label = sa.Column(sa.String)
@@ -38,6 +38,14 @@ DEFAULT_RESOLVER_BUILDERS = {
38
38
  parent_list=list(runtime.condition_modifiers.tumor_grade.ids),
39
39
  resolver_name="tumor_grade",
40
40
  ),
41
+ "rt_procedures": lambda session: build_parent_resolver(
42
+ session,
43
+ parent_list=[
44
+ runtime.cancer_procedures.cancer_procedure_types.rt_externalbeam, # type: ignore
45
+ runtime.cancer_procedures.cancer_procedure_types.rt_procedure
46
+ ],
47
+ resolver_name="rt_procedures",
48
+ )
41
49
  }
42
50
 
43
51
  def get_registry_engine(env_path: str = __file__):
@@ -1,25 +0,0 @@
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
- )