Skip to content

Commit 8e7a2fa

Browse files
authored
Merge pull request #806 from AllenNeuralDynamics/feat-765-optional-injection-material
feat:injection materials is optional list
2 parents f3c3740 + 2e4c079 commit 8e7a2fa

File tree

3 files changed

+83
-6
lines changed

3 files changed

+83
-6
lines changed

src/aind_data_schema/core/metadata.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -192,12 +192,13 @@ def validate_smartspim_metadata(self):
192192
raise ValueError(
193193
"Missing some metadata for SmartSpim. Requires subject, procedures, acquisition, and instrument."
194194
)
195+
195196
if (
196197
self.data_description
197198
and self.data_description.platform == SmartSpim
198199
and self.procedures
199200
and any(
200-
isinstance(surgery, Injection) and getattr(surgery, "injection_materials", []) == []
201+
isinstance(surgery, Injection) and getattr(surgery, "injection_materials", None) is None
201202
for subject_procedure in self.procedures.subject_procedures
202203
if isinstance(subject_procedure, Surgery)
203204
for surgery in subject_procedure.procedures
@@ -223,7 +224,7 @@ def validate_ecephys_metadata(self):
223224
and self.data_description.platform == Ecephys
224225
and self.procedures
225226
and any(
226-
isinstance(surgery, Injection) and getattr(surgery, "injection_materials", []) == []
227+
isinstance(surgery, Injection) and getattr(surgery, "injection_materials", None) is None
227228
for subject_procedure in self.procedures.subject_procedures
228229
if isinstance(subject_procedure, Surgery)
229230
for surgery in subject_procedure.procedures

src/aind_data_schema/core/procedures.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -353,7 +353,7 @@ class Injection(AindModel):
353353
injection_materials: Annotated[
354354
List[Union[ViralMaterial, NonViralMaterial]],
355355
Field(title="Injection material", min_length=1, discriminator="material_type"),
356-
] = []
356+
]
357357
recovery_time: Optional[Decimal] = Field(None, title="Recovery time")
358358
recovery_time_unit: TimeUnit = Field(TimeUnit.M, title="Recovery time unit")
359359
injection_duration: Optional[Decimal] = Field(None, title="Injection duration")

tests/test_procedures.py

Lines changed: 79 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -47,11 +47,11 @@ def test_injection_material_check(self):
4747
subject_procedures=[
4848
Surgery(
4949
start_date=start_date,
50-
experimenter_full_name="tom",
50+
experimenter_full_name="Chip Munk",
5151
procedures=[
5252
RetroOrbitalInjection(
5353
start_date=start_date,
54-
experimenter_full_name="tom",
54+
experimenter_full_name="Chip Munk",
5555
protocol_id="134",
5656
injection_materials=[], # An empty list is invalid
5757
injection_volume=1,
@@ -64,12 +64,76 @@ def test_injection_material_check(self):
6464
],
6565
)
6666

67+
# validate error for injection_materials=[]
68+
with self.assertRaises(ValidationError) as e:
69+
Procedures(
70+
subject_id="12345",
71+
subject_procedures=[
72+
Surgery(
73+
start_date=start_date,
74+
experimenter_full_name="Chip Munk",
75+
procedures=[
76+
RetroOrbitalInjection(
77+
protocol_id="134",
78+
injection_materials=[], # An empty list is invalid
79+
injection_volume=1,
80+
injection_eye="Left",
81+
injection_duration=1,
82+
recovery_time=10,
83+
),
84+
],
85+
)
86+
],
87+
)
88+
expected_exception = (
89+
"1 validation error for RetroOrbitalInjection\n"
90+
"injection_materials\n"
91+
" List should have at least 1 item after validation, not 0 [type=too_short, input_value=[], "
92+
"input_type=list]\n"
93+
f" For further information visit https://errors.pydantic.dev/{PYD_VERSION}/v/too_short"
94+
)
95+
96+
self.assertEqual(expected_exception, repr(e.exception))
97+
98+
# validate error for injection_materials=None
99+
with self.assertRaises(ValidationError) as e:
100+
p = Procedures(
101+
subject_id="12345",
102+
subject_procedures=[
103+
Surgery(
104+
start_date=start_date,
105+
experimenter_full_name="Chip Munk",
106+
procedures=[
107+
RetroOrbitalInjection(
108+
protocol_id="134",
109+
injection_materials=None,
110+
injection_volume=1,
111+
injection_eye="Left",
112+
injection_duration=1,
113+
recovery_time=10,
114+
),
115+
],
116+
)
117+
],
118+
)
119+
120+
expected_exception = (
121+
"1 validation error for RetroOrbitalInjection\n"
122+
"injection_materials\n"
123+
" Input should be a valid list [type=list_type, input_value=None, input_type=NoneType]\n"
124+
f" For further information visit https://errors.pydantic.dev/{PYD_VERSION}/v/list_type"
125+
)
126+
127+
self.assertEqual(expected_exception, repr(e.exception))
128+
129+
# Validate injection_materials is list of one ViralMaterial or NonViralMaterial item
130+
67131
p = Procedures(
68132
subject_id="12345",
69133
subject_procedures=[
70134
Surgery(
71135
start_date=start_date,
72-
experimenter_full_name="tom",
136+
experimenter_full_name="Chip Munk",
73137
iacuc_protocol="234",
74138
procedures=[
75139
RetroOrbitalInjection(
@@ -251,6 +315,18 @@ def test_coordinate_volume_validator(self):
251315
injection_angle=1,
252316
injection_coordinate_depth=[0, 1],
253317
injection_volume=[1, 2],
318+
injection_materials=[
319+
ViralMaterial(
320+
material_type="Virus",
321+
name="AAV2-Flex-ChrimsonR",
322+
tars_identifiers=TarsVirusIdentifiers(
323+
virus_tars_id="AiV222",
324+
plasmid_tars_alias="AiP222",
325+
prep_lot_number="VT222",
326+
),
327+
titer=2300000000,
328+
)
329+
],
254330
)
255331
self.assertEqual(len(inj1.injection_coordinate_depth), len(inj1.injection_volume))
256332

0 commit comments

Comments
 (0)