API Reference

Auto-generated API documentation from source docstrings.

Architecture Overview

mesoSPIM-control is a PyQt5 application built around a strict thread-safety model. All inter-component communication goes through Qt signals and slots (using QueuedConnection so that callers never block the GUI event loop). The diagram below shows how the major pieces fit together:

mesoSPIM-control architecture diagram

Key architectural concepts

mesoSPIM_StateSingleton (src/mesoSPIM_State.py)

A mutex-protected singleton dictionary that stores the complete hardware and acquisition state: laser selection, camera exposure, stage positions, ETL/galvo parameters, current acquisition list, and more. All threads read and write state through this object using QMutex for thread safety.

mesoSPIM_Core (src/mesoSPIM_Core.py)

The orchestration layer — described in its own docstring as “the pacemaker of a mesoSPIM”. It does not perform hardware I/O itself; instead it emits signals to the worker threads in the correct order and waits for their acknowledgement via BlockingQueuedConnection when synchronisation is required.

Worker threads

Only two worker objects run on dedicated QThread instances:

  • mesoSPIM_Camera — arms the camera, triggers exposures, and pushes raw frames into a shared deque (frame_queue).

  • mesoSPIM_ImageWriter — consumes frame_queue and writes files; supports a plugin API (src/plugins/ImageWriterApi.py) for custom output formats.

mesoSPIM_WaveFormGenerator and mesoSPIM_Serial both live in the Core thread alongside mesoSPIM_Core itself. The waveformer performs blocking NI-DAQ calls, and the serial worker performs synchronous serial/USB calls, both within the Core event loop. (A BlockingQueuedConnection from Core to either of those workers would deadlock, which is why QueuedConnection is used throughout.)

Device abstraction (src/devices/)

Every hardware class has a Demo_* counterpart that simulates the device in software. The correct class is selected at runtime from the config file, so the full acquisition pipeline can be exercised without physical hardware.

GUI sub-windows (src/mesoSPIM_*Window.py)

Thin PyQt5 views wired to MainWindow signals. They never touch hardware directly — all user actions are translated into signal emissions that travel to Core and then onwards to the appropriate worker.

