|
5 | 5 | from datetime import date |
6 | 6 | from typing import List, Optional, Union |
7 | 7 |
|
8 | | -from pydantic import Field |
| 8 | +from pydantic import Field, root_validator |
9 | 9 | from pydantic.typing import Annotated |
10 | 10 |
|
11 | 11 | from aind_data_schema.base import AindCoreModel |
@@ -90,3 +90,47 @@ class Rig(AindCoreModel): |
90 | 90 | description="Path to file that details the CCF-to-lab coordinate transform", |
91 | 91 | ) |
92 | 92 | notes: Optional[str] = Field(None, title="Notes") |
| 93 | + |
| 94 | + @root_validator |
| 95 | + def validate_device_names(cls, values): # noqa: C901 |
| 96 | + """validate that all DAQ channels are connected to devices that |
| 97 | + actually exist |
| 98 | + """ |
| 99 | + |
| 100 | + cameras = values.get("cameras") |
| 101 | + ephys_assemblies = values.get("ephys_assemblies") |
| 102 | + laser_assemblies = values.get("laser_assemblies") |
| 103 | + mouse_platform = values.get("mouse_platform") |
| 104 | + daqs = values.get("daqs") |
| 105 | + |
| 106 | + if daqs is None: |
| 107 | + return values |
| 108 | + |
| 109 | + device_names = [None] |
| 110 | + |
| 111 | + if cameras is not None: |
| 112 | + device_names += [c.camera.name for c in cameras] |
| 113 | + |
| 114 | + if daqs is not None: |
| 115 | + device_names += [daq.name for daq in daqs] |
| 116 | + |
| 117 | + if ephys_assemblies is not None: |
| 118 | + device_names += [probe.name for ephys_assembly in ephys_assemblies for probe in ephys_assembly.probes] |
| 119 | + |
| 120 | + if laser_assemblies is not None: |
| 121 | + device_names += [laser.name for laser_assembly in laser_assemblies for laser in laser_assembly.lasers] |
| 122 | + |
| 123 | + if mouse_platform is not None: |
| 124 | + device_names += [mouse_platform.name] |
| 125 | + |
| 126 | + for daq in daqs: |
| 127 | + if daq.channels is not None: |
| 128 | + for channel in daq.channels: |
| 129 | + if channel.device_name not in device_names: |
| 130 | + raise ValueError( |
| 131 | + f"Device name validation error: '{channel.device_name}' " |
| 132 | + + f"is connected to '{channel.channel_name}' on '{daq.name}', but " |
| 133 | + + "this device is not part of the rig." |
| 134 | + ) |
| 135 | + |
| 136 | + return values |
0 commit comments