diff --git a/examples/rig.py b/examples/rig.py index 67b3237..50feca2 100644 --- a/examples/rig.py +++ b/examples/rig.py @@ -18,7 +18,9 @@ AindDynamicForagingRig, DynamicForagingAindManipulator, DynamicForagingSoundCard, + DynamicForagingSpinnakerCamera, RigCalibration, + SpinnakerCamera, ) manipulator_calibration = AindManipulatorCalibration( @@ -48,14 +50,14 @@ rig_name="test_rig", computer_name="test_computer", data_directory="D:/Data/", - triggered_camera_controller=cameras.CameraController[cameras.SpinnakerCamera]( + triggered_camera_controller=cameras.CameraController[DynamicForagingSpinnakerCamera]( frame_rate=120, cameras={ - "BodyCamera": cameras.SpinnakerCamera( - serial_number="23349426", binning=1, exposure=1000, gain=8, video_writer=None + "BodyCamera": DynamicForagingSpinnakerCamera( + camera=SpinnakerCamera(serial_number="23349426", binning=1, exposure=1000, gain=8, video_writer=None) ), - "SideCamera": cameras.SpinnakerCamera( - serial_number="23349424", binning=1, exposure=1000, gain=8, video_writer=None + "SideCamera": DynamicForagingSpinnakerCamera( + camera=SpinnakerCamera(serial_number="23349424", binning=1, exposure=1000, gain=8, video_writer=None) ), }, ), diff --git a/schema/aind_behavior_dynamic_foraging.json b/schema/aind_behavior_dynamic_foraging.json index 3b66b54..44d04a5 100644 --- a/schema/aind_behavior_dynamic_foraging.json +++ b/schema/aind_behavior_dynamic_foraging.json @@ -31,7 +31,7 @@ "type": "string" }, "triggered_camera_controller": { - "$ref": "#/$defs/CameraController_SpinnakerCamera_", + "$ref": "#/$defs/CameraController_DynamicForagingSpinnakerCamera_", "description": "Required camera controller to triggered cameras." }, "monitoring_camera_controller": { @@ -970,7 +970,7 @@ "title": "BlockBasedTrialGeneratorSpec", "type": "object" }, - "CameraController_SpinnakerCamera_": { + "CameraController_DynamicForagingSpinnakerCamera_": { "properties": { "device_type": { "const": "CameraController", @@ -992,7 +992,7 @@ }, "cameras": { "additionalProperties": { - "$ref": "#/$defs/SpinnakerCamera" + "$ref": "#/$defs/DynamicForagingSpinnakerCamera" }, "description": "Cameras to be instantiated", "title": "Cameras", @@ -1016,7 +1016,7 @@ "required": [ "cameras" ], - "title": "CameraController[SpinnakerCamera]", + "title": "CameraController[DynamicForagingSpinnakerCamera]", "type": "object" }, "CameraController_WebCamera_": { @@ -1750,6 +1750,28 @@ "title": "DynamicForagingSoundCard", "type": "object" }, + "DynamicForagingSpinnakerCamera": { + "description": "A SpinnakerCamera for the dynamic foraging rig that includes camera image rotation for visualizers.", + "properties": { + "camera": { + "$ref": "#/$defs/SpinnakerCamera", + "description": "Spinnaker camera instance" + }, + "visualizer_settings": { + "$ref": "#/$defs/VisualizerSettings", + "default": { + "flip_state": null, + "rotation": 0.0 + }, + "description": "Visualizer settings for the camera" + } + }, + "required": [ + "camera" + ], + "title": "DynamicForagingSpinnakerCamera", + "type": "object" + }, "ExponentialDistribution": { "description": "An exponential probability distribution.\n\nModels time between events in a Poisson process. Commonly used\nfor wait times and inter-event intervals.", "properties": { @@ -4111,6 +4133,37 @@ "title": "VideoWriterOpenCv", "type": "object" }, + "VisualizerSettings": { + "description": "Visualizer settings for the dynamic foraging rig's camera. This includes camera image rotation and flip state for visualizers.", + "properties": { + "flip_state": { + "default": null, + "description": "Camera flip state", + "oneOf": [ + { + "enum": [ + "horizontal", + "vertical", + "both" + ], + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Flip State" + }, + "rotation": { + "default": 0, + "description": "Camera rotation angle in radians", + "title": "Rotation", + "type": "number" + } + }, + "title": "VisualizerSettings", + "type": "object" + }, "WaterValveCalibration": { "description": "Represents a water valve calibration.", "properties": { diff --git a/src/Extensions/AindBehaviorDynamicForaging.Generated.cs b/src/Extensions/AindBehaviorDynamicForaging.Generated.cs index 7519d11..6a0590f 100644 --- a/src/Extensions/AindBehaviorDynamicForaging.Generated.cs +++ b/src/Extensions/AindBehaviorDynamicForaging.Generated.cs @@ -25,7 +25,7 @@ public partial class AindDynamicForagingRig private string _dataDirectory; - private CameraControllerSpinnakerCamera _triggeredCameraController; + private CameraControllerDynamicForagingSpinnakerCamera _triggeredCameraController; private CameraControllerWebCamera _monitoringCameraController; @@ -51,7 +51,7 @@ public AindDynamicForagingRig() { _aindBehaviorServicesPkgVersion = "0.13.7"; _version = "0.0.2-rc37"; - _triggeredCameraController = new CameraControllerSpinnakerCamera(); + _triggeredCameraController = new CameraControllerDynamicForagingSpinnakerCamera(); _harpBehavior = new HarpBehavior(); _harpClockGenerator = new HarpWhiteRabbit(); _harpSoundCard = new DynamicForagingSoundCard(); @@ -162,7 +162,7 @@ public string DataDirectory [System.Xml.Serialization.XmlIgnoreAttribute()] [Newtonsoft.Json.JsonPropertyAttribute("triggered_camera_controller", Required=Newtonsoft.Json.Required.Always)] [System.ComponentModel.DescriptionAttribute("Required camera controller to triggered cameras.")] - public CameraControllerSpinnakerCamera TriggeredCameraController + public CameraControllerDynamicForagingSpinnakerCamera TriggeredCameraController { get { @@ -1822,25 +1822,25 @@ protected override bool PrintMembers(System.Text.StringBuilder stringBuilder) [System.CodeDom.Compiler.GeneratedCodeAttribute("Bonsai.Sgen", "0.9.0.0 (Newtonsoft.Json v13.0.0.0)")] [Bonsai.WorkflowElementCategoryAttribute(Bonsai.ElementCategory.Source)] [Bonsai.CombinatorAttribute(MethodName="Generate")] - public partial class CameraControllerSpinnakerCamera + public partial class CameraControllerDynamicForagingSpinnakerCamera { private string _deviceType; private BaseModel _calibration; - private System.Collections.Generic.Dictionary _cameras; + private System.Collections.Generic.Dictionary _cameras; private int? _frameRate; - public CameraControllerSpinnakerCamera() + public CameraControllerDynamicForagingSpinnakerCamera() { _deviceType = "CameraController"; - _cameras = new System.Collections.Generic.Dictionary(); + _cameras = new System.Collections.Generic.Dictionary(); _frameRate = 30; } - protected CameraControllerSpinnakerCamera(CameraControllerSpinnakerCamera other) + protected CameraControllerDynamicForagingSpinnakerCamera(CameraControllerDynamicForagingSpinnakerCamera other) { _deviceType = other._deviceType; _calibration = other._calibration; @@ -1885,7 +1885,7 @@ public BaseModel Calibration [System.Xml.Serialization.XmlIgnoreAttribute()] [Newtonsoft.Json.JsonPropertyAttribute("cameras", Required=Newtonsoft.Json.Required.Always)] [System.ComponentModel.DescriptionAttribute("Cameras to be instantiated")] - public System.Collections.Generic.Dictionary Cameras + public System.Collections.Generic.Dictionary Cameras { get { @@ -1914,14 +1914,14 @@ public int? FrameRate } } - public System.IObservable Generate() + public System.IObservable Generate() { - return System.Reactive.Linq.Observable.Defer(() => System.Reactive.Linq.Observable.Return(new CameraControllerSpinnakerCamera(this))); + return System.Reactive.Linq.Observable.Defer(() => System.Reactive.Linq.Observable.Return(new CameraControllerDynamicForagingSpinnakerCamera(this))); } - public System.IObservable Generate(System.IObservable source) + public System.IObservable Generate(System.IObservable source) { - return System.Reactive.Linq.Observable.Select(source, _ => new CameraControllerSpinnakerCamera(this)); + return System.Reactive.Linq.Observable.Select(source, _ => new CameraControllerDynamicForagingSpinnakerCamera(this)); } protected virtual bool PrintMembers(System.Text.StringBuilder stringBuilder) @@ -3444,6 +3444,101 @@ public override string ToString() } + /// + /// A SpinnakerCamera for the dynamic foraging rig that includes camera image rotation for visualizers. + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("Bonsai.Sgen", "0.9.0.0 (Newtonsoft.Json v13.0.0.0)")] + [System.ComponentModel.DescriptionAttribute("A SpinnakerCamera for the dynamic foraging rig that includes camera image rotatio" + + "n for visualizers.")] + [Bonsai.WorkflowElementCategoryAttribute(Bonsai.ElementCategory.Source)] + [Bonsai.CombinatorAttribute(MethodName="Generate")] + public partial class DynamicForagingSpinnakerCamera + { + + private SpinnakerCamera _camera; + + private VisualizerSettings _visualizerSettings; + + public DynamicForagingSpinnakerCamera() + { + _camera = new SpinnakerCamera(); + _visualizerSettings = new VisualizerSettings(); + } + + protected DynamicForagingSpinnakerCamera(DynamicForagingSpinnakerCamera other) + { + _camera = other._camera; + _visualizerSettings = other._visualizerSettings; + } + + /// + /// Spinnaker camera instance + /// + [System.Xml.Serialization.XmlIgnoreAttribute()] + [Newtonsoft.Json.JsonPropertyAttribute("camera", Required=Newtonsoft.Json.Required.Always)] + [System.ComponentModel.DescriptionAttribute("Spinnaker camera instance")] + public SpinnakerCamera Camera + { + get + { + return _camera; + } + set + { + _camera = value; + } + } + + /// + /// Visualizer settings for the camera + /// + [System.Xml.Serialization.XmlIgnoreAttribute()] + [Newtonsoft.Json.JsonPropertyAttribute("visualizer_settings")] + [System.ComponentModel.DescriptionAttribute("Visualizer settings for the camera")] + public VisualizerSettings VisualizerSettings + { + get + { + return _visualizerSettings; + } + set + { + _visualizerSettings = value; + } + } + + public System.IObservable Generate() + { + return System.Reactive.Linq.Observable.Defer(() => System.Reactive.Linq.Observable.Return(new DynamicForagingSpinnakerCamera(this))); + } + + public System.IObservable Generate(System.IObservable source) + { + return System.Reactive.Linq.Observable.Select(source, _ => new DynamicForagingSpinnakerCamera(this)); + } + + protected virtual bool PrintMembers(System.Text.StringBuilder stringBuilder) + { + stringBuilder.Append("Camera = " + _camera + ", "); + stringBuilder.Append("VisualizerSettings = " + _visualizerSettings); + return true; + } + + public override string ToString() + { + System.Text.StringBuilder stringBuilder = new System.Text.StringBuilder(); + stringBuilder.Append(GetType().Name); + stringBuilder.Append(" { "); + if (PrintMembers(stringBuilder)) + { + stringBuilder.Append(" "); + } + stringBuilder.Append("}"); + return stringBuilder.ToString(); + } + } + + [System.CodeDom.Compiler.GeneratedCodeAttribute("Bonsai.Sgen", "0.9.0.0 (Newtonsoft.Json v13.0.0.0)")] [Bonsai.WorkflowElementCategoryAttribute(Bonsai.ElementCategory.Source)] [Bonsai.CombinatorAttribute(MethodName="Generate")] @@ -7744,6 +7839,98 @@ protected override bool PrintMembers(System.Text.StringBuilder stringBuilder) } + /// + /// Visualizer settings for the dynamic foraging rig's camera. This includes camera image rotation and flip state for visualizers. + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("Bonsai.Sgen", "0.9.0.0 (Newtonsoft.Json v13.0.0.0)")] + [System.ComponentModel.DescriptionAttribute("Visualizer settings for the dynamic foraging rig\'s camera. This includes camera i" + + "mage rotation and flip state for visualizers.")] + [Bonsai.WorkflowElementCategoryAttribute(Bonsai.ElementCategory.Source)] + [Bonsai.CombinatorAttribute(MethodName="Generate")] + public partial class VisualizerSettings + { + + private FlipState? _flipState; + + private double _rotation; + + public VisualizerSettings() + { + _rotation = 0D; + } + + protected VisualizerSettings(VisualizerSettings other) + { + _flipState = other._flipState; + _rotation = other._rotation; + } + + /// + /// Camera flip state + /// + [Newtonsoft.Json.JsonPropertyAttribute("flip_state")] + [System.ComponentModel.DescriptionAttribute("Camera flip state")] + public FlipState? FlipState + { + get + { + return _flipState; + } + set + { + _flipState = value; + } + } + + /// + /// Camera rotation angle in radians + /// + [Newtonsoft.Json.JsonPropertyAttribute("rotation")] + [System.ComponentModel.DescriptionAttribute("Camera rotation angle in radians")] + public double Rotation + { + get + { + return _rotation; + } + set + { + _rotation = value; + } + } + + public System.IObservable Generate() + { + return System.Reactive.Linq.Observable.Defer(() => System.Reactive.Linq.Observable.Return(new VisualizerSettings(this))); + } + + public System.IObservable Generate(System.IObservable source) + { + return System.Reactive.Linq.Observable.Select(source, _ => new VisualizerSettings(this)); + } + + protected virtual bool PrintMembers(System.Text.StringBuilder stringBuilder) + { + stringBuilder.Append("FlipState = " + _flipState + ", "); + stringBuilder.Append("Rotation = " + _rotation); + return true; + } + + public override string ToString() + { + System.Text.StringBuilder stringBuilder = new System.Text.StringBuilder(); + stringBuilder.Append(GetType().Name); + stringBuilder.Append(" { "); + if (PrintMembers(stringBuilder)) + { + stringBuilder.Append(" "); + } + stringBuilder.Append("}"); + return stringBuilder.ToString(); + } + } + + /// /// Represents a water valve calibration. /// @@ -8281,6 +8468,22 @@ public enum SpinnakerCameraColorProcessing } + [System.CodeDom.Compiler.GeneratedCodeAttribute("Bonsai.Sgen", "0.9.0.0 (Newtonsoft.Json v13.0.0.0)")] + [Newtonsoft.Json.JsonConverter(typeof(Newtonsoft.Json.Converters.StringEnumConverter))] + public enum FlipState + { + + [System.Runtime.Serialization.EnumMemberAttribute(Value="horizontal")] + Horizontal = 0, + + [System.Runtime.Serialization.EnumMemberAttribute(Value="vertical")] + Vertical = 1, + + [System.Runtime.Serialization.EnumMemberAttribute(Value="both")] + Both = 2, + } + + [System.CodeDom.Compiler.GeneratedCodeAttribute("Bonsai.Sgen", "0.9.0.0 (Newtonsoft.Json v13.0.0.0)")] [Newtonsoft.Json.JsonConverter(typeof(Newtonsoft.Json.Converters.StringEnumConverter))] public enum WaveformType @@ -8630,9 +8833,9 @@ public System.IObservable Process(System.IObservable(source); } - public System.IObservable Process(System.IObservable source) + public System.IObservable Process(System.IObservable source) { - return Process(source); + return Process(source); } public System.IObservable Process(System.IObservable source) @@ -8675,6 +8878,11 @@ public System.IObservable Process(System.IObservable(source); } + public System.IObservable Process(System.IObservable source) + { + return Process(source); + } + public System.IObservable Process(System.IObservable source) { return Process(source); @@ -8810,6 +9018,11 @@ public System.IObservable Process(System.IObservable return Process(source); } + public System.IObservable Process(System.IObservable source) + { + return Process(source); + } + public System.IObservable Process(System.IObservable source) { return Process(source); @@ -8850,7 +9063,7 @@ public System.IObservable Process(System.IObservable source) [System.Xml.Serialization.XmlIncludeAttribute(typeof(Bonsai.Expressions.TypeMapping))] [System.Xml.Serialization.XmlIncludeAttribute(typeof(Bonsai.Expressions.TypeMapping))] [System.Xml.Serialization.XmlIncludeAttribute(typeof(Bonsai.Expressions.TypeMapping))] - [System.Xml.Serialization.XmlIncludeAttribute(typeof(Bonsai.Expressions.TypeMapping))] + [System.Xml.Serialization.XmlIncludeAttribute(typeof(Bonsai.Expressions.TypeMapping))] [System.Xml.Serialization.XmlIncludeAttribute(typeof(Bonsai.Expressions.TypeMapping))] [System.Xml.Serialization.XmlIncludeAttribute(typeof(Bonsai.Expressions.TypeMapping))] [System.Xml.Serialization.XmlIncludeAttribute(typeof(Bonsai.Expressions.TypeMapping))] @@ -8859,6 +9072,7 @@ public System.IObservable Process(System.IObservable source) [System.Xml.Serialization.XmlIncludeAttribute(typeof(Bonsai.Expressions.TypeMapping))] [System.Xml.Serialization.XmlIncludeAttribute(typeof(Bonsai.Expressions.TypeMapping))] [System.Xml.Serialization.XmlIncludeAttribute(typeof(Bonsai.Expressions.TypeMapping))] + [System.Xml.Serialization.XmlIncludeAttribute(typeof(Bonsai.Expressions.TypeMapping))] [System.Xml.Serialization.XmlIncludeAttribute(typeof(Bonsai.Expressions.TypeMapping))] [System.Xml.Serialization.XmlIncludeAttribute(typeof(Bonsai.Expressions.TypeMapping))] [System.Xml.Serialization.XmlIncludeAttribute(typeof(Bonsai.Expressions.TypeMapping))] @@ -8886,6 +9100,7 @@ public System.IObservable Process(System.IObservable source) [System.Xml.Serialization.XmlIncludeAttribute(typeof(Bonsai.Expressions.TypeMapping))] [System.Xml.Serialization.XmlIncludeAttribute(typeof(Bonsai.Expressions.TypeMapping))] [System.Xml.Serialization.XmlIncludeAttribute(typeof(Bonsai.Expressions.TypeMapping))] + [System.Xml.Serialization.XmlIncludeAttribute(typeof(Bonsai.Expressions.TypeMapping))] [System.Xml.Serialization.XmlIncludeAttribute(typeof(Bonsai.Expressions.TypeMapping))] [System.Xml.Serialization.XmlIncludeAttribute(typeof(Bonsai.Expressions.TypeMapping))] [System.Xml.Serialization.XmlIncludeAttribute(typeof(Bonsai.Expressions.TypeMapping))] diff --git a/src/Extensions/Hardware.bonsai b/src/Extensions/Hardware.bonsai index 70a5223..22cac23 100644 --- a/src/Extensions/Hardware.bonsai +++ b/src/Extensions/Hardware.bonsai @@ -376,7 +376,7 @@ ThisCamera - Value + Value.Camera @@ -394,7 +394,7 @@ ThisCamera - Value + Value.Camera RegionOfInterest diff --git a/src/Extensions/HardwareQA.bonsai b/src/Extensions/HardwareQA.bonsai index 4fda059..fad0c85 100644 --- a/src/Extensions/HardwareQA.bonsai +++ b/src/Extensions/HardwareQA.bonsai @@ -172,7 +172,7 @@ ThisCamera - Value.Exposure + Value.Camera.Exposure TriggeredCameraController diff --git a/src/Extensions/Logging.bonsai b/src/Extensions/Logging.bonsai index fffea67..771fea5 100644 --- a/src/Extensions/Logging.bonsai +++ b/src/Extensions/Logging.bonsai @@ -1107,7 +1107,7 @@ - Value.VideoWriter + Value.Camera.VideoWriter @@ -1273,7 +1273,7 @@ - Value.VideoWriter + Value.Camera.VideoWriter diff --git a/src/aind_behavior_dynamic_foraging/rig.py b/src/aind_behavior_dynamic_foraging/rig.py index 8608a95..0bd71e6 100644 --- a/src/aind_behavior_dynamic_foraging/rig.py +++ b/src/aind_behavior_dynamic_foraging/rig.py @@ -1,7 +1,8 @@ from typing import Annotated, Literal, Optional import aind_behavior_services.rig as rig -from aind_behavior_services.rig import aind_manipulator, cameras, harp, water_valve +from aind_behavior_services.rig import aind_manipulator, harp, water_valve +from aind_behavior_services.rig.cameras import CameraController, SpinnakerCamera, WebCamera from pydantic import BaseModel, Field, model_validator from aind_behavior_dynamic_foraging import __semver__ @@ -72,12 +73,30 @@ class DynamicForagingAindManipulator(aind_manipulator.AindManipulator): ) +class VisualizerSettings(BaseModel): + """Visualizer settings for the dynamic foraging rig's camera. This includes camera image rotation and flip state for visualizers.""" + + flip_state: None | Literal["horizontal", "vertical", "both"] = Field( + default=None, description="Camera flip state", validate_default=True + ) + rotation: float = Field(default=0, description="Camera rotation angle in radians", validate_default=True) + + +class DynamicForagingSpinnakerCamera(BaseModel): + """A SpinnakerCamera for the dynamic foraging rig that includes camera image rotation for visualizers.""" + + camera: SpinnakerCamera = Field(description="Spinnaker camera instance") + visualizer_settings: VisualizerSettings = Field( + default=VisualizerSettings(), description="Visualizer settings for the camera", validate_default=True + ) + + class AindDynamicForagingRig(rig.Rig): version: Literal[__semver__] = __semver__ - triggered_camera_controller: cameras.CameraController[cameras.SpinnakerCamera] = Field( + triggered_camera_controller: CameraController[DynamicForagingSpinnakerCamera] = Field( description="Required camera controller to triggered cameras." ) - monitoring_camera_controller: Optional[cameras.CameraController[cameras.WebCamera]] = Field( + monitoring_camera_controller: Optional[CameraController[WebCamera]] = Field( default=None, description="Optional camera controller for monitoring cameras." ) harp_behavior: harp.HarpBehavior = Field(description="Harp behavior") diff --git a/workspace/aind_behavior_dynamic_foraging_metadata_mapper/src/aind_behavior_dynamic_foraging_metadata_mapper/acquisition.py b/workspace/aind_behavior_dynamic_foraging_metadata_mapper/src/aind_behavior_dynamic_foraging_metadata_mapper/acquisition.py index b315e8d..60f4ec9 100644 --- a/workspace/aind_behavior_dynamic_foraging_metadata_mapper/src/aind_behavior_dynamic_foraging_metadata_mapper/acquisition.py +++ b/workspace/aind_behavior_dynamic_foraging_metadata_mapper/src/aind_behavior_dynamic_foraging_metadata_mapper/acquisition.py @@ -10,7 +10,7 @@ from aind_behavior_curriculum import TrainerState from aind_behavior_dynamic_foraging.data_contract import dataset as df_foraging_dataset from aind_behavior_dynamic_foraging.data_contract.utils import calculate_consumed_water -from aind_behavior_dynamic_foraging.rig import AindDynamicForagingRig +from aind_behavior_dynamic_foraging.rig import AindDynamicForagingRig, CameraController, DynamicForagingSpinnakerCamera from aind_behavior_dynamic_foraging.task_logic import AindDynamicForagingTaskLogic from aind_behavior_services.rig import Device as AbsDevice from aind_behavior_services.rig import cameras as abs_camera @@ -120,7 +120,11 @@ def _map(self) -> Acquisition: python_code = _get_python_as_code(repository) curriculum_code = _get_curriculum_as_code(repository, trainer_state) - cameras = data_mapper_helpers.get_cameras(rig_model, exclude_without_video_writer=True) + cameras: dict[str, DynamicForagingSpinnakerCamera] = {} + camera_controllers = [x[1] for x in get_fields_of_type(rig_model, CameraController)] + for controller in camera_controllers: + cameras.update({k: v for k, v in controller.cameras.items() if v.camera.video_writer is not None}) + camera_configs = [_get_camera_config(k, v, repository) for k, v in cameras.items()] # construct data stream diff --git a/workspace/aind_behavior_dynamic_foraging_metadata_mapper/src/aind_behavior_dynamic_foraging_metadata_mapper/instrument.py b/workspace/aind_behavior_dynamic_foraging_metadata_mapper/src/aind_behavior_dynamic_foraging_metadata_mapper/instrument.py index 96ee90e..a60744a 100644 --- a/workspace/aind_behavior_dynamic_foraging_metadata_mapper/src/aind_behavior_dynamic_foraging_metadata_mapper/instrument.py +++ b/workspace/aind_behavior_dynamic_foraging_metadata_mapper/src/aind_behavior_dynamic_foraging_metadata_mapper/instrument.py @@ -146,7 +146,7 @@ def _map(self) -> Instrument: controller = rig.triggered_camera_controller fps = float(controller.frame_rate) if controller.frame_rate else float("nan") for name, cam in rig.triggered_camera_controller.cameras.items(): - additional_settings = cam.model_dump() + additional_settings = cam.camera.model_dump() additional_settings["note"] = ( "The additional_settings values are the input parameters used to initialize the camera. Model found at https://github.com/AllenNeuralDynamics/Aind.Behavior.Services/blob/a6c0f539275f73af87da82a8ea0101836389f1b3/src/aind_behavior_services/rig/cameras.py#L226. Enum clarifications: adc_bit_depth is an " "Spinnaker SDK enum-coded value (0=ADC8BIT, 1=ADC10BIT, 2=ADC12BIT), and pixel_format " @@ -166,12 +166,12 @@ def _map(self) -> Instrument: model="Blackfly S BFS-U3-04S2M", frame_rate=Decimal(str(fps)), frame_rate_unit=FrequencyUnit.HZ, - gain=Decimal(str(cam.gain) if cam.gain is not None else "0"), - serial_number=cam.serial_number, - crop_offset_x=cam.region_of_interest.x if cam.region_of_interest.x > 0 else None, - crop_offset_y=cam.region_of_interest.y if cam.region_of_interest.y > 0 else None, - crop_width=cam.region_of_interest.width if cam.region_of_interest.width > 0 else None, - crop_height=cam.region_of_interest.height if cam.region_of_interest.height > 0 else None, + gain=Decimal(str(cam.camera.gain) if cam.camera.gain is not None else "0"), + serial_number=cam.camera.serial_number, + crop_offset_x=cam.camera.region_of_interest.x if cam.camera.region_of_interest.x > 0 else None, + crop_offset_y=cam.camera.region_of_interest.y if cam.camera.region_of_interest.y > 0 else None, + crop_width=cam.camera.region_of_interest.width if cam.camera.region_of_interest.width > 0 else None, + crop_height=cam.camera.region_of_interest.height if cam.camera.region_of_interest.height > 0 else None, crop_unit=SizeUnit.PX, additional_settings=GenericModel.model_validate(additional_settings), )