nci-cidc-api-modules 1.2.34__py3-none-any.whl → 1.2.53__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (151) hide show
  1. boot.py +14 -0
  2. cidc_api/__init__.py +1 -0
  3. cidc_api/config/db.py +21 -1
  4. cidc_api/config/settings.py +5 -10
  5. cidc_api/models/__init__.py +0 -2
  6. cidc_api/models/data.py +15 -6
  7. cidc_api/models/db/stage1/__init__.py +56 -0
  8. cidc_api/models/db/stage1/additional_treatment_orm.py +22 -0
  9. cidc_api/models/db/stage1/adverse_event_orm.py +46 -0
  10. cidc_api/models/db/stage1/base_orm.py +7 -0
  11. cidc_api/models/db/stage1/baseline_clinical_assessment_orm.py +22 -0
  12. cidc_api/models/db/stage1/comorbidity_orm.py +23 -0
  13. cidc_api/models/db/stage1/consent_group_orm.py +32 -0
  14. cidc_api/models/db/stage1/demographic_orm.py +47 -0
  15. cidc_api/models/db/stage1/disease_orm.py +52 -0
  16. cidc_api/models/db/stage1/exposure_orm.py +22 -0
  17. cidc_api/models/db/stage1/gvhd_diagnosis_acute_orm.py +34 -0
  18. cidc_api/models/db/stage1/gvhd_diagnosis_chronic_orm.py +36 -0
  19. cidc_api/models/db/stage1/gvhd_organ_acute_orm.py +21 -0
  20. cidc_api/models/db/stage1/gvhd_organ_chronic_orm.py +21 -0
  21. cidc_api/models/db/stage1/medical_history_orm.py +30 -0
  22. cidc_api/models/db/stage1/other_malignancy_orm.py +29 -0
  23. cidc_api/models/db/stage1/participant_orm.py +77 -0
  24. cidc_api/models/db/stage1/prior_treatment_orm.py +29 -0
  25. cidc_api/models/db/stage1/radiotherapy_dose_orm.py +39 -0
  26. cidc_api/models/db/stage1/response_by_system_orm.py +30 -0
  27. cidc_api/models/db/stage1/response_orm.py +28 -0
  28. cidc_api/models/db/stage1/specimen_orm.py +46 -0
  29. cidc_api/models/db/stage1/stem_cell_transplant_orm.py +25 -0
  30. cidc_api/models/db/stage1/surgery_orm.py +27 -0
  31. cidc_api/models/db/stage1/therapy_agent_dose_orm.py +31 -0
  32. cidc_api/models/db/stage1/treatment_orm.py +38 -0
  33. cidc_api/models/db/stage1/trial_orm.py +35 -0
  34. cidc_api/models/db/stage2/additional_treatment_orm.py +6 -7
  35. cidc_api/models/db/stage2/administrative_person_orm.py +4 -4
  36. cidc_api/models/db/stage2/administrative_role_assignment_orm.py +4 -4
  37. cidc_api/models/db/stage2/adverse_event_orm.py +11 -13
  38. cidc_api/models/db/stage2/arm_orm.py +3 -3
  39. cidc_api/models/db/stage2/base_orm.py +7 -0
  40. cidc_api/models/db/stage2/baseline_clinical_assessment_orm.py +5 -7
  41. cidc_api/models/db/stage2/cohort_orm.py +3 -3
  42. cidc_api/models/db/stage2/comorbidity_orm.py +6 -8
  43. cidc_api/models/db/stage2/consent_group_orm.py +4 -4
  44. cidc_api/models/db/stage2/contact_orm.py +16 -20
  45. cidc_api/models/db/stage2/demographic_orm.py +3 -3
  46. cidc_api/models/db/stage2/disease_orm.py +4 -4
  47. cidc_api/models/db/stage2/exposure_orm.py +3 -3
  48. cidc_api/models/db/stage2/file_orm.py +6 -9
  49. cidc_api/models/db/stage2/gvhd_diagnosis_acute_orm.py +4 -4
  50. cidc_api/models/db/stage2/gvhd_diagnosis_chronic_orm.py +4 -6
  51. cidc_api/models/db/stage2/gvhd_organ_acute_orm.py +3 -3
  52. cidc_api/models/db/stage2/gvhd_organ_chronic_orm.py +3 -3
  53. cidc_api/models/db/stage2/institution_orm.py +7 -7
  54. cidc_api/models/db/stage2/medical_history_orm.py +9 -9
  55. cidc_api/models/db/stage2/other_clinical_endpoint_orm.py +8 -12
  56. cidc_api/models/db/stage2/other_malignancy_orm.py +8 -10
  57. cidc_api/models/db/stage2/participant_orm.py +23 -24
  58. cidc_api/models/db/stage2/prior_treatment_orm.py +12 -13
  59. cidc_api/models/db/stage2/publication_orm.py +9 -11
  60. cidc_api/models/db/stage2/radiotherapy_dose_orm.py +8 -9
  61. cidc_api/models/db/stage2/response_by_system_orm.py +3 -3
  62. cidc_api/models/db/stage2/response_orm.py +3 -3
  63. cidc_api/models/db/stage2/shipment_orm.py +17 -17
  64. cidc_api/models/db/stage2/shipment_specimen_orm.py +4 -4
  65. cidc_api/models/db/stage2/specimen_orm.py +7 -6
  66. cidc_api/models/db/stage2/stem_cell_transplant_orm.py +6 -7
  67. cidc_api/models/db/stage2/surgery_orm.py +6 -7
  68. cidc_api/models/db/stage2/therapy_agent_dose_orm.py +7 -8
  69. cidc_api/models/db/stage2/treatment_orm.py +15 -15
  70. cidc_api/models/db/stage2/trial_orm.py +15 -17
  71. cidc_api/models/errors.py +7 -0
  72. cidc_api/models/files/facets.py +4 -0
  73. cidc_api/models/models.py +167 -11
  74. cidc_api/models/pydantic/base.py +109 -0
  75. cidc_api/models/pydantic/stage1/__init__.py +56 -0
  76. cidc_api/models/pydantic/stage1/additional_treatment.py +23 -0
  77. cidc_api/models/pydantic/stage1/adverse_event.py +127 -0
  78. cidc_api/models/pydantic/stage1/baseline_clinical_assessment.py +23 -0
  79. cidc_api/models/pydantic/stage1/comorbidity.py +43 -0
  80. cidc_api/models/pydantic/stage1/consent_group.py +30 -0
  81. cidc_api/models/pydantic/stage1/demographic.py +140 -0
  82. cidc_api/models/pydantic/stage1/disease.py +200 -0
  83. cidc_api/models/pydantic/stage1/exposure.py +38 -0
  84. cidc_api/models/pydantic/stage1/gvhd_diagnosis_acute.py +33 -0
  85. cidc_api/models/pydantic/stage1/gvhd_diagnosis_chronic.py +32 -0
  86. cidc_api/models/pydantic/stage1/gvhd_organ_acute.py +22 -0
  87. cidc_api/models/pydantic/stage1/gvhd_organ_chronic.py +23 -0
  88. cidc_api/models/pydantic/stage1/medical_history.py +43 -0
  89. cidc_api/models/pydantic/stage1/other_malignancy.py +55 -0
  90. cidc_api/models/pydantic/stage1/participant.py +63 -0
  91. cidc_api/models/pydantic/stage1/prior_treatment.py +45 -0
  92. cidc_api/models/pydantic/stage1/radiotherapy_dose.py +92 -0
  93. cidc_api/models/pydantic/stage1/response.py +84 -0
  94. cidc_api/models/pydantic/stage1/response_by_system.py +220 -0
  95. cidc_api/models/pydantic/stage1/specimen.py +31 -0
  96. cidc_api/models/pydantic/stage1/stem_cell_transplant.py +35 -0
  97. cidc_api/models/pydantic/stage1/surgery.py +57 -0
  98. cidc_api/models/pydantic/stage1/therapy_agent_dose.py +80 -0
  99. cidc_api/models/pydantic/stage1/treatment.py +64 -0
  100. cidc_api/models/pydantic/stage1/trial.py +45 -0
  101. cidc_api/models/pydantic/stage2/additional_treatment.py +2 -4
  102. cidc_api/models/pydantic/stage2/administrative_person.py +1 -1
  103. cidc_api/models/pydantic/stage2/administrative_role_assignment.py +2 -2
  104. cidc_api/models/pydantic/stage2/adverse_event.py +1 -1
  105. cidc_api/models/pydantic/stage2/arm.py +2 -2
  106. cidc_api/models/pydantic/stage2/baseline_clinical_assessment.py +1 -1
  107. cidc_api/models/pydantic/stage2/cohort.py +1 -1
  108. cidc_api/models/pydantic/stage2/comorbidity.py +1 -1
  109. cidc_api/models/pydantic/stage2/consent_group.py +2 -2
  110. cidc_api/models/pydantic/stage2/contact.py +1 -1
  111. cidc_api/models/pydantic/stage2/demographic.py +1 -1
  112. cidc_api/models/pydantic/stage2/disease.py +1 -1
  113. cidc_api/models/pydantic/stage2/exposure.py +1 -1
  114. cidc_api/models/pydantic/stage2/file.py +2 -2
  115. cidc_api/models/pydantic/stage2/gvhd_diagnosis_acute.py +1 -1
  116. cidc_api/models/pydantic/stage2/gvhd_diagnosis_chronic.py +1 -1
  117. cidc_api/models/pydantic/stage2/gvhd_organ_acute.py +1 -1
  118. cidc_api/models/pydantic/stage2/gvhd_organ_chronic.py +1 -1
  119. cidc_api/models/pydantic/stage2/institution.py +1 -1
  120. cidc_api/models/pydantic/stage2/medical_history.py +1 -1
  121. cidc_api/models/pydantic/stage2/other_clinical_endpoint.py +1 -1
  122. cidc_api/models/pydantic/stage2/other_malignancy.py +1 -1
  123. cidc_api/models/pydantic/stage2/participant.py +6 -3
  124. cidc_api/models/pydantic/stage2/prior_treatment.py +6 -15
  125. cidc_api/models/pydantic/stage2/publication.py +2 -2
  126. cidc_api/models/pydantic/stage2/radiotherapy_dose.py +1 -1
  127. cidc_api/models/pydantic/stage2/response.py +2 -2
  128. cidc_api/models/pydantic/stage2/response_by_system.py +1 -1
  129. cidc_api/models/pydantic/stage2/shipment.py +2 -2
  130. cidc_api/models/pydantic/stage2/shipment_specimen.py +1 -1
  131. cidc_api/models/pydantic/stage2/specimen.py +6 -3
  132. cidc_api/models/pydantic/stage2/stem_cell_transplant.py +2 -2
  133. cidc_api/models/pydantic/stage2/surgery.py +1 -1
  134. cidc_api/models/pydantic/stage2/therapy_agent_dose.py +1 -1
  135. cidc_api/models/pydantic/stage2/treatment.py +1 -1
  136. cidc_api/models/pydantic/stage2/trial.py +8 -10
  137. cidc_api/models/types.py +30 -16
  138. cidc_api/shared/assay_handling.py +68 -0
  139. cidc_api/shared/auth.py +5 -5
  140. cidc_api/shared/file_handling.py +18 -4
  141. cidc_api/shared/gcloud_client.py +96 -16
  142. cidc_api/shared/utils.py +18 -9
  143. cidc_api/telemetry.py +101 -0
  144. {nci_cidc_api_modules-1.2.34.dist-info → nci_cidc_api_modules-1.2.53.dist-info}/METADATA +25 -15
  145. nci_cidc_api_modules-1.2.53.dist-info/RECORD +167 -0
  146. {nci_cidc_api_modules-1.2.34.dist-info → nci_cidc_api_modules-1.2.53.dist-info}/WHEEL +1 -1
  147. {nci_cidc_api_modules-1.2.34.dist-info → nci_cidc_api_modules-1.2.53.dist-info}/top_level.txt +1 -0
  148. cidc_api/models/db/base_orm.py +0 -25
  149. cidc_api/models/pydantic/stage2/base.py +0 -48
  150. nci_cidc_api_modules-1.2.34.dist-info/RECORD +0 -109
  151. {nci_cidc_api_modules-1.2.34.dist-info → nci_cidc_api_modules-1.2.53.dist-info}/licenses/LICENSE +0 -0
