Skip to content

Commit de9fd11

Browse files
authored
Merge pull request #1590 from AllenNeuralDynamics/1589-ensure-merging-files-valid-valid-outputs-a-valid-file
hotfix: move the subject_details validator out of Acquisition
2 parents 341142c + bb481cb commit de9fd11

File tree

5 files changed

+59
-20
lines changed

5 files changed

+59
-20
lines changed

src/aind_data_schema/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
""" base module for aind-data-schema
22
"""
33

4-
__version__ = "2.0.4"
4+
__version__ = "2.0.5"

src/aind_data_schema/core/acquisition.py

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -311,14 +311,6 @@ class Acquisition(DataCoreModel):
311311
)
312312
subject_details: Optional[AcquisitionSubjectDetails] = Field(default=None, title="Subject details")
313313

314-
@model_validator(mode="after")
315-
def subject_details_if_not_specimen(self):
316-
"""Check that subject details are present if no specimen ID"""
317-
if not self.specimen_id and not self.subject_details:
318-
raise ValueError("Subject details are required for in vivo experiments")
319-
320-
return self
321-
322314
@model_validator(mode="after")
323315
def check_subject_specimen_id(self):
324316
"""Check that the subject and specimen IDs match"""

src/aind_data_schema/core/metadata.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,16 @@ def validate_core_fields(cls, value, info: ValidationInfo):
133133
core_model = value
134134
return core_model
135135

136+
@model_validator(mode="after")
137+
def validate_subject_details_if_not_specimen(self):
138+
"""Check that subject details are present if an in vivo experiment"""
139+
140+
if self.acquisition and not self.acquisition.specimen_id:
141+
if not self.acquisition.subject_details:
142+
raise ValueError("Acquisition.subject_details are required for in vivo experiments")
143+
144+
return self
145+
136146
@model_validator(mode="after")
137147
def validate_expected_files_by_modality(self):
138148
"""Validator warns users if required files are missing"""

tests/test_acquisition.py

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -101,17 +101,6 @@ def test_constructors(self):
101101

102102
assert mri is not None
103103

104-
def test_subject_details_if_not_specimen(self):
105-
"""Test that subject details are required if no specimen ID"""
106-
with self.assertRaises(ValueError) as context:
107-
acq = ephys_acquisition.model_copy()
108-
109-
acq.subject_details = None
110-
111-
Acquisition.model_validate_json(acq.model_dump_json())
112-
113-
self.assertIn("Subject details are required for in vivo experiments", str(context.exception))
114-
115104
def test_check_subject_specimen_id(self):
116105
"""Test that subject and specimen IDs match"""
117106
with self.assertRaises(ValueError) as context:

tests/test_metadata.py

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -884,6 +884,54 @@ def test_validate_calibration_object_tags(self):
884884
)
885885
self.assertIsNotNone(metadata)
886886

887+
def test_validate_subject_details_if_not_specimen(self):
888+
"""Tests that subject details are required if acquisition.specimen_id is not provided"""
889+
890+
# Case where specimen_id is provided - should pass without subject_details
891+
acquisition_with_specimen = Acquisition.model_construct(
892+
instrument_id="Test",
893+
subject_id="123456",
894+
specimen_id="123456-001",
895+
data_streams=[],
896+
)
897+
metadata_with_specimen = Metadata(
898+
name="Test Metadata",
899+
location="Test Location",
900+
subject=subject,
901+
acquisition=acquisition_with_specimen,
902+
)
903+
self.assertIsNotNone(metadata_with_specimen)
904+
905+
# Case where specimen_id is not provided and subject_details is provided - should pass
906+
acquisition_with_details = Acquisition.model_construct(
907+
instrument_id="Test",
908+
subject_id="123456",
909+
data_streams=[],
910+
subject_details=AcquisitionSubjectDetails.model_construct(),
911+
)
912+
metadata_with_details = Metadata(
913+
name="Test Metadata",
914+
location="Test Location",
915+
subject=subject,
916+
acquisition=acquisition_with_details,
917+
)
918+
self.assertIsNotNone(metadata_with_details)
919+
920+
# Case where neither specimen_id nor subject_details is provided - should fail
921+
acquisition_missing_both = Acquisition.model_construct(
922+
subject_id="123456",
923+
instrument_id="Test",
924+
data_streams=[],
925+
)
926+
with self.assertRaises(ValueError) as context:
927+
Metadata(
928+
name="Test Metadata",
929+
location="Test Location",
930+
subject=subject,
931+
acquisition=acquisition_missing_both,
932+
)
933+
self.assertIn("Acquisition.subject_details are required for in vivo experiments", str(context.exception))
934+
887935

888936
if __name__ == "__main__":
889937
unittest.main()

0 commit comments

Comments
 (0)