From 0900f03c1e6daf157c75da51a2d75b34dfba19a1 Mon Sep 17 00:00:00 2001 From: Benedict Diederich Date: Fri, 8 Mar 2024 23:53:51 +0100 Subject: [PATCH 1/2] Adding isrgb to daheng camera --- .../imcontrol/model/interfaces/gxipycamera.py | 4 +- .../model/managers/detectors/GXPIPYManager.py | 12 +++- .../managers/lasers/ESP32LEDLaserManager.py | 6 +- tools/loadTimeSeriesStackChannel.py | 59 +++++++++++++++++++ 4 files changed, 73 insertions(+), 8 deletions(-) create mode 100644 tools/loadTimeSeriesStackChannel.py diff --git a/imswitch/imcontrol/model/interfaces/gxipycamera.py b/imswitch/imcontrol/model/interfaces/gxipycamera.py index 5abc3684d..2a18cc112 100644 --- a/imswitch/imcontrol/model/interfaces/gxipycamera.py +++ b/imswitch/imcontrol/model/interfaces/gxipycamera.py @@ -14,14 +14,14 @@ class TriggerMode: CONTINUOUS = 'Continuous Acqusition' class CameraGXIPY: - def __init__(self,cameraNo=None, exposure_time = 10000, gain = 0, frame_rate=-1, blacklevel=100, binning=1, flipImage=(False, False)): + def __init__(self,cameraNo=None, exposure_time = 10000, gain = 0, frame_rate=-1, blacklevel=100, binning=1, flipImage=(False, False), isRGB=False): super().__init__() self.__logger = initLogger(self, tryInheritParent=True) # many to be purged self.model = "CameraGXIPY" self.shape = (0, 0) - + self.isRGB = isRGB self.is_connected = False self.is_streaming = False diff --git a/imswitch/imcontrol/model/managers/detectors/GXPIPYManager.py b/imswitch/imcontrol/model/managers/detectors/GXPIPYManager.py index 5c9231a58..c7258b2df 100644 --- a/imswitch/imcontrol/model/managers/detectors/GXPIPYManager.py +++ b/imswitch/imcontrol/model/managers/detectors/GXPIPYManager.py @@ -47,9 +47,15 @@ def __init__(self, detectorInfo, name, **_lowLevelManagers): except: self.flipY = False + + try: + self._isRGB = detectorInfo.managerProperties['gxipycam']['isRGB'] + except: + self._isRGB = False + self.flipImage = (self.flipX, self.flipY) - self._camera = self._getGXObj(self.cameraId, self.binningValue, self.flipImage) + self._camera = self._getGXObj(self.cameraId, self.binningValue, self.flipImage, self._isRGB) fullShape = (self._camera.SensorWidth, self._camera.SensorHeight) @@ -305,7 +311,7 @@ def _performSafeCameraAction(self, function): def openPropertiesDialog(self): self._camera.openPropertiesGUI() - def _getGXObj(self, cameraId, binning=1, flipImage=(False, False)): + def _getGXObj(self, cameraId, binning=1, flipImage=(False, False), isRGB=False): try: import os if os.name == 'darwin': @@ -314,7 +320,7 @@ def _getGXObj(self, cameraId, binning=1, flipImage=(False, False)): else: from imswitch.imcontrol.model.interfaces.gxipycamera import CameraGXIPY self.__logger.debug(f'Trying to initialize Daheng Imaging camera {cameraId}') - camera = CameraGXIPY(cameraNo=cameraId, binning=binning, flipImage=flipImage) + camera = CameraGXIPY(cameraNo=cameraId, binning=binning, flipImage=flipImage, isRGB=isRGB) except Exception as e: self.__logger.debug(e) self.__logger.warning(f'Failed to initialize CameraGXIPY {cameraId}, loading TIS mocker') diff --git a/imswitch/imcontrol/model/managers/lasers/ESP32LEDLaserManager.py b/imswitch/imcontrol/model/managers/lasers/ESP32LEDLaserManager.py index 52218b5f4..53e1ba444 100644 --- a/imswitch/imcontrol/model/managers/lasers/ESP32LEDLaserManager.py +++ b/imswitch/imcontrol/model/managers/lasers/ESP32LEDLaserManager.py @@ -48,7 +48,7 @@ def __init__(self, laserInfo, name, **lowLevelManagers): self.enabled = False self.setEnabled(self.enabled) - def setEnabled(self, enabled, getReturn=True): + def setEnabled(self, enabled, getReturn=False): """Turn on (N) or off (F) laser emission""" self.enabled = enabled if self.channel_index == "LED": @@ -60,7 +60,7 @@ def setEnabled(self, enabled, getReturn=True): int(self.power*self.enabled), despeckleAmplitude = self.laser_despeckle_amplitude, despecklePeriod = self.laser_despeckle_period, - is_blocking=True) + is_blocking=getReturn) def setValue(self, power, getReturn=False): """Handles output power. @@ -82,7 +82,7 @@ def setValue(self, power, getReturn=False): int(self.power), despeckleAmplitude = self.laser_despeckle_amplitude, despecklePeriod = self.laser_despeckle_period, - is_blocking=True) + is_blocking=getReturn) def sendTrigger(self, triggerId): self._esp32.digital.sendTrigger(triggerId) diff --git a/tools/loadTimeSeriesStackChannel.py b/tools/loadTimeSeriesStackChannel.py new file mode 100644 index 000000000..c2669e808 --- /dev/null +++ b/tools/loadTimeSeriesStackChannel.py @@ -0,0 +1,59 @@ +import os +import re +import tifffile +import numpy as np +import cv2 + +# Function to extract information from filename +def parse_filename(filename): + # Extract date, Z position, and channel using regex + match = re.search(r'(\d{4}_\d{2}_\d{2})-.*_Z_(-?\d+\.\d+).*_(LED|Laser\d)_', filename) + if match: + return match.group(1), float(match.group(2)), match.group(3) + return None, None, None + +# Function to load images from a folder +def load_images_from_folder(folder): + images = {} + for filename in os.listdir(folder): + if filename.endswith(".tif"): + date, z_pos, channel = parse_filename(filename) + if date and z_pos and channel: + key = (date, channel, z_pos) + img_path = os.path.join(folder, filename) + img = tifffile.imread(img_path) + if key in images: + images[key].append(img) + else: + images[key] = [img] + return images + +# Loading images from all folders +all_images = {} + +import os +# Specify the parent directory +parent_directory = 'C:\\Users\\user\\Documents\\ImSwitchConfig\\recordings\\2024_01_22-04-43-17_PM' +# List all subdirectories starting with 't' +subfolders = [f.name for f in os.scandir(parent_directory) if f.is_dir() and f.name.startswith('t')] +# Print the list of subfolders +print(subfolders) + +for folder in subfolders: + all_images.update(load_images_from_folder(parent_directory+"\\"+folder)) + +# Organizing and concatenating images for each channel +timelapses = {} +for key in sorted(all_images.keys()): + date, channel, z_pos = key + if channel not in timelapses: + timelapses[channel] = [] + # Assuming that images for the same channel and date are part of the same timeseries + timelapses[channel].append(np.concatenate(all_images[key], axis=1)) + +# Creating timelapse videos +for channel in timelapses: + out = cv2.VideoWriter(f'timelapse_{channel}.avi', cv2.VideoWriter_fourcc(*'DIVX'), 10, (width, height)) + for img in timelapses[channel]: + out.write(img) + out.release() From 9d746a8cb302d8198aa479e84e50fd31ed883f52 Mon Sep 17 00:00:00 2001 From: Benedict Diederich Date: Mon, 11 Mar 2024 21:58:04 +0100 Subject: [PATCH 2/2] Update TemperatureController.py --- .../imcontrol/controller/controllers/TemperatureController.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/imswitch/imcontrol/controller/controllers/TemperatureController.py b/imswitch/imcontrol/controller/controllers/TemperatureController.py index a73790e34..53f577ea3 100644 --- a/imswitch/imcontrol/controller/controllers/TemperatureController.py +++ b/imswitch/imcontrol/controller/controllers/TemperatureController.py @@ -35,10 +35,12 @@ def __init__(self, *args, **kwargs): self.Ki = 0.1 self.Kd = .5 self.PIDenabled = False + self.pollingPeriod = 5 # get hold on the Temperature Controller try: self.temperatureController = self._master.rs232sManager["ESP32"]._esp32.temperature + self.temperatureController.start_temperature_polling(period=self.pollingPeriod) except: return # Connect TemperatureWidget signals @@ -130,7 +132,7 @@ def updateSetPointData(self): def updateMeasurements(self): while self.is_measure: self.temperatureValue = self.temperatureController.get_temperature() - if self.temperatureValue > -200: # if not, we have faulty values + if self.temperatureValue and self.temperatureValue > -200: # if not, we have faulty values self._widget.updateTemperature(self.temperatureValue)