Configuration files (config/*.py)

Plain Python modules imported at startup. A configuration file declares dictionaries (camera_parameters, stage_parameters, laser_parameters, etc.) that Core and the device classes read to select hardware drivers and calibration values.

Plugin system (src/plugins/)

Custom image writers can be registered via PluginRegistry and ImageWriterApi, allowing new file formats or live-streaming sinks to be added without modifying the core acquisition loop.

Core modules

mesoSPIM_Core

Core for the mesoSPIM project

mesoSPIM.src.mesoSPIM_Core.logger = <Logger mesoSPIM.src.mesoSPIM_Core (WARNING)>

PyQt5 Imports

class mesoSPIM.src.mesoSPIM_Core.mesoSPIM_Core(*args: Any, **kwargs: Any)[source]

Bases: QObject

This class is the pacemaker of a mesoSPIM

append_timing_info_to_metadata(acq)[source]

Appends a metadata.txt file Path contains the file to be written

check_motion_limits(acq_list)[source]

Check if the motion limits of the stage are violated for each acquisition in the given list.

Parameters:

acq_list (list) – A list of dictionaries representing acquisitions, where each dictionary contains the x, y, and z positions.

Returns:

A list of indices of acquisitions in the input list that violate the motion limits.

Return type:

list

close_acquisition(acq, acq_list)[source]

Finalise a single acquisition: flush the image series, collect timing, and increment the counter.

Also disables TTL motion if it was enabled for ASI stages, and appends timing metadata to the sidecar file.

Parameters:
close_acquisition_list(acq_list)[source]
close_image_series()[source]

Cleans up after series without waveform update

close_shutters()

If shutterswitch = True in the config: Assumes that the shutter_left line is the general shutter and the shutter_right line is the left/right switch (Right==True)

execute_galil_program()[source]

Little helper method to execute the program loaded onto the Galil stage: allows hand controller to operate

execute_script(script)

Execute a user-provided Python script string inside the Core event loop.

The script runs with access to self (the Core object) so it can call any public API method. Errors are caught via traceback.print_exc().

Parameters:

script (str) – Valid Python source code to execute.

frame_queue_display

The signal-slot switchboard

get_free_disk_space(acq_list)[source]

Take the disk location of the first file and compute the free disk space

get_required_disk_space(acq_list)[source]

“Compute total image data size from the acquisition list, in bytes

lightsheet_alignment_mode()[source]

Continuous live mode that alternates left/right shutters for dual-lightsheet co-alignment.

Loops until self.stopflag is set, alternating 'Left' and 'Right' shutter configs between snaps.

list_to_string_with_carriage_return(input_list)[source]

Join list items into a newline-separated string for warning dialogs or logs.

Parameters:

input_list (list) – Items to join.

Returns:

All items joined by ' \n '.

Return type:

str

live()[source]

Run a continuous live-preview loop using the current state parameters.

Starts the camera in live mode, streams frames to the camera window via frame_queue_display, and drives NI-DAQ waveforms repeatedly until stop() sets self.stopflag = True.

move_absolute(sdict, wait_until_done=False, use_internal_position=True)

Move one or more stage axes to an absolute position.

Parameters:
  • sdict (dict) – Axis → target mapping, e.g. {'z_abs': 5000.0} (in μm).

  • wait_until_done (bool) – If True, calls the serial worker directly (bypassing the signal) to block until the move completes.

  • use_internal_position (bool) – When True, the stage applies the user-visible offset stored in mesoSPIM_StateSingleton.

move_relative(dict, wait_until_done=False)

Move one or more stage axes by a relative offset.

Parameters:
  • dict (dict) – Axis → step mapping, e.g. {'x_rel': 100.0} (in μm).

  • wait_until_done (bool) – If True, block until the move is complete.

open_shutters()

Here the left/right mode is hacked in If shutterswitch = True in the config: Assumes that the shutter_left line is the general shutter and the shutter_right line is the left/right switch (Right==True)

prepare_acquisition(acq, acq_list)[source]

Housekeeping: Prepare the acquisition

prepare_acquisition_list(acq_list)[source]

Housekeeping: Prepare the acquisition list

prepare_image_series()[source]

Prepares an image series without waveform update

preview_acquisition(z_update=True)[source]

Drive the stages along the start/end positions of the selected acquisition without acquiring images.

Useful for visually verifying sample placement and focus before a full run.

Parameters:

z_update (bool) – If True, move z to the acquisition start z; if False, keep z at its current position and only update x/y/f/theta.

read_config_parameter(key, dictionary)[source]

Helper method to check if key exists in the dictionary and read its value, or throw a meaningful error

run_acquisition(acq, acq_list)[source]

Execute a single acquisition: start waveforms, trigger the camera, and collect frames.

Steps the z (and optionally f) axis acq.get_image_count() times, emitting sig_add_images_to_image_series at each plane so the ImageWriter receives frames in order. Honours self.stopflag for mid-acquisition abort.

Parameters:
  • acq (Acquisition) – Acquisition descriptor for the current volume.

  • acq_list (AcquisitionList) – Full list (provides tile/channel/rotation context).

run_acquisition_list(acq_list)[source]

Iterate over every acquisition in acq_list and image each one.

For each Acquisition, calls prepare_acquisition(), run_acquisition(), and close_acquisition() sequentially, unless self.stopflag is set.

Parameters:

acq_list (AcquisitionList) – The list of acquisitions to execute.

run_time_lapse(tpoints=1, time_interval_sec=60)[source]

A quick and dirty implementation of time lapse via recursive function.

send_progress(cur_acq, tot_acqs, cur_image, images_in_acq, total_image_count, image_counter, time_passed_string, remaining_time_string)[source]
send_status_message_to_gui(string)

Emit a status string to the main window status bar.

Parameters:

string (str) – Human-readable message to display.

set_camera_exposure_time(time)

Forward a new exposure time (in seconds) to the waveform generator state.

Parameters:

time (float) – Exposure duration in seconds.

set_camera_line_interval(time)

Forward a new camera line interval (sCMOS rolling-shutter timing) to the waveform generator state.

Parameters:

time (float) – Line interval in seconds.

set_filter(filter, wait_until_done=False)

Switch the emission filter wheel to the named filter position.

Parameters:
  • filter (str) – Filter name as defined in cfg.filterdict.

  • wait_until_done (bool) – If True, block until the wheel is settled.

set_intensity(intensity, wait_until_done=False)

Set the laser intensity (analogue voltage) via the waveform generator.

Parameters:
  • intensity (int | float) – Intensity value 0–100 (%).

  • wait_until_done (bool) – If True, block until the waveformer has applied it.

set_laser(laser, wait_until_done=False, update_etl=True)

Select the active laser line and optionally reload ETL parameters for it.

Parameters:
  • laser (str) – Laser designation as defined in cfg.laserdict (e.g. '488 nm').

  • wait_until_done (bool) – If True, use a blocking signal so the waveformer applies the change before this call returns.

  • update_etl (bool) – Whether to update ETL parameters from calibration for the new laser.

set_shutterconfig(shutterconfig)

Select which light-sheet shutter(s) are opened during illumination.

Parameters:

shutterconfig (str) – One of 'Left', 'Right', 'Both', or 'Interleaved'.

set_state(state)[source]

Dispatch a high-level state string to the appropriate acquisition method.

Accepted values and their effect:

  • 'live' — start continuous live preview.

  • 'snap' — acquire and save a single snap image.

  • 'run_selected_acquisition' — run the row currently selected in the Acquisition Manager table.

  • 'run_acquisition_list' — run every acquisition in the list.

  • 'preview_acquisition_with_z_update' / 'preview_acquisition_without_z_update' — drive stages to the start/end of an acquisition without recording.

  • 'idle' — stop all ongoing activities.

  • 'lightsheet_alignment_mode' / 'visual_mode' — special live modes.

Parameters:

state (str) – One of the state strings listed above.

set_zoom(zoom, wait_until_done=True, update_etl=True)

Move the zoom body / objective revolver and optionally update ETL calibration.

If f_objective_exchange is configured in the stage parameters, the focus axis is first driven to the exchange position before the zoom changes, then returned to its previous value.

Parameters:
  • zoom (str) – Zoom designation as defined in cfg.zoomdict (e.g. '2x').

  • wait_until_done (bool) – Block until the zoom mechanism has settled.

  • update_etl (bool) – Emit a state request to reload ETL parameters for the new zoom value from the calibration CSV.

sig_add_images_to_image_series

alias of Acquisition

sig_end_image_series

alias of Acquisition

sig_end_live

Movement-related signals:

sig_get_snap_image

alias of bool

sig_move_absolute

alias of dict

sig_move_relative

alias of dict

sig_move_relative_and_wait_until_done

alias of dict

sig_polling_stage_position_start

ETL-related signals

sig_polling_stage_position_stop

ETL-related signals

sig_position

alias of dict

sig_prepare_image_series

alias of Acquisition

sig_progress

alias of dict

sig_run_timepoint

Camera-related signals

alias of int

sig_state_request

alias of dict

sig_state_request_and_wait_until_done

alias of dict

sig_status_message

alias of str

sig_unzero_axes

alias of list

sig_warning

alias of str

sig_write_metadata

alias of Acquisition

sig_zero_axes

alias of list

snap(write_flag=True, laser_blanking=True)[source]
snap_image(laser_blanking=True)[source]

Snaps a single image after updating the waveforms.

Can be used in acquisitions where changing waveforms are required, but there is additional overhead due to the need to write the waveforms into the buffers of the NI cards.

snap_image_in_series(laser_blanking=True)[source]

Snaps and image from a series without waveform update

start(row=None)[source]

Entry point for running one selected acquisition or the full acquisition list.

Performs pre-flight checks (disk space, motion limits), then delegates to run_acquisition_list() or run_selected_acquisition().

Parameters:

row (int | None) – Table row index to run, or None to run all rows.

state_request_handler(dict)
stop()[source]

Abort any ongoing acquisition, reset state to 'idle', and clear the frame queue.

stop_movement()

Send an emergency stop signal to all stage axes.

unzero_axes(list)

Restore the physical (absolute) coordinate system for the given axes.

Parameters:

list (list[str]) – Axis names to unzero, e.g. ['x', 'z'].

visual_mode()[source]

Continuous live mode with ETL amplitude set to zero for widefield-style illumination.

ETL amplitudes are temporarily zeroed so the light-sheet does not sweep, giving a fixed illumination plane for visual inspection. The previous ETL amplitudes are restored on exit.

zero_axes(list)

Define the current position as the zero/origin for the given axes.

Parameters:

list (list[str]) – Axis names to zero, e.g. ['x', 'y'].

mesoSPIM_State

mesoSPIM State class. Only nominally a singleton class, but actually inherited by classes from their parent class.

class mesoSPIM.src.mesoSPIM_State.mesoSPIM_StateSingleton(*args, **kwargs)[source]

Bases: QObject

Singleton object containing the whole mesoSPIM state.

Only classes which control.

Access to attributes is mutex-locked to allow access from multiple threads.

If more than one state parameter should be set at the same time, the set_parameter

block_signals(boolean)[source]
get_parameter_dict(list)[source]

For a list of keys, get a state dict with the current values back.

All the values are read out under a QMutexLocker so that the state cannot be updated at the same time.

get_parameter_list(list)[source]

For a list of keys, get a state list with the current values back.

This is especially useful for unpacking.

All the values are read out under a QMutexLocker so that the state cannot be updated at the same time.

instance = None
mutex = <PyQt5.QtCore.QMutex object>
set_parameters(dict)[source]

Sometimes, several parameters should be set at once without allowing the state being updated while a parameter is read.

mesoSPIM_Camera

mesoSPIM Camera class, intended to run in its own thread

class mesoSPIM.src.mesoSPIM_Camera.mesoSPIM_Camera(*args: Any, **kwargs: Any)[source]

Bases: QObject

Top-level class for all cameras

add_images_to_series(**kwargs)
end_image_series(acq, acq_list)
end_live()
get_live_image()
prepare_image_series(acq, acq_list)

Row is a row in a AcquisitionList

prepare_live()
set_camera_binning(value)[source]
set_camera_display_acquisition_subsampling(factor)[source]
set_camera_display_live_subsampling(factor)[source]
set_camera_exposure_time(time)[source]

Sets the exposure time in seconds

Parameters:

time (float) – exposure time to set

set_camera_line_interval(time)[source]

Sets the line interval in seconds

Parameters:

time (float) – interval time to set

set_state(value)[source]
sig_status_message

alias of str

sig_write_images

alias of Acquisition

snap_image(write_flag=True)

“Snap an image and display it

state_request_handler(dict)

The request handling is done with exec() to write fewer lines of code.

stop()

Stops acquisition

class mesoSPIM.src.mesoSPIM_Camera.mesoSPIM_DemoCamera(*args: Any, **kwargs: Any)[source]

Bases: mesoSPIM_GenericCamera

Software-only camera driver for use without physical hardware.

Generates synthetic sinusoidal fringe images so that the GUI, image writer, and acquisition-sequencing logic can be exercised without a physical camera. Used for development, demos, and CI/testing.

close_camera()[source]
get_image()[source]

Should return a single numpy array

get_images_in_series()[source]

Should return a single numpy array

get_live_image()[source]
open_camera()[source]
set_binning(binning_string)[source]
class mesoSPIM.src.mesoSPIM_Camera.mesoSPIM_GenericCamera(*args: Any, **kwargs: Any)[source]

Bases: QObject

Abstract base class for all mesoSPIM camera drivers.

Concrete subclasses override the hardware-interaction methods listed below. The base class reads sensor dimensions and binning from cfg.camera_parameters and provides no-op stubs for every camera lifecycle method.

Lifecycle sequence expected by mesoSPIM_Core:

  • Live mode: open_camerainitialize_live_modeget_live_image (repeated) → close_live_modeclose_camera

  • Acquisition: open_camerainitialize_image_seriesget_images_in_series (repeated) → close_image_seriesclose_camera

All subclass instances run in the Camera thread (a high-priority QThread spawned in mesoSPIM_Core).

close_camera()[source]
close_image_series()[source]
close_live_mode()[source]
get_image()[source]

Should return a single numpy array

get_images_in_series()[source]

Should return a single numpy array

get_live_image()[source]
initialize_image_series()[source]
initialize_live_mode()[source]
open_camera()[source]
set_binning(binning_string)[source]
set_exposure_time(time)[source]
set_line_interval(time)[source]
class mesoSPIM.src.mesoSPIM_Camera.mesoSPIM_HamamatsuCamera(*args: Any, **kwargs: Any)[source]

Bases: mesoSPIM_GenericCamera

Camera driver for Hamamatsu ORCA-Flash / ORCA-Fusion cameras.

Uses the hamamatsu_camera Python wrapper (a ctypes-based interface to the DCAM-API SDK included in devices/cameras/hamamatsu/). Sensor mode, defect correction, binning, and readout speed are applied at open_camera() time from cfg.camera_parameters.

close_camera()[source]
close_image_series()[source]
close_live_mode()[source]
get_image()[source]

Should return a single numpy array

get_images_in_series()[source]

Should return a single numpy array

get_live_image()[source]
initialize_image_series()[source]
initialize_live_mode()[source]
open_camera()[source]

Hamamatsu-specific code

print_camera_properties(message='Camera properties')[source]

Camera properties

set_binning(binningstring)[source]
set_camera_sensor_mode(mode)[source]
set_exposure_time(time)[source]
set_line_interval(time)[source]
class mesoSPIM.src.mesoSPIM_Camera.mesoSPIM_PCOCamera(*args: Any, **kwargs: Any)[source]

Bases: mesoSPIM_GenericCamera

Camera driver for PCO scientific cameras (e.g. pco.edge sCMOS).

Uses the pco Python SDK (pip install pco). Acquires frames in rolling-shutter light-sheet mode; frame transfer timing is set by the global line interval from cfg.startup.

close_camera()[source]
close_image_series()[source]
close_live_mode()[source]
get_image()[source]

Should return a single numpy array

get_images_in_series()[source]

Should return a single numpy array

get_live_image()[source]
initialize_image_series()[source]
initialize_live_mode()[source]
open_camera()[source]
set_binning(binningstring)[source]
set_exposure_time(time)[source]
set_line_interval(time)[source]
class mesoSPIM.src.mesoSPIM_Camera.mesoSPIM_PhotometricsCamera(*args: Any, **kwargs: Any)[source]

Bases: mesoSPIM_GenericCamera

Camera driver for Photometrics (Teledyne) sCMOS cameras.

Uses the pyvcam Python SDK. Requires the PVCAM runtime to be installed on the host PC. Camera properties (speed table index, port index, gain, exposure mode) are configured in cfg.camera_parameters.

close_camera()[source]
close_image_series()[source]
close_live_mode()[source]
get_image()[source]

Should return a single numpy array

get_images_in_series()[source]

Should return a single numpy array

get_live_image()[source]
initialize_image_series()[source]

The Photometrics cameras expect integer exposure times, otherwise they default to the minimum value

initialize_live_mode()[source]

The Photometrics cameras expect integer exposure times, otherwise they default to the minimum value

open_camera()[source]
report_pvcam_parameter(description, parameter)[source]
set_binning(binningstring)[source]
set_exposure_time(time)[source]
set_line_interval(time)[source]

mesoSPIM_Stages

mesoSPIM Stage classes

class mesoSPIM.src.mesoSPIM_Stages.mesoSPIM_ASI_Stages(*args: Any, **kwargs: Any)[source]

Bases: mesoSPIM_Stage

Stage driver for Applied Scientific Instrumentation (ASI) Tiger or MS-2000 controllers.

Communicates via serial (RS-232) using the ASI ASCII protocol through mesoSPIM.src.devices.stages.asi.asicontrol.StageControlASI. Supports TTL-triggered motion via enable_ttl_motion() and execute_program().

Config file keys are defined in cfg.asi_parameters.

enable_ttl_motion(boolean)[source]
load_sample()[source]

Move the Y axis to cfg.stage_parameters['y_load_position'] (sample exchange position).

log_slice(dictionary)
move_absolute(dict, wait_until_done=False, use_internal_position=True)[source]

ASI move absolute method

Lots of implementation details in here, should be replaced by a facade

move_relative(sdict, wait_until_done=False)[source]

ASI move relative method Lots of implementation details in here, should be replaced by a facade

report_position()[source]
set_speed_from_config()[source]
stop()[source]
unload_sample()[source]

Move the Y axis to cfg.stage_parameters['y_unload_position'].

class mesoSPIM.src.mesoSPIM_Stages.mesoSPIM_DemoStage(*args: Any, **kwargs: Any)[source]

Bases: mesoSPIM_Stage

Software-only stage for use without physical hardware.

All movement commands are handled by the base-class mesoSPIM_Stage implementation, which simply updates the internal position variables and optionally waits a short delay to simulate motion settle time. No serial or USB connections are opened. Intended for development, demos, and CI/testing.

class mesoSPIM.src.mesoSPIM_Stages.mesoSPIM_PI_1toN(*args: Any, **kwargs: Any)[source]

Bases: mesoSPIM_Stage

Configuration with 1 controller connected to N stages, (e.g. C-884, default mesoSPIM V5 setup).

Note: configs as declared in mesoSPIM_config.py:

stage_parameters = {‘stage_type’‘PI_1controllerNstages’,

… }

pi_parameters = {‘controllername’‘C-884’,

‘stages’ : (‘L-509.20DG10’,’L-509.40DG10’,’L-509.20DG10’,’M-060.DG’,’M-406.4PD’,’NOSTAGE’), ‘refmode’ : (‘FRF’,), ‘serialnum’ : (‘118075764’), }

block_till_controller_is_ready()[source]

Blocks further execution (especially during referencing moves) till the PI controller returns ready

load_sample()[source]

Move the Y axis to cfg.stage_parameters['y_load_position'] (sample exchange position).

move_absolute(sdict, wait_until_done=False, use_internal_position=True)

Lots of implementation details in here, should be replaced by a facade

TODO: Also lots of repeating code. TODO: DRY principle violated

move_relative(sdict, wait_until_done=False)

PI move relative method

Lots of implementation details in here, should be replaced by a facade

pitools

Setting up the PI stages

report_position()[source]
stop()
unload_sample()[source]

Move the Y axis to cfg.stage_parameters['y_unload_position'].

class mesoSPIM.src.mesoSPIM_Stages.mesoSPIM_PI_NtoN(*args: Any, **kwargs: Any)[source]

Bases: mesoSPIM_Stage

Expects following microscope configuration:

Sample XYZ movement: Physik Instrumente stage with three L-509-type stepper motor stages and individual C-663 controller. F movement: Physik Instrumente C-663 controller and custom stage with stepper motor Rotation: not implemented

All stage controller are of same type and the sample stages work with reference setting. Focus stage has reference mode set to off.

Note

configs as declared in mesoSPIM_config.py: stage_parameters = {‘stage_type’ : ‘PI_NcontrollersNstages’,

… }

pi_parameters = {‘axes_names’: (‘x’, ‘y’, ‘z’, ‘theta’, ‘f’),

‘stages’: (‘L-509.20SD00’, ‘L-509.40SD00’, ‘L-509.20SD00’, None, ‘MESOSPIM_FOCUS’), ‘controllername’: (‘C-663’, ‘C-663’, ‘C-663’, None, ‘C-663’), ‘serialnum’: (’******’, ‘******’, ‘******’, None, ‘******’), ‘refmode’: (‘FRF’, ‘FRF’, ‘FRF’, None, ‘RON’) }

make sure that reference points are not in conflict with general microscope setup and will not hurt optics under referencing at startup

load_sample()[source]

bring sample to imaging position

move_absolute(move_dict, wait_until_done=False, use_internal_position=True)[source]
move_relative(move_dict, wait_until_done=False)[source]

PI move relative method

report_position()[source]

report stage position

stop()[source]

stop stage movement

unload_sample()[source]

lift sample to sample handling position

wait_for_controller(controller)[source]
class mesoSPIM.src.mesoSPIM_Stages.mesoSPIM_PI_rotz_and_Galil_xyf_Stages(*args: Any, **kwargs: Any)[source]

Bases: mesoSPIM_Stage

Stage driver combining a Physik Instrumente Z- and rotation axes with Galil-driven XYF axes.

Sample XYF movement: Galil controller with 3 axes Z-Movement and Rotation: PI C-884 mercury controller

block_till_controller_is_ready()[source]

Blocks further execution (especially during referencing moves) till the PI controller returns ready

execute_program()[source]

Executes program stored on the Galil controller

f_encodercounts_per_um

XYZ

Type:

Setting up the Galil stages

load_sample()[source]

Move the Y axis to cfg.stage_parameters['y_load_position'] (sample exchange position).

move_absolute(dict, wait_until_done=False, use_internal_position=True)[source]

Galil move absolute method

Lots of implementation details in here, should be replaced by a facade

move_relative(sdict, wait_until_done=False)[source]

Galil move relative method

Lots of implementation details in here, should be replaced by a facade

pitools

Setting up the PI stages

report_position()[source]
stop()[source]
unload_sample()[source]

Move the Y axis to cfg.stage_parameters['y_unload_position'].

xyf_stage

PI-specific code

class mesoSPIM.src.mesoSPIM_Stages.mesoSPIM_Stage(*args: Any, **kwargs: Any)[source]

Bases: QObject

Abstract base class for all mesoSPIM stage drivers.

Concrete subclasses (mesoSPIM_DemoStage, mesoSPIM_PI_1toN, mesoSPIM_PI_NtoN, mesoSPIM_PI_rotz_and_Galil_xyf_Stages, mesoSPIM_ASI_Stages) implement the hardware-specific communication.

The base class provides:

  • A 100 ms QTimer that calls report_position() to keep the GUI position readouts up to date.

  • Software (“internal”) position tracking with per-axis zeroing offsets so that users can zero any axis without the physical stage moving.

  • Motion-limit checking using cfg.stage_parameters (x_min, x_max, y_min, y_max, etc., all in micrometres).

  • Default implementations of load_sample(), unload_sample(), and center_sample() driven by config values.

This object is owned by mesoSPIM_Serial and therefore lives in the Core thread.

center_sample()[source]

Move X (and optionally Z) to the configured center / midpoint position.

Values are taken from cfg.stage_parameters['x_center_position'] and cfg.stage_parameters['z_center_position']. If a key is absent the corresponding axis is left at its current position and a message is logged.

create_internal_position_dict()[source]

Populate self.int_position_dict with the user-visible (software-zeroed) axis positions.

create_position_dict()[source]

Populate self.position_dict with the current raw (hardware) axis positions and store it in state['position_absolute'].

int_theta_pos

Create offsets

It should be:

int_x_pos = x_pos + int_x_pos_offset self.int_x_pos = self.x_pos + self.int_x_pos_offset

OR

x_pos = int_x_pos - int_x_pos_offset self.x_pos = self.int_x_pos - self.int_x_pos_offset

int_theta_pos_offset

currently hardcoded

Open question: Should these be in mm or microns? Answer: Microns for now….

Type:

Setting movement limits

load_sample()[source]

Move the Y axis to cfg.stage_parameters['y_load_position'] (sample exchange position).

move_absolute(dict, wait_until_done=False, use_internal_position=True)

Move one or more axes to absolute target positions (demo / base-class implementation).

Parameters:
  • dict (dict) – Axis → target mapping in micrometres, e.g. {'x_abs': 5000.0, 'z_abs': -200.0}.

  • wait_until_done (bool) – If True, block for 1 s and confirm completion via report_position().

  • use_internal_position (bool) – When True the zeroing offsets are subtracted so that the user sees the zeroed coordinate system.

move_relative(sdict, wait_until_done=False)

Move one or more axes by a relative offset (demo / base-class implementation).

Parameters:
  • sdict (dict) – Axis → step mapping in micrometres, e.g. {'z_rel': -100.0, 'f_rel': 50.0}.

  • wait_until_done (bool) – If True, block for 100 ms and call report_position() to simulate a settle delay.

report_position()

Read current positions, apply zeroing offsets, update state, and emit sig_position.

Called automatically every 100 ms by the internal QTimer and also explicitly after blocking moves (wait_until_done=True).

sig_position

alias of dict

sig_status_message

alias of str

state

The movement signals are emitted by the mesoSPIM_Core, which in turn instantiates the mesoSPIM_Serial object, both (must be) running in the same Core thread.

Therefore, the signals are emitted by the parent of the parent, which is slightly confusing and dirty.

stop()

Immediately stop all axis motion and emit a ‘Stopped’ status message.

theta_pos

Internal (software) positions

unload_sample()[source]

Move the Y axis to cfg.stage_parameters['y_unload_position'].

unzero_axes(list)[source]

Clear the internal-position offset for each axis in list, restoring the hardware coordinate as the user-visible position.

zero_axes(list)[source]

Set the internal-position offset so that the current physical position reads 0 for each axis in list (e.g. ['x', 'z']).

mesoSPIM_ImageWriter

mesoSPIM Image Writer class, intended to run in the Camera Thread and handle file I/O

class mesoSPIM.src.mesoSPIM_ImageWriter.mesoSPIM_ImageWriter(*args: Any, **kwargs: Any)[source]

Bases: QObject

Image and metadata writer that runs in its own high-priority QThread.

Consumes raw frames pushed into frame_queue by mesoSPIM_Camera and writes them to disk using a pluggable writer backend (TIFF, HDF5, OME-ZARR, …). Writer backends are selected per-acquisition via the image_writer_plugin field of each Acquisition.

Signals are connected by mesoSPIM_Core during construction.

abort_writing()

Terminate writing and close all files if STOP button is pressed

check_versions()[source]

Take care of API changes in different library versions

end_acquisition(acq, acq_list)

Finalise and close the writer backend after the last frame of an acquisition.

Also closes any optional MIP (maximum intensity projection) TIFF file. Called via BlockingQueuedConnection from mesoSPIM_Core.

Parameters:
image_to_disk(**kwargs)
prepare_acquisition(acq, acq_list)[source]

Open the writer backend and prepare file paths for a new acquisition.

For the very first acquisition in acq_list this also instantiates the writer plugin. Called via BlockingQueuedConnection from mesoSPIM_Core before imaging starts.

Parameters:
write_images(acq, acq_list)

Write available images to disk. The actual images are passed via self.frame_queue from the Camera thread, NOT via the signal/slot mechanism as before, starting from v.1.10.0. This is to avoid the overhead of signal/slot mechanism and to improve performance.

write_metadata(acq, acq_list)
write_snap_image(image)[source]

Save a single snap-shot frame to the snap folder as a timestamped TIFF.

Parameters:

image (np.ndarray) – 2-D uint16 frame from the camera.

write_snap_metadata(path)[source]

Write a plain-text metadata sidecar file alongside a snap TIFF.

Records current laser, intensity, zoom, filter, stage positions, ETL parameters, and camera settings.

Parameters:

path (str) – Absolute path of the snap TIFF whose sidecar is to be written.

mesoSPIM_WaveFormGenerator

mesoSPIM Waveform Generator - Creates and allows control of waveform generation.

mesoSPIM.src.mesoSPIM_WaveFormGenerator.logger = <Logger mesoSPIM.src.mesoSPIM_WaveFormGenerator (WARNING)>

National Instruments Imports

class mesoSPIM.src.mesoSPIM_WaveFormGenerator.mesoSPIM_DemoWaveFormGenerator(*args: Any, **kwargs: Any)[source]

Bases: mesoSPIM_WaveFormGenerator

Demo subclass of mesoSPIM_WaveFormGenerator class

close_tasks()[source]

Demo: closes the tasks for triggering, analog and counter outputs.

create_tasks()[source]

“Demo version of the actual DAQmx-based function.

run_tasks()[source]

Demo: runs the tasks for triggering, analog and counter outputs.

start_tasks()[source]

Demo: starts the tasks for camera triggering and analog outputs.

stop_tasks()[source]

“Demo: stop tasks

write_waveforms_to_tasks()[source]

Demo: write the waveforms to the slave tasks

class mesoSPIM.src.mesoSPIM_WaveFormGenerator.mesoSPIM_WaveFormGenerator(*args: Any, **kwargs: Any)[source]

Bases: QObject

This class contains the microscope state

Any access to this global state should only be done via signals sent by the responsible class for actually causing that state change in hardware.

bundle_galvo_and_etl_waveforms()[source]

Stacks the Galvo and ETL waveforms into a numpy array adequate for the NI cards.

In here, the assignment of output channels of the Galvo / ETL card to the corresponding output channel is hardcoded: This could be improved.

calculate_samples()[source]
close_tasks(**kwargs)
config_check()[source]

Check config file for old/wrong/deprecated pieces

create_etl_waveforms()[source]
create_galvo_waveforms()[source]
create_laser_waveforms()[source]
create_tasks(**kwargs)
create_waveforms()[source]
rescale_galvo_amplitude_by_zoom(zoom: float)[source]
run_tasks(**kwargs)
save_etl_parameters_to_csv()

Saves the current ETL left/right offsets and amplitudes from the values to the ETL csv files

The .csv file needs to contain the following columns:

Wavelength Zoom ETL-Left-Offset ETL-Left-Amp ETL-Right-Offset ETL-Right-Amp

Creates a temporary cfg file with the ending _tmp

start_tasks(**kwargs)
state_request_handler(dict)
stop_tasks(**kwargs)
update_etl_parameters_from_csv(cfg_path, laser, zoom)[source]

Updates the internal ETL left/right offsets and amplitudes from the values in the ETL csv files

The .csv file needs to contain the follwing columns:

Wavelength Zoom ETL-Left-Offset ETL-Left-Amp ETL-Right-Offset ETL-Right-Amp

update_etl_parameters_from_laser(laser)[source]

Little helper method: Because laser changes need an ETL parameter update

update_etl_parameters_from_zoom(zoom)[source]

Little helper method: Because the mesoSPIM core is not handling the serial Zoom connection.

write_waveforms_to_tasks(**kwargs)

mesoSPIM_Serial

Serial thread for the mesoSPIM project

This thread handles all connections with serial devices such as stages, filter wheels, zoom systems etc.

class mesoSPIM.src.mesoSPIM_Serial.mesoSPIM_Serial(*args: Any, **kwargs: Any)[source]

Bases: QObject

This class handles mesoSPIM serial connections.

Acts as a facade over three hardware sub-systems:

  • Stage — one of several concrete mesoSPIM_Stage subclasses (PI, ASI, Demo …) selected from the config file.

  • Filter wheel — one of the mesoSPIM_FilterWheel implementations (Ludl, Dynamixel, Sutter, ZWO, Demo).

  • Zoom — one of the DynamixelZoom / MitutoyoZoom / DemoZoom implementations.

All three are instantiated in __init__ based on config parameters. This object stays in the Core thread (see mesoSPIM_Core); slot calls therefore run synchronously in that event loop.

enable_ttl_motion(boolean)

Enable or disable TTL-triggered motion on ASI stages during an acquisition.

Parameters:

boolean (bool) – True to enable TTL motion, False to disable.

execute_stage_program()[source]

Trigger the pre-loaded Galil/ASI stage program for TTL-driven motion.

go_to_rotation_position(wait_until_done=False)

Move the rotation axis to the stored rotation/sample-exchange position.

Parameters:

wait_until_done (bool) – Block until the rotation is complete.

move_absolute(sdict, wait_until_done=False, use_internal_position=True)

Move one or more axes to an absolute position.

Parameters:
  • sdict (dict) – Axis → target mapping, e.g. {'x_abs': 1000.0} (μm).

  • wait_until_done (bool) – Block until the stage controller confirms completion.

  • use_internal_position (bool) – Apply the user-visible position offset stored in mesoSPIM_StateSingleton when True.

move_relative(sdict, wait_until_done=False)

Move one or more axes by a relative offset after checking motion limits.

If the requested movement would violate a stage limit, the move is suppressed and a warning message is emitted instead.

Parameters:
  • sdict (dict) – Axis → step mapping, e.g. {'z_rel': 50.0} (μm).

  • wait_until_done (bool) – Block until the stage controller confirms completion.

report_position(sdict)

Receive a position update from the stage driver and broadcast it to the GUI.

Writes the new position into mesoSPIM_StateSingleton and emits sig_position so the main window can update the position readouts.

Parameters:

sdict (dict) – Position dictionary, e.g. {'x_pos': 0.0, 'y_pos': 0.0, 'z_pos': 0.0, 'f_pos': 0.0, 'theta_pos': 0.0}.

send_status_message(string)

Re-emit a stage status message up to mesoSPIM_Core / GUI.

Parameters:

string (str) – Human-readable status string from the stage driver.

set_filter(sfilter, wait_until_done=False)

Move the filter wheel to the named filter position and update state.

Parameters:
  • sfilter (str) – Filter name as defined in cfg.filterdict.

  • wait_until_done (bool) – Block until the wheel has settled.

set_zoom(zoom, wait_until_done=True)

Move the zoom body to the named zoom position and update state.

State is updated before the physical move to keep the GUI responsive.

Parameters:
  • zoom (str) – Zoom designation, e.g. '2x', as defined in cfg.zoomdict.

  • wait_until_done (bool) – Block until the zoom mechanism has settled.

sig_position

alias of dict

sig_state_request

alias of dict

sig_status_message

alias of str

sig_unzero_axes

alias of list

sig_zero_axes

alias of list

stage_limits_OK(sdict, safety_margin_n_moves=3)[source]

Safety margin is added to deal with delays in position reporting.

stage_limits_warning

Attaching the filterwheel

state_request_handler(sdict, wait_until_done=False)

Route state-change requests from Core to the appropriate hardware method.

Recognised keys: 'filter', 'zoom', 'stage_program', 'ttl_movement_enabled_during_acq'.

Parameters:
  • sdict (dict) – Key/value pairs describing the desired state change.

  • wait_until_done (bool) – Passed down to set_filter / set_zoom.

mesoSPIM_Zoom

mesoSPIM Module for controlling a discrete zoom changer

class mesoSPIM.src.mesoSPIM_Zoom.DemoZoom(*args: Any, **kwargs: Any)[source]

Bases: QObject

Software-only zoom driver for use without physical hardware.

All set_zoom() calls validate the requested zoom string against zoomdict and optionally sleep 100 ms to simulate settling time. No serial or USB connections are opened. Used for development and testing.

set_zoom(zoom, wait_until_done=True)[source]

Simulate moving the zoom body to the named zoom position.

Parameters:
  • zoom (str) – Zoom designation, e.g. '2x', that must be a key in self.zoomdict.

  • wait_until_done (bool) – When True, sleep 100 ms to simulate a mechanical settle delay.

class mesoSPIM.src.mesoSPIM_Zoom.DynamixelZoom(*args: Any, **kwargs: Any)[source]

Bases: Dynamixel

Zoom driver that controls a Dynamixel servo-driven zoom body.

Inherits from mesoSPIM.src.devices.servos.dynamixel.dynamixel.Dynamixel which handles low-level serial communication with the Dynamixel protocol. The zoomdict maps user-facing zoom strings (e.g. '2x') to the corresponding servo goal-position values.

set_zoom(zoom, wait_until_done=True)[source]

Changes zoom after checking that the commanded value exists

class mesoSPIM.src.mesoSPIM_Zoom.MitutoyoZoom(*args: Any, **kwargs: Any)[source]

Bases: QObject

Zoom driver for a Mitutoyo motorised objective revolver.

set_zoom(zoom, wait_until_done=True)[source]

Move the revolver to the named objective position. Communicates via RS-232 serial using the Mitutoyo ASCII protocol (RWRMV<X> commands where X is one of AE). The zoomdict maps user-facing zoom strings to revolver positions 'A' through 'E'.

Parameters:
  • zoom (str) – Zoom designation that must be a key in self.zoomdict and whose value must be a letter in ('A', 'B', 'C', 'D', 'E').

  • wait_until_done (bool) – When True, wait 1 s for the revolver to complete its rotation before returning.

mesoSPIM_Optimizer

Frontend of the optimizer which allows to use auto-focus or optimization of other microscope parameters Auto-focus is based on Autopilot paper (Royer at al, Nat Biotechnol. 2016 Dec;34(12):1267-1278. doi: 10.1038/nbt.3708.) author: Nikita Vladimirov, @nvladimus, 2021 License: GPL-3

class mesoSPIM.src.mesoSPIM_Optimizer.mesoSPIM_Optimizer(*args: Any, **kwargs: Any)[source]

Bases: QWidget

accept_new_state()[source]

Apply the fitted optimum value, snap a confirmation image, and close the results window.

close_window()[source]
create_results_window()[source]
discard_new_state()[source]

Discard the fitted optimum and close the results window without changing hardware state.

get_params_from_gui()[source]
get_roi_dims(roi_dims)[source]
plot_results()[source]
results_string()[source]

Pretty formatting

run_optimization()[source]

Execute the optimisation sweep and display results in a pop-up window.

  • Stops Live mode if active.

  • Reads parameters from the GUI controls.

  • Snaps n_points images uniformly distributed over the search range, computing the DCT-Shannon sharpness metric shannon_dct() for each.

  • Fits a Gaussian to the metric curve to locate the optimum.

  • Opens a create_results_window() overlay for the user to accept or discard the new parameter value.

set_etl_amp_to_zero()[source]
set_mode_from_gui(choice)[source]
set_parameters(param_dict=None, update_gui=True)[source]

Update internal optimiser parameters from a dict and refresh the GUI.

Parameters:
  • param_dict (dict, optional) – Any subset of {'mode', 'amplitude', 'n_points'}.

  • update_gui (bool) – Call update_gui() after applying the parameters.

set_roi(orientation='h', roi_perc=0.25)[source]

Set a rectangular ROI on the camera window and update roi_dims.

Parameters:
  • orientation (str) – 'h' — horizontal strip across the image centre; 'v' — vertical strip; 'c' — centred square; None — full image frame.

  • roi_perc (float) – Fraction of the image dimension used for the ROI, e.g. 0.25 = 25 %.

set_state(new_val)[source]
sig_move_absolute

GUI widget for automated optimisation of imaging parameters.

Implements a 1-D Gaussian-fit-based auto-focus and parameter optimiser as described in:

Royer et al., Nature Biotechnology 34, 1267–1278 (2016). https://doi.org/10.1038/nbt.3708

Supported optimisation modes (set via the comboBoxMode drop-down):

  • ETL offset — searches etl_l_offset / etl_r_offset for the value that maximises the DCT-Shannon sharpness metric.

  • ETL amplitude — searches etl_l_amplitude / etl_r_amplitude to maximise contrast depth.

  • Focus — moves the focus (F) axis to find the sharpest plane.

Workflow:

  1. Click Run to trigger run_optimization().

  2. The algorithm snaps images at n_points positions spanning ± search_amplitude around the current state value.

  3. Results are fitted with a Gaussian and displayed in a pop-up window.

  4. Click Accept / Discard to keep or revert the new optimum.

sig_state_request

int = …, arguments: Sequence = …) -> PYQT_SIGNAL

types is normally a sequence of individual types. Each type is either a type object or a string that is the name of a C++ type. Alternatively each type could itself be a sequence of types each describing a different overloaded signal. name is the optional C++ name of the signal. If it is not specified then the name of the class attribute that is bound to the signal is used. revision is the optional revision of the signal that is exported to QML. If it is not specified then 0 is used. arguments is the optional sequence of the names of the signal’s arguments.

Type:

pyqtSignal(*types, name

Type:

str = …, revision

update_gui()[source]
update_image()[source]

Pull the latest frame from frame_queue_display and update the current ROI.

GUI windows

mesoSPIM_MainWindow

class mesoSPIM.src.mesoSPIM_MainWindow.mesoSPIM_MainWindow(package_directory, config, title='mesoSPIM Main Window')[source]

Bases: QMainWindow

Main application window which instantiates worker objects and moves them to a thread.

cascade_all_windows()[source]
check_config_file()[source]

Checks missing blocks in config file and gives suggestions. Todo: all new config options

check_instances(widget)[source]

Method to check whether a widget belongs to one of the Qt Classes specified.

Parameters:

widget (QtWidgets.QWidget) – Widget to check

Returns:

True if widget is in the list, False if not.

Return type:

return_value (bool)

choose_etl_config()[source]

File dialog for choosing the config file

choose_snap_folder()[source]
close_app()[source]
connect_combobox_to_state_parameter(combobox, option_list, state_parameter, int_conversion=False)[source]

Helper method to connect and initialize a combobox from the config

Parameters:
  • combobox (QtWidgets.QComboBox) – Combobox in the GUI to be connected

  • option_list (list) – List of selection options

  • state_parameter (str) – State parameter (has to exist in the config)

connect_spinbox_to_state_parameter(spinbox, state_parameter, conversion_factor=1)[source]

Helper method to connect and initialize a spinbox from the config

Parameters:
  • spinbox (QtWidgets.QSpinBox or QtWidgets.QDoubleSpinbox) – Spinbox in the GUI to be connected

  • state_parameter (str) – State parameter (has to exist in the config)

  • conversion_factor (float) – Conversion factor. If the config is in seconds, the spinbox displays ms: conversion_factor = 1000. If the config is in seconds and the spinbox displays microseconds: conversion_factor = 1000000

connect_widget_to_state_parameter(widget, state_parameter, conversion_factor)[source]

Helper method to (currently) connect spinboxes

create_script_window()[source]

Creates a script window for the user to input Python code.

create_widget_list(list, widget_list)[source]

Helper method to recursively loop through all the widgets in a list and their children. :param list: List of QtWidgets.QWidget objects :type list: list

display_status_message(string)[source]

Displays a message in the status bar for a time in ms

display_warning(string)[source]
enable_gui(boolean)[source]
enable_mode_control_buttons(boolean)[source]
enable_move_buttons(axis='x', state=True)[source]
enable_stop_button(boolean)[source]
execute_script(script)[source]
finished()[source]
get_state_parameter(state_parameter)[source]
initialize_and_connect_menubar()[source]
initialize_and_connect_widgets()[source]

Connecting the menu actions

launch_contrast_window()[source]
launch_optimizer(ini_dict=None)[source]
move_relative(pos_dict)[source]
open_tiff()[source]

Open and display a TIFF file (stack), eg for demo and debugging purposes.

open_tile_view_window()[source]
open_webcam_window()[source]

Open USB webcam window using cam ID specified in config file.

pos2str(position)[source]

Little helper method for converting positions to strings

run_acquisition_list()[source]
run_lightsheet_alignment_mode()[source]
run_live()[source]
run_selected_acquisition()[source]
run_snap()[source]
run_timepoint(timepoint)[source]
run_visual_mode()[source]
save_etl_config()[source]

Save current ETL parameters into config

scale_galvo_amp_w_zoom()[source]
set_laser_intensity(value)[source]
set_progressbars_to_busy()[source]

If min and max of a progress bar are 0, it shows a “busy” indicator

set_progressbars_to_standard()[source]
sig_center_sample

int = …, arguments: Sequence = …) -> PYQT_SIGNAL

types is normally a sequence of individual types. Each type is either a type object or a string that is the name of a C++ type. Alternatively each type could itself be a sequence of types each describing a different overloaded signal. name is the optional C++ name of the signal. If it is not specified then the name of the class attribute that is bound to the signal is used. revision is the optional revision of the signal that is exported to QML. If it is not specified then 0 is used. arguments is the optional sequence of the names of the signal’s arguments.

Type:

pyqtSignal(*types, name

Type:

str = …, revision

sig_enable_gui

int = …, arguments: Sequence = …) -> PYQT_SIGNAL

types is normally a sequence of individual types. Each type is either a type object or a string that is the name of a C++ type. Alternatively each type could itself be a sequence of types each describing a different overloaded signal. name is the optional C++ name of the signal. If it is not specified then the name of the class attribute that is bound to the signal is used. revision is the optional revision of the signal that is exported to QML. If it is not specified then 0 is used. arguments is the optional sequence of the names of the signal’s arguments.

Type:

pyqtSignal(*types, name

Type:

str = …, revision

sig_execute_script

int = …, arguments: Sequence = …) -> PYQT_SIGNAL

types is normally a sequence of individual types. Each type is either a type object or a string that is the name of a C++ type. Alternatively each type could itself be a sequence of types each describing a different overloaded signal. name is the optional C++ name of the signal. If it is not specified then the name of the class attribute that is bound to the signal is used. revision is the optional revision of the signal that is exported to QML. If it is not specified then 0 is used. arguments is the optional sequence of the names of the signal’s arguments.

Type:

pyqtSignal(*types, name

Type:

str = …, revision

sig_finished

int = …, arguments: Sequence = …) -> PYQT_SIGNAL

types is normally a sequence of individual types. Each type is either a type object or a string that is the name of a C++ type. Alternatively each type could itself be a sequence of types each describing a different overloaded signal. name is the optional C++ name of the signal. If it is not specified then the name of the class attribute that is bound to the signal is used. revision is the optional revision of the signal that is exported to QML. If it is not specified then 0 is used. arguments is the optional sequence of the names of the signal’s arguments.

Type:

pyqtSignal(*types, name

Type:

str = …, revision

sig_launch_contrast_window

int = …, arguments: Sequence = …) -> PYQT_SIGNAL

types is normally a sequence of individual types. Each type is either a type object or a string that is the name of a C++ type. Alternatively each type could itself be a sequence of types each describing a different overloaded signal. name is the optional C++ name of the signal. If it is not specified then the name of the class attribute that is bound to the signal is used. revision is the optional revision of the signal that is exported to QML. If it is not specified then 0 is used. arguments is the optional sequence of the names of the signal’s arguments.

Type:

pyqtSignal(*types, name

Type:

str = …, revision

sig_launch_optimizer

int = …, arguments: Sequence = …) -> PYQT_SIGNAL

types is normally a sequence of individual types. Each type is either a type object or a string that is the name of a C++ type. Alternatively each type could itself be a sequence of types each describing a different overloaded signal. name is the optional C++ name of the signal. If it is not specified then the name of the class attribute that is bound to the signal is used. revision is the optional revision of the signal that is exported to QML. If it is not specified then 0 is used. arguments is the optional sequence of the names of the signal’s arguments.

Type:

pyqtSignal(*types, name

Type:

str = …, revision

sig_load_sample

int = …, arguments: Sequence = …) -> PYQT_SIGNAL

types is normally a sequence of individual types. Each type is either a type object or a string that is the name of a C++ type. Alternatively each type could itself be a sequence of types each describing a different overloaded signal. name is the optional C++ name of the signal. If it is not specified then the name of the class attribute that is bound to the signal is used. revision is the optional revision of the signal that is exported to QML. If it is not specified then 0 is used. arguments is the optional sequence of the names of the signal’s arguments.

Type:

pyqtSignal(*types, name

Type:

str = …, revision

sig_move_absolute

int = …, arguments: Sequence = …) -> PYQT_SIGNAL

types is normally a sequence of individual types. Each type is either a type object or a string that is the name of a C++ type. Alternatively each type could itself be a sequence of types each describing a different overloaded signal. name is the optional C++ name of the signal. If it is not specified then the name of the class attribute that is bound to the signal is used. revision is the optional revision of the signal that is exported to QML. If it is not specified then 0 is used. arguments is the optional sequence of the names of the signal’s arguments.

Type:

pyqtSignal(*types, name

Type:

str = …, revision

sig_move_relative

int = …, arguments: Sequence = …) -> PYQT_SIGNAL

types is normally a sequence of individual types. Each type is either a type object or a string that is the name of a C++ type. Alternatively each type could itself be a sequence of types each describing a different overloaded signal. name is the optional C++ name of the signal. If it is not specified then the name of the class attribute that is bound to the signal is used. revision is the optional revision of the signal that is exported to QML. If it is not specified then 0 is used. arguments is the optional sequence of the names of the signal’s arguments.

Type:

pyqtSignal(*types, name

Type:

str = …, revision

sig_poke_demo_thread

int = …, arguments: Sequence = …) -> PYQT_SIGNAL

types is normally a sequence of individual types. Each type is either a type object or a string that is the name of a C++ type. Alternatively each type could itself be a sequence of types each describing a different overloaded signal. name is the optional C++ name of the signal. If it is not specified then the name of the class attribute that is bound to the signal is used. revision is the optional revision of the signal that is exported to QML. If it is not specified then 0 is used. arguments is the optional sequence of the names of the signal’s arguments.

Type:

pyqtSignal(*types, name

Type:

str = …, revision

sig_save_etl_config

int = …, arguments: Sequence = …) -> PYQT_SIGNAL

types is normally a sequence of individual types. Each type is either a type object or a string that is the name of a C++ type. Alternatively each type could itself be a sequence of types each describing a different overloaded signal. name is the optional C++ name of the signal. If it is not specified then the name of the class attribute that is bound to the signal is used. revision is the optional revision of the signal that is exported to QML. If it is not specified then 0 is used. arguments is the optional sequence of the names of the signal’s arguments.

Type:

pyqtSignal(*types, name

Type:

str = …, revision

sig_state_request

int = …, arguments: Sequence = …) -> PYQT_SIGNAL

types is normally a sequence of individual types. Each type is either a type object or a string that is the name of a C++ type. Alternatively each type could itself be a sequence of types each describing a different overloaded signal. name is the optional C++ name of the signal. If it is not specified then the name of the class attribute that is bound to the signal is used. revision is the optional revision of the signal that is exported to QML. If it is not specified then 0 is used. arguments is the optional sequence of the names of the signal’s arguments.

Type:

pyqtSignal(*types, name

Type:

str = …, revision

sig_stop

int = …, arguments: Sequence = …) -> PYQT_SIGNAL

types is normally a sequence of individual types. Each type is either a type object or a string that is the name of a C++ type. Alternatively each type could itself be a sequence of types each describing a different overloaded signal. name is the optional C++ name of the signal. If it is not specified then the name of the class attribute that is bound to the signal is used. revision is the optional revision of the signal that is exported to QML. If it is not specified then 0 is used. arguments is the optional sequence of the names of the signal’s arguments.

Type:

pyqtSignal(*types, name

Type:

str = …, revision

sig_stop_movement

int = …, arguments: Sequence = …) -> PYQT_SIGNAL

types is normally a sequence of individual types. Each type is either a type object or a string that is the name of a C++ type. Alternatively each type could itself be a sequence of types each describing a different overloaded signal. name is the optional C++ name of the signal. If it is not specified then the name of the class attribute that is bound to the signal is used. revision is the optional revision of the signal that is exported to QML. If it is not specified then 0 is used. arguments is the optional sequence of the names of the signal’s arguments.

Type:

pyqtSignal(*types, name

Type:

str = …, revision

sig_unload_sample

int = …, arguments: Sequence = …) -> PYQT_SIGNAL

types is normally a sequence of individual types. Each type is either a type object or a string that is the name of a C++ type. Alternatively each type could itself be a sequence of types each describing a different overloaded signal. name is the optional C++ name of the signal. If it is not specified then the name of the class attribute that is bound to the signal is used. revision is the optional revision of the signal that is exported to QML. If it is not specified then 0 is used. arguments is the optional sequence of the names of the signal’s arguments.

Type:

pyqtSignal(*types, name

Type:

str = …, revision

sig_unzero_axes

int = …, arguments: Sequence = …) -> PYQT_SIGNAL

types is normally a sequence of individual types. Each type is either a type object or a string that is the name of a C++ type. Alternatively each type could itself be a sequence of types each describing a different overloaded signal. name is the optional C++ name of the signal. If it is not specified then the name of the class attribute that is bound to the signal is used. revision is the optional revision of the signal that is exported to QML. If it is not specified then 0 is used. arguments is the optional sequence of the names of the signal’s arguments.

Type:

pyqtSignal(*types, name

Type:

str = …, revision

sig_zero_axes

int = …, arguments: Sequence = …) -> PYQT_SIGNAL

types is normally a sequence of individual types. Each type is either a type object or a string that is the name of a C++ type. Alternatively each type could itself be a sequence of types each describing a different overloaded signal. name is the optional C++ name of the signal. If it is not specified then the name of the class attribute that is bound to the signal is used. revision is the optional revision of the signal that is exported to QML. If it is not specified then 0 is used. arguments is the optional sequence of the names of the signal’s arguments.

Type:

pyqtSignal(*types, name

Type:

str = …, revision

slow_down_spinbox(spinbox)[source]
spinbox_to_state_parameter(new_value, spinbox, state_parameter, conversion_factor)[source]
update_GUI_by_shutter_state()[source]

Disables controls for the opposite ETL to avoid overriding parameters

update_etl_increments()[source]
update_gui_from_state()[source]
update_position_indicators(dict)[source]
update_progressbars(dict)[source]
update_widget_from_state(widget, state_parameter_string, conversion_factor)[source]
zero_galvo_amp()[source]

Set the amplitude of both galvos to zero, or back to where it was, depending on button state

zero_left_etl()[source]

Zeros the amplitude of the left ETL for faster alignment

zero_right_etl()[source]

Zeros the amplitude of the right ETL for faster alignment

mesoSPIM_AcquisitionManagerWindow

mesoSPIM Acquisition Manager Window

class mesoSPIM.src.mesoSPIM_AcquisitionManagerWindow.MyStyle[source]

Bases: QProxyStyle

drawPrimitive(element, option, painter, widget=None)[source]

Draw a line across the entire row rather than just the column we’re hovering over.

class mesoSPIM.src.mesoSPIM_AcquisitionManagerWindow.mesoSPIM_AcquisitionManagerWindow(parent=None)[source]

Bases: QWidget

Acquisition table editor and sequencer for mesoSPIM.

Provides a spreadsheet-like interface (backed by AcquisitionModel) where each row represents one tiled Z-stack (“acquisition”). Columns include position (x, y, z, f, theta), Z range and step size, filter, laser, intensity, exposure, zoom, ETL parameters, and output file path.

Key capabilities:

  • Add / delete / copy / reorder rows in the acquisition list.

  • Mark current buttons to capture the live stage position, ETL state, and/or filter into the selected row without typing.

  • Save / Load the table as a binary file.

  • Wizards for tiling patterns, focus tracking, and image-processing pipelines.

  • Auto-illumination button to automatically set illumination parameters based on the current acquisition list.

The model state key 'acquisition_list' is kept in sync with the table so that mesoSPIM_Core can iterate over it.

add_row()[source]
append_time_index_to_filenames(time_index)[source]

Appends the time index to each filename

auto_illumination(margin_um=500)[source]
copy_row()[source]
delete_all_rows()[source]

Displays a warning that this will delete the entire table and then proceeds to delete if the user clicks ‘Yes’

delete_row()[source]

Deletes the selected row

disable()[source]
disable_gui()[source]

Disables all buttons and controls, enables stop button

display_information(string, fontsize=12)[source]
display_no_row_selected_warning()[source]
display_status_message(string, time=0)[source]

Displays a message in the status bar for a time in ms

If time=0, the message will stay.

display_warning(string)[source]
enable()[source]
enable_gui()[source]

Enables all GUI controls, disables stop button

generate_filenames()[source]
get_first_selected_row()[source]

Little helper method to provide the first row out of a selection range

get_selected_rows()[source]

Little helper method to provide the selected rows

load_table()[source]
mark_all_current_parameters()[source]
mark_current_etl_parameters()[source]
mark_current_focus()[source]

Marks both foci start focus

mark_current_rotation()[source]
mark_current_state()[source]
mark_current_xy_position()[source]
move_selected_row_down()[source]
move_selected_row_up()[source]
preview_acquisition()[source]
run_focus_tracking_wizard()[source]
run_image_processing_wizard()[source]
run_tiling_wizard()[source]
save_table()[source]
selected_row_changed(new_selection, old_selection)[source]
set_folder_names()[source]
set_item_delegates()[source]

Several columns should have certain delegates

If I decide to move colums, the delegates should move with them

Here, I need the configuration to provide the options for the delegates.

set_selected_row(row)[source]

Little helper method to allow setting the selected row

set_state()[source]
sig_move_absolute

int = …, arguments: Sequence = …) -> PYQT_SIGNAL

types is normally a sequence of individual types. Each type is either a type object or a string that is the name of a C++ type. Alternatively each type could itself be a sequence of types each describing a different overloaded signal. name is the optional C++ name of the signal. If it is not specified then the name of the class attribute that is bound to the signal is used. revision is the optional revision of the signal that is exported to QML. If it is not specified then 0 is used. arguments is the optional sequence of the names of the signal’s arguments.

Type:

pyqtSignal(*types, name

Type:

str = …, revision

sig_warning

int = …, arguments: Sequence = …) -> PYQT_SIGNAL

types is normally a sequence of individual types. Each type is either a type object or a string that is the name of a C++ type. Alternatively each type could itself be a sequence of types each describing a different overloaded signal. name is the optional C++ name of the signal. If it is not specified then the name of the class attribute that is bound to the signal is used. revision is the optional revision of the signal that is exported to QML. If it is not specified then 0 is used. arguments is the optional sequence of the names of the signal’s arguments.

Type:

pyqtSignal(*types, name

Type:

str = …, revision

start_selected()[source]

Get the selected row and run this (single) row only

Indices is a list of selected QModelIndex objects, we’re only interested in the first.

statusBar

Setting the model up

update_acquisition_size_prediction()[source]

Compute and display the estimated total data size for the current acquisition list.

update_acquisition_time_prediction()[source]

Compute and display the estimated total acquisition time in the GUI label.

Uses the current camera framerate from state and sums up the planned Z-stack images across all rows in the acquisition model.

mesoSPIM_CameraWindow

mesoSPIM CameraWindow

class mesoSPIM.src.mesoSPIM_CameraWindow.mesoSPIM_CameraWindow(parent=None)[source]

Bases: QWidget

adjust_levels(pct_low=25, pct_hi=99.99)[source]

Stretch the display histogram to the pct_lowpct_hi percentile range.

Parameters:
  • pct_low (float) – Lower percentile clipping level (default 25).

  • pct_hi (float) – Upper percentile clipping level (default 99.99).

change_overlay(overlay_name)[source]
disable_auto_range()[source]

Hard disable ViewBox auto-range which was causing high CPU loads

draw_crosshairs()[source]

Add (or re-add) the red crosshair lines to the image view.

draw_lightsheet_marker()[source]

Show the yellow arrow overlay indicating the active light-sheet side.

The left arrow is shown when state['shutterconfig'] is 'Left', the right arrow when it is 'Right', and both when it is 'Both'.

get_image_shape()[source]
get_roi()[source]

Return the image array within the currently active overlay ROI.

If the overlay is a draggable box the ROI is cropped to that region and sig_update_roi is emitted with (x, y, w, h). Otherwise the full image is returned and the ROI covers the whole frame.

Returns:

2-D uint16 pixel array of the ROI.

Return type:

numpy.ndarray

hide_light_sheet_marker()[source]
ini_subsampling

Initialize crosshairs

px2um(px, scale=1)[source]

Convert a pixel distance to micrometres using the current zoom pixel size.

Parameters:
  • px (float) – Pixel count.

  • scale (float) – Additional scaling factor (e.g. the display sub-sampling ratio).

Returns:

Distance in micrometres.

Return type:

float

set_image(image)[source]
set_roi(mode='box', x_y_w_h=(0, 0, 100, 100))[source]

Set the overlay mode and reposition the ROI rectangle.

Parameters:
  • mode (str or None) – 'box' — show draggable rectangle; 'LS marker' — show light-sheet direction arrows; None — no overlay.

  • x_y_w_h (tuple) – (x, y, width, height) in screen (sub-sampled) pixel coordinates.

sig_update_roi

int = …, arguments: Sequence = …) -> PYQT_SIGNAL

types is normally a sequence of individual types. Each type is either a type object or a string that is the name of a C++ type. Alternatively each type could itself be a sequence of types each describing a different overloaded signal. name is the optional C++ name of the signal. If it is not specified then the name of the class attribute that is bound to the signal is used. revision is the optional revision of the signal that is exported to QML. If it is not specified then 0 is used. arguments is the optional sequence of the names of the signal’s arguments.

Type:

pyqtSignal(*types, name

Type:

str = …, revision

sig_update_status

Live-view camera display window for mesoSPIM.

Renders camera frames in real time using PyQtGraph’s ImageView widget. Key features:

  • Subsampled display — independent sub-sampling factors controlled GUI mesoSPIM_MainWindow for live and acquisition modes (camera_display_live_subsampling / camera_display_acquisition_subsampling from state).

  • Histogram / level adjustment — manual (button) or automatic percentile stretch via adjust_levels().

  • Overlays — three overlay modes selectable from a combo-box:

    • LS marker — colour-coded arrow showing active light-sheet direction.

    • Box ROI — draggable rectangle used by mesoSPIM_Optimizer.

    • None — clean view.

  • ROI reporting — emits sig_update_roi whenever the box ROI changes so that the Optimizer can crop its sharpness measurements.

  • Status updates — emits sig_update_status to notify other components of changes in the camera window status.

Receives frames via set_image() (called from the Core thread via a queued connection).

update_image_from_deque()[source]

Poll the head of frame_queue_display and call set_image() if a frame is available.

If the deque is empty the call is a no-op.

update_status(subsampling=2.0)[source]

Devices

Cameras

class mesoSPIM.src.devices.cameras.Demo_Camera.Demo_Camera[source]

Bases: object

startAcquisition()[source]

Filter wheels

mesoSPIM Filterwheel classes Authors: Fabian Voigt, Nikita Vladimirov

class mesoSPIM.src.devices.filter_wheels.mesoSPIM_FilterWheel.DynamixelFilterWheel(*args: Any, **kwargs: Any)[source]

Bases: Dynamixel

set_filter(filter, wait_until_done=False)[source]

Changes filter after checking that the commanded value exists

class mesoSPIM.src.devices.filter_wheels.mesoSPIM_FilterWheel.LudlFilterWheel(*args: Any, **kwargs: Any)[source]

Bases: QObject

Class to control a 10-position Ludl filterwheel

Needs a dictionary which combines filter designations and position IDs in the form:

filters = {‘405-488-647-Tripleblock’0,

‘405-488-561-640-Quadrupleblock’: 1, ‘464 482-35’: 2, ‘508 520-35’: 3, ‘515LP’:4, ‘529 542-27’:5, ‘561LP’:6, ‘594LP’:7, ‘Empty’:8,}

If there are tuples instead of integers as values, the filterwheel is assumed to be a double wheel.

I.e.: ‘508 520-35’: (2,3)

set_filter(filter, wait_until_done=False)[source]

Moves filter using the pyserial command set. No checks are done whether the movement is completed or finished in time.

wait_until_done_delay

If the first entry of the filterdict has a tuple as value, it is assumed that it is a double-filterwheel to change the serial commands accordingly.

TODO: This doesn’t check that the tuple has length 2.

class mesoSPIM.src.devices.filter_wheels.mesoSPIM_FilterWheel.SutterLambda10BFilterWheel(filterwheel_parameters, filterdict, read_on_init=True)[source]

Bases: object

close()[source]
double_wheel

Delay in s for the wait until done function

read(num_bytes)[source]
set_filter(filterposition=0, wait_until_done=False)[source]
class mesoSPIM.src.devices.filter_wheels.mesoSPIM_FilterWheel.ZwoFilterWheel(*args: Any, **kwargs: Any)[source]

Bases: QObject

Astronomy filter wheels from https://astronomy-imaging-camera.com

set_filter(filter, wait_until_done=False)[source]
class mesoSPIM.src.devices.filter_wheels.mesoSPIM_FilterWheel.mesoSPIM_DemoFilterWheel(*args: Any, **kwargs: Any)[source]

Bases: QObject

set_filter(filter, wait_until_done=False)[source]

Lasers

mesoSPIM Module for enabling single laser lines via NI-DAQmx

class mesoSPIM.src.devices.lasers.mesoSPIM_LaserEnabler.mesoSPIM_LaserEnabler(laserdict)[source]

Bases: object

Class for interacting with the laser enable DO lines via NI-DAQmx This uses the property of NI-DAQmx-outputs to keep their last digital state or analog voltage for as long the device is not powered down. This means that the NI tasks are closed after calls to “enable”, “disable”, etc which in turn means that this class is not intended for fast switching in complicated waveforms. Needs a dictionary which combines laser wavelengths and device outputs in the form: {‘488 nm’: ‘PXI1Slot4/port0/line2’, ‘515 nm’: ‘PXI1Slot4/port0/line3’}

disable_all()[source]

Disables all laser lines.

enable(laser)[source]

Enables a single laser line. All other lines are switched off.

state()[source]

Returns laserline if a laser is on, otherwise “False”

Shutters

mesoSPIM Module for controlling a shutter via NI-DAQmx Author: Fabian Voigt #TODO

class mesoSPIM.src.devices.shutters.NI_Shutter.NI_Shutter(shutterline)[source]

Bases: object

Slow shutter, intended more as a gating device than a fast open/close because the NI task is recreated and deleted every time a shutter is actuated.

Thus, the shutter has more a “gating” function to protect the sample than fast control of the laser, this is done via the laser intensity anyway.

This uses the property of NI-DAQmx-outputs to keep their last digital state or analog voltage for as long the device is not powered down.

close(*args)[source]
open(*args)[source]
state(*args)[source]

Returns “True” if the shutter is open, otherwise “False”

Utilities

acquisitions.py

Helper classes for mesoSPIM acquisitions

class mesoSPIM.src.utils.acquisitions.Acquisition(*args: Any, **kwargs: Any)[source]

Bases: IndexedOrderedDict

Custom acquisition dictionary. Contains all the information to run a single acquisition.

Parameters:
  • x_pos (float) – X start position in microns

  • y_pos (float) – Y start position in microns

  • z_start (float) – Z start position in microns

  • z_end (float) – Z end position in microns

  • z_step (float) – Z stepsize in microns ,

  • theta_pos (float) – Rotation angle in microns

  • f_pos (float) – Focus position in microns

  • laser (str) – Laser designation

  • intensity (int) – Laser intensity in 0-100

  • filter (str) – Filter designation (has to be in the config)

  • zoom (str) – Zoom designation

  • filename (str) – Filename for the file to be saved

Attributes:

Note

Getting keys: keys = [key for key in acq1.keys()]

Example

Getting keys: keys = [key for key in acq1.keys()]

Todo

Testtodo-Entry

get_acquisition_time(framerate)[source]

Method to return the time the acquisition will take at a certain framerate.

Parameters:

float – framerate of the microscope

Returns:

Acquisition time in seconds

Return type:

float

get_capitalized_keylist()[source]

Here, a list of capitalized keys is returned for usage as a table header

get_delta_dict()[source]

Returns relative movement dict for z-steps and f-steps

get_delta_z_and_delta_f_dict(inverted=False)[source]

Returns relative movement dict for z- and f-steps

get_endpoint()[source]
get_focus_stepsize_generator(f_stage_min_step_um=0.25)[source]

‘ Provides a generator object to correct rounding errors for focus tracking acquisitions.

The focus stage has to travel a shorter distance than the sample z-stage, ideally only a fraction of the z-step size. However, due to the limited minimum step size of the focus stage, rounding errors can accumulate over thousands of steps.

Therefore, the generator tracks the rounding error and applies correcting steps here and there to minimize the error.

This assumes a minimum step size of around 0.25 micron that the focus stage is capable of.

This method contains lots of round functions to keep residual rounding errors at bay.

get_image_count()[source]

Method to return the number of planes in the acquisition

get_keylist()[source]

A list keys is returned for usage as a table header

get_startpoint()[source]

Provides a dictionary with the startpoint coordinates

class mesoSPIM.src.utils.acquisitions.AcquisitionList(*args)[source]

Bases: list

Class for a list of acquisition objects

Examples: “([acq1,acq2,acq3])” is due to the fact that list takes only a single argument acq_list = AcquisitionList([acq1,acq2,acq3]) acq_list.time() > 3600 acq_list.planes() > 18000

acq_list[2](2) >10 acq_list[2][‘y_pos’] >10 acq_list[2][‘y_pos’] = 34

check_filename_extensions()[source]

Returns files that have no extension, so their format is undefined.

check_for_duplicated_filenames()[source]

Returns a list of duplicated filenames

check_for_existing_filenames()[source]

Returns a list of existing filenames

check_for_nonexisting_folders()[source]

Returns a list of nonexisting folders

find_value_index(value: str = '488 nm', key: str = 'laser')[source]

Find the attribute index in the acquisition list. Example: al = AcquisitionList([Acquisition(), Acquisition(), Acquisition(), Acquisition()]) al[0][‘laser’] = ‘488 nm’ # al[1][‘laser’] = ‘488 nm’ # gets removed because non-unique al[2][‘laser’] = ‘561 nm’ # al[3][‘laser’] = ‘637 nm’ # Output: al.find_value_index(‘488 nm’, ‘laser’) # -> 0 al.find_value_index(‘561 nm’, ‘laser’) # -> 1 al.find_value_index(‘637 nm’, ‘laser’) # -> 2

get_acquisition_time(framerate)[source]

Returns total time in seconds of a list of acquisitions

get_all_filenames()[source]

Returns a list of all filenames

get_capitalized_keylist()[source]
get_duplicates_in_list(in_list)[source]
get_image_count()[source]

Returns the total number of planes for a list of acquistions

get_keylist()[source]

Here, a list of capitalized keys is returned for usage as a table header

get_n_angles()[source]

Get the number of unique angles

get_n_lasers()[source]

Get the number of unique laser lines

get_n_shutter_configs()[source]

Get the number of unique shutter configs (1 or 2)

get_n_tiles()[source]

Get the number of tiles as unique (x,y,z_start,rot) combinations

get_startpoint()[source]
get_tile_index(acq)[source]

Get the the tile index for given acquisition

get_unique_attr_list(key: str = 'laser') list[source]

Return ordered list of acquisition attributes.

Parameters:

key: str

One of (‘laser’, ‘shutterconfig’, ‘rot’)

Returns:

List of strings, e.g. (‘488’, ‘561’) for key=’laser’, in the order of acquisition.

Contains a variety of mesoSPIM utility functions

mesoSPIM.src.utils.utility_functions.GetCurrentProcessorNumber()
mesoSPIM.src.utils.utility_functions.convert_seconds_to_string(delta_t)[source]

Converts an input value in seconds into a string in the format hh:mm:ss

Interestingly, a variant using np.divmod is around 4-5x slower in initial tests.

mesoSPIM.src.utils.utility_functions.format_data_size(bytes)[source]

Converts bytes into human-readable format (kb, MB, GB)

mesoSPIM.src.utils.utility_functions.gb_size_of_array_shape(shape)[source]

Given a tuple of array shape, return the size in GB of a uint16 array.

Parameters:

shape (tuple[int]) – Array dimensions, e.g. (100, 2048, 2048).

Returns:

Size in gibibytes (GiB).

Return type:

float

mesoSPIM.src.utils.utility_functions.log_cpu_core(logger, msg='')[source]

Log (at DEBUG level) which logical CPU core the calling thread is currently running on.

Useful for verifying thread affinity in the Core / Camera / Writer thread model——each Qt thread should remain pinned to a consistent CPU core.

Parameters:
  • logger (logging.Logger) – Logger instance used for the debug message.

  • msg (str) – Optional prefix string included in the log message.

mesoSPIM.src.utils.utility_functions.replace_with_underscores(string)[source]

Replace spaces, slashes and percent signs with underscores or ASCII equivalents.

Used for sanitising file and folder names produced from user inputs.

Parameters:

string (str) – Raw string, e.g. a filter name like "488 nm / 50%".

Returns:

Sanitised string safe for use in file paths.

Return type:

str

mesoSPIM.src.utils.utility_functions.timed(func)[source]

Decorator to time functions and log the elapsed time

mesoSPIM.src.utils.utility_functions.write_line(file, key='', value='')[source]

Little helper method to write a single line with a key and value for metadata Adds a line break at the end.