Skip to content

Commit

Permalink
Merge pull request #86 from Alpaca233/ldi
Browse files Browse the repository at this point in the history
Fix LDI laser engine errors caused by IlluminationController
  • Loading branch information
hongquanli authored Feb 3, 2025
2 parents c428144 + 411f924 commit 04b65fb
Show file tree
Hide file tree
Showing 6 changed files with 56 additions and 87 deletions.
51 changes: 14 additions & 37 deletions software/control/celesta.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,10 @@
from squid.abc import LightSource
from control.microscope import LightSourceType, IntensityControlMode, ShutterControlMode

import squid.logging

log = squid.logging.get_logger(__name__)


def lumencor_httpcommand(command="GET IP", ip="192.168.201.200"):
"""
Expand Down Expand Up @@ -43,9 +47,9 @@ def __init__(self, **kwds):
self.n_lasers = self.get_number_lasers()
self.live = True
except:
print(traceback.format_exc())
log.error(traceback.format_exc())
self.live = False
print("Failed to connect to Lumencor Laser at ip:", ip)
log.error("Failed to connect to Lumencor Laser at ip:", ip)

if self.live:
[self.pmin, self.pmax] = self.get_intensity_range()
Expand Down Expand Up @@ -89,17 +93,14 @@ def get_color(self, laser_id):
"""Returns the color of the current laser"""
self.message = lumencor_httpcommand(command="GET CHMAP", ip=self.ip)
colors = self.message["message"].split(" ")[2:]
print(colors)
log.info(colors)
return colors[int(laser_id)]

def get_IP(self):
self.message = lumencor_httpcommand(command="GET IP", ip=self.ip)
return self.message

def get_shutter_control_mode(self):
"""
Return True/False the lasers can be controlled with TTL.
"""
self.message = lumencor_httpcommand(command="GET TTLENABLE", ip=self.ip)
response = self.message["message"]
if response[-1] == "1":
Expand All @@ -108,63 +109,45 @@ def get_shutter_control_mode(self):
return ShutterControlMode.Software

def set_shutter_control_mode(self, mode):
"""
Turn on/off external TTL control mode.
"""
if mode == ShutterControlMode.TTL:
ttl_enable = "1"
else:
ttl_enable = "0"
self.message = lumencor_httpcommand(command="SET TTLENABLE " + ttl_enable, ip=self.ip)

def get_shutter_state(self, laser_id):
"""
Return True/False the laser is on/off.
"""
self.message = lumencor_httpcommand(command="GET CH " + str(laser_id), ip=self.ip)
response = self.message["message"]
self.on = response[-1] == "1"
return self.on

def get_intensity_range(self):
"""
Return [minimum power, maximum power].
"""
max_int = 1000 # default
self.message = lumencor_httpcommand(command="GET MAXINT", ip=self.ip)
if self.message["message"][0] == "A":
max_int = float(self.message["message"].split(" ")[-1])
return [0, max_int]

def get_intensity(self, laser_id):
"""
Return the current laser power.
"""
self.message = lumencor_httpcommand(command="GET CHINT " + str(laser_id), ip=self.ip)
# print(command = 'GET CHINT '+str(laser_id), ip=self.ip)
log.debug(command = 'GET CHINT '+str(laser_id), ip=self.ip)
response = self.message["message"]
power = float(response.split(" ")[-1])
return power
intensity = power / self.pmax * 100
return intensity

def set_shutter_state(self, laser_id, on):
"""
Turn the laser on/off.
"""
if on:
self.message = lumencor_httpcommand(command="SET CH " + str(laser_id) + " 1", ip=self.ip)
self.on = True
else:
self.message = lumencor_httpcommand(command="SET CH " + str(laser_id) + " 0", ip=self.ip)
self.on = False
print("Turning On/Off", self.on, self.message)
log.info("Turning On/Off", self.on, self.message)

def set_intensity(self, laser_id, power_in_mw):
"""
power_in_mw - The desired laser power in mW.
"""
print("Setting Power", power_in_mw, self.message)
if power_in_mw > self.pmax:
power_in_mw = self.pmax
def set_intensity(self, laser_id, intensity):
log.info("Setting intensity to ", intensity)
power_in_mw = self.pmax * intensity / 100
self.message = lumencor_httpcommand(
command="SET CHINT " + str(laser_id) + " " + str(int(power_in_mw)), ip=self.ip
)
Expand All @@ -173,18 +156,12 @@ def set_intensity(self, laser_id, power_in_mw):
return False

def shut_down(self):
"""
Turn the laser off.
"""
if self.live:
for i in range(self.n_lasers):
self.set_intensity(i, 0)
self.set_shutter_state(i, False)

def get_status(self):
"""
Get the status
"""
return self.live


Expand Down
3 changes: 0 additions & 3 deletions software/control/core/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -522,9 +522,6 @@ def __init__(

self.enable_channel_auto_filter_switching = True

if USE_LDI_SERIAL_CONTROL:
self.ldi = self.microscope.ldi

if SUPPORT_SCIMICROSCOPY_LED_ARRAY:
# to do: add error handling
self.led_array = serial_peripherals.SciMicroscopyLEDArray(
Expand Down
6 changes: 3 additions & 3 deletions software/control/gui_hcs.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
import squid.config
import squid.stage.utils
import control.microscope
from control.microscope import LightSourceType, IntensityControlMode, ShutterControlMode
from control.microscope import LightSourceType, IntensityControlMode, ShutterControlMode, IlluminationController

log = squid.logging.get_logger(__name__)

Expand Down Expand Up @@ -374,7 +374,7 @@ def loadHardwareObjects(self):
if USE_LDI_SERIAL_CONTROL:
try:
self.ldi = serial_peripherals.LDI()
self.illuminationController = control.microscope.IlluminationController(
self.illuminationController = IlluminationController(
self.microcontroller, self.ldi.intensity_mode, self.ldi.shutter_mode, LightSourceType.LDI, self.ldi
)
except Exception:
Expand All @@ -386,7 +386,7 @@ def loadHardwareObjects(self):
import control.celesta

self.celesta = control.celesta.CELESTA()
self.illuminationController = control.microscope.IlluminationController(
self.illuminationController = IlluminationController(
self.microcontroller,
IntensityControlMode.Software,
ShutterControlMode.TTL,
Expand Down
13 changes: 2 additions & 11 deletions software/control/microscope.py
Original file line number Diff line number Diff line change
Expand Up @@ -213,7 +213,6 @@ def __init__(
self.channel_mappings_software = {}
self.is_on = {}
self.intensity_settings = {}
self.pmin, self.pmax = 0, 1000
self.current_channel = None

if self.light_source_type is not None:
Expand All @@ -224,7 +223,6 @@ def configure_light_source(self):
self.set_intensity_control_mode(self.intensity_control_mode)
self.set_shutter_control_mode(self.shutter_control_mode)
self.channel_mappings_software = self.light_source.channel_mappings
self.get_intensity_range()
for ch in self.channel_mappings_software:
self.intensity_settings[ch] = self.get_intensity(ch)
self.is_on[ch] = self.light_source.get_shutter_state(self.channel_mappings_software[ch])
Expand All @@ -249,14 +247,9 @@ def get_shutter_control_mode(self):
self.shutter_control_mode = mode
return mode

def get_intensity_range(self, channel=None):
if self.intensity_control_mode == IntensityControlMode.Software:
[self.pmin, self.pmax] = self.light_source.get_intensity_range()

def get_intensity(self, channel):
if self.intensity_control_mode == IntensityControlMode.Software:
power = self.light_source.get_intensity(self.channel_mappings_software[channel])
intensity = power / self.pmax * 100
intensity = self.light_source.get_intensity(self.channel_mappings_software[channel])
self.intensity_settings[channel] = intensity
return intensity # 0 - 100

Expand All @@ -267,7 +260,6 @@ def turn_on_illumination(self, channel=None):
if self.shutter_control_mode == ShutterControlMode.Software:
self.light_source.set_shutter_state(self.channel_mappings_software[channel], on=True)
elif self.shutter_control_mode == ShutterControlMode.TTL:
print("TTL!!")
# self.microcontroller.set_illumination(self.channel_mappings_TTL[channel], self.intensity_settings[channel])
self.microcontroller.turn_on_illumination()

Expand All @@ -290,8 +282,7 @@ def set_current_channel(self, channel):
def set_intensity(self, channel, intensity):
if self.intensity_control_mode == IntensityControlMode.Software:
if intensity != self.intensity_settings[channel]:
power = intensity / 100 * self.pmax
self.light_source.set_intensity(self.channel_mappings_software[channel], power)
self.light_source.set_intensity(self.channel_mappings_software[channel], intensity)
self.intensity_settings[channel] = intensity
self.microcontroller.set_illumination(self.channel_mappings_TTL[channel], intensity)

Expand Down
60 changes: 37 additions & 23 deletions software/control/serial_peripherals.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
import time
from typing import Tuple, Optional
import struct
from control.microscope import LightSourceType, IntensityControlMode, ShutterControlMode
from control._def import *
from squid.abc import LightSource

import squid.logging
Expand Down Expand Up @@ -430,6 +432,7 @@ def __init__(self, SN="00000001"):
735: 730,
750: 730,
}
self.active_channel = None

def initialize(self):
self.serial_connection.write_and_check("run!\r", "ok")
Expand Down Expand Up @@ -459,33 +462,48 @@ def set_intensity(self, channel, intensity):
intensity = "{:.2f}".format(intensity)
self.log.debug("set:" + channel + "=" + intensity + "\r")
self.serial_connection.write_and_check("set:" + channel + "=" + intensity + "\r", "ok")
self.log.debug("active channel: " + str(self.active_channel))

def get_intensity(self, channel):
return 0 # To be implemented

def get_intensity_range(self):
return [0, 100]

def set_shutter_state(self, channel, state):
try:
response = self.serial_connection.write_and_read("set?\r")
pairs = response.replace('SET:', '').split(',')
intensities = {}
for pair in pairs:
channel, value = pair.split('=')
intensities[int(channel)] = int(value)
return intensity[channel]
except:
return None

def set_shutter_state(self, channel, on):
channel = str(channel)
state = str(state)
state = str(on)
if self.active_channel is not None and channel != self.active_channel:
self.set_active_channel_shutter(False)
self.serial_connection.write_and_check("shutter:" + channel + "=" + state + "\r", "ok")
if on:
self.active_channel = channel

def get_shutter_state(self, channel):
self.serial_connection.write_and_check("shutter?\r", "")
return 0 # To be implemented

def set_active_channel(self, channel):
self.active_channel = channel
self.log.debug("[set active channel to " + str(channel) + "]")
try:
response = self.serial_connection.write_and_read("shutter?" + channel + "\r")
state = response.split('=')[1]
return 1 if state == 'OPEN' else 0
except:
return None

def set_active_channel_shutter(self, state):
channel = str(self.active_channel)
state = str(state)
self.log.debug("shutter:" + channel + "=" + state + "\r")
self.serial_connection.write_and_check("shutter:" + channel + "=" + state + "\r", "ok")

def shut_down(self):
for ch in list(set(self.channel_mappings.values())):
self.set_intensity(ch, 0)
self.set_shutter_state(ch, False)
self.serial_connection.close()


class LDI_Simulation(LightSource):
"""Wrapper for communicating with LDI over serial"""
Expand Down Expand Up @@ -539,25 +557,21 @@ def set_intensity(self, channel, intensity):
def get_intensity(self, channel):
return 0

def get_intensity_range(self):
return [0, 100]

def set_shutter_state(self, channel, state):
def set_shutter_state(self, channel, on):
channel = str(channel)
state = str(state)
state = str(on)

def get_shutter_state(self, channel):
return 0

def set_active_channel(self, channel):
self.active_channel = channel
self.log.debug("[set active channel to " + str(channel) + "]")

def set_active_channel_shutter(self, state):
channel = str(self.active_channel)
state = str(state)
self.log.debug("shutter:" + channel + "=" + state + "\r")

def shut_down(self):
pass


class SciMicroscopyLEDArray:
"""Wrapper for communicating with SciMicroscopy over serial"""
Expand Down
10 changes: 0 additions & 10 deletions software/squid/abc.py
Original file line number Diff line number Diff line change
Expand Up @@ -106,16 +106,6 @@ def get_intensity(self, channel) -> float:
"""
pass

@abstractmethod
def get_intensity_range(self) -> Tuple[float, float]:
"""
Get the valid intensity range.
Returns:
Tuple[float, float]: (minimum intensity, maximum intensity)
"""
pass

@abstractmethod
def shut_down(self):
"""Safely shut down the light source."""
Expand Down

0 comments on commit 04b65fb

Please sign in to comment.