nci-cidc-api-modules 1.2.54__py3-none-any.whl → 1.2.56__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.
- boot.py +8 -0
- cidc_api/__init__.py +1 -1
- cidc_api/models/dataset.py +80 -0
- cidc_api/models/db/stage1/additional_treatment_orm.py +8 -1
- cidc_api/models/db/stage1/adverse_event_orm.py +8 -1
- cidc_api/models/db/stage1/baseline_clinical_assessment_orm.py +8 -1
- cidc_api/models/db/stage1/comorbidity_orm.py +8 -1
- cidc_api/models/db/stage1/consent_group_orm.py +6 -6
- cidc_api/models/db/stage1/demographic_orm.py +8 -1
- cidc_api/models/db/stage1/disease_orm.py +8 -1
- cidc_api/models/db/stage1/exposure_orm.py +8 -1
- cidc_api/models/db/stage1/gvhd_diagnosis_acute_orm.py +8 -3
- cidc_api/models/db/stage1/gvhd_diagnosis_chronic_orm.py +8 -3
- cidc_api/models/db/stage1/gvhd_organ_acute_orm.py +8 -1
- cidc_api/models/db/stage1/gvhd_organ_chronic_orm.py +8 -1
- cidc_api/models/db/stage1/medical_history_orm.py +8 -1
- cidc_api/models/db/stage1/other_malignancy_orm.py +8 -1
- cidc_api/models/db/stage1/participant_orm.py +4 -5
- cidc_api/models/db/stage1/prior_treatment_orm.py +8 -2
- cidc_api/models/db/stage1/radiotherapy_dose_orm.py +8 -1
- cidc_api/models/db/stage1/response_by_system_orm.py +8 -1
- cidc_api/models/db/stage1/response_orm.py +9 -2
- cidc_api/models/db/stage1/specimen_orm.py +9 -25
- cidc_api/models/db/stage1/stem_cell_transplant_orm.py +8 -1
- cidc_api/models/db/stage1/surgery_orm.py +8 -1
- cidc_api/models/db/stage1/therapy_agent_dose_orm.py +8 -1
- cidc_api/models/db/stage1/treatment_orm.py +8 -1
- cidc_api/models/db/stage1/trial_orm.py +1 -2
- cidc_api/models/db/stage2/additional_treatment_orm.py +8 -1
- cidc_api/models/db/stage2/administrative_person_orm.py +8 -1
- cidc_api/models/db/stage2/administrative_role_assignment_orm.py +1 -0
- cidc_api/models/db/stage2/adverse_event_orm.py +8 -1
- cidc_api/models/db/stage2/arm_orm.py +5 -4
- cidc_api/models/db/stage2/baseline_clinical_assessment_orm.py +8 -1
- cidc_api/models/db/stage2/cohort_orm.py +5 -4
- cidc_api/models/db/stage2/comorbidity_orm.py +8 -1
- cidc_api/models/db/stage2/consent_group_orm.py +5 -5
- cidc_api/models/db/stage2/contact_orm.py +10 -1
- cidc_api/models/db/stage2/demographic_orm.py +8 -1
- cidc_api/models/db/stage2/disease_orm.py +8 -1
- cidc_api/models/db/stage2/exposure_orm.py +8 -1
- cidc_api/models/db/stage2/file_orm.py +4 -4
- cidc_api/models/db/stage2/gvhd_diagnosis_acute_orm.py +8 -3
- cidc_api/models/db/stage2/gvhd_diagnosis_chronic_orm.py +8 -3
- cidc_api/models/db/stage2/gvhd_organ_acute_orm.py +8 -1
- cidc_api/models/db/stage2/gvhd_organ_chronic_orm.py +8 -1
- cidc_api/models/db/stage2/institution_orm.py +4 -4
- cidc_api/models/db/stage2/medical_history_orm.py +8 -1
- cidc_api/models/db/stage2/other_clinical_endpoint_orm.py +9 -1
- cidc_api/models/db/stage2/other_malignancy_orm.py +8 -1
- cidc_api/models/db/stage2/participant_orm.py +6 -6
- cidc_api/models/db/stage2/prior_treatment_orm.py +9 -3
- cidc_api/models/db/stage2/publication_orm.py +5 -4
- cidc_api/models/db/stage2/radiotherapy_dose_orm.py +9 -2
- cidc_api/models/db/stage2/response_by_system_orm.py +8 -1
- cidc_api/models/db/stage2/response_orm.py +9 -2
- cidc_api/models/db/stage2/shipment_orm.py +5 -5
- cidc_api/models/db/stage2/shipment_specimen_orm.py +8 -2
- cidc_api/models/db/stage2/specimen_orm.py +9 -75
- cidc_api/models/db/stage2/stem_cell_transplant_orm.py +8 -1
- cidc_api/models/db/stage2/surgery_orm.py +8 -1
- cidc_api/models/db/stage2/therapy_agent_dose_orm.py +8 -1
- cidc_api/models/db/stage2/treatment_orm.py +8 -1
- cidc_api/models/db/stage2/trial_orm.py +1 -2
- cidc_api/models/pydantic/stage1/response_by_system.py +62 -0
- cidc_api/models/pydantic/stage1/trial.py +1 -1
- cidc_api/models/pydantic/stage2/adverse_event.py +52 -25
- cidc_api/models/pydantic/stage2/comorbidity.py +15 -8
- cidc_api/models/pydantic/stage2/demographic.py +45 -28
- cidc_api/models/pydantic/stage2/disease.py +100 -58
- cidc_api/models/pydantic/stage2/exposure.py +14 -8
- cidc_api/models/pydantic/stage2/medical_history.py +15 -8
- cidc_api/models/pydantic/stage2/other_malignancy.py +17 -11
- cidc_api/models/pydantic/stage2/participant.py +27 -15
- cidc_api/models/pydantic/stage2/prior_treatment.py +2 -0
- cidc_api/models/pydantic/stage2/radiotherapy_dose.py +27 -14
- cidc_api/models/pydantic/stage2/response.py +42 -23
- cidc_api/models/pydantic/stage2/response_by_system.py +138 -30
- cidc_api/models/pydantic/stage2/specimen.py +2 -185
- cidc_api/models/pydantic/stage2/surgery.py +15 -7
- cidc_api/models/pydantic/stage2/therapy_agent_dose.py +27 -14
- cidc_api/models/pydantic/stage2/treatment.py +30 -16
- cidc_api/telemetry.py +13 -13
- {nci_cidc_api_modules-1.2.54.dist-info → nci_cidc_api_modules-1.2.56.dist-info}/METADATA +1 -1
- nci_cidc_api_modules-1.2.56.dist-info/RECORD +163 -0
- cidc_api/models/data.py +0 -28
- nci_cidc_api_modules-1.2.54.dist-info/RECORD +0 -163
- {nci_cidc_api_modules-1.2.54.dist-info → nci_cidc_api_modules-1.2.56.dist-info}/WHEEL +0 -0
- {nci_cidc_api_modules-1.2.54.dist-info → nci_cidc_api_modules-1.2.56.dist-info}/licenses/LICENSE +0 -0
- {nci_cidc_api_modules-1.2.54.dist-info → nci_cidc_api_modules-1.2.56.dist-info}/top_level.txt +0 -0
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
from
|
|
2
|
-
|
|
3
|
-
from pydantic import NonNegativeInt, NonNegativeFloat, model_validator
|
|
1
|
+
from pydantic import NonNegativeInt, NonNegativeFloat
|
|
2
|
+
from cidc_api.models.pydantic.base import forced_validator, forced_validators
|
|
4
3
|
|
|
4
|
+
from cidc_api.models.errors import ValueLocError
|
|
5
5
|
from cidc_api.models.pydantic.base import Base
|
|
6
6
|
from cidc_api.models.types import (
|
|
7
7
|
YN,
|
|
@@ -13,6 +13,7 @@ from cidc_api.models.types import (
|
|
|
13
13
|
)
|
|
14
14
|
|
|
15
15
|
|
|
16
|
+
@forced_validators
|
|
16
17
|
class RadiotherapyDose(Base):
|
|
17
18
|
__data_category__ = "radiotherapy_dose"
|
|
18
19
|
__cardinality__ = "many"
|
|
@@ -67,14 +68,26 @@ class RadiotherapyDose(Base):
|
|
|
67
68
|
# CDE: https://cadsr.cancer.gov/onedata/dmdirect/NIH/NCI/CO/CDEDD?filter=CDEDD.ITEM_ID=7063755%20and%20ver_nr=1
|
|
68
69
|
radiation_extent: RadiationExtent
|
|
69
70
|
|
|
70
|
-
@
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
71
|
+
@forced_validator
|
|
72
|
+
@classmethod
|
|
73
|
+
def validate_changes_delays_description_cr(cls, data, info) -> None:
|
|
74
|
+
dose_changes_delays = data.get("dose_changes_delays", None)
|
|
75
|
+
changes_delays_description = data.get("changes_delays_description", None)
|
|
76
|
+
|
|
77
|
+
if dose_changes_delays == "Yes" and not changes_delays_description:
|
|
78
|
+
raise ValueLocError(
|
|
79
|
+
'If dose_changes_delays is "Yes", please provide changes_delays_description.',
|
|
80
|
+
loc="changes_delays_description",
|
|
81
|
+
)
|
|
82
|
+
|
|
83
|
+
@forced_validator
|
|
84
|
+
@classmethod
|
|
85
|
+
def validate_planned_dose_units_cr(cls, data, info) -> None:
|
|
86
|
+
planned_dose = data.get("planned_dose", None)
|
|
87
|
+
planned_dose_units = data.get("planned_dose_units", None)
|
|
88
|
+
|
|
89
|
+
if planned_dose and not planned_dose_units:
|
|
90
|
+
raise ValueLocError(
|
|
91
|
+
"If planned_dose is provided, please provide planned_dose_units.",
|
|
92
|
+
loc="planned_dose_units",
|
|
93
|
+
)
|
|
@@ -1,11 +1,12 @@
|
|
|
1
|
-
from
|
|
2
|
-
|
|
3
|
-
from pydantic import NonNegativeInt, model_validator
|
|
1
|
+
from pydantic import NonNegativeInt
|
|
2
|
+
from cidc_api.models.pydantic.base import forced_validator, forced_validators
|
|
4
3
|
|
|
4
|
+
from cidc_api.models.errors import ValueLocError
|
|
5
5
|
from cidc_api.models.pydantic.base import Base
|
|
6
|
-
from cidc_api.models.types import SurvivalStatus,
|
|
6
|
+
from cidc_api.models.types import SurvivalStatus, YNUNA, YN, CauseOfDeath
|
|
7
7
|
|
|
8
8
|
|
|
9
|
+
@forced_validators
|
|
9
10
|
class Response(Base):
|
|
10
11
|
__data_category__ = "response"
|
|
11
12
|
__cardinality__ = "one"
|
|
@@ -44,22 +45,40 @@ class Response(Base):
|
|
|
44
45
|
evaluable_for_efficacy: YN
|
|
45
46
|
|
|
46
47
|
# Days from enrollment date to the last time the patient's vital status was verified.
|
|
47
|
-
days_to_last_vital_status: NonNegativeInt | None = None
|
|
48
|
-
|
|
49
|
-
@
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
@
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
48
|
+
days_to_last_vital_status: NonNegativeInt | None = None
|
|
49
|
+
|
|
50
|
+
@forced_validator
|
|
51
|
+
@classmethod
|
|
52
|
+
def validate_cause_of_death_cr(cls, data, info) -> None:
|
|
53
|
+
survival_status = data.get("survival_status", None)
|
|
54
|
+
cause_of_death = data.get("cause_of_death", None)
|
|
55
|
+
|
|
56
|
+
if survival_status == "Dead" and not cause_of_death:
|
|
57
|
+
raise ValueLocError(
|
|
58
|
+
'If survival_status is "Dead" then cause_of_death is required.',
|
|
59
|
+
loc="cause_of_death",
|
|
60
|
+
)
|
|
61
|
+
|
|
62
|
+
@forced_validator
|
|
63
|
+
@classmethod
|
|
64
|
+
def validate_cause_of_death_cr2(cls, data, info) -> None:
|
|
65
|
+
survival_status = data.get("survival_status", None)
|
|
66
|
+
cause_of_death = data.get("cause_of_death", None)
|
|
67
|
+
|
|
68
|
+
if survival_status == "Alive" and cause_of_death:
|
|
69
|
+
raise ValueLocError(
|
|
70
|
+
'If survival_status is "Alive", please leave cause_of_death blank.',
|
|
71
|
+
loc="cause_of_death",
|
|
72
|
+
)
|
|
73
|
+
|
|
74
|
+
@forced_validator
|
|
75
|
+
@classmethod
|
|
76
|
+
def validate_days_to_death_cr(cls, data, info) -> None:
|
|
77
|
+
survival_status = data.get("survival_status", None)
|
|
78
|
+
days_to_death = data.get("days_to_death", None)
|
|
79
|
+
|
|
80
|
+
if survival_status in ["Alive", "Unknown"] and days_to_death:
|
|
81
|
+
raise ValueLocError(
|
|
82
|
+
"If survival_status does not indicate death, please leave days_to_death blank.",
|
|
83
|
+
loc="days_to_death",
|
|
84
|
+
)
|
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
from typing import Self
|
|
2
2
|
|
|
3
|
-
from pydantic import PositiveInt,
|
|
3
|
+
from pydantic import PositiveInt, NonNegativeInt, model_validator
|
|
4
|
+
from cidc_api.models.pydantic.base import forced_validator, forced_validators
|
|
4
5
|
|
|
6
|
+
from cidc_api.models.errors import ValueLocError
|
|
5
7
|
from cidc_api.models.pydantic.base import Base
|
|
8
|
+
from cidc_api.models.pydantic.stage1.response import Response
|
|
6
9
|
from cidc_api.models.types import ResponseSystem, ResponseSystemVersion, BestOverallResponse, YNUNA, YN
|
|
7
10
|
|
|
8
11
|
|
|
@@ -17,6 +20,7 @@ negative_response_values = [
|
|
|
17
20
|
]
|
|
18
21
|
|
|
19
22
|
|
|
23
|
+
@forced_validators
|
|
20
24
|
class ResponseBySystem(Base):
|
|
21
25
|
__data_category__ = "response_by_system"
|
|
22
26
|
__cardinality__ = "many"
|
|
@@ -28,6 +32,9 @@ class ResponseBySystem(Base):
|
|
|
28
32
|
# CDE: https://cadsr.cancer.gov/onedata/dmdirect/NIH/NCI/CO/CDEDD?filter=CDEDD.ITEM_ID=12220014%20and%20ver_nr=1
|
|
29
33
|
participant_id: str | None = None
|
|
30
34
|
|
|
35
|
+
# The linked parent response for the participant. Used for cross-model validation.
|
|
36
|
+
response: Response | None = None
|
|
37
|
+
|
|
31
38
|
# A standardized method used to evaluate and categorize the participant’s clinical response to treatment based on predefined criteria.
|
|
32
39
|
# CDE: https://cadsr.cancer.gov/onedata/dmdirect/NIH/NCI/CO/CDEDD?filter=CDEDD.ITEM_ID=13381490%20and%20ver_nr=1
|
|
33
40
|
response_system: ResponseSystem
|
|
@@ -66,47 +73,148 @@ class ResponseBySystem(Base):
|
|
|
66
73
|
# CDE: https://cadsr.cancer.gov/onedata/dmdirect/NIH/NCI/CO/CDEDD?filter=CDEDD.ITEM_ID=5143957%20and%20ver_nr=1
|
|
67
74
|
progression_free_survival: PositiveInt | None = None
|
|
68
75
|
|
|
69
|
-
@
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
76
|
+
@forced_validator
|
|
77
|
+
@classmethod
|
|
78
|
+
def validate_response_duration_cr(cls, data, info) -> None:
|
|
79
|
+
best_overall_response = data.get("best_overall_response", None)
|
|
80
|
+
response_duration = data.get("response_duration", None)
|
|
81
|
+
|
|
82
|
+
if best_overall_response in negative_response_values and response_duration:
|
|
83
|
+
raise ValueLocError(
|
|
73
84
|
"If best_overall_response does not indicate a positive response, "
|
|
74
|
-
"please leave response_duration blank."
|
|
85
|
+
"please leave response_duration blank.",
|
|
86
|
+
loc="response_duration",
|
|
75
87
|
)
|
|
76
|
-
return self
|
|
77
88
|
|
|
78
|
-
@
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
89
|
+
@forced_validator
|
|
90
|
+
@classmethod
|
|
91
|
+
def validate_days_to_first_response_cr(cls, data, info) -> None:
|
|
92
|
+
best_overall_response = data.get("best_overall_response", None)
|
|
93
|
+
days_to_first_response = data.get("days_to_first_response", None)
|
|
94
|
+
|
|
95
|
+
if best_overall_response in negative_response_values and days_to_first_response:
|
|
96
|
+
raise ValueLocError(
|
|
82
97
|
"If best_overall_response does not indicate a positive response, "
|
|
83
|
-
"please leave days_to_first_response blank."
|
|
98
|
+
"please leave days_to_first_response blank.",
|
|
99
|
+
loc="days_to_first_response",
|
|
84
100
|
)
|
|
85
|
-
return self
|
|
86
101
|
|
|
87
|
-
@
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
102
|
+
@forced_validator
|
|
103
|
+
@classmethod
|
|
104
|
+
def validate_days_to_best_response_cr(cls, data, info) -> None:
|
|
105
|
+
best_overall_response = data.get("best_overall_response", None)
|
|
106
|
+
days_to_best_response = data.get("days_to_best_response", None)
|
|
107
|
+
|
|
108
|
+
if best_overall_response in negative_response_values and days_to_best_response:
|
|
109
|
+
raise ValueLocError(
|
|
110
|
+
"If best_overall_response does not indicate a positive response, "
|
|
111
|
+
"please leave days_to_best_response blank.",
|
|
112
|
+
loc="days_to_best_response",
|
|
93
113
|
)
|
|
94
|
-
|
|
114
|
+
|
|
115
|
+
@forced_validator
|
|
116
|
+
@classmethod
|
|
117
|
+
def validate_days_to_disease_progression_cr(cls, data, info) -> None:
|
|
118
|
+
progression = data.get("progression", None)
|
|
119
|
+
days_to_disease_progression = data.get("days_to_disease_progression", None)
|
|
120
|
+
|
|
121
|
+
if progression in ["No", "Unknown", "Not Applicable"] and days_to_disease_progression:
|
|
122
|
+
raise ValueLocError(
|
|
123
|
+
"If progression does not indicate confirmed progression of the disease, "
|
|
124
|
+
"please leave days_to_disease_progression blank.",
|
|
125
|
+
loc="days_to_disease_progression",
|
|
126
|
+
)
|
|
127
|
+
|
|
128
|
+
@forced_validator
|
|
129
|
+
@classmethod
|
|
130
|
+
def validate_progression_free_survival_cr(cls, data, info) -> None:
|
|
131
|
+
progression_free_survival_event = data.get("progression_free_survival_event", None)
|
|
132
|
+
progression_free_survival = data.get("progression_free_survival", None)
|
|
133
|
+
|
|
134
|
+
if progression_free_survival_event in ["Unknown", "Not Applicable"] and progression_free_survival:
|
|
135
|
+
raise ValueLocError(
|
|
136
|
+
"If progression_free_survival_event is not known, " "please leave progression_free_survival blank.",
|
|
137
|
+
loc="progression_free_survival",
|
|
138
|
+
)
|
|
139
|
+
|
|
140
|
+
@forced_validator
|
|
141
|
+
@classmethod
|
|
142
|
+
def validate_days_to_best_response_chronology(cls, data, info) -> None:
|
|
143
|
+
days_to_first_response = data.get("days_to_first_response", None)
|
|
144
|
+
days_to_best_response = data.get("days_to_best_response", None)
|
|
145
|
+
|
|
146
|
+
if days_to_best_response is not None and days_to_first_response is not None:
|
|
147
|
+
if int(days_to_best_response) < int(days_to_first_response):
|
|
148
|
+
raise ValueLocError(
|
|
149
|
+
'Violate "days_to_best_response" >= days_to_first_response"',
|
|
150
|
+
loc="days_to_best_response",
|
|
151
|
+
)
|
|
152
|
+
|
|
153
|
+
@forced_validator
|
|
154
|
+
@classmethod
|
|
155
|
+
def validate_days_to_disease_progression_chronology(cls, data, info) -> None:
|
|
156
|
+
days_to_disease_progression = data.get("days_to_disease_progression", None)
|
|
157
|
+
days_to_first_response = data.get("days_to_first_response", None)
|
|
158
|
+
|
|
159
|
+
if days_to_first_response is not None and days_to_disease_progression is not None:
|
|
160
|
+
if int(days_to_first_response) >= int(days_to_disease_progression):
|
|
161
|
+
raise ValueLocError(
|
|
162
|
+
'Violate "days_to_first_response" < "days_to_disease_progression"',
|
|
163
|
+
loc="days_to_first_response",
|
|
164
|
+
)
|
|
165
|
+
|
|
166
|
+
@forced_validator
|
|
167
|
+
@classmethod
|
|
168
|
+
def validate_days_to_best_response_progression_chronology(cls, data, info) -> None:
|
|
169
|
+
days_to_disease_progression = data.get("days_to_disease_progression", None)
|
|
170
|
+
days_to_best_response = data.get("days_to_best_response", None)
|
|
171
|
+
|
|
172
|
+
if days_to_best_response is not None and days_to_disease_progression is not None:
|
|
173
|
+
if int(days_to_best_response) >= int(days_to_disease_progression):
|
|
174
|
+
raise ValueLocError(
|
|
175
|
+
'Violate "days_to_best_response" < "days_to_disease_progression"',
|
|
176
|
+
loc="days_to_best_response",
|
|
177
|
+
)
|
|
95
178
|
|
|
96
179
|
@model_validator(mode="after")
|
|
97
|
-
def
|
|
98
|
-
if
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
180
|
+
def validate_days_to_last_vital_status_chronology(self) -> Self:
|
|
181
|
+
if not self.response:
|
|
182
|
+
return self
|
|
183
|
+
|
|
184
|
+
if not self.response.days_to_last_vital_status:
|
|
185
|
+
return self
|
|
186
|
+
|
|
187
|
+
max_value = max(
|
|
188
|
+
self.response.days_to_last_vital_status or 0,
|
|
189
|
+
self.days_to_first_response or 0,
|
|
190
|
+
self.days_to_best_response or 0,
|
|
191
|
+
self.days_to_disease_progression or 0,
|
|
192
|
+
)
|
|
193
|
+
if (self.response.days_to_last_vital_status or 0) != max_value:
|
|
194
|
+
raise ValueLocError(
|
|
195
|
+
'"days_to_last_vital_status" is not the max of all events. Rule: days_to_last_vital_status '
|
|
196
|
+
">= max(days_to_first_response,days_to_best_response,days_to_disease_progression)",
|
|
197
|
+
loc="days_to_last_vital_status,days_to_first_response,days_to_best_response,days_to_disease_progression",
|
|
102
198
|
)
|
|
103
199
|
return self
|
|
104
200
|
|
|
105
201
|
@model_validator(mode="after")
|
|
106
|
-
def
|
|
107
|
-
if
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
202
|
+
def validate_days_to_death_chronology(self) -> Self:
|
|
203
|
+
if not self.response:
|
|
204
|
+
return self
|
|
205
|
+
if not self.response.days_to_death:
|
|
206
|
+
return self
|
|
207
|
+
|
|
208
|
+
max_value = max(
|
|
209
|
+
self.response.days_to_death or 0,
|
|
210
|
+
self.days_to_first_response or 0,
|
|
211
|
+
self.days_to_best_response or 0,
|
|
212
|
+
self.days_to_disease_progression or 0,
|
|
213
|
+
)
|
|
214
|
+
if (self.response.days_to_death or 0) != max_value:
|
|
215
|
+
raise ValueLocError(
|
|
216
|
+
'"days_to_death" is not the max of all events. Rule: days_to_death'
|
|
217
|
+
">= max(days_to_first_response,days_to_best_response,days_to_disease_progression)",
|
|
218
|
+
loc="days_to_death,days_to_first_response,days_to_best_response,days_to_disease_progression",
|
|
111
219
|
)
|
|
112
220
|
return self
|
|
@@ -1,32 +1,11 @@
|
|
|
1
1
|
from datetime import datetime
|
|
2
2
|
|
|
3
3
|
from cidc_api.models.pydantic.base import Base
|
|
4
|
-
from cidc_api.models.types import
|
|
5
|
-
UberonAnatomicalTerm,
|
|
6
|
-
ICDO3MorphologicalCode,
|
|
7
|
-
SpecimenType,
|
|
8
|
-
SpecimenDescription,
|
|
9
|
-
TumorType,
|
|
10
|
-
CollectionProcedure,
|
|
11
|
-
FixationStabilizationType,
|
|
12
|
-
PrimaryContainerType,
|
|
13
|
-
VolumeUnits,
|
|
14
|
-
ProcessedType,
|
|
15
|
-
ConcentrationUnits,
|
|
16
|
-
DerivativeType,
|
|
17
|
-
PBMCRestingPeriodUsed,
|
|
18
|
-
MaterialUnits,
|
|
19
|
-
MaterialStorageCondition,
|
|
20
|
-
QCCondition,
|
|
21
|
-
ReplacementRequested,
|
|
22
|
-
ResidualUse,
|
|
23
|
-
DiagnosisVerification,
|
|
24
|
-
AssayType,
|
|
25
|
-
)
|
|
4
|
+
from cidc_api.models.types import UberonAnatomicalTerm
|
|
26
5
|
|
|
27
6
|
|
|
28
7
|
class Specimen(Base):
|
|
29
|
-
|
|
8
|
+
__data_category__ = "specimen"
|
|
30
9
|
__cardinality__ = "many"
|
|
31
10
|
|
|
32
11
|
# The unique internal identifier for the specimen record
|
|
@@ -40,173 +19,11 @@ class Specimen(Base):
|
|
|
40
19
|
# Formatted as CTTTPPPSS.AA for trial code TTT, participant PPP, sample SS, and aliquot AA.
|
|
41
20
|
cimac_id: str
|
|
42
21
|
|
|
43
|
-
# The external identifier for the pathology report
|
|
44
|
-
surgical_pathology_report_id: str | None = None
|
|
45
|
-
|
|
46
|
-
# The external identifier for the clinical report
|
|
47
|
-
clinical_report_id: str | None = None
|
|
48
|
-
|
|
49
|
-
# The unique identifier for the specimen from which this specimen was derived
|
|
50
|
-
parent_specimen_id: str | None = None
|
|
51
|
-
|
|
52
|
-
# The unique identifier for the specimen after undergoing processing
|
|
53
|
-
processed_specimen_id: str | None = None
|
|
54
|
-
|
|
55
|
-
# The location within the body from which a specimen was originally obtained as captured in the Uberon anatomical term.
|
|
56
|
-
# CDE: https://cadsr.cancer.gov/onedata/dmdirect/NIH/NCI/CO/CDEDD?filter=CDEDD.ITEM_ID=12083894%20and%20ver_nr=1
|
|
57
|
-
organ_site_of_collection: UberonAnatomicalTerm | None = None
|
|
58
|
-
|
|
59
|
-
# ICD-O-3 code for histology and behavior. e.g. 9665/3"
|
|
60
|
-
# CDE: TBD
|
|
61
|
-
histology_behavior: ICDO3MorphologicalCode | None = None
|
|
62
|
-
|
|
63
|
-
# Histology description. e.g. Hodgkin lymphoma, nod. scler., grade 1",
|
|
64
|
-
histology_behavior_description: str | None = None
|
|
65
|
-
|
|
66
22
|
# Categorical description of timepoint at which the sample was taken.
|
|
67
23
|
# CDE: https://cadsr.cancer.gov/onedata/dmdirect/NIH/NCI/CO/CDEDD?filter=CDEDD.ITEM_ID=5899851%20and%20ver_nr=1
|
|
68
24
|
# Note: CIDC doesn't conform to this CDE's PVs
|
|
69
25
|
collection_event_name: str
|
|
70
26
|
|
|
71
|
-
# The type of the specimen
|
|
72
|
-
specimen_type: SpecimenType | None = None
|
|
73
|
-
|
|
74
|
-
# The type of the specimen, if not captured by specimen_type
|
|
75
|
-
specimen_type_other: str | None = None
|
|
76
|
-
|
|
77
|
-
# A general description of the specimen
|
|
78
|
-
specimen_description: SpecimenDescription | None = None
|
|
79
|
-
|
|
80
|
-
# The type of the tumor present in the specimen
|
|
81
|
-
tumor_type: TumorType | None = None
|
|
82
|
-
|
|
83
|
-
# Description of the procedure used to collect the specimen from the participant
|
|
84
|
-
collection_procedure: CollectionProcedure | None = None
|
|
85
|
-
|
|
86
|
-
# Description of the procedure used to collect the specimen from the participant, if not captured by collection_procedure
|
|
87
|
-
collection_procedure_other: str | None = None
|
|
88
|
-
|
|
89
|
-
# The biopsy core number from which the sample was taken.
|
|
90
|
-
core_number: str | None = None
|
|
91
|
-
|
|
92
|
-
# Type of specimen fixation or stabilization that was employed by the site directly after collection.
|
|
93
|
-
fixation_stabilization_type: FixationStabilizationType | None = None
|
|
94
|
-
|
|
95
|
-
# The type of container in which the specimen was shipped
|
|
96
|
-
primary_container_type: PrimaryContainerType | None = None
|
|
97
|
-
|
|
98
|
-
# The type of container in which the specimen was shipped, if not captured by primary_container_type
|
|
99
|
-
primary_container_type_other: str | None = None
|
|
100
|
-
|
|
101
|
-
# Volume of the specimen
|
|
102
|
-
volume: float | None = None
|
|
103
|
-
|
|
104
|
-
# The unit of measure of the volume of the specimen
|
|
105
|
-
volume_units: VolumeUnits | None = None
|
|
106
|
-
|
|
107
|
-
# The type of processing that was performed on the collected specimen by the biobank
|
|
108
|
-
processed_type: ProcessedType | None = None
|
|
109
|
-
|
|
110
|
-
# The volume of the specimen after being processed by the biobank
|
|
111
|
-
processed_volume: float | None = None
|
|
112
|
-
|
|
113
|
-
# The unit of measure of the volume of the specimen after being processed by the biobank
|
|
114
|
-
processed_volume_units: VolumeUnits | None = None
|
|
115
|
-
|
|
116
|
-
# The concentration of the sample after being processed by the biobank
|
|
117
|
-
processed_concentration: float | None = None
|
|
118
|
-
|
|
119
|
-
# The unit of measure of the concentration of the sample after being processed by the biobank
|
|
120
|
-
processed_concentration_units: ConcentrationUnits | None = None
|
|
121
|
-
|
|
122
|
-
# The quantity of the sample after being processed by the biobank
|
|
123
|
-
processed_quantity: float | None = None
|
|
124
|
-
|
|
125
|
-
# The type of the sample derivative
|
|
126
|
-
derivative_type: DerivativeType | None = None
|
|
127
|
-
|
|
128
|
-
# The volume of the sample derivative
|
|
129
|
-
derivative_volume: float | None = None
|
|
130
|
-
|
|
131
|
-
# The unit of measure of the volume of the sample derivative
|
|
132
|
-
derivative_volume_units: VolumeUnits | None = None
|
|
133
|
-
|
|
134
|
-
# The concentration of the sample derivative
|
|
135
|
-
derivative_concentration: float | None = None
|
|
136
|
-
|
|
137
|
-
# The unit of measure of the concentration of the sample derivative
|
|
138
|
-
derivative_concentration_units: ConcentrationUnits | None = None
|
|
139
|
-
|
|
140
|
-
# Score the percentage of tumor (including tumor bed) tissue area of the slide (e.g. vs non-malignant or normal tissue) (0-100)
|
|
141
|
-
tumor_tissue_total_area_percentage: float | None = None
|
|
142
|
-
|
|
143
|
-
# Score the percentage of viable tumor cells comprising the tumor bed area
|
|
144
|
-
viable_tumor_area_percentage: float | None = None
|
|
145
|
-
|
|
146
|
-
# Score the evaluation of stromal elements (this indicates the % area of tumor bed occupied by non-tumor cells,
|
|
147
|
-
# including inflammatory cells [lymphocytes, histiocytes, etc], endothelial cells, fibroblasts, etc)
|
|
148
|
-
viable_stroma_area_percentage: float | None = None
|
|
149
|
-
|
|
150
|
-
# Score the percentage area of necrosis
|
|
151
|
-
necrosis_area_percentage: float | None = None
|
|
152
|
-
|
|
153
|
-
# Score the percentage area of Fibrosis
|
|
154
|
-
fibrosis_area_percentage: float | None = None
|
|
155
|
-
|
|
156
|
-
# Provides a DNA Integrity Number as an indication of extraction quality (values of 1-10)
|
|
157
|
-
din: float | None = None
|
|
158
|
-
|
|
159
|
-
# Provides an absorbance percentage ratio indicating purity of DNA (values of 0 to 2)
|
|
160
|
-
a260_a280: float | None = None
|
|
161
|
-
|
|
162
|
-
# Provides an absorbance percentage ratio indicating presence of contaminants (values of 0 to 3)
|
|
163
|
-
a260_a230: float | None = None
|
|
164
|
-
|
|
165
|
-
# Receiving site determines the percent recovered cells that are viable after thawing.
|
|
166
|
-
pbmc_viability: float | None = None
|
|
167
|
-
|
|
168
|
-
# Receiving site determines number for PBMCs per vial recovered upon receipt.
|
|
169
|
-
pbmc_recovery: float | None = None
|
|
170
|
-
|
|
171
|
-
# Receiving site indicates if a resting period was used after PBMC recovery.
|
|
172
|
-
pbmc_resting_period_used: PBMCRestingPeriodUsed | None = None
|
|
173
|
-
|
|
174
|
-
# Receiving site indicates how much material was used for assay purposes.
|
|
175
|
-
material_used: float | None = None
|
|
176
|
-
|
|
177
|
-
# Unit of measure for the amount of material used
|
|
178
|
-
material_used_units: MaterialUnits | None = None
|
|
179
|
-
|
|
180
|
-
# Receiving site indicates how much material remains after assay use.
|
|
181
|
-
material_remaining: float | None = None
|
|
182
|
-
|
|
183
|
-
# Unit of measure for the amount of material remaining.
|
|
184
|
-
material_remaining_units: MaterialUnits | None = None
|
|
185
|
-
|
|
186
|
-
# Storage condition of the material once it was received.
|
|
187
|
-
material_storage_condition: MaterialStorageCondition | None = None
|
|
188
|
-
|
|
189
|
-
# Final status of sample after QC and pathology review.
|
|
190
|
-
qc_condition: QCCondition | None = None
|
|
191
|
-
|
|
192
|
-
# Indication if sample replacement is/was requested.
|
|
193
|
-
replacement_requested: ReplacementRequested | None = None
|
|
194
|
-
|
|
195
|
-
# Indication if sample was sent to another location or returned back to biorepository.
|
|
196
|
-
residual_use: ResidualUse | None = None
|
|
197
|
-
|
|
198
|
-
# Additional comments on sample testing
|
|
199
|
-
comments: str | None = None
|
|
200
|
-
|
|
201
|
-
# Indicates whether the local pathology review was consistent with the diagnostic pathology report.
|
|
202
|
-
diagnosis_verification: DiagnosisVerification | None = None
|
|
203
|
-
|
|
204
|
-
# The assay that this sample is expected to be used as input for.
|
|
205
|
-
intended_assay: AssayType | None = None
|
|
206
|
-
|
|
207
|
-
# The datetime that CIDC ingested the sample/manifest
|
|
208
|
-
date_ingested: datetime | None = None
|
|
209
|
-
|
|
210
27
|
# Days from enrollment date to date specimen was collected.
|
|
211
28
|
days_to_specimen_collection: int
|
|
212
29
|
|
|
@@ -1,11 +1,13 @@
|
|
|
1
|
-
from
|
|
1
|
+
from pydantic import NonNegativeInt
|
|
2
|
+
from cidc_api.models.pydantic.base import forced_validator, forced_validators
|
|
2
3
|
|
|
3
|
-
from pydantic import NonNegativeInt, model_validator
|
|
4
4
|
|
|
5
|
+
from cidc_api.models.errors import ValueLocError
|
|
5
6
|
from cidc_api.models.pydantic.base import Base
|
|
6
7
|
from cidc_api.models.types import SurgicalProcedure, UberonAnatomicalTerm, YNU
|
|
7
8
|
|
|
8
9
|
|
|
10
|
+
@forced_validators
|
|
9
11
|
class Surgery(Base):
|
|
10
12
|
__data_category__ = "surgery"
|
|
11
13
|
__cardinality__ = "many"
|
|
@@ -42,8 +44,14 @@ class Surgery(Base):
|
|
|
42
44
|
# CDE: https://cadsr.cancer.gov/onedata/dmdirect/NIH/NCI/CO/CDEDD?filter=CDEDD.ITEM_ID=13362284%20and%20ver_nr=1
|
|
43
45
|
extent_of_residual_disease: str | None = None
|
|
44
46
|
|
|
45
|
-
@
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
47
|
+
@forced_validator
|
|
48
|
+
@classmethod
|
|
49
|
+
def validate_procedure_other_cr(cls, data, info) -> None:
|
|
50
|
+
procedure = data.get("procedure", None)
|
|
51
|
+
procedure_other = data.get("procedure_other", None)
|
|
52
|
+
|
|
53
|
+
if procedure == "Other, specify" and not procedure_other:
|
|
54
|
+
raise ValueLocError(
|
|
55
|
+
'If procedure is "Other, specify", please provide procedure_other.',
|
|
56
|
+
loc="procedure_other",
|
|
57
|
+
)
|
|
@@ -1,11 +1,12 @@
|
|
|
1
|
-
from
|
|
2
|
-
|
|
3
|
-
from pydantic import NonNegativeInt, NonNegativeFloat, PositiveFloat, model_validator
|
|
1
|
+
from pydantic import NonNegativeInt, NonNegativeFloat, PositiveFloat
|
|
2
|
+
from cidc_api.models.pydantic.base import forced_validator, forced_validators
|
|
4
3
|
|
|
4
|
+
from cidc_api.models.errors import ValueLocError
|
|
5
5
|
from cidc_api.models.pydantic.base import Base
|
|
6
6
|
from cidc_api.models.types import YNU, TherapyAgentDoseUnits
|
|
7
7
|
|
|
8
8
|
|
|
9
|
+
@forced_validators
|
|
9
10
|
class TherapyAgentDose(Base):
|
|
10
11
|
__data_category__ = "therapy_agent_dose"
|
|
11
12
|
__cardinality__ = "many"
|
|
@@ -54,14 +55,26 @@ class TherapyAgentDose(Base):
|
|
|
54
55
|
# Description of the dose changes, misses, or delays.
|
|
55
56
|
changes_delays_description: str | None = None
|
|
56
57
|
|
|
57
|
-
@
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
58
|
+
@forced_validator
|
|
59
|
+
@classmethod
|
|
60
|
+
def validate_changes_delays_description_cr(cls, data, info) -> None:
|
|
61
|
+
dose_changes_delays = data.get("dose_changes_delays", None)
|
|
62
|
+
changes_delays_description = data.get("changes_delays_description", None)
|
|
63
|
+
|
|
64
|
+
if dose_changes_delays == "Yes" and not changes_delays_description:
|
|
65
|
+
raise ValueLocError(
|
|
66
|
+
'If dose_changes_delays is "Yes", please provide changes_delays_description.',
|
|
67
|
+
loc="changes_delays_description",
|
|
68
|
+
)
|
|
69
|
+
|
|
70
|
+
@forced_validator
|
|
71
|
+
@classmethod
|
|
72
|
+
def validate_planned_dose_units_cr(cls, data, info) -> None:
|
|
73
|
+
planned_dose = data.get("planned_dose", None)
|
|
74
|
+
planned_dose_units = data.get("planned_dose_units", None)
|
|
75
|
+
|
|
76
|
+
if planned_dose and not planned_dose_units:
|
|
77
|
+
raise ValueLocError(
|
|
78
|
+
"If planned_dose is provided, please provide planned_dose_units.",
|
|
79
|
+
loc="planned_dose_units",
|
|
80
|
+
)
|