2626class _DeviceNode :
2727 """Helper class to keep track of devices, their connections and spawned devices"""
2828
29+ device_name : str
2930 device : devices .Device
3031 connections_from : list [connections .Connection ] = dataclasses .field (default_factory = list )
3132 spawned_devices : list [devices .Device ] = dataclasses .field (default_factory = list )
3233
33- @property
34- def device_name (self ) -> str :
35- return self .device .name
36-
3734 def get_spawned_device (self , name : str ) -> devices .Device :
3835 for d in self .spawned_devices :
3936 if d .name == name :
@@ -165,7 +162,7 @@ def _get_calibrations(rig: AindVrForagingRig) -> list[measurements.Calibration]:
165162 @staticmethod
166163 def _get_harp_behavior_node (rig : AindVrForagingRig ) -> _DeviceNode :
167164 _connections : list [connections .Connection ] = []
168- source_device = rig . harp_behavior . name or "harp_behavior"
165+ source_device = validate_name ( rig , "harp_behavior" )
169166
170167 # Add triggered camera controller
171168 if rig .triggered_camera_controller :
@@ -239,14 +236,15 @@ def _get_harp_behavior_node(rig: AindVrForagingRig) -> _DeviceNode:
239236 )
240237
241238 return _DeviceNode (
239+ device_name = source_device ,
242240 device = _harp_device ,
243241 connections_from = _connections ,
244242 spawned_devices = [speaker , photodiode , water_valve ],
245243 )
246244
247245 @staticmethod
248246 def _get_harp_treadmill_node (rig : AindVrForagingRig ) -> _DeviceNode :
249- source_device = rig . harp_treadmill . name or "harp_treadmill"
247+ source_device = validate_name ( rig , "harp_treadmill" )
250248
251249 _connections = [
252250 connections .Connection (
@@ -293,12 +291,16 @@ def _get_harp_treadmill_node(rig: AindVrForagingRig) -> _DeviceNode:
293291 )
294292
295293 return _DeviceNode (
296- device = _harp_device , connections_from = _connections , spawned_devices = [magnetic_brake , encoder , torque_sensor ]
294+ device_name = source_device ,
295+ device = _harp_device ,
296+ connections_from = _connections ,
297+ spawned_devices = [magnetic_brake , encoder , torque_sensor ],
297298 )
298299
299300 @staticmethod
300301 def _get_harp_clock_generate_node (rig : AindVrForagingRig , components : list [devices .Device ]) -> _DeviceNode :
301- source_device = rig .harp_clock_generator .name or "harp_clock_generator"
302+ source_device = validate_name (rig , "harp_clock_generator" )
303+
302304 harp_devices = [d for d in components if isinstance (d , devices .HarpDevice )]
303305 _connections = [
304306 connections .Connection (
@@ -321,7 +323,7 @@ def _get_harp_clock_generate_node(rig: AindVrForagingRig, components: list[devic
321323 ],
322324 )
323325
324- return _DeviceNode (device = harp_device , connections_from = _connections )
326+ return _DeviceNode (device_name = source_device , device = harp_device , connections_from = _connections )
325327
326328 @staticmethod
327329 def _get_wheel (
@@ -367,16 +369,25 @@ def _get_all_components_and_connections(
367369
368370 # Get all other harp devices
369371 harp_lickometer = devices .HarpDevice (
370- name = rig . harp_lickometer . name or "harp_lickometer" ,
372+ name = validate_name ( rig , "harp_lickometer" ) ,
371373 harp_device_type = devices .HarpDeviceType .LICKETYSPLIT ,
372374 manufacturer = devices .Organization .AIND ,
373375 is_clock_generator = False ,
374376 )
375377
378+ harp_stepper_motor = devices .HarpDevice (
379+ name = validate_name (rig , "manipulator" ),
380+ harp_device_type = devices .HarpDeviceType .STEPPERDRIVER ,
381+ manufacturer = devices .Organization .OEPS ,
382+ is_clock_generator = False ,
383+ )
384+
385+ _components .append (harp_stepper_motor )
386+
376387 if rig .harp_sniff_detector is not None :
377388 _components .append (
378389 devices .HarpDevice (
379- name = rig . harp_sniff_detector . name or "harp_sniff_detector" ,
390+ name = validate_name ( rig , "harp_sniff_detector" ) ,
380391 harp_device_type = devices .HarpDeviceType .SNIFFDETECTOR ,
381392 is_clock_generator = False ,
382393 )
@@ -385,7 +396,7 @@ def _get_all_components_and_connections(
385396 if rig .harp_environment_sensor is not None :
386397 _components .append (
387398 devices .HarpDevice (
388- name = rig . harp_environment_sensor . name or "harp_environment_sensor" ,
399+ name = validate_name ( rig , "harp_environment_sensor" ) ,
389400 harp_device_type = devices .HarpDeviceType .ENVIRONMENTSENSOR ,
390401 is_clock_generator = False ,
391402 )
@@ -490,7 +501,7 @@ def _get_lickspout_assembly(
490501 model = "328-300-00" ,
491502 travel = Decimal ("30" ),
492503 travel_unit = units .SizeUnit .CM ,
493- notes = "This stage is driven by the HarpStepperDriver device." ,
504+ notes = "This stage is driven by the manipulator device." ,
494505 )
495506
496507 return devices .LickSpoutAssembly (
@@ -695,3 +706,10 @@ def _get_olfactometer_channel(
695706 channel_type = ch_type_to_ch_type [ch .channel_type ],
696707 flow_capacity = ch .flow_rate_capacity ,
697708 )
709+
710+
711+ def validate_name (obj : object , name : str ) -> str :
712+ if hasattr (obj , name ):
713+ return name
714+ else :
715+ raise ValueError (f"Model { obj .__class__ .__name__ } does not contain a field { name } ." )
0 commit comments