diff --git a/labscript_devices/IMAQdxCamera/blacs_tabs.py b/labscript_devices/IMAQdxCamera/blacs_tabs.py
index f3b42226..0dd52ac1 100644
--- a/labscript_devices/IMAQdxCamera/blacs_tabs.py
+++ b/labscript_devices/IMAQdxCamera/blacs_tabs.py
@@ -50,13 +50,15 @@ class ImageReceiver(ZMQServer):
"""ZMQServer that receives images on a zmq.REP socket, replies 'ok', and updates the
image widget and fps indicator"""
- def __init__(self, image_view, label_fps):
+ def __init__(self, image_view, label_fps, autolevels_button):
ZMQServer.__init__(self, port=None, dtype='multipart')
self.image_view = image_view
self.label_fps = label_fps
self.last_frame_time = None
self.frame_rate = None
- self.update_event = None
+ self.image = None
+ self.bg_image = None
+ self.autolevels_button = autolevels_button
@inmain_decorator(wait_for_return=True)
def handler(self, data):
@@ -80,14 +82,10 @@ def handler(self, data):
else:
self.frame_rate = 1 / dt
self.last_frame_time = this_frame_time
- if self.image_view.image is None:
- # First time setting an image. Do autoscaling etc:
- self.image_view.setImage(image.swapaxes(-1, -2))
- else:
- # Updating image. Keep zoom/pan/levels/etc settings.
- self.image_view.setImage(
- image.swapaxes(-1, -2), autoRange=False, autoLevels=False
- )
+
+ self.image = image
+ self.update_image()
+
# Update fps indicator:
if self.frame_rate is not None:
self.label_fps.setText(f"{self.frame_rate:.01f} fps")
@@ -105,6 +103,34 @@ def handler(self, data):
QtGui.QApplication.instance().sendPostedEvents()
return self.NO_RESPONSE
+ @inmain_decorator(wait_for_return=True)
+ def update_image(self):
+ image = self.image
+ if self.bg_image is not None:
+ image = self.image.astype(float) - self.bg_image.astype(float)
+ autolevels = self.autolevels_button.isChecked()
+ if self.image_view.image is None:
+ # First time setting an image. Do autoscaling etc:
+ self.image_view.setImage(image.swapaxes(-1, -2))
+ else:
+ self.image_view.setImage(
+ image.swapaxes(-1, -2),
+ autoRange=False,
+ autoLevels=autolevels,
+ autoHistogramRange=autolevels,
+ )
+
+ @inmain_decorator()
+ def set_bg_image(self):
+ self.bg_image = self.image
+ self.update_image()
+
+ @inmain_decorator()
+ def clear_bg_image(self):
+ self.bg_image = None
+ self.update_image()
+
+
class IMAQdxCameraTab(DeviceTab):
# Subclasses may override this if all they do is replace the worker class with a
@@ -128,6 +154,8 @@ def initialise_GUI(self):
self.ui.pushButton_snap.clicked.connect(self.on_snap_clicked)
self.ui.pushButton_attributes.clicked.connect(self.on_attributes_clicked)
self.ui.toolButton_nomax.clicked.connect(self.on_reset_rate_clicked)
+ self.ui.pushButton_set_bg.clicked.connect(self.on_set_bg_clicked)
+ self.ui.pushButton_clear_bg.clicked.connect(self.on_clear_bg_clicked)
self.attributes_dialog = UiLoader().load(attributes_ui_filepath)
self.attributes_dialog.setParent(self.ui.parent())
@@ -146,6 +174,7 @@ def initialise_GUI(self):
)
self.ui.horizontalLayout.addWidget(self.image)
self.ui.pushButton_stop.hide()
+ self.ui.pushButton_clear_bg.hide()
self.ui.doubleSpinBox_maxrate.hide()
self.ui.toolButton_nomax.hide()
self.ui.label_fps.hide()
@@ -163,7 +192,9 @@ def initialise_GUI(self):
widget.setSizePolicy(size_policy)
# Start the image receiver ZMQ server:
- self.image_receiver = ImageReceiver(self.image, self.ui.label_fps)
+ self.image_receiver = ImageReceiver(
+ self.image, self.ui.label_fps, self.ui.pushButtonAutoLevels
+ )
self.acquiring = False
self.supports_smart_programming(self.use_smart_programming)
@@ -173,7 +204,8 @@ def get_save_data(self):
'attribute_visibility': self.attributes_dialog.comboBox.currentText(),
'acquiring': self.acquiring,
'max_rate': self.ui.doubleSpinBox_maxrate.value(),
- 'colormap': repr(self.image.ui.histogram.gradient.saveState())
+ 'colormap': repr(self.image.ui.histogram.gradient.saveState()),
+ 'autolevels': self.ui.pushButtonAutoLevels.isChecked(),
}
def restore_save_data(self, save_data):
@@ -188,6 +220,7 @@ def restore_save_data(self, save_data):
self.image.ui.histogram.gradient.restoreState(
ast.literal_eval(save_data['colormap'])
)
+ self.ui.pushButtonAutoLevels.setChecked(save_data.get('autolevels', False))
def initialise_workers(self):
@@ -259,6 +292,16 @@ def on_stop_clicked(self, button):
self.acquiring = False
self.stop_continuous()
+ def on_set_bg_clicked(self, button):
+ self.image_receiver.set_bg_image()
+ self.ui.pushButton_set_bg.hide()
+ self.ui.pushButton_clear_bg.show()
+
+ def on_clear_bg_clicked(self, button):
+ self.image_receiver.clear_bg_image()
+ self.ui.pushButton_set_bg.show()
+ self.ui.pushButton_clear_bg.hide()
+
def on_copy_clicked(self, button):
text = self.attributes_dialog.plainTextEdit.toPlainText()
clipboard = QtGui.QApplication.instance().clipboard()
pFad - Phonifier reborn
Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.
Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.
Alternative Proxies:
Alternative Proxy
pFad Proxy
pFad v3 Proxy
pFad v4 Proxy