Skip to content

Feat/pymmcore integration#264

Open
beniroquai wants to merge 2 commits into
masterfrom
feat/pymmcore-integration
Open

Feat/pymmcore integration#264
beniroquai wants to merge 2 commits into
masterfrom
feat/pymmcore-integration

Conversation

@beniroquai
Copy link
Copy Markdown
Collaborator

This pull request introduces comprehensive support for integrating Micro-Manager device adapters into ImSwitch via the pymmcore-plus Python bindings. It adds detailed documentation, provides example configuration files for various hardware setups, and establishes a new GitHub Actions workflow to build and test Micro-Manager adapters (including on arm64). These changes make it significantly easier to use a wide range of hardware with ImSwitch, both in development and deployment environments.

Micro-Manager integration and documentation:

  • Added a new documentation file, docs/pymmcore-integration.md, that explains how to use ImSwitch with Micro-Manager adapters via pymmcore-plus, including installation steps, configuration modes, adapter discovery, and platform-specific notes.

Example configuration files:

  • Added example_mmcore_demo.json showing a minimal DemoCamera setup, and example_mmcore_andor_cfg.json for inline device declaration, both demonstrating how to configure detectors, lasers, and positioners using the new MMCore manager classes. [1] [2]
  • Added example_mmcore_andor.json showing a setup using a Micro-Manager .cfg file for real hardware (Andor camera and ASI stage), illustrating configuration for both Windows and Linux paths.

CI and build improvements:

  • Introduced a new GitHub Actions workflow (.github/workflows/build-mm-arm64.yml) to build Micro-Manager adapters for arm64, test pymmcore-plus integration, and publish prebuilt binaries as workflow artifacts or GitHub Releases. This facilitates using Micro-Manager on platforms like Raspberry Pi.

Known LImitations:

  • Exposure/Gain changes not working since we do not have a unified interface for camera-related parameters. Frontend writes exposure, MM provides Exposure
  • Builds are currently not working

beniroquai added 2 commits May 1, 2026 10:53
Introduce optional pymmcore-plus integration: add a process-wide MMCoreManager singleton and three MMCore* device managers (detector, positioner, laser) that wrap Micro-Manager adapters. Include unit tests that exercise the DemoCamera adapter, example setup JSON files for demo and Andor configurations, and user documentation for pymmcore-plus integration. Add a GitHub Actions workflow to run MMCore tests and to build/publish arm64 mmCoreAndDevices artifacts, plus a Raspberry Pi install script for building Micro-Manager on arm64. Minor controller comment and pyproject update included.
Improve Micro-Manager (pymmcore) integration and fix several device manager behaviors. Docs: require MM 2.0, add detailed install/discovery guidance and adapter-path resolution. Add new example_mmcore_andor_cfg.json and update example_mmcore_andor.json. Tests: use MMCoreManager.discover_adapter_paths() for adapter availability and clearer skip reason. MMCoreManager: implement discover_adapter_paths(), platform globs, Windows DLL dir handling, adapter-path resolution, MM2 verification, and better logging. LaserController: return [0,1] for binary lasers. DetectorManager: fix parameter name mapping (gain) and avoid raising on unknown parameters. MMCoreDetectorManager: track running/frame number, make getLatestFrame optionally return frame number and handle errors, and update running flag on start/stop. MMCorePositionerManager.move: extend signature to support absolute moves, optional blocking, and emit position update signal after moves.
Copilot AI review requested due to automatic review settings May 2, 2026 05:59
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adds a new integration layer that lets ImSwitch control Micro-Manager device adapters (camera/stage/laser) via pymmcore-plus, along with example setups, docs, tests, and a CI workflow for arm64 adapter builds.

Changes:

  • Introduces MMCoreManager (shared singleton) plus MMCore*Manager device managers for detectors, positioners, and lasers.
  • Adds documentation, example setup JSONs, and Raspberry Pi install guidance for Micro-Manager adapters.
  • Adds unit tests for the new managers and a GitHub Actions workflow to test on x86_64 and build adapters for arm64.

Reviewed changes

Copilot reviewed 18 out of 18 changed files in this pull request and generated 9 comments.

