Feat/pymmcore integration#264
Open
beniroquai wants to merge 57 commits into
Open
Conversation
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.
Contributor
There was a problem hiding this comment.
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) plusMMCore*Managerdevice 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 |
Introduce a new server API (testDeviceAction) to send device-specific validation commands over serial (motor, ledarray, laser) after flashing. The controller builds JSON commands, writes to the specified serial port, reads a short response with timeout, and returns success/warning/error with the command and response snippet. Add a frontend axios wrapper (apiUC2ConfigControllerTestDeviceAction.js) and integrate a hardware validation panel into UsbFlashWizard.jsx: new UI controls and state for baud, motor/LED/laser params, a runDeviceTest flow that calls the API, and result display with success/warning/error handling and dispatch of user messages. This enables quick verification of slave firmware functionality (movement, LEDs, laser) post-flash.
UsbFlashWizard: include nodeId and canMotorAxis in the CAN activation payload so the sent /can_act message contains address, nodeId and canMotorAxis. Hologram notebook: large overhaul of imswitch/_data/user_defaults/imnotebook/hologram_education_notebook.ipynb — reorganized content and headings, clarified theory, added imswitchclient connection examples, REST helper wrappers for InLineHoloController, local Fresnel reconstruction code, interactive controls and MJPEG stream integration, plus many minor cleanup and documentation improvements. Added a German localized notebook imswitch/_data/user_defaults/imnotebook/hologram_education_notebook_de.ipynb. Also applied a minor update to imswitch/imcontrol/controller/controllers/UC2ConfigController.py.
Add comprehensive streaming review notes and migration/session planning docs, rename featurelist file, and implement multiple streaming-related improvements. New docs: ISSUES_SESSION_PLAN.md, MIGRATION.md, ReviewCameraStreamingIssues.md, STREAMING_4B_NOTES.md, STREAMING_REVIEW.md, and NEWSWITCH_FEATURE_MINDMAP.svg; renamed docs/ImSwitch_Featurelist.md -> docs/NEWSWITCH_FEATURE_INVENTORY.md. Code changes touch frontend WebSocket/LiveView components and backend streaming/recording paths to reduce allocations and improve throughput: preallocated u8/u16 buffers and PyTurboJPEG fallback in LiveViewController; WebRTC producer-side resize; avoid per-client metadata copies in noqt; recording dispatch thread and bounded queue to offload synchronous writes; keep TiffWriter open and add compression/compression_level support in OMETiffWriter; safe HIK SDK flip and robust binning flow; small config hook in UC2ConfigController for enabling qid-done handling. Also update pyproject.toml. These changes aim to improve live-preview latency and recording reliability on large sensors (9MP+) and document migration to the new newswitch stack.
Introduce a full MMCore (Micro-Manager) integration: frontend UI, backend controller, and API helpers to browse/set device parameters and perform long-exposure snap-to-disk jobs. Frontend: add MMCoreController React component, add API wrappers (getDetectors, getParameters, setParameter, snapToDisk, getSnapStatus), and wire the plugin into App.jsx and appRegistry. UI supports grouped parameter editing, exposure-in-seconds editing, snap-to-disk submission and polled job status display. Backend: implement imswitch.imcontrol.controller.controllers.MMCoreController exposing REST methods for detector discovery, parameter read/write, background snap jobs (writes TIFFs, reports progress) and job listing/status. Snap jobs run in background threads and emit updates; TimeOut is temporarily raised for long exposures. Model: update MMCoreDetectorManager.setParameter to handle exposure name variants case-insensitively, set core exposure properly, and echo back actual device-accepted values for UI consistency. Also update example setup JSONs to enable the MMCore widget.
Introduce frontend and backend changes to support manual ESP32 serial port/baudrate overrides and cancelling USB flashing runs. Adds two API clients (setSerialConfig, cancelUSBFlash), a new ESP32 Serial override panel in ConnectionSettings (list ports, apply session-only or persist), and USB flash UI improvements in UsbFlashWizard: auto-detect master/slave firmware to set disconnect/reconnect defaults, and an action to cancel an ongoing flash with optimistic UI updates. On the backend UC2ConfigManager: add ping(), accept port in initSerial(), implement setSerialConfig() which reconnects and optionally persists the port/baudrate to the setup JSON (with fallbacks for older UC2-REST reconnect signatures) and error handling/logging.
…pymmcore-integration
Co-authored-by: Copilot <copilot@github.com>
…witch into fix/streaminglatency
…witch into fix/streaminglatency
Frontend: use createImageBitmap (when available) in LiveViewComponent for off-thread JPEG decode, add cancellation for in-flight frames, and keep a legacy img fallback; normalize data URLs and improve error handling. WebSocketHandler: handle binary msgpack JPEG frames by re-encoding or passing through base64 as needed, and treat "cancelled" as a terminal usb-flash state (surface a cancelled result to the UI). Backend (noqt.py): avoid per-client metadata copies when packing MessagePack frames, send raw JPEG bytes as binary (msgpack bin) to reduce CPU and wire cost, and keep metadata updates per-client minimal. LiveViewController / StreamWorker & workers: add StreamParams.broadcast_frames flag to control per-frame fan-out; introduce _JpegEncoder that prefers PyTurboJPEG and falls back to OpenCV; preallocate buffers and optimize uint16→uint8 conversion without allocs; reorder crop/subsample/dtype conversion to perform expensive ops on smaller frames; emit raw JPEG bytes (not base64) to save CPU and bandwidth; move heavy preprocessing for WebRTC frames onto the worker thread (resize, dtype cast, channel layout, even-dim alignment) to reduce aiortc loop work and improve latency. UC2ConfigController: add reconnect port/baud handling and setSerialConfig API, add strict uc2_board_is_connected ping mode, implement cancellable esptool subprocess management (cancelUSBFlash), cooperative cancel flag and process termination, and reentrant flash handling that cancels a previous run if a new request starts. Emits appropriate cancelled/failed statuses so UI unblocks. Overall: reduces per-frame CPU and allocations, moves expensive work off hot event loops/main thread, prefers faster JPEG backends, and adds robust cancellable USB flashing for better responsiveness and resource usage.
Multiple frontend and backend changes to add synthetic LED-matrix channels, tiling behaviours, and grouped scan areas: Frontend: - CoordinateCalculator: group points by groupId and merge them into single scan areas (buildMergedScanArea) so freehand / multi-FOV selections behave as one area and preserve scan ordering. - WellSelector & Tiling tabs: keep XY scan speed controls in sync; add UI toggles for "Return to origin" and "Override per-group Z with current Z" (override is disabled while a focus map is active). - ChannelsDimension & ExperimentDesigner: support syntheticChannels (ring/DPC) advertised separately from conventional illuSources; merge synthetic defs into the UI list but split them back into conventional illumination + syntheticChannels payload when starting experiments; zero out disabled channels and build syntheticChannels payload including RGB/radius/exposure/gain. - FocusMapDimension: improved "Clear All" to fully disable focus mapping, clear manual points and prevent stale Z re-application. - Middleware & state: ParameterRangeSlice gains syntheticChannels state + actions; middleware populates syntheticChannels from backend. - ExperimentSlice: add tiling toggles (returnToOrigin, overrideZWithCurrentZ) and related setters. Backend: - models: add SyntheticChannel and SyntheticKind; expose syntheticChannels in ExperimentWorkflowParams and ParameterValue. - ExperimentController: accept syntheticChannels list (separate from conventional illumination), merge enabled synthetic channels into internal parallel arrays (intensity/gains/exposures) in one place instead of RGB→intensity promotion hacks; add per-experiment flags for focus-map activation and tiling toggles (_focus_map_active, _return_to_origin, _override_z_with_current_z) and honor their precedence (focus map wins over manual override); use experiment-configured XY/Z speeds for stage moves; optionally return to initial XYZ at end of scan. IO fixes: - OME writer: do not eagerly create empty tile directories; provide ensure_tiff_dir and ensure base_dir exists before writers/stitcher create files to avoid littering empty folders. Overall these changes formalise synthetic LED channels as a separate model, add useful tiling options, improve focus-map and grouping behaviour, and tidy filesystem handling for OME outputs.
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Introduce true freehand/region-style scan support and move the "override per-group Z with current Z" behavior to the frontend. CoordinateCalculator now consumes neighborPointList for region points, maps neighbors into rawPositions and derives iX/iY when missing so snake/raster ordering works. WellSelectorComponent stores freehand regions as a single point with neighborPointList (one logical scan area) and triggers an objective status refresh on mount to pick up current pixel/FOV. ExperimentSlice persists neighborPointList. ChannelsDimension memoizes merged illumination arrays (illuSources, kinds and min/max) to prevent a re-render loop. ExperimentDesigner applies the Z-override by rewriting position Zs before sending; backend controller/models were simplified to remove server-side override handling and related fields, and minor cleanup/fixes were applied (AutofocusController fetch URL cleanup and user-facing message wording).
…witch into fix/streaminglatency
Backend: add getLastSnapPreview endpoint that returns a contrast-stretched, downsampled PNG for a finished snap; cache the most recent snaps in memory (bounded) for fast preview rendering; implement percentile stretch and max-dimension downsampling to keep preview generation cheap; introduce Pydantic request models and switch several API methods (setMMCoreParameter, setMMCoreParameters, snapMMCoreToDisk) to use them and return HTTPExceptions on bad input. Frontend: add apiMMCoreControllerGetLastSnapPreview URL helper, show a passive live preview card (reads live state only) and render the captured frame as an <img> when a job finishes (uses finishedAt as cache-bust). Also import LiveViewControlWrapper and use connection settings from redux. Misc: update FRAME_6_ANDOR.json defaults (various device/feature additions and reordering) and add a .bak of the file.
…pymmcore-integration
Introduce a first-run onboarding tour using intro.js: add OnboardingTour component, CSS, onboardingTour constants, and a Redux OnboardingSlice (with tests). Wire tour anchors by adding data-tour attributes across UI components and expose a "Start Intro Tour" entry in Settings. Persist onboarding state in the store and add intro.js as a frontend dependency. Also improve Windows streaming reliability by setting WindowsSelectorEventLoopPolicy when running on win32 and forcing the websockets backend in the server Uvicorn config to reduce websocket latency and increase FPS on Windows.
Introduce an HTTP MJPEG viewer and UI controls, plus server-side improvements to live parameter handling and Windows websocket behavior. - Add frontend MJPEGViewer component and wire it into LiveViewControlWrapper to support plain HTTP multipart MJPEG streams (bypassing socket.io). Update StreamControlOverlay and StreamPresets to expose MJPEG settings and selection alongside existing JPEG/WebRTC/Binary options. - Change LiveViewController to apply stream/detector parameter changes in-place on running workers (mutate worker._params and saved params) instead of stopping/restarting streams to avoid thrash and dropped WebRTC sessions; responses now report updated_detectors/updated_live. - On server startup (ImSwitchServer), set WindowsSelectorEventLoopPolicy on Windows and force uvicorn ws="websockets" to avoid websocket upgrade/latency issues on Windows clients. - Loosen python-socketio dependency constraint in pyproject.toml to "python-socketio[asyncio]>=5.11,<6". These changes improve Windows streaming performance, provide an alternative transport for flaky socket.io websocket upgrades, and reduce restart churn when adjusting stream parameters.
…pymmcore-integration
Centralize stream parameter construction and simplify submit flow in StreamControlOverlay: build protocol-specific params from a single draft, push defaults to the backend, atomically swap workers when format changes (stop/start), then update Redux (format, settings, crop/min/max). Mirror backend capabilities, save per-detector settings and perform fire-and-forget backend persist. Improve error messaging formatting. Increase MAX_FRAME_LAG in noqt.py from 1 to 3 and document rationale to allow more pipelining (reducing Windows latency issues at the cost of a few extra in-flight frames). Add a diagnostic print in ImSwitchServer to log the actual server event loop type at startup to detect uvicorn overrides of the chosen Windows event loop policy.
Frontend: make parameter inputs use a local draft state and only commit on blur/Enter (or immediate for lists), add helper text, and prevent server refreshes from clobbering mid-edit. Add an "Apply" button for exposure separate from Snap, implement onApplyExposure, and provide a download link for the full-resolution TIFF plus file path display; adjust layout and button sizing. imcommon/framework/noqt.py: relax frame lag allowance (MAX_FRAME_LAG increased to 3). Controller: before snapping, clear the circular buffer and use core.snap() (which returns the image) to avoid double getImage() calls and adapter errors. ArkitektManager: defer optional imports into the constructor (avoid importing arkitekt_next/koil/mikro_next at module import time) so the module can be used when those packages are absent.
…pymmcore-integration
Log full exception stacktraces when controller creation fails, and refactor MMCoreDetectorManager.getLatestFrame to robustly handle live sequence vs idle modes. When a sequence is running, read from the circular buffer (getLastImage) and avoid snap(); return a zero placeholder (and -1 frame number) if no frame is available to prevent blocking. When no sequence is running, prefer the buffered last image, otherwise call snap(), using np.asarray to normalize returned images and avoid extra getImage() calls (fixes errors with some adapters like Andor). Add debug/error logging and maintain the frame number handling.
Install required system libraries and mirror test.yml by installing ImSwitch with full deps so runtime imports (Options/ViewSetupInfo) succeed. Force a pure-Python psygnal (uninstall/reinstall specific version and run psygnal.utils.decompile()), install pymmcore-plus[cli], and remove the editable pip install step. Adjust pytest invocation to disable the arkitekt_next plugin (-p no:arkitekt_next) and shorten tracebacks (--tb=short). These changes ensure CI has the native libs and dependency layout needed for the MMCore manager tests.
Expand pymmcore integration docs with architecture diagrams (simplified and detailed Mermaid flowcharts) explaining the MMCoreManager singleton, managerName routing, and how pymmcore-plus/pymmcore/adapters interact. Add a comprehensive Raspberry Pi (arm64) section describing the prebuilt micro-manager-arm64.tar.gz artifact, device-interface-version compatibility rules, where to obtain the tarball, and how ImSwitch discovers adapters. Provide two reproducible deployment recipes: Recipe A (bake adapters into Docker image with a build-micromanager.sh script and Dockerfile snippet, build pymmcore from source) and Recipe B (bind-mount adapters at runtime), plus a short sanity-check and usage examples for headless Docker runs.
…2/ImSwitch into feat/pymmcore-integration
…2/ImSwitch into feat/pymmcore-integration
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
This pull request introduces comprehensive support for integrating Micro-Manager device adapters into ImSwitch via the
pymmcore-plusPython 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:
docs/pymmcore-integration.md, that explains how to use ImSwitch with Micro-Manager adapters viapymmcore-plus, including installation steps, configuration modes, adapter discovery, and platform-specific notes.Example configuration files:
example_mmcore_demo.jsonshowing a minimal DemoCamera setup, andexample_mmcore_andor_cfg.jsonfor inline device declaration, both demonstrating how to configure detectors, lasers, and positioners using the new MMCore manager classes. [1] [2]example_mmcore_andor.jsonshowing a setup using a Micro-Manager.cfgfile for real hardware (Andor camera and ASI stage), illustrating configuration for both Windows and Linux paths.CI and build improvements:
.github/workflows/build-mm-arm64.yml) to build Micro-Manager adapters for arm64, testpymmcore-plusintegration, and publish prebuilt binaries as workflow artifacts or GitHub Releases. This facilitates using Micro-Manager on platforms like Raspberry Pi.Known LImitations:
exposure, MM providesExposure