Skip to content

Commit 7757287

Browse files
committed
new validator and tests
1 parent 15279a1 commit 7757287

File tree

2 files changed

+36
-4
lines changed

2 files changed

+36
-4
lines changed

src/aind_data_schema/core/mri_session.py

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
from enum import Enum
66
from typing import List, Literal, Optional
77

8-
from pydantic import Field, ValidationInfo, field_validator
8+
from pydantic import Field, ValidationInfo, field_validator, model_validator
99

1010
from aind_data_schema.base import AindCoreModel, AindGenericType, AindModel
1111
from aind_data_schema.core.procedures import Anaesthetic
@@ -47,13 +47,13 @@ class MRIScan(AindModel):
4747
scan_sequence_type: MriScanSequence = Field(..., title="Scan sequence")
4848
rare_factor: Optional[int] = Field(None, title="RARE factor")
4949
echo_time: Decimal = Field(..., title="Echo time (ms)")
50-
effective_echo_time: Decimal = Field(..., title="Effective echo time (ms)")
50+
effective_echo_time: Optional[Decimal] = Field(None, title="Effective echo time (ms)")
5151
echo_time_unit: TimeUnit = Field(TimeUnit.MS, title="Echo time unit")
5252
repetition_time: Decimal = Field(..., title="Repetition time (ms)")
5353
repetition_time_unit: TimeUnit = Field(TimeUnit.MS, title="Repetition time unit")
5454
# fields required to get correct orientation
55-
vc_orientation: Rotation3dTransform = Field(..., title="Scan orientation")
56-
vc_position: Translation3dTransform = Field(..., title="Scan position")
55+
vc_orientation: Optional[Rotation3dTransform] = Field(None, title="Scan orientation")
56+
vc_position: Optional[Translation3dTransform] = Field(None, title="Scan position")
5757
subject_position: SubjectPosition = Field(..., title="Subject position")
5858
# other fields
5959
voxel_sizes: Scale3dTransform = Field(..., title="Voxel sizes", description="Resolution")
@@ -77,6 +77,14 @@ def validate_other(cls, value: Optional[str], info: ValidationInfo) -> Optional[
7777
" Describe the scan_sequence_type in the notes field."
7878
)
7979
return value
80+
81+
@model_validator(mode="after")
82+
def validate_primary_scan(self):
83+
if self.primary_scan:
84+
if not self.vc_orientation or not self.vc_position:
85+
raise ValueError(
86+
"Primary scan must have vc_orientation and vc_position"
87+
)
8088

8189

8290
class MriSession(AindCoreModel):

tests/test_imaging.py

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -319,5 +319,29 @@ def test_validators(self):
319319
self.assertEqual(expected_exception, repr(e.exception))
320320

321321

322+
with self.assertRaises(ValueError) as e:
323+
ms.MRIScan(
324+
scan_index=1,
325+
scan_type="3D Scan",
326+
scan_sequence_type="RARE",
327+
rare_factor=4,
328+
primary_scan=True,
329+
subject_position="Supine",
330+
voxel_sizes=Scale3dTransform(scale=[0.1, 0.1, 0.1]),
331+
echo_time=2.2,
332+
effective_echo_time=2.0,
333+
repetition_time=1.2,
334+
additional_scan_parameters={"number_averages": 3},
335+
)
336+
337+
expected_exception = (
338+
"1 validation error for MRIScan\n"
339+
" Value error, Primary scan must have vc_orientation and vc_position [type=value_error, "
340+
"input_value={'scan_index': 1, 'scan_t... {'number_averages': 3}}, input_type=dict]\n"
341+
f" For further information visit https://errors.pydantic.dev/{PYD_VERSION}/v/value_error"
342+
)
343+
self.assertEqual(expected_exception, repr(e.exception))
344+
345+
322346
if __name__ == "__main__":
323347
unittest.main()

0 commit comments

Comments
 (0)