From 7aed6d9de39129511619845bc6ab6b15b3b903d5 Mon Sep 17 00:00:00 2001 From: spielman Date: Tue, 24 May 2022 13:08:07 -0400 Subject: [PATCH 1/7] Check for exception_on_failed_shots in acquisition loop not just afterwards. --- labscript_devices/IMAQdxCamera/blacs_workers.py | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/labscript_devices/IMAQdxCamera/blacs_workers.py b/labscript_devices/IMAQdxCamera/blacs_workers.py index 07b3d492..3752e6f0 100644 --- a/labscript_devices/IMAQdxCamera/blacs_workers.py +++ b/labscript_devices/IMAQdxCamera/blacs_workers.py @@ -118,7 +118,7 @@ def close(self): class IMAQdx_Camera(object): - def __init__(self, serial_number): + def __init__(self, serial_number, exception_on_failed_shot=True): global nv import nivision as nv _monkeypatch_imaqdispose() @@ -139,6 +139,7 @@ def __init__(self, serial_number): ) # Keep an img attribute so we don't have to create it every time self.img = nv.imaqCreateImage(nv.IMAQ_IMAGE_U16) + self.exception_on_failed_shot = exception_on_failed_shot self._abort_acquisition = False def set_attributes(self, attr_dict): @@ -219,7 +220,14 @@ def grab_multiple(self, n_images, images, waitForNextBuffer=True): if e.code == nv.IMAQdxErrorTimeout.value: print('.', end='') continue - raise + + if self.exception_on_failed_shot: + raise + else: + print(e, file=sys.stderr) + + + print(f"Got {len(images)} of {n_images} images.") def stop_acquisition(self): @@ -277,7 +285,8 @@ def get_camera(self): if self.mock: return MockCamera() else: - return self.interface_class(self.serial_number) + return self.interface_class(self.serial_number, + exception_on_failed_shot=self.exception_on_failed_shot) def set_attributes_smart(self, attributes): """Call self.camera.set_attributes() to set the given attributes, only setting From 33a09e2fb637112bddd34edfca450cd0c7d07f37 Mon Sep 17 00:00:00 2001 From: spielman Date: Tue, 24 May 2022 13:08:39 -0400 Subject: [PATCH 2/7] So not sort attributes because they need to be commanded in a specific order. --- labscript_devices/IMAQdxCamera/blacs_workers.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/labscript_devices/IMAQdxCamera/blacs_workers.py b/labscript_devices/IMAQdxCamera/blacs_workers.py index 3752e6f0..3783e3f5 100644 --- a/labscript_devices/IMAQdxCamera/blacs_workers.py +++ b/labscript_devices/IMAQdxCamera/blacs_workers.py @@ -174,7 +174,7 @@ def get_attribute_names(self, visibility_level, writeable_only=True): if not a.Readable: continue attributes.append(a.Name.decode('utf8')) - return sorted(attributes) + return attributes def get_attribute(self, name): """Return current value of attribute of the given name""" From bdf6e84cb71b2561ddacfc015be7c0659df6a06d Mon Sep 17 00:00:00 2001 From: spielman Date: Tue, 24 May 2022 13:12:27 -0400 Subject: [PATCH 3/7] Stop acquisition on error. --- labscript_devices/IMAQdxCamera/blacs_workers.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/labscript_devices/IMAQdxCamera/blacs_workers.py b/labscript_devices/IMAQdxCamera/blacs_workers.py index 3783e3f5..ef1067c3 100644 --- a/labscript_devices/IMAQdxCamera/blacs_workers.py +++ b/labscript_devices/IMAQdxCamera/blacs_workers.py @@ -224,7 +224,9 @@ def grab_multiple(self, n_images, images, waitForNextBuffer=True): if self.exception_on_failed_shot: raise else: + # stop acquisition print(e, file=sys.stderr) + break From ea54aa883e0e55bedc5ce84a604361b8d5cb06fc Mon Sep 17 00:00:00 2001 From: MiniLab Date: Tue, 24 May 2022 15:47:41 -0400 Subject: [PATCH 4/7] Had to move exception_on_failed_shot to be a connection table item (so that it is used in the initialization of the camera subclass) --- labscript_devices/IMAQdxCamera/labscript_devices.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/labscript_devices/IMAQdxCamera/labscript_devices.py b/labscript_devices/IMAQdxCamera/labscript_devices.py index 112b84a4..935f50db 100644 --- a/labscript_devices/IMAQdxCamera/labscript_devices.py +++ b/labscript_devices/IMAQdxCamera/labscript_devices.py @@ -29,12 +29,12 @@ class IMAQdxCamera(TriggerableDevice): "pixel_size", "magnification", "manual_mode_camera_attributes", + "exception_on_failed_shot", "mock", ], "device_properties": [ "camera_attributes", "stop_acquisition_timeout", - "exception_on_failed_shot", "saved_attribute_visibility_level" ], } @@ -162,6 +162,7 @@ def __init__( if isinstance(serial_number, (str, bytes)): serial_number = int(serial_number, 16) self.serial_number = serial_number + self.exception_on_failed_shot = exception_on_failed_shot self.BLACS_connection = hex(self.serial_number)[2:].upper() if camera_attributes is None: camera_attributes = {} From ba4c4dd95e0cda5f029abf3d70413c4dbc0b0cc0 Mon Sep 17 00:00:00 2001 From: MiniLab Date: Tue, 24 May 2022 15:53:18 -0400 Subject: [PATCH 5/7] Try resetting the camera class each shot instead. --- labscript_devices/IMAQdxCamera/blacs_workers.py | 8 ++++---- labscript_devices/IMAQdxCamera/labscript_devices.py | 3 +-- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/labscript_devices/IMAQdxCamera/blacs_workers.py b/labscript_devices/IMAQdxCamera/blacs_workers.py index ef1067c3..42bcb258 100644 --- a/labscript_devices/IMAQdxCamera/blacs_workers.py +++ b/labscript_devices/IMAQdxCamera/blacs_workers.py @@ -118,7 +118,7 @@ def close(self): class IMAQdx_Camera(object): - def __init__(self, serial_number, exception_on_failed_shot=True): + def __init__(self, serial_number): global nv import nivision as nv _monkeypatch_imaqdispose() @@ -139,7 +139,7 @@ def __init__(self, serial_number, exception_on_failed_shot=True): ) # Keep an img attribute so we don't have to create it every time self.img = nv.imaqCreateImage(nv.IMAQ_IMAGE_U16) - self.exception_on_failed_shot = exception_on_failed_shot + self.exception_on_failed_shot = True self._abort_acquisition = False def set_attributes(self, attr_dict): @@ -287,8 +287,7 @@ def get_camera(self): if self.mock: return MockCamera() else: - return self.interface_class(self.serial_number, - exception_on_failed_shot=self.exception_on_failed_shot) + return self.interface_class(self.serial_number) def set_attributes_smart(self, attributes): """Call self.camera.set_attributes() to set the given attributes, only setting @@ -396,6 +395,7 @@ def transition_to_buffered(self, device_name, h5_filepath, initial_values, fresh self.stop_acquisition_timeout = properties['stop_acquisition_timeout'] self.exception_on_failed_shot = properties['exception_on_failed_shot'] saved_attr_level = properties['saved_attribute_visibility_level'] + self.camera.exception_on_failed_shot = self.exception_on_failed_shot # Only reprogram attributes that differ from those last programmed in, or all of # them if a fresh reprogramming was requested: if fresh: diff --git a/labscript_devices/IMAQdxCamera/labscript_devices.py b/labscript_devices/IMAQdxCamera/labscript_devices.py index 935f50db..112b84a4 100644 --- a/labscript_devices/IMAQdxCamera/labscript_devices.py +++ b/labscript_devices/IMAQdxCamera/labscript_devices.py @@ -29,12 +29,12 @@ class IMAQdxCamera(TriggerableDevice): "pixel_size", "magnification", "manual_mode_camera_attributes", - "exception_on_failed_shot", "mock", ], "device_properties": [ "camera_attributes", "stop_acquisition_timeout", + "exception_on_failed_shot", "saved_attribute_visibility_level" ], } @@ -162,7 +162,6 @@ def __init__( if isinstance(serial_number, (str, bytes)): serial_number = int(serial_number, 16) self.serial_number = serial_number - self.exception_on_failed_shot = exception_on_failed_shot self.BLACS_connection = hex(self.serial_number)[2:].upper() if camera_attributes is None: camera_attributes = {} From 7c463c8a8d1a1adf8d3e8d91f8a83ff1ef26e0b7 Mon Sep 17 00:00:00 2001 From: spielman Date: Tue, 24 May 2022 16:16:53 -0400 Subject: [PATCH 6/7] Added exception_on_failed_shot attribute to all devices that subclass IMAQdx imaging, but did not actually implement code to catch their internal errors. --- labscript_devices/AndorSolis/blacs_workers.py | 1 + labscript_devices/FlyCapture2Camera/blacs_workers.py | 3 ++- labscript_devices/PylonCamera/blacs_workers.py | 2 ++ labscript_devices/SpinnakerCamera/blacs_workers.py | 1 + 4 files changed, 6 insertions(+), 1 deletion(-) diff --git a/labscript_devices/AndorSolis/blacs_workers.py b/labscript_devices/AndorSolis/blacs_workers.py index e9f92604..241992d2 100644 --- a/labscript_devices/AndorSolis/blacs_workers.py +++ b/labscript_devices/AndorSolis/blacs_workers.py @@ -20,6 +20,7 @@ def __init__(self): from .andor_sdk.andor_utils import AndorCam self.camera = AndorCam() self.attributes = self.camera.default_acquisition_attrs + self.exception_on_failed_shot = True def set_attributes(self, attr_dict): self.attributes.update(attr_dict) diff --git a/labscript_devices/FlyCapture2Camera/blacs_workers.py b/labscript_devices/FlyCapture2Camera/blacs_workers.py index bc00ddce..3e0c11d6 100644 --- a/labscript_devices/FlyCapture2Camera/blacs_workers.py +++ b/labscript_devices/FlyCapture2Camera/blacs_workers.py @@ -91,7 +91,8 @@ def __init__(self, serial_number): self.pixel_formats = IntEnum('pixel_formats',fmts) self._abort_acquisition = False - + self.exception_on_failed_shot = True + # check if GigE camera. If so, ensure max packet size is used cam_info = self.camera.getCameraInfo() if cam_info.interfaceType == PyCapture2.INTERFACE_TYPE.GIGE: diff --git a/labscript_devices/PylonCamera/blacs_workers.py b/labscript_devices/PylonCamera/blacs_workers.py index 6e7d1ae6..b88e661d 100644 --- a/labscript_devices/PylonCamera/blacs_workers.py +++ b/labscript_devices/PylonCamera/blacs_workers.py @@ -45,6 +45,8 @@ def __init__(self, serial_number): # Keep a nodeMap reference so we don't have to re-create a lot self.nodeMap = self.camera.GetNodeMap() self._abort_acquisition = False + self.exception_on_failed_shot = True + def set_attributes(self, attributes_dict): """Sets all attribues in attr_dict. diff --git a/labscript_devices/SpinnakerCamera/blacs_workers.py b/labscript_devices/SpinnakerCamera/blacs_workers.py index 6bb6d9af..eef857d5 100644 --- a/labscript_devices/SpinnakerCamera/blacs_workers.py +++ b/labscript_devices/SpinnakerCamera/blacs_workers.py @@ -55,6 +55,7 @@ def __init__(self, serial_number): # Set the abort acquisition thingy: self._abort_acquisition = False + self.exception_on_failed_shot = True def get_attribute_names(self, visibility): names = [] From 404074d68a1fbb7989e5b1727ddc222687758379 Mon Sep 17 00:00:00 2001 From: spielman Date: Sun, 29 May 2022 16:48:23 -0400 Subject: [PATCH 7/7] Added exception_on_failed_shot to MockCamera since it too might be called. --- labscript_devices/IMAQdxCamera/blacs_workers.py | 1 + 1 file changed, 1 insertion(+) diff --git a/labscript_devices/IMAQdxCamera/blacs_workers.py b/labscript_devices/IMAQdxCamera/blacs_workers.py index 42bcb258..b53e923a 100644 --- a/labscript_devices/IMAQdxCamera/blacs_workers.py +++ b/labscript_devices/IMAQdxCamera/blacs_workers.py @@ -67,6 +67,7 @@ class MockCamera(object): def __init__(self): print("Starting device worker as a mock device") self.attributes = {} + self.exception_on_failed_shot = True def set_attributes(self, attributes): self.attributes.update(attributes)