Skip to main content

redsun-mimir

License Apache Software License 2.0 PyPI Python Version codecov

Bundle of redsun components for the openUC2 "Mimir" microscope

About mimir

Mimir is the codename for an in-development portable interferometric scattering microscope (iSCAT), with an hardware controller developed by openUC2. The hardware is driven from separate processes: pymmcore-plus for the camera and the stages, pyserial for the openUC2 board. Each runs as a redsun service and is reached over PVAccess, served by fastcs.

redsun-mimir is a bundle of components developed to target the specific hardware and software requirements for real-time acquisition with said microscope.

Installation

It is strongly reccomended to install redsun-mimir in a virtual environment.

uv (reccomended)

Be sure to install uv first.

# create the venv
uv venv --python 3.11

# activate the environment in...
# ... linux
source .venv/bin/activate

# ... windows
.venv\Scripts\activate

uv pip install redsun-mimir
pip

You should have Python installed in your machine.

# create the venv
python -m venv .venv

# activate the environment in...
# ... linux
source .venv/bin/activate

# ... windows
.venv\Scripts\activate

pip install redsun-mimir

Installing from source

redsun-mimir is developed via uv; you can clone the repository and install development dependencies:

git clone https://github.com/redsun-acquisition/redsun-mimir

cd redsun-mimir

uv sync

Running a simulator container

redsun-mimir comes with a simple simulation environment with simulated devices for demonstration purposes.

To run it, you have to:

  1. install the package in your virtual environment by adding the sim optional dependencies;
  2. run mmcore install (or alternatively one of the methods described here).
  3. run the container via mimir sim.
uv (reccomended)
# in your virtual environment
uv pip install redsun-mimir[sim]

# install micro-manager device adapters
mmcore install --test-adapters

# run the example container via command line
mimir sim
pip
# in your virtual environment
pip install redsun-mimir[sim]

# install micro-manager device adapters
mmcore install --test-adapters

# run the example container via command line
mimir sim

Installing the napari application hook

ImageView embeds a napari viewer but carries no stylesheet of its own: it is styled by the application it is built under. NapariApplication supplies that application. It serves two hook points, returning the application napari itself would build (create_application) and putting napari's stylesheet on it (configure_application).

A session built only from a configuration file installs it in a hooks: section. One entry serves both points, so a YAML anchor keeps it a single provider instance:

hooks:
  create_application: &napari
    provider: "redsun_mimir.hooks:NapariApplication"
  configure_application: *napari

Without it the viewer still works and its canvas still follows the theme in napari's settings, but nothing sets a stylesheet on the application, so the layer list, the layer controls and the rest of the Qt chrome keep their default look.

The shipped containers declare the hook themselves, so mimir sim and mimir uc2 need no hooks: section.

Services

Every piece of hardware runs in its own process. A service owns the driver, a redsun session starts and stops it, and the device in the session talks to it over PVAccess. The bundle ships three:

service what it owns arguments
mmcore-camera one Micro-Manager camera --adapter, --device, --properties
mmcore-stage one Micro-Manager stage --adapter, --device, --axes
youseetoo-controller the openUC2 board's serial port --port, --baudrate

A session declares them beside its devices, and each device names the service it belongs to:

services:
  transport: pv-access
  camera1_ioc:
    plugin_name: redsun-mimir
    plugin_id: mmcore-camera
    prefix: "MIMIR-CAM1:"
    args: ["--adapter", "DemoCamera", "--device", "DCam", "--properties", "Binning"]

--properties names the camera's own properties to publish beside exposure and roi, comma-separated; without it none are.

class MimirSimulator(MimirApp, config=_CONFIG):
    mmcamera = declare_device(MMCamera, service="camera1_ioc")

A service reads its prefix from the environment the session launches it with, and the device connects at that prefix, so the session file names it once.

The directory a capture goes to is a session setting:

storage:
  base_dir: "D:/mimir-data"   # optional; the user data directory otherwise

Wiring a session from YAML

The shipped containers declare their connections in wire(). A session built only from a configuration file has no wire() to override, so it must declare them in a wiring: section: without one the components build and connect to nothing.

Do not add this section to a configuration that already backs a container class with a wire() method. The two are applied one after the other, so every rule would connect a second time and each slot would run twice per emission.

wiring:
  - from: det_ctrl.sig_new_data
    to: img_widget.update_layers
  - from: median_ctrl.median
    to: img_widget.update_layers
  - from: median_ctrl.filtered
    to: img_widget.update_layers
  - from: det_widget.sig_property_changed
    to: det_ctrl.set
  - from: det_ctrl.sig_new_configuration
    to: det_widget.on_new_configuration
  - from: det_ctrl.sig_new_configuration
    to: img_widget.on_new_configuration
  - from: img_widget.sig_roi_drawn
    to: det_widget.on_roi_drawn
  - from: det_widget.sig_roi_selection
    to: img_widget.set_roi_selection
  - from: det_widget.sig_roi_edited
    to: img_widget.set_roi_box
  - from: motor_widget.sig_motor_move
    to: motor_ctrl.move
  - from: light_widget.sig_toggle_light_request
    to: light_ctrl.trigger
  - from: light_widget.sig_intensity_request
    to: light_ctrl.set
  - from: acq_widget.sig_launch_plan_request
    to: acq_ctrl.launch_plan
  - from: acq_widget.sig_stop_plan_request
    to: acq_ctrl.stop_plan
  - from: acq_widget.sig_pause_resume_request
    to: acq_ctrl.pause_or_resume_plan
  - from: acq_widget.sig_action_request
    to: acq_ctrl.toggle_action_event
  - from: acq_ctrl.sig_plan_done
    to: acq_widget.on_plan_done
  - from: acq_ctrl.sig_action_done
    to: acq_widget.on_action_done
  - from: acq_widget.sig_base_dir_request
    to: acq_ctrl.set_base_dir
  - from: acq_ctrl.sig_base_dir_changed
    to: acq_widget.on_base_dir_changed
  - from: acq_ctrl.sig_pre_launch_notify
    to: median_ctrl.clear_medians
  - from: acq_ctrl.sig_pre_launch_notify
    to: path_provider.set_plan
  - from: acq_ctrl.sig_plan_done
    to: path_provider.reset_plan
  - from: acq_ctrl.sig_base_dir_changed
    to: path_provider.set_base_dir

Component names are the keys used under devices:, presenters: and views:; port names are the signal attributes and the names the slots declare. The three rules reaching path_provider go to the session's own path provider, which is what names the directory a capture is written to.

There is no rule feeding motor_widget.update_setpoint: the motor view subscribes to the axis readbacks themselves, so its labels track the stage even when a plan is what moved it.

Features

  • Live data capture.
  • Region of interest chosen on the image: Select ROI in a detector's settings opens an editor and shows a box over its layer. Drag the box or type the numbers, each follows the other; Full fills in the whole sensor, OK applies. A change asked for during a plan lands between two of its messages.
  • Median computation based on square-scan movement for background noise reduction following the procedure described in this paper. The scan's stack of frames is written beside the next capture as <detector>_scan; the median stays in memory.
  • Every capture and every scan is a run of its own, nested in the live plan's run, with the run it serves and the scan it follows named on its start document.
  • The session's log records in a view of their own, from redsun.
  • Image visualization leveraging napari.
  • Data storage in Zarr v3 format via acquire-zarr, written by the camera's own service.
  • Manual control of light source and motor drivers.
  • Fully extensible via additional components following the redsun framework.

Contributing

Contributions are very welcome. Tests can be run with pytest, please ensure the coverage at least stays the same before you submit a pull request.

License

Distributed under the terms of the Apache Software License 2.0 license, redsun-mimir is free and open source software

Issues

If you encounter any problems, please file an issue along with a detailed description.

Release files for redsun-mimir 0.5.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for redsun-mimir 0.5.0
File Size Uploaded
redsun_mimir-0.5.0.tar.gz 72.9 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for redsun-mimir 0.5.0
File Interpreter ABI Platform
redsun_mimir-0.5.0-py3-none-any.whl Python 3 none any Details

Total release size: 168.7 kB

Release files / redsun_mimir-0.5.0.tar.gz

Download URL redsun_mimir-0.5.0.tar.gz
Size 72.9 kB
Tags Source
SHA-256 checksum
How to use checksums
4d5b83d2aff9590470b300077a7d2dbcd451a20705f9dc5e8027526916adb7fe
BLAKE2b-256 checksum
How to use checksums
1f0c713006108521d41134eab56b01fbc083eeed9bece0c012ac372bd46a2e5d
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 24, 2026.

Transparency log

Release files / redsun_mimir-0.5.0-py3-none-any.whl

Download URL redsun_mimir-0.5.0-py3-none-any.whl
Size 95.8 kB
Tags Python 3
SHA-256 checksum
How to use checksums
3c087324073cee110199a9c5fa7257a666de3ce89b56c268fad8c9785500e961
BLAKE2b-256 checksum
How to use checksums
62f5ae164e38d48746d1eea53c2a942ba49d844e3ad0fcb448d935a5d7cae3ec
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 24, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.5.0 This release

2 release files

0.4.1

2 release files

0.4.0

2 release files

0.3.1

2 release files

0.3.0

2 release files

0.2.0

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page