boot.py ADDED
@@ -0,0 +1,14 @@
1
+ from os import mkdir, path
2
+ import shutil
3
+
4
+ TEMPLATES_DIR = path.join("/tmp", "templates")
5
+
6
+
7
+ # set up the directories for holding generated templates
8
+ def set_up_templates_directories():
9
+ if path.exists(TEMPLATES_DIR):
10
+ shutil.rmtree(TEMPLATES_DIR)
11
+ mkdir(TEMPLATES_DIR)
12
+ for family in ["assays", "manifests", "analyses"]:
13
+ family_dir = path.join(TEMPLATES_DIR, family)
14
+ mkdir(family_dir)
cidc_api/__init__.py ADDED
@@ -0,0 +1 @@
1
+ __version__ = "1.2.53"
cidc_api/config/db.py CHANGED
@@ -1,8 +1,10 @@
1
1
  from os import environ
2
+ from typing import Self
2
3
 
3
4
  from flask import Flask
4
5
  from flask_sqlalchemy import SQLAlchemy
5
6
  from flask_migrate import Migrate, upgrade
7
+ from sqlalchemy import MetaData
6
8
  from sqlalchemy.engine.url import URL
7
9
  from sqlalchemy.orm import declarative_base
8
10
  from google.cloud.sql.connector import Connector, IPTypes