Show a summary per file
File Description
pyproject.toml Adds pymmcore-plus as an optional dependency extra (pymmcore).
imswitch/imcontrol/model/managers/MMCoreManager.py Implements lazy, shared CMMCorePlus singleton + adapter path discovery helpers.
imswitch/imcontrol/model/managers/__init__.py Exposes MMCoreManager from the managers package for imports/tests.
imswitch/imcontrol/model/managers/detectors/MMCoreDetectorManager.py New detector manager wrapping MMCore camera devices, including dynamic property discovery.
imswitch/imcontrol/model/managers/positioners/MMCorePositionerManager.py New positioner manager wrapping MMCore XY/Z stages with cfg/manual loading modes.
imswitch/imcontrol/model/managers/lasers/MMCoreLaserManager.py New laser manager supporting shutter mode and property mode.
imswitch/imcontrol/model/managers/detectors/DetectorManager.py Alters parameter-setting behavior (exposure/gain name mapping).
imswitch/imcontrol/controller/controllers/LaserController.py Changes binary laser range reporting to return [0, 1].
imswitch/imcontrol/controller/controllers/experiment_controller/experiment_normal_mode.py Adds a TODO comment.
imswitch/imcontrol/_test/unit/test_mmcore_managers.py Adds pytest coverage for MMCore managers using DemoCamera (skipped if unavailable).
imswitch/_data/user_defaults/imcontrol_setups/example_mmcore_demo.json Adds DemoCamera-based example setup (manual mode).
imswitch/_data/user_defaults/imcontrol_setups/example_mmcore_andor_cfg.json Adds an Andor inline-declaration example setup.
imswitch/_data/user_defaults/imcontrol_setups/example_mmcore_andor.json Adds cfg-based “real hardware” example setup.
docs/pymmcore-integration.md Adds end-user documentation for installing and using the integration.
.github/workflows/build-mm-arm64.yml Adds CI workflow to test integration on x86 and build arm64 adapters.
install_micromanager_raspi.sh Adds Raspberry Pi build/install script for Micro-Manager + pymmcore stack.
micromanager-userguide.md Adds a standalone usage guide for Micro-Manager + pymmcore-plus.
pymmcore-feature-integraion.md Adds a long implementation-plan style document (currently reads like an internal prompt).

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +210 to +221
def getLatestFrame(self, returnFrameNumber=False) -> np.ndarray:
try:
if self._core.getRemainingImageCount() > 0:
return self._core.getLastImage()
except Exception:
pass
try:
self._core.snap()
self._frameNunber += 1
if returnFrameNumber:
return self._core.getImage(), self._frameNunber
return self._core.getImage()
Comment on lines +133 to +136
new_pos = self.getPosition(axis)
self._position[axis] = new_pos
self._commChannel.sigUpdateMotorPosition.emit() # TODO: This is a hacky workaround to force Imswitch to update the motor positions in the gui..

Comment on lines +3 to +7
# install_micromanager_rpi.sh
#
# Build and install Micro-Manager (MMCore + device adapters) and pymmcore-plus
# on a Raspberry Pi running Pi OS Bookworm (64-bit / arm64).
#
Comment on lines +1 to +49
# CLAUDE.md — pymmcore-plus Integration into ImSwitch

You are implementing Micro-Manager hardware support in the openUC2/ImSwitch
microscopy platform via `pymmcore-plus`. This adds support for any camera,
stage, or laser that has a Micro-Manager device adapter (Andor, Hamamatsu,
Basler, ASI, Prior, Thorlabs, Coherent, etc.) alongside the existing
ESP32/UC2-REST managers.


## STEP 0 — Reconnaissance (do this FIRST, before writing any code)

Run these commands and summarize what you find. Paste the summary as a
comment in the first commit.

```bash
# Check for any existing pymmcore/MMCore work
rg -n -S "pymmcore|MMCore|micromanager|micro.manager" --type py

# Map the manager directory structure
find imswitch/imcontrol/model/managers -name "*.py" | head -60

# Read the base classes — you MUST match these signatures exactly
cat imswitch/imcontrol/model/managers/detectors/DetectorManager.py
cat imswitch/imcontrol/model/managers/positioners/PositionerManager.py
cat imswitch/imcontrol/model/managers/lasers/LaserManager.py

# Read one concrete example of each to understand the pattern
cat imswitch/imcontrol/model/managers/detectors/HIKCamManager.py 2>/dev/null || \
ls imswitch/imcontrol/model/managers/detectors/
cat imswitch/imcontrol/model/managers/positioners/ESP32StageManager.py 2>/dev/null || \
ls imswitch/imcontrol/model/managers/positioners/
cat imswitch/imcontrol/model/managers/lasers/ESP32LEDLaserManager.py 2>/dev/null || \
ls imswitch/imcontrol/model/managers/lasers/

# Check how managers are registered / discovered
cat imswitch/imcontrol/model/managers/detectors/__init__.py
cat imswitch/imcontrol/model/managers/positioners/__init__.py
cat imswitch/imcontrol/model/managers/lasers/__init__.py

# Check the setup JSON schema / info classes
rg -n "class DetectorInfo" --type py
rg -n "class LaserInfo" --type py
rg -n "class PositionerInfo" --type py

# Check how lowLevelManagers work
rg -n "lowLevelManagers" imswitch/imcontrol/model/managers/ --type py | head -20

# Look at an existing setup JSON for the structure
find . -name "*.json" -path "*/imcontrol_setups/*" | head -10
Comment on lines +119 to +124
parameters["Exposure"] = DetectorNumberParameter(
group="Acquisition",
value=current_exposure,
editable=True,
valueUnits="ms",
)
Comment on lines +129 to +132
else:
self._logger.warning(f"Ignoring move on unsupported axis '{axis}'")
return self._position[axis]

Comment on lines 229 to 232
if lManager.isBinary:
return None
return [0, 1]
else:
return (lManager.valueRangeMin, lManager.valueRangeMax)
Comment on lines +7 to +11
"managerProperties": {
"cfgPath_": "/home/pi/micro-manager-configs/Andor_ASI.cfg",
"cfgPath": "C:\\Users\\benir\\Desktop\\andor.cfg",
"deviceLabel": "Andor sCMOS Camera"
},
Comment on lines 159 to 162
if name.find("posure")>0:name = "exposure" # TODO: Hacky fix for inconsistent naming
if name.find("ain")>0:name = "gain" # TODO: Hacky fix for inconsistent naming
self.__parameters[name].value = value
return self.parameters
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants