Skip to content
19 changes: 5 additions & 14 deletions src/navigate/controller/thread_pool.py
Original file line number Diff line number Diff line change
Expand Up @@ -97,11 +97,7 @@ def run(self):
try:
self._target(*self._args, **self._kwargs)
except Exception as e:
print(
f"{self.name} thread ended because of exception!: {e}",
traceback.format_exc(),
)
logger.debug(
logger.exception(
f"{self.name} thread ended because of exception!: {e}",
traceback.format_exc(),
)
Expand Down Expand Up @@ -251,13 +247,7 @@ def func(*args, **kwargs):
try:
target(*args, **kwargs)
except Exception as e:
print(
threading.current_thread().name,
"thread exception happened!",
e,
traceback.format_exc(),
)
logger.debug(
logger.exception(
threading.current_thread().name,
"thread exception happened!",
e,
Expand Down Expand Up @@ -422,10 +412,11 @@ def localtrace(self, frame, event, arg):
"""

if event == "exception":
print("****in local trace: exception stops the thread")
logger.debug("****in local trace: exception stops the thread")
if os.getenv("GITHUB_ACTIONS") == "true":
return

# Silence traceback to avoid printing to console.
sys.tracebacklimit = 0
raise SystemExit()
return self.localtrace

Expand Down
3 changes: 2 additions & 1 deletion src/navigate/model/devices/camera/hamamatsu.py
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,8 @@ def __str__(self):

def __del__(self):
"""Delete HamamatsuOrca class."""
pass
self.camera_controller.dev_close()
# self.close_camera()

@property
def serial_number(self):
Expand Down
21 changes: 18 additions & 3 deletions src/navigate/model/devices/daq/ni.py
Original file line number Diff line number Diff line change
Expand Up @@ -110,8 +110,23 @@ def __str__(self) -> str:

def __del__(self) -> None:
"""Destructor."""
if self.camera_trigger_task is not None:
self.stop_acquisition()
for task in [self.camera_trigger_task, self.master_trigger_task, self.laser_switching_task]:
if task:
try:
task.stop()
task.close()
except Exception:
logger.exception(f"Error stopping task: {traceback.format_exc()}")

if self.analog_output_tasks:
for k, task in self.analog_output_tasks.items():
if task:
try:
task.stop()
task.close()
except Exception:
logger.exception(f"Error stopping task: {traceback.format_exc()}")


def set_external_trigger(self, external_trigger=None) -> None:
"""Set trigger mode.
Expand Down Expand Up @@ -220,7 +235,7 @@ def wait_for_external_trigger(
return False
# Create a digital input task and wait until either a trigger is detected,
# or the timeout is exceeded. If timeout < 0, wait forever...
external_trigger_task = nidaqmx.Task("WaitDigitalEdge")
external_trigger_task = nidaqmx.Task()
external_trigger_task.di_channels.add_di_chan(trigger_channel)

total_wait_time = 0.0
Expand Down
10 changes: 7 additions & 3 deletions src/navigate/model/devices/filter_wheel/asi.py
Original file line number Diff line number Diff line change
Expand Up @@ -87,15 +87,15 @@ def __init__(self, device_connection, device_config):

Parameters
----------
device_connection : dict
Dictionary of device connections.
device_connection : TigerController
Communication object for the ASI Filter Wheel.
device_config : dict
Dictionary of device configuration parameters.
"""

super().__init__(device_connection, device_config)

#: obj: ASI Tiger Controller object.
#: TigerController: ASI Tiger Controller object.
self.filter_wheel = device_connection

#: dict: Configuration dictionary.
Expand Down Expand Up @@ -170,6 +170,10 @@ def close(self):
logger.debug("ASI Filter Wheel - Closing Device.")
self.filter_wheel.disconnect_from_serial()

def __del__(self):
"""Destructor for the ASIFilterWheel class."""
self.close()


@log_initialization
class ASICubeSlider(FilterWheelBase):
Expand Down
19 changes: 12 additions & 7 deletions src/navigate/model/devices/filter_wheel/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@

# Standard Library Imports
import logging
from typing import Any, Dict

# Third Party Imports

Expand All @@ -47,20 +48,20 @@
class FilterWheelBase:
"""FilterWheelBase - Parent class for controlling filter wheels."""

def __init__(self, device_connection, device_config):
def __init__(self, device_connection: Any, device_config: Dict[str, Any]) -> None:
"""Initialize the FilterWheelBase class.

Parameters
----------
device_connection : dict
Dictionary of device connections.
device_config : dict
device_connection : Any
The communication instance with the device.
device_config : Dict[str, Any]
Dictionary of device configuration parameters.
"""
#: object: Device connection object.
#: Any: Device connection object.
self.device_connection = device_connection

#: dict: Dictionary of device configuration parameters.
#: Dict[str, Any]: Dictionary of device configuration parameters.
self.device_config = device_config

#: dict: Dictionary of filters available on the filter wheel.
Expand All @@ -72,10 +73,14 @@ def __init__(self, device_connection, device_config):
#: int: index of filter wheel
self.filter_wheel_number = device_config["hardware"]["wheel_number"]

def __str__(self):
def __str__(self) -> str:
"""Return the string representation of the FilterWheelBase class."""
return "FilterWheelBase"

def __del__(self) -> None:
"""Destructor for the FilterWheelBase class."""
pass

def check_if_filter_in_filter_dictionary(self, filter_name: str) -> bool:
"""Checks if the filter designation (string) given exists in the
filter dictionary
Expand Down
5 changes: 5 additions & 0 deletions src/navigate/model/devices/filter_wheel/ludl.py
Original file line number Diff line number Diff line change
Expand Up @@ -161,3 +161,8 @@ def close(self):
logger.debug("LUDLFilterWheel - Closing the Filter Wheel Serial Port")
self.set_filter(list(self.filter_dictionary.keys())[0])
self.serial.close()

def __del__(self):
"""Destructor for the LUDLFilterWheel class."""
if self.serial.is_open:
self.close()
12 changes: 11 additions & 1 deletion src/navigate/model/devices/filter_wheel/ni.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
# Standard Library Imports
import logging
import time
import traceback

# Third Party Imports
import nidaqmx
Expand Down Expand Up @@ -144,9 +145,18 @@ def set_filter(self, filter_name, wait_until_done=True):
except DaqError as e:
logger.debug(e)

def close(self):
def close(self) -> None:
"""Close the DAQ Filter Wheel

Sets the filter wheel to the home position and then closes the port.
"""
pass

def __del__(self) -> None:
"""Delete the DAQFilterWheel object."""
if self.filter_wheel_task:
try:
self.filter_wheel_task.stop()
self.filter_wheel_task.close()
except Exception:
logger.exception(f"Error stopping task: {traceback.format_exc()}")
41 changes: 19 additions & 22 deletions src/navigate/model/devices/filter_wheel/sutter.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ def build_filter_wheel_connection(comport, baudrate, timeout=0.25):
Returns
-------
serial.Serial
Serial port connection to the filter wheel.
The serial port connection to the filter wheel.

Raises
------
Expand Down Expand Up @@ -94,17 +94,18 @@ def __init__(self, device_connection, device_config):

Parameters
----------
device_connection : dict
Dictionary of device connections.
device_config : dict
device_connection : serial.Serial
The communication instance with the filter wheel.
device_config : Dict[str, Any]
Dictionary of device configuration parameters.
"""
super().__init__(device_connection, device_config)

#: obj: Serial port connection to the filter wheel.
#: serial.Serial: Serial port connection to the filter wheel.
self.serial = device_connection

#: dict: Dictionary of filter names and corresponding filter wheel positions.
#: Dict[str, Any]: Dictionary of filter names and corresponding filter wheel
# positions.
self.device_config = device_config

#: bool: Wait until filter wheel has completed movement.
Expand Down Expand Up @@ -146,20 +147,11 @@ def __init__(self, device_connection, device_config):
# Set filter to the 0th position by default upon initialization.
self.set_filter(list(self.filter_dictionary.keys())[0])

def __str__(self):
def __str__(self) -> str:
"""String representation of the class."""
return "SutterFilterWheel"

def __enter__(self):
"""Enter the SutterFilterWheel context manager."""
return self

def __exit__(self, *args, **kwargs):
"""Exit the SutterFilterWheel context manager."""
logger.debug("SutterFilterWheel - Closing Device.")
self.close()

def filter_change_delay(self, filter_name):
def filter_change_delay(self, filter_name: str) -> None:
"""Calculate duration of time necessary to change filter wheel positions.

Calculate duration of time necessary to change filter wheel positions.
Expand Down Expand Up @@ -195,7 +187,7 @@ def filter_change_delay(self, filter_name):
except IndexError:
self.wait_until_done_delay = 0.01

def set_filter(self, filter_name, wait_until_done=True):
def set_filter(self, filter_name: str, wait_until_done: bool = True):
"""Change the filter wheel to the filter designated by the filter
position argument.

Expand Down Expand Up @@ -249,7 +241,7 @@ def set_filter(self, filter_name, wait_until_done=True):
# read 0D back.
self.read(1)

def read(self, num_bytes):
def read(self, num_bytes: int) -> bytes:
"""Reads the specified number of bytes from the serial port.

Parameters
Expand All @@ -259,8 +251,8 @@ def read(self, num_bytes):

Returns
-------
bytes
Bytes read from the serial port.
response : bytes
The bytes read from the serial port.

Raises
------
Expand All @@ -285,11 +277,16 @@ def read(self, num_bytes):
)
return self.serial.read(num_bytes)

def close(self):
def close(self) -> None:
"""Close the SutterFilterWheel serial port.

Sets the filter wheel to the Empty-Alignment position and then closes the port.
"""
logger.debug("SutterFilterWheel - Closing the Filter Wheel Serial Port")
self.set_filter(list(self.filter_dictionary.keys())[0])
self.serial.close()

def __del__(self) -> None:
"""Delete the SutterFilterWheel class."""
if self.serial.is_open:
self.close()
4 changes: 4 additions & 0 deletions src/navigate/model/devices/filter_wheel/synthetic.py
Original file line number Diff line number Diff line change
Expand Up @@ -108,3 +108,7 @@ def close(self):
Sets the filter wheel to the Empty-Alignment position and then closes the port.
"""
pass

def __del__(self):
"""Delete the SyntheticFilterWheel."""
pass
9 changes: 7 additions & 2 deletions src/navigate/model/devices/galvo/ni.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@

# Standard Library Imports
import logging
import traceback
from typing import Any, Dict

# Third Party Imports
Expand Down Expand Up @@ -129,5 +130,9 @@ def turn_off(self) -> None:
task.write([0], auto_start=True)
task.stop()
task.close()
except Exception as e:
print(f"Galvo turn_off error: {e}")
except Exception:
logger.exception(f"Error stopping task: {traceback.format_exc()}")

def __del__(self):
"""Close the GalvoNI at exit."""
self.turn_off()
15 changes: 15 additions & 0 deletions src/navigate/model/devices/lasers/ni.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@

# Standard Library Imports
import logging
import traceback
from typing import Any, Dict

# Third Party Imports
Expand Down Expand Up @@ -234,3 +235,17 @@ def close(self) -> None:
self.laser_do_task.close()
except DaqError as e:
logger.exception(e)

def __del__(self):
"""Delete the NI Task before exit."""
if self.laser_ao_task:
try:
self.laser_ao_task.close()
except Exception as e:
logger.exception(f"Error stopping task: {traceback.format_exc()}")

if self.laser_do_task:
try:
self.laser_do_task.close()
except Exception as e:
logger.exception(f"Error stopping task: {traceback.format_exc()}")
6 changes: 5 additions & 1 deletion src/navigate/model/devices/mirrors/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ def __init__(self, microscope_name, device_connection, configuration):
Name of microscope in configuration
device_connection : object
Hardware device to connect to
configuration : multiprocesing.managers.DictProxy
configuration : multiprocessing.managers.DictProxy
Global configuration of the microscope
"""
if microscope_name not in configuration["configuration"]["microscopes"].keys():
Expand All @@ -81,3 +81,7 @@ def __init__(self, microscope_name, device_connection, configuration):
def __str__(self):
"""Return the string representation of the mirror."""
return "MirrorBase"

def __del__(self) -> None:
"""Delete the MirrorBase class."""
pass
4 changes: 4 additions & 0 deletions src/navigate/model/devices/mirrors/imop.py
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,10 @@ def __init__(self, microscope_name, device_connection, configuration):
# flatten the mirror
self.flat()

def __del__(self) -> None:
"""Delete the ImagineOpticsMirror class."""
pass

def flat(self):
"""Move the mirror to the flat position."""
self.mirror_controller.flat()
Expand Down
Loading
Loading