@@ -11,6 +13,8 @@ from .secrets import get_secrets_manager
11
13
 
12
14
  db = SQLAlchemy()
13
15
  BaseModel = db.Model
16
+ Stage1BaseModel = SQLAlchemy(metadata=MetaData(schema="stage1")).Model
17
+ Stage2BaseModel = SQLAlchemy(metadata=MetaData(schema="stage2")).Model
14
18
 
15
19
  connector = Connector()
16
20
 
@@ -46,7 +50,6 @@ def get_sqlalchemy_database_uri(testing: bool = False) -> str:
46
50
  db_uri = f"postgresql+pg8000://{environ.get('CLOUD_SQL_DB_USER')}:xxx@/{environ.get('CLOUD_SQL_DB_NAME')}"
47
51
 
48
52
  assert db_uri
49
-
50
53
  return db_uri
51
54
 
52
55
 
@@ -56,3 +59,20 @@ def cloud_connector(testing: bool = False):
56
59
  return {"creator": getconn}
57
60
  else:
58
61
  return {}
62
+
63
+
64
+ class ModelMixin:
65
+ def merge(self, d: dict) -> Self:
66
+ """Merge keys and values from dict d into this model, overwriting as necessary."""
67
+ for key, value in d.items():
68
+ setattr(self, key, value)
69
+ return self
70
+
71
+ def clone(self) -> "BaseORM":
72
+ """Clones a SQLAlchemy ORM object, excluding primary keys."""
73
+ mapper = self.__mapper__
74
+ new_instance = self.__class__()
75
+ for column in mapper.columns:
76
+ if not column.primary_key:
77
+ setattr(new_instance, column.key, getattr(self, column.key))
78
+ return new_instance
@@ -5,11 +5,11 @@ Any 'UPPER_CASE' variables will be exported as a key-value pair
5
5
  in the `SETTINGS` dictionary defined at the bottom of this file.
