Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: move lighting tools to their own module to avoid circular import #89

Merged
merged 8 commits into from
Feb 4, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 17 additions & 12 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,25 +10,30 @@ jobs:
contents: read
runs-on: ubuntu-22.04
steps:
# Our workflows were running out of memory. We don't need most of the pre-installed machinery in the
# github ubuntu image, so remove it using this helper action.
# See: https://github.com/marketplace/actions/free-disk-space-ubuntu
- name: Free Disk Space (Ubuntu)
uses: jlumbroso/free-disk-space@main
with:
tool-cache: false
android: true
dotnet: true
haskell: true
large-packages: true
docker-images: true
swap-storage: true
- name: Checkout the Squid repo
uses: actions/checkout@v4
- name: Run the setup script for Ubuntu 22.04
run: ./setup_22.04.sh
run: ./setup_22.04.sh -r=${{ github.workspace }}
working-directory: ./software
env:
SRC_ROOT: "${{ runner.temp }}"
- name: Run the cuda setup script
run: ./setup_cuda_22.04.sh
working-directory: ./software
env:
SRC_ROOT: "${{ runner.temp }}"
# NOTE(imo): Our setup script checks out the repository, so we actually check it out twice.
# Once to get the script (using actions/checkout@v4), then again via the script. We want to do
# all of our actually testing in the one the script checks out, though, so make sure we set SRC_ROOT
# properly and then use the same working directory for running within the setup script's checkout
- name: "TEMPORARY: copy a valid config into the repo software root"
- name: "Copy a valid config into the repo software root"
run: cp configurations/configuration_Squid+.ini .
working-directory: "${{ runner.temp }}/Squid/software"
working-directory: ./software
- name: Run the tests
run: python3 -m pytest
working-directory: "${{ runner.temp }}/Squid/software"
working-directory: ./software
2 changes: 1 addition & 1 deletion software/control/celesta.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
import urllib.request
import traceback
from squid.abc import LightSource
from control.microscope import LightSourceType, IntensityControlMode, ShutterControlMode
from control.lighting import LightSourceType, IntensityControlMode, ShutterControlMode

import squid.logging

Expand Down
6 changes: 4 additions & 2 deletions software/control/gui_hcs.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
# set QT_API environment variable
import os

import control.lighting

os.environ["QT_API"] = "pyqt5"
import serial
import time
Expand All @@ -21,7 +23,7 @@
import squid.config
import squid.stage.utils
import control.microscope
from control.microscope import LightSourceType, IntensityControlMode, ShutterControlMode, IlluminationController
from control.lighting import LightSourceType, IntensityControlMode, ShutterControlMode, IlluminationController

log = squid.logging.get_logger(__name__)

Expand Down Expand Up @@ -325,7 +327,7 @@ def loadSimulationObjects(self):
self.camera_focus = camera_fc.Camera_Simulation()
if USE_LDI_SERIAL_CONTROL:
self.ldi = serial_peripherals.LDI_Simulation()
self.illuminationController = control.microscope.IlluminationController(
self.illuminationController = control.lighting.IlluminationController(
self.microcontroller, self.ldi.intensity_mode, self.ldi.shutter_mode, LightSourceType.LDI, self.ldi
)
self.camera = camera.Camera_Simulation(rotate_image_angle=ROTATE_IMAGE_ANGLE, flip_image=FLIP_IMAGE)
Expand Down
127 changes: 127 additions & 0 deletions software/control/lighting.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
from enum import Enum


class LightSourceType(Enum):
SquidLED = 0
SquidLaser = 1
LDI = 2
CELESTA = 3
VersaLase = 4
SCI = 5


class IntensityControlMode(Enum):
SquidControllerDAC = 0
Software = 1


class ShutterControlMode(Enum):
TTL = 0
Software = 1


class IlluminationController:
def __init__(
self, microcontroller, intensity_control_mode, shutter_control_mode, light_source_type=None, light_source=None
):
self.microcontroller = microcontroller
self.intensity_control_mode = intensity_control_mode
self.shutter_control_mode = shutter_control_mode
self.light_source_type = light_source_type
self.light_source = light_source
self.channel_mappings_TTL = {
405: 11,
470: 12,
488: 12,
545: 14,
550: 14,
555: 14,
561: 14,
638: 13,
640: 13,
730: 15,
735: 15,
750: 15,
}

self.channel_mappings_software = {}
self.is_on = {}
self.intensity_settings = {}
self.current_channel = None

if self.light_source_type is not None:
self.configure_light_source()

def configure_light_source(self):
self.light_source.initialize()
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
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])

def set_intensity_control_mode(self, mode):
self.light_source.set_intensity_control_mode(mode)
self.intensity_control_mode = mode

def get_intensity_control_mode(self):
mode = self.light_source.get_intensity_control_mode()
if mode is not None:
self.intensity_control_mode = mode
return mode