6
6
  """
7
7
 
8
- import shutil
9
- from os import environ, path, mkdir
8
+ from os import environ, path
10
9
 
11
10
  from dotenv import load_dotenv
12
11
 
12
+ from boot import TEMPLATES_DIR as templates_dir
13
13
  from .db import get_sqlalchemy_database_uri, cloud_connector
14
14
  from .secrets import get_secrets_manager
15
15
 
@@ -36,14 +36,7 @@ PAGINATION_PAGE_SIZE = 25
36
36
  MAX_PAGINATION_PAGE_SIZE = 200
37
37
  INACTIVE_USER_DAYS = 60
38
38
  MAX_THREADPOOL_WORKERS = 32
39
- TEMPLATES_DIR = path.join("/tmp", "templates")
40
- # Also, set up the directories for holding generated templates
41
- if path.exists(TEMPLATES_DIR):
42
- shutil.rmtree(TEMPLATES_DIR)
43
- mkdir(TEMPLATES_DIR)
44
- for family in ["assays", "manifests", "analyses"]:
45
- family_dir = path.join(TEMPLATES_DIR, family)
46
- mkdir(family_dir)
39
+ TEMPLATES_DIR = templates_dir
47
40
 
48
41
  ### Configure prism encrypt ###
49
42
  if not TESTING:
@@ -84,6 +77,8 @@ GOOGLE_ARTIFACT_UPLOAD_TOPIC = environ["GOOGLE_ARTIFACT_UPLOAD_TOPIC"]
84
77
  GOOGLE_GRANT_DOWNLOAD_PERMISSIONS_TOPIC = environ["GOOGLE_GRANT_DOWNLOAD_PERMISSIONS_TOPIC"]
85
78
  GOOGLE_HL_CLINICAL_VALIDATION_TOPIC = environ["GOOGLE_HL_CLINICAL_VALIDATION_TOPIC"]
86
79
  GOOGLE_DL_CLINICAL_VALIDATION_TOPIC = environ["GOOGLE_DL_CLINICAL_VALIDATION_TOPIC"]
80
+ GOOGLE_ASSAY_METADATA_VALIDATION_TOPIC = environ["GOOGLE_ASSAY_METADATA_VALIDATION_TOPIC"]
81
+ GOOGLE_CLINICAL_DATA_INGESTION_PROCESSING_TOPIC = "ingestion"
87
82
  GOOGLE_AND_OPERATOR = " && "
88
83
  GOOGLE_OR_OPERATOR = " || "
89
84
 
@@ -1,5 +1,3 @@
1
1
  from .models import *
2
2
  from .files import *
3
3
  from .schemas import *
4
-
5
- from cidc_api.models.db.base_orm import BaseORM
cidc_api/models/data.py CHANGED
@@ -1,19 +1,28 @@
1
- from cidc_api.models.pydantic.stage2 import all_models
2
- from cidc_api.models.db.stage2 import all_models as all_db_models
1
+ from cidc_api.models.pydantic.stage1 import all_models as stage1_all_models
2
+ from cidc_api.models.pydantic.stage2 import all_models as stage2_all_models
3
+ from cidc_api.models.db.stage1 import all_models as stage1_all_db_models
4
+ from cidc_api.models.db.stage2 import all_models as stage2_all_db_models
3
5
 
4
- standard_data_categories = [model.__data_category__ for model in all_models if hasattr(model, "__data_category__")]
6
+ standard_data_categories = [
7
+ model.__data_category__ for model in stage1_all_models if hasattr(model, "__data_category__")
8
+ ]
5
9
 
6
10
 
7
11
  # A class to hold the representation of a trial's dataset all at once
8
12
  class Dataset(dict):
9
13
  def __init__(self, *args, **kwargs):
10
- super().__init__(*args, **kwargs)
11
14
  for data_category in standard_data_categories:
12
15
  self[data_category] = []
16
+ super().__init__(*args, **kwargs)
13
17
 
14
18
 
15
19
  # Maps data categories like "treatment" to their associated pydantic model
16
- data_category_to_model = {model.__data_category__: model for model in all_models if hasattr(model, "__data_category__")}
20
+ data_category_to_model = {
21
+ "stage1": {model.__data_category__: model for model in stage1_all_models if hasattr(model, "__data_category__")},
22
+ "stage2": {model.__data_category__: model for model in stage2_all_models if hasattr(model, "__data_category__")},
23
+ }
24
+
17
25
  data_category_to_db_model = {
18
- model.__data_category__: model for model in all_db_models if hasattr(model, "__data_category__")
26
+ "stage1": {model.__data_category__: model for model in stage1_all_db_models if hasattr(model, "__data_category__")},
27
+ "stage2": {model.__data_category__: model for model in stage2_all_db_models if hasattr(model, "__data_category__")},
19
28
  }
@@ -0,0 +1,56 @@
1
+ from .additional_treatment_orm import AdditionalTreatmentORM
2
+ from .adverse_event_orm import AdverseEventORM
3
+ from .baseline_clinical_assessment_orm import BaselineClinicalAssessmentORM
4
+ from .comorbidity_orm import ComorbidityORM
5
+ from .consent_group_orm import ConsentGroupORM
6
+ from .demographic_orm import DemographicORM
7
+ from .disease_orm import DiseaseORM
8
+ from .exposure_orm import ExposureORM
9
+ from .gvhd_diagnosis_acute_orm import GVHDDiagnosisAcuteORM
10
+ from .gvhd_diagnosis_chronic_orm import GVHDDiagnosisChronicORM
11
+ from .gvhd_organ_acute_orm import GVHDOrganAcuteORM
12
+ from .gvhd_organ_chronic_orm import GVHDOrganChronicORM
13
+ from .medical_history_orm import MedicalHistoryORM
14
+ from .other_malignancy_orm import OtherMalignancyORM
15
+ from .participant_orm import ParticipantORM
16
+ from .prior_treatment_orm import PriorTreatmentORM
17
+ from .radiotherapy_dose_orm import RadiotherapyDoseORM
18
+ from .response_by_system_orm import ResponseBySystemORM
19
+ from .response_orm import ResponseORM
20
+ from .specimen_orm import SpecimenORM
21
+ from .stem_cell_transplant_orm import StemCellTransplantORM
22
+ from .surgery_orm import SurgeryORM
23
+ from .therapy_agent_dose_orm import TherapyAgentDoseORM
24
+ from .treatment_orm import TreatmentORM
25
+ from .trial_orm import TrialORM
26
+
27
+
28
+ __all__ = [
29
+ "AdditionalTreatmentORM",
30
+ "AdverseEventORM",
31
+ "BaselineClinicalAssessmentORM",
32
+ "ComorbidityORM",
33
+ "ConsentGroupORM",
34
+ "DemographicORM",
35
+ "DiseaseORM",
36
+ "ExposureORM",
37
+ "GVHDDiagnosisAcuteORM",
38
+ "GVHDDiagnosisChronicORM",
39
+ "GVHDOrganAcuteORM",
40
+ "GVHDOrganChronicORM",
41
+ "MedicalHistoryORM",
42
+ "OtherMalignancyORM",
43
+ "ParticipantORM",
44
+ "PriorTreatmentORM",
45
+ "RadiotherapyDoseORM",
46
+ "ResponseBySystemORM",
47
+ "ResponseORM",
48
+ "SpecimenORM",
49
+ "StemCellTransplantORM",
50
+ "SurgeryORM",
51
+ "TherapyAgentDoseORM",
52
+ "TreatmentORM",
53
+ "TrialORM",
54
+ ]
55
+
56
+ all_models = [globals()[cls_name] for cls_name in __all__]
@@ -0,0 +1,22 @@
1
+ from __future__ import annotations
2
+ from pydantic import NonNegativeInt
3
+
4
+ from sqlalchemy import ForeignKey
5
+ from sqlalchemy.orm import Mapped, mapped_column, relationship
6
+
7
+ from cidc_api.models.db.stage1.base_orm import BaseORM
8
+
9
+
10
+ class AdditionalTreatmentORM(BaseORM):
11
+ __tablename__ = "additional_treatment"
12
+ __repr_attrs__ = ["additional_treatment_id", "participant_id"]
13
+ __data_category__ = "additional_treatment"
14
+
15
+ additional_treatment_id: Mapped[int] = mapped_column(primary_key=True)
16
+ participant_id: Mapped[int] = mapped_column(ForeignKey("stage1.participant.participant_id", ondelete="CASCADE"))
17
+
18
+ additional_treatment_days_to_start: Mapped[NonNegativeInt | None]
19
+ additional_treatment_days_to_end: Mapped[NonNegativeInt | None]
20
+ additional_treatment_description: Mapped[str]
21
+
22
+ participant: Mapped["ParticipantORM"] = relationship(back_populates="additional_treatments", cascade="all, delete")
@@ -0,0 +1,46 @@
1
+ from __future__ import annotations
2
+ from pydantic import NonNegativeInt
3
+ from sqlalchemy import ForeignKey
4
+ from sqlalchemy.orm import Mapped, mapped_column, relationship
5
+
6
+ from cidc_api.models.db.stage1.base_orm import BaseORM
7
+ from cidc_api.models.types import (
8
+ CTCAEEventTerm,
9
+ CTCAEEventCode,
10
+ SeverityGradeSystem,
11
+ SeverityGradeSystemVersion,
12
+ SeverityGrade,
13
+ SystemOrganClass,
14
+ AttributionCause,
15
+ AttributionLikelihood,
16
+ YNU,
17
+ )
18
+
19
+
20
+ class AdverseEventORM(BaseORM):
21
+ __tablename__ = "adverse_event"
22
+ __repr_attrs__ = ["adverse_event_id", "participant_id", "event_term"]
23
+ __data_category__ = "adverse_event"
24
+
25
+ adverse_event_id: Mapped[int] = mapped_column(primary_key=True)
26
+ participant_id: Mapped[int] = mapped_column(ForeignKey("stage1.participant.participant_id", ondelete="CASCADE"))
27
+ treatment_id: Mapped[int | None] = mapped_column(ForeignKey("stage1.treatment.treatment_id", ondelete="CASCADE"))
28
+
29
+ event_term: Mapped[CTCAEEventTerm | None]
30
+ event_code: Mapped[CTCAEEventCode | None]
31
+ severity_grade_system: Mapped[SeverityGradeSystem]
32
+ severity_grade_system_version: Mapped[SeverityGradeSystemVersion]
33
+ severity_grade: Mapped[SeverityGrade]
34
+ event_other_specify: Mapped[str | None]
35
+ system_organ_class: Mapped[SystemOrganClass | None]
36
+ discontinuation_due_to_event: Mapped[bool]
37
+ days_to_onset_of_event: Mapped[NonNegativeInt]
38
+ days_to_resolution_of_event: Mapped[NonNegativeInt | None]
39
+ serious_adverse_event: Mapped[YNU]
40
+ dose_limiting_toxicity: Mapped[YNU]
41
+ attribution_cause: Mapped[AttributionCause]
42
+ attribution_likelihood: Mapped[AttributionLikelihood]
43
+ individual_therapy: Mapped[str | None]
44
+
45
+ participant: Mapped[ParticipantORM] = relationship(back_populates="adverse_events", cascade="all, delete")
46
+ treatment: Mapped[TreatmentORM] = relationship(back_populates="adverse_events", cascade="all, delete")
@@ -0,0 +1,7 @@
1
+ from sqlalchemy_mixins import SerializeMixin, ReprMixin
2
+ from cidc_api.config.db import Stage1BaseModel, ModelMixin
3
+
4
+
5
+ class BaseORM(Stage1BaseModel, ModelMixin, ReprMixin, SerializeMixin):
6
+ __abstract__ = True
7
+ __repr__ = ReprMixin.__repr__
@@ -0,0 +1,22 @@
1
+ from __future__ import annotations
2
+ from sqlalchemy import ForeignKey
3
+ from sqlalchemy.orm import Mapped, mapped_column, relationship
4
+
5
+ from cidc_api.models.db.stage1.base_orm import BaseORM
6
+ from cidc_api.models.types import ECOGScore, KarnofskyScore
7
+
8
+
9
+ class BaselineClinicalAssessmentORM(BaseORM):
10
+ __tablename__ = "baseline_clinical_assessment"
11
+ __repr_attrs__ = ["baseline_clinical_assessment_id", "participant_id"]
12
+ __data_category__ = "baseline_clinical_assessment"
13
+
14
+ baseline_clinical_assessment_id: Mapped[int] = mapped_column(primary_key=True)
15
+ participant_id: Mapped[int] = mapped_column(ForeignKey("stage1.participant.participant_id", ondelete="CASCADE"))
16
+
17
+ ecog_score: Mapped[ECOGScore | None]
18
+ karnofsky_score: Mapped[KarnofskyScore | None]
19
+
20
+ participant: Mapped[ParticipantORM] = relationship(
21
+ back_populates="baseline_clinical_assessment", cascade="all, delete"
22
+ )
@@ -0,0 +1,23 @@
1
+ from __future__ import annotations
2
+ from sqlalchemy import ForeignKey
3
+ from sqlalchemy.orm import Mapped, mapped_column, relationship
4
+
5
+ from cidc_api.models.db.stage1.base_orm import BaseORM
6
+ from cidc_api.models.types import ICD10CMCode, ICD10CMTerm
7
+
8
+
9
+ class ComorbidityORM(BaseORM):
10
+ __tablename__ = "comorbidity"
11
+ __repr_attrs__ = ["comorbidity_id", "comorbidity_term"]
12
+ __data_category__ = "comorbidity"
13
+
14
+ comorbidity_id: Mapped[int] = mapped_column(primary_key=True)
15
+ medical_history_id: Mapped[int] = mapped_column(
16
+ ForeignKey("stage1.medical_history.medical_history_id", ondelete="CASCADE")
17
+ )
18
+
19
+ comorbidity_code: Mapped[ICD10CMCode | None]
20
+ comorbidity_term: Mapped[ICD10CMTerm | None]
21
+ comorbidity_other: Mapped[str | None]
22
+
23
+ medical_history: Mapped[MedicalHistoryORM] = relationship(back_populates="comorbidities", cascade="all, delete")
@@ -0,0 +1,32 @@
1
+ from __future__ import annotations
2
+ from typing import List
3
+
4
+ from pydantic import NonNegativeInt
5
+ from sqlalchemy import ForeignKeyConstraint
6
+ from sqlalchemy.orm import Mapped, mapped_column, relationship
7
+
8
+ from cidc_api.models.db.stage1.base_orm import BaseORM
9
+
10
+
11
+ class ConsentGroupORM(BaseORM):
12
+ __tablename__ = "consent_group"
13
+ __repr_attrs__ = ["consent_group_id", "consent_group_name"]
14
+ __table_args__ = (
15
+ ForeignKeyConstraint(
16
+ ["trial_id", "version"], ["stage1.trial.trial_id", "stage1.trial.version"], ondelete="CASCADE"
17
+ ),
18
+ )
19
+ __data_category__ = "consent_group"
20
+
21
+ consent_group_id: Mapped[int] = mapped_column(primary_key=True)
22
+ trial_id: Mapped[str]
23
+ version: Mapped[str]
24
+
25
+ consent_group_short_name: Mapped[str]
26
+ consent_group_name: Mapped[str]
27
+ consent_group_number: Mapped[NonNegativeInt]
28
+
29
+ trial: Mapped[TrialORM] = relationship(back_populates="consent_groups", cascade="all, delete")
30
+ participants: Mapped[List[ParticipantORM]] = relationship(
31
+ back_populates="consent_group", cascade="all, delete", passive_deletes=True
32
+ )
@@ -0,0 +1,47 @@
1
+ from __future__ import annotations
2
+ from pydantic import NonNegativeFloat, PositiveFloat, PositiveInt
3
+ from typing import List
4
+
5
+ from sqlalchemy import ForeignKey
6
+ from sqlalchemy.orm import Mapped, mapped_column, relationship
7
+ from sqlalchemy.types import JSON
8
+
9
+ from cidc_api.models.db.stage1.base_orm import BaseORM
10
+ from cidc_api.models.types import (
11
+ Sex,
12
+ Race,
13
+ Ethnicity,
14
+ HeightUnits,
15
+ WeightUnits,
16
+ BodySurfaceAreaUnits,
17
+ Occupation,
18
+ Education,
19
+ AgeAtEnrollmentUnits,
20
+ )
21
+
22
+
23
+ class DemographicORM(BaseORM):
24
+ __tablename__ = "demographic"
25
+ __repr_attrs__ = ["demographic_id", "participant_id", "age_at_enrollment", "sex"]
26
+ __data_category__ = "demographic"
27
+
28
+ demographic_id: Mapped[int] = mapped_column(primary_key=True)
29
+ participant_id: Mapped[int] = mapped_column(ForeignKey("stage1.participant.participant_id", ondelete="CASCADE"))
30
+ age_at_enrollment: Mapped[PositiveInt | None]
31
+ age_at_enrollment_units: Mapped[AgeAtEnrollmentUnits | None]
32
+ age_90_or_over: Mapped[bool]
33
+ sex: Mapped[Sex]
34
+ race: Mapped[List[Race]] = mapped_column(JSON)
35
+ ethnicity: Mapped[Ethnicity]
36
+ height: Mapped[PositiveFloat]
37
+ height_units: Mapped[HeightUnits]
38
+ weight: Mapped[PositiveFloat]
39
+ weight_units: Mapped[WeightUnits]
40
+ body_mass_index: Mapped[PositiveFloat | None]
41
+ body_surface_area: Mapped[PositiveFloat | None]
42
+ body_surface_area_units: Mapped[BodySurfaceAreaUnits | None]
43
+ occupation: Mapped[Occupation | None]
44
+ income: Mapped[NonNegativeFloat | None]
45
+ highest_level_of_education: Mapped[Education | None]
46
+
47
+ participant: Mapped[ParticipantORM] = relationship(back_populates="demographic", cascade="all, delete")
@@ -0,0 +1,52 @@
1
+ from __future__ import annotations
2
+ from typing import List
3
+
4
+ from pydantic import NonPositiveInt
5
+ from sqlalchemy import ForeignKey
6
+ from sqlalchemy.orm import Mapped, mapped_column, relationship
7
+ from sqlalchemy.types import JSON
8
+
9
+ from cidc_api.models.db.stage1.base_orm import BaseORM
10
+ from cidc_api.models.types import (
11
+ TumorGrade,
12
+ CancerStageSystem,
13
+ CancerStageSystemVersion,
14
+ CancerStage,
15
+ TCategory,
16
+ NCategory,
17
+ MCategory,
18
+ UberonAnatomicalTerm,
19
+ ICDO3MorphologicalCode,
20
+ ICDO3MorphologicalTerm,
21
+ YNU,
22
+ )
23
+ from sqlalchemy import String
24
+
25
+
26
+ class DiseaseORM(BaseORM):
27
+ __tablename__ = "disease"
28
+ __repr_attrs__ = [
29
+ "disease_id",
30
+ "participant_id",
31
+ ]
32
+ __data_category__ = "disease"
33
+
34
+ disease_id: Mapped[int] = mapped_column(primary_key=True)
35
+ participant_id: Mapped[int] = mapped_column(ForeignKey("stage1.participant.participant_id", ondelete="CASCADE"))
36
+ primary_disease_site: Mapped[UberonAnatomicalTerm]
37
+ morphological_code: Mapped[ICDO3MorphologicalCode | None]
38
+ morphological_term: Mapped[ICDO3MorphologicalTerm | None]
39
+ cancer_type_description: Mapped[str | None]
40
+ days_since_original_diagnosis: Mapped[NonPositiveInt | None]
41
+ tumor_grade: Mapped[TumorGrade | None]
42
+ cancer_stage_system: Mapped[CancerStageSystem]
43
+ cancer_stage_system_version: Mapped[CancerStageSystemVersion | None] = mapped_column(String, nullable=True)
44
+ cancer_stage: Mapped[CancerStage | None] = mapped_column(String)
45
+ t_category: Mapped[TCategory | None]
46
+ n_category: Mapped[NCategory | None]
47
+ m_category: Mapped[MCategory | None]
48
+ metastatic_organ: Mapped[List[UberonAnatomicalTerm] | None] = mapped_column(JSON, nullable=True)
49
+ solely_extramedullary_disease: Mapped[YNU]
50
+ extramedullary_organ: Mapped[List[UberonAnatomicalTerm]] = mapped_column(JSON, nullable=True)
51
+
52
+ participant: Mapped[ParticipantORM] = relationship(back_populates="diseases", cascade="all, delete")
@@ -0,0 +1,22 @@
1
+ from __future__ import annotations
2
+ from typing import List
3
+
4
+ from sqlalchemy import ForeignKey
5
+ from sqlalchemy.orm import Mapped, mapped_column, relationship
6
+
7
+ from cidc_api.models.db.stage1.base_orm import BaseORM
8
+ from cidc_api.models.types import YNU, ExposureType
9
+
10
+
11
+ class ExposureORM(BaseORM):
12
+ __tablename__ = "exposure"
13
+ __repr_attrs__ = ["exposure_id", "exposure_type", "carcinogen_exposure"]
14
+ __data_category__ = "exposure"
15
+
16
+ exposure_id: Mapped[int] = mapped_column(primary_key=True)
17
+ participant_id: Mapped[int] = mapped_column(ForeignKey("stage1.participant.participant_id", ondelete="CASCADE"))
18
+
19
+ carcinogen_exposure: Mapped[YNU]
20
+ exposure_type: Mapped[ExposureType | None]
21
+
22
+ participant: Mapped[ParticipantORM] = relationship(back_populates="exposures", cascade="all, delete")
@@ -0,0 +1,34 @@
1
+ from __future__ import annotations
2
+ from typing import List
3
+
4
+ from sqlalchemy import ForeignKey, UniqueConstraint
5
+ from sqlalchemy.orm import Mapped, mapped_column, relationship
6
+
7
+ from cidc_api.models.db.stage1.base_orm import BaseORM
8
+ from cidc_api.models.types import (
9
+ GVHDDiagnosisAcuteAssessmentSystem,
10
+ GVHDDiagnosisAcuteAssessmentSystemVersion,
11
+ GVHDDiagnosisAcuteGrade,
12
+ PreOrPostEnrollment,
13
+ )
14
+
15
+
16
+ class GVHDDiagnosisAcuteORM(BaseORM):
17
+ __tablename__ = "gvhd_diagnosis_acute"
18
+ __table_args__ = (
19
+ UniqueConstraint("participant_id", "pre_or_post_enrollment", name="unique_ix_gvhd_diagnosis_acute_pre_or_post"),
20
+ )
21
+ __repr_attrs__ = ["gvhd_diagnosis_acute_id", "pre_or_post_enrollment"]
22
+ __data_category__ = "gvhd_diagnosis_acute"
23
+
24
+ gvhd_diagnosis_acute_id: Mapped[int] = mapped_column(primary_key=True)
25
+ participant_id: Mapped[int] = mapped_column(ForeignKey("stage1.participant.participant_id", ondelete="CASCADE"))
26
+ acute_assessment_system: Mapped[GVHDDiagnosisAcuteAssessmentSystem]
27
+ system_version: Mapped[GVHDDiagnosisAcuteAssessmentSystemVersion]
28
+ acute_grade: Mapped[GVHDDiagnosisAcuteGrade]
29
+ pre_or_post_enrollment: Mapped[PreOrPostEnrollment]
30
+
31
+ participant: Mapped[ParticipantORM] = relationship(back_populates="gvhd_diagnosis_acutes", cascade="all, delete")
32
+ organs: Mapped[List[GVHDOrganAcuteORM]] = relationship(
33
+ back_populates="diagnosis", cascade="all, delete", passive_deletes=True
34
+ )
@@ -0,0 +1,36 @@
1
+ from __future__ import annotations
2
+ from typing import List
3
+
4
+ from sqlalchemy import ForeignKey, UniqueConstraint
5
+ from sqlalchemy.orm import Mapped, mapped_column, relationship
6
+
7
+ from cidc_api.models.db.stage1.base_orm import BaseORM
8
+ from cidc_api.models.types import (
9
+ GVHDDiagnosisChronicAssessmentSystem,
10
+ GVHDDiagnosisChronicAssessmentSystemVersion,
11
+ GVHDDiagnosisChronicGlobalSeverity,
12
+ PreOrPostEnrollment,
13
+ )
14
+
15
+
16
+ class GVHDDiagnosisChronicORM(BaseORM):
17
+ __tablename__ = "gvhd_diagnosis_chronic"
18
+ __table_args__ = (
19
+ UniqueConstraint(
20
+ "participant_id", "pre_or_post_enrollment", name="unique_ix_gvhd_diagnosis_chronic_pre_or_post"
21
+ ),
22
+ )
23
+ __repr_attrs__ = ["gvhd_diagnosis_chronic_id", "pre_or_post_enrollment"]
24
+ __data_category__ = "gvhd_diagnosis_chronic"
25
+
26
+ gvhd_diagnosis_chronic_id: Mapped[int] = mapped_column(primary_key=True)
27
+ participant_id: Mapped[int] = mapped_column(ForeignKey("stage1.participant.participant_id", ondelete="CASCADE"))
28
+ chronic_assessment_system: Mapped[GVHDDiagnosisChronicAssessmentSystem]
29
+ system_version: Mapped[GVHDDiagnosisChronicAssessmentSystemVersion]
30
+ chronic_global_severity: Mapped[GVHDDiagnosisChronicGlobalSeverity]
31
+ pre_or_post_enrollment: Mapped[PreOrPostEnrollment]
32
+
33
+ participant: Mapped[ParticipantORM] = relationship(back_populates="gvhd_diagnosis_chronics", cascade="all, delete")
34
+ organs: Mapped[List[GVHDOrganChronicORM]] = relationship(
35
+ back_populates="diagnosis", cascade="all, delete", passive_deletes=True
36
+ )
@@ -0,0 +1,21 @@
1
+ from __future__ import annotations
2
+ from sqlalchemy import ForeignKey
3
+ from sqlalchemy.orm import Mapped, mapped_column, relationship
4
+
5
+ from cidc_api.models.db.stage1.base_orm import BaseORM
6
+ from cidc_api.models.types import GVHDOrgan, GVHDOrganAcuteStage
7
+
8
+
9
+ class GVHDOrganAcuteORM(BaseORM):
10
+ __tablename__ = "gvhd_organ_acute"
11
+ __repr_attrs__ = ["gvhd_organ_acute_id", "organ"]
12
+ __data_category__ = "gvhd_organ_acute"
13
+
14
+ gvhd_organ_acute_id: Mapped[int] = mapped_column(primary_key=True)
15
+ gvhd_diagnosis_acute_id: Mapped[int] = mapped_column(
16
+ ForeignKey("stage1.gvhd_diagnosis_acute.gvhd_diagnosis_acute_id", ondelete="CASCADE")
17
+ )
18
+ organ: Mapped[GVHDOrgan]
19
+ acute_stage: Mapped[GVHDOrganAcuteStage]
20
+
21
+ diagnosis: Mapped[GVHDDiagnosisAcuteORM] = relationship(back_populates="organs", cascade="all, delete")
@@ -0,0 +1,21 @@
1
+ from __future__ import annotations
2
+ from sqlalchemy import ForeignKey
3
+ from sqlalchemy.orm import Mapped, mapped_column, relationship
4
+
5
+ from cidc_api.models.db.stage1.base_orm import BaseORM
6
+ from cidc_api.models.types import GVHDOrgan, GVHDOrganChronicScore
7
+
8
+
9
+ class GVHDOrganChronicORM(BaseORM):
10
+ __tablename__ = "gvhd_organ_chronic"
11
+ __repr_attrs__ = ["gvhd_organ_chronic_id", "organ"]
12
+ __data_category__ = "gvhd_organ_chronic"
13
+
14
+ gvhd_organ_chronic_id: Mapped[int] = mapped_column(primary_key=True)
15
+ gvhd_diagnosis_chronic_id: Mapped[int] = mapped_column(
16
+ ForeignKey("stage1.gvhd_diagnosis_chronic.gvhd_diagnosis_chronic_id", ondelete="CASCADE")
17
+ )
18
+ organ: Mapped[GVHDOrgan]
19
+ chronic_score: Mapped[GVHDOrganChronicScore]
20
+
21
+ diagnosis: Mapped[GVHDDiagnosisChronicORM] = relationship(back_populates="organs", cascade="all, delete")
@@ -0,0 +1,30 @@
1
+ from __future__ import annotations
2
+ from typing import List
3
+
4
+ from pydantic import NonNegativeInt, PositiveFloat
5
+ from sqlalchemy import ForeignKey
6
+ from sqlalchemy.orm import Mapped, mapped_column, relationship
7
+
8
+ from cidc_api.models.db.stage1.base_orm import BaseORM
9
+ from cidc_api.models.types import TobaccoSmokingStatus
10
+
11
+
12
+ class MedicalHistoryORM(BaseORM):
13
+ __tablename__ = "medical_history"
14
+ __repr_attrs__ = ["medical_history_id"]
15
+ __data_category__ = "medical_history"
16
+
17
+ medical_history_id: Mapped[int] = mapped_column(primary_key=True)
18
+ participant_id: Mapped[int] = mapped_column(ForeignKey("stage1.participant.participant_id", ondelete="CASCADE"))
19
+
20
+ tobacco_smoking_status: Mapped[TobaccoSmokingStatus | None]
21
+ pack_years_smoked: Mapped[PositiveFloat | None]
22
+ num_prior_systemic_therapies: Mapped[NonNegativeInt | None]
23
+
24
+ participant: Mapped[ParticipantORM] = relationship(back_populates="medical_history", cascade="all, delete")
25
+ other_malignancies: Mapped[List[OtherMalignancyORM]] = relationship(
26
+ back_populates="medical_history", cascade="all, delete", passive_deletes=True
27
+ )
28
+ comorbidities: Mapped[List[ComorbidityORM]] = relationship(
29
+ back_populates="medical_history", cascade="all, delete", passive_deletes=True
30
+ )
@@ -0,0 +1,29 @@
1
+ from __future__ import annotations
2
+ from pydantic import NonPositiveInt
3
+ from sqlalchemy import ForeignKey
4
+ from sqlalchemy.orm import Mapped, mapped_column, relationship
5
+
6
+ from cidc_api.models.db.stage1.base_orm import BaseORM
7
+ from cidc_api.models.types import UberonAnatomicalTerm, ICDO3MorphologicalCode, ICDO3MorphologicalTerm, MalignancyStatus
8
+
9
+
10
+ class OtherMalignancyORM(BaseORM):
11
+ __tablename__ = "other_malignancy"
12
+ __repr_attrs__ = ["other_malignancy_id", "primary_disease_site"]
13
+ __data_category__ = "other_malignancy"
14
+
15
+ other_malignancy_id: Mapped[int] = mapped_column(primary_key=True)
16
+ medical_history_id: Mapped[int] = mapped_column(
17
+ ForeignKey("stage1.medical_history.medical_history_id", ondelete="CASCADE")
18
+ )
19
+
20
+ other_malignancy_primary_disease_site: Mapped[UberonAnatomicalTerm]
21
+ other_malignancy_morphological_code: Mapped[ICDO3MorphologicalCode | None]
22
+ other_malignancy_morphological_term: Mapped[ICDO3MorphologicalTerm | None]
23
+ other_malignancy_description: Mapped[str | None]
24
+ other_malignancy_days_since_diagnosis: Mapped[NonPositiveInt | None]
25
+ other_malignancy_status: Mapped[MalignancyStatus | None]
26
+
27
+ medical_history: Mapped[MedicalHistoryORM] = relationship(
28
+ back_populates="other_malignancies", cascade="all, delete"
29
+ )