def set_shutter_control_mode(self, mode):
self.light_source.set_shutter_control_mode(mode)
self.shutter_control_mode = mode

def get_shutter_control_mode(self):
mode = self.light_source.get_shutter_control_mode()
if mode is not None:
self.shutter_control_mode = mode
return mode

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

def turn_on_illumination(self, channel=None):
if channel is None:
channel = self.current_channel

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:
# self.microcontroller.set_illumination(self.channel_mappings_TTL[channel], self.intensity_settings[channel])
self.microcontroller.turn_on_illumination()

self.is_on[channel] = True

def turn_off_illumination(self, channel=None):
if channel is None:
channel = self.current_channel

if self.shutter_control_mode == ShutterControlMode.Software:
self.light_source.set_shutter_state(self.channel_mappings_software[channel], on=False)
elif self.shutter_control_mode == ShutterControlMode.TTL:
self.microcontroller.turn_off_illumination()

self.is_on[channel] = False

def set_current_channel(self, channel):
self.current_channel = channel

def set_intensity(self, channel, intensity):
if self.intensity_control_mode == IntensityControlMode.Software:
if intensity != self.intensity_settings[channel]:
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)

def get_shutter_state(self):
return self.is_on

def close(self):
self.light_source.shut_down()
128 changes: 0 additions & 128 deletions software/control/microscope.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
import serial
import time
from enum import Enum

from PyQt5.QtCore import QObject

Expand Down Expand Up @@ -166,129 +164,3 @@ def close(self):
self.microcontroller.close()
if USE_ZABER_EMISSION_FILTER_WHEEL or USE_OPTOSPIN_EMISSION_FILTER_WHEEL:
self.emission_filter_wheel.close()


class LightSourceType(Enum):
SquidLED = 0
SquidLaser = 1
LDI = 2
CELESTA = 3
VersaLase = 4
SCI = 5


class IntensityControlMode(Enum):
SquidControllerDAC = 0
Software = 1


class ShutterControlMode(Enum):
TTL = 0
Software = 1


class IlluminationController:
def __init__(
self, microcontroller, intensity_control_mode, shutter_control_mode, light_source_type=None, light_source=None
):
self.microcontroller = microcontroller
self.intensity_control_mode = intensity_control_mode
self.shutter_control_mode = shutter_control_mode
self.light_source_type = light_source_type
self.light_source = light_source
self.channel_mappings_TTL = {
405: 11,
470: 12,
488: 12,
545: 14,
550: 14,
555: 14,
561: 14,
638: 13,
640: 13,
730: 15,
735: 15,
750: 15,
}

self.channel_mappings_software = {}
self.is_on = {}
self.intensity_settings = {}
self.current_channel = None

if self.light_source_type is not None:
self.configure_light_source()

def configure_light_source(self):
self.light_source.initialize()
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
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])

def set_intensity_control_mode(self, mode):
self.light_source.set_intensity_control_mode(mode)
self.intensity_control_mode = mode

def get_intensity_control_mode(self):
mode = self.light_source.get_intensity_control_mode()
if mode is not None:
self.intensity_control_mode = mode
return mode

def set_shutter_control_mode(self, mode):
self.light_source.set_shutter_control_mode(mode)
self.shutter_control_mode = mode

def get_shutter_control_mode(self):
mode = self.light_source.get_shutter_control_mode()
if mode is not None:
self.shutter_control_mode = mode
return mode

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

def turn_on_illumination(self, channel=None):
if channel is None:
channel = self.current_channel

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:
# self.microcontroller.set_illumination(self.channel_mappings_TTL[channel], self.intensity_settings[channel])
self.microcontroller.turn_on_illumination()

self.is_on[channel] = True

def turn_off_illumination(self, channel=None):
if channel is None:
channel = self.current_channel

if self.shutter_control_mode == ShutterControlMode.Software:
self.light_source.set_shutter_state(self.channel_mappings_software[channel], on=False)
elif self.shutter_control_mode == ShutterControlMode.TTL:
self.microcontroller.turn_off_illumination()

self.is_on[channel] = False

def set_current_channel(self, channel):
self.current_channel = channel

def set_intensity(self, channel, intensity):
if self.intensity_control_mode == IntensityControlMode.Software:
if intensity != self.intensity_settings[channel]:
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)

def get_shutter_state(self):
return self.is_on

def close(self):
self.light_source.shut_down()
2 changes: 1 addition & 1 deletion software/control/serial_peripherals.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import time
from typing import Tuple, Optional
import struct
from control.microscope import LightSourceType, IntensityControlMode, ShutterControlMode
from control.lighting import LightSourceType, IntensityControlMode, ShutterControlMode
from control._def import *
from squid.abc import LightSource

Expand Down
Loading
Loading