Skip to content

Commit e5e4122

Browse files
jeskesenJustin Eskesenieivanovclaude
authored
repository restructure & mantis v2 PoC (#218)
* renamed mantis to shrimpy * renamed mantis v1 acquisition engine to mantis/archive * updated pyproject.toml to reflect new directory structure * refactor to have consistent initialization of engine and core in CLI and GUI * ported autofocus implementation from mantis_v1 * Fixed some typos * Added stage and ROI wigets * Added workaround for Snap() not working properly on PrimeBSI camera. * Added a log widget. Configs are command line args * added mantis2_mda.yaml example * added launch_mantis_gui script (previously forgotten * Fixed crash which stemmed from trying to modify the MDA Sequence, which is immutable. Now, A copy is made. * added a pause button to acquisition. split acquisition into its own thread, so the pause button could actually be clicked (and because its the right thing to do). * Added CLAUDE.md documentation file Created comprehensive documentation for Claude Code to understand the shrimPy/mantis codebase architecture. Includes development commands, V1 acquisition engine (pycromanager-based), and V2 acquisition engine (pymmcore-plus-based) currently in development on branch 212-mantis-v2-poc. Documents API references and data organization. Co-Authored-By: Claude Sonnet 4.5 <[email protected]> * cherry-pick of code from other 212-branch Applied project formatting standards using black and isort to ensure consistent code style across the codebase. Removed unused imports. Co-Authored-By: Claude Sonnet 4.5 <[email protected]> * Mantis-v2-logging (#214) * add mantis logger * update project requirements * relax numpy requirement * reformat mantis acq config file * v1 of acq engine logger * add extra logging * upgrade to python>=3.11 * refactor mda examples mantis2: acq engine demo - MMConfig_demo mantis - mantis microscope justin - minimal setup with camera and TS on Justin's desk * fix debug message bug * fixed merge in pyproject which wasn't saved during the last commit * python version in pyproject.toml was updated to 3.11 but the CI was still expecting 3.10 * somehow, a merge conflict got committed before resolution * add archive directories to the list of things ignored by flake8 * fix logger import path * moved mantis directory under shrimpy * updated pyproject to have mantis be a submodule of shrimpy * updated dependencies to what mantis_v2 actually needs now. Old dependencies were commented out so they can be recovered. * updated import paths * moved pycromanager archive into archive/pycromanager * added pymmcore-plus based engine to archive. simple copy from another branch (#170) * bump to pymmcore_plus==0.17.0 * ran isort * somehow, the rename to from mantis_v2 to mantis_engine didn't get committed earlier * update acq engine from mantis microscope * reshuffle AcquisitionSettings * add archived acq engine requirements * fix acq_engine.py merge * move old scripts * move tests * archive cli * add mantis __init__.py * create plateholder for isim acquisition engine * Update README.md * remove lingering mantis references * format * lint * format * add shrimpy version * Update CLAUDE.md * attempt to fix logging bug * fix mantis logger bug? * debug - disable pymmcore-plus file logging * skip logger tests for now * style --------- Co-authored-by: Justin Eskesen <[email protected]> Co-authored-by: Ivan Ivanov <[email protected]> Co-authored-by: Claude Sonnet 4.5 <[email protected]>
1 parent 109a98f commit e5e4122

File tree

79 files changed

+6824
-77
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

79 files changed

+6824
-77
lines changed

.flake8

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,4 +37,5 @@ exclude =
3737
ignore,
3838
legacy,
3939
examples,
40-
scripts
40+
scripts,
41+
archive

.github/workflows/pull-request-ci.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ jobs:
2222
with:
2323
python-version: ${{ matrix.python-version }}
2424

25-
- name: Install the mantis package
25+
- name: Install the shrimpy package
2626
run: pip install -e ".[dev]"
2727

2828
- name: Check code style with Black
@@ -49,7 +49,7 @@ jobs:
4949
with:
5050
python-version: ${{ matrix.python-version }}
5151

52-
- name: Install the mantis package
52+
- name: Install the shrimpy package
5353
run: pip install -e ".[dev]"
5454

5555
- name: Run tests

CLAUDE.md

Lines changed: 248 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,248 @@
1+
# CLAUDE.md
2+
3+
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
4+
5+
## Overview
6+
7+
shrimPy is a Python framework for high-throughput smart microscopy that synchronizes data collection using hardware triggering and performs intelligent acquisition tasks like autofocus and autoexposure. The framework is designed to support multiple microscope platforms (mantis, iSIM, Dragonfly) through a modular, extensible architecture built on pymmcore-plus.
8+
9+
Current status: Alpha version, actively restructuring from mantis-only to multi-microscope support (branch: `215-restructure-repository-for-multi-microscope-support`).
10+
11+
## Common Development Commands
12+
13+
### Setup
14+
```bash
15+
# Install in development mode with dev dependencies
16+
pip install -e ".[dev]"
17+
18+
# Or using make
19+
make setup-develop
20+
21+
# Install pre-commit hooks (required for contributors)
22+
pre-commit install
23+
```
24+
25+
### Code Quality
26+
```bash
27+
# Format code (black + isort)
28+
make format
29+
30+
# Check formatting without modifying files
31+
make check-format
32+
33+
# Lint with flake8
34+
make lint
35+
36+
# Run all pre-commit hooks
37+
make pre-commit
38+
```
39+
40+
### Testing
41+
```bash
42+
# Run all tests
43+
make test
44+
45+
# Or directly with pytest
46+
python -m pytest . --disable-pytest-warnings
47+
48+
# Run specific test file
49+
pytest shrimpy/tests/test_mantis_logger.py
50+
```
51+
52+
### Running the Mantis GUI
53+
```bash
54+
# Launch the GUI-based acquisition interface
55+
python -m shrimpy.mantis.launch_mantis_gui
56+
```
57+
58+
### Demo Mode Acquisition (Legacy)
59+
The legacy CLI is archived but provides a pattern for programmatic acquisition:
60+
```bash
61+
shrimpy acquire mantis \
62+
--config-filepath examples/acquisition_settings/example_mda_sequence.yaml \
63+
--output-dirpath ./YYYY_MM_DD_experiment/acquisition_name \
64+
--mm-config-filepath path/to/MMConfig_Demo.cfg
65+
```
66+
67+
## Architecture
68+
69+
### Microscope Module Structure
70+
```
71+
shrimpy/
72+
├── mantis/ # Label-free + Light-sheet microscope (fully implemented)
73+
│ ├── mantis_engine.py # MDAEngine subclass (~455 lines)
74+
│ ├── mantis_acquisition_widget.py # Qt GUI (~815 lines)
75+
│ ├── mantis_logger.py # Logging configuration
76+
│ ├── launch_mantis_gui.py # GUI entry point
77+
│ └── archive/ # Historical implementations (pycromanager, old pymmcore-plus)
78+
79+
├── isim/ # iSIM microscope (placeholder for future implementation)
80+
├── viewer/ # Data visualization (placeholder)
81+
├── cli/ # Command-line interface (in transition, currently empty)
82+
└── tests/ # Unit tests
83+
```
84+
85+
### Key Design Patterns
86+
87+
#### 1. Engine Abstraction Pattern
88+
Each microscope implements a custom `MDAEngine` subclass:
89+
```python
90+
class MantisEngine(MDAEngine):
91+
def setup_sequence(sequence: MDASequence) -> SummaryMetaV1:
92+
# Configure hardware before acquisition starts
93+
# - Set ROI, focus device, initialization settings
94+
# - Configure hardware sequencing
95+
# - Setup autofocus parameters
96+
97+
def setup_event(event: MDAEvent):
98+
# Prepare for each acquisition event
99+
# - Configure TriggerScope if using hardware sequencing
100+
101+
def _set_event_xy_position(event: MDAEvent):
102+
# Custom XY positioning with intelligent stage movement
103+
# - Variable speed (2.0 mm/s short, 5.75 mm/s long distances)
104+
# - Post-movement autofocus engagement with retry logic
105+
# - Stage settlement waiting
106+
```
107+
108+
To add a new microscope:
109+
1. Create `shrimpy/<microscope_name>/` directory
110+
2. Subclass `MDAEngine` in `<microscope_name>_engine.py`
111+
3. Override `setup_sequence()`, `setup_event()`, and positioning methods as needed
112+
4. Define microscope-specific metadata schema
113+
5. Create Qt widget for GUI (optional)
114+
115+
#### 2. Metadata Propagation Pattern
116+
Configuration is passed through MDASequence metadata:
117+
```python
118+
sequence = MDASequence.from_file('config.yaml')
119+
sequence.metadata = {
120+
'mantis': {
121+
'roi': [x, y, width, height],
122+
'z_stage': 'AP Galvo',
123+
'initialization_settings': [[device, property, value], ...],
124+
'setup_hardware_sequencing_settings': [...],
125+
'autofocus': {
126+
'enabled': True,
127+
'stage': 'ZDrive',
128+
'method': 'PFS', # Nikon Perfect Focus System
129+
'wait_after_correction': 0.5,
130+
'wait_before_acquire': 0.1,
131+
},
132+
}
133+
}
134+
```
135+
136+
#### 3. Logging Pattern
137+
Each microscope module uses a separate logger instance:
138+
```python
139+
from shrimpy.mantis.mantis_logger import configure_mantis_logger, get_mantis_logger
140+
141+
# During acquisition setup
142+
logger = configure_mantis_logger(save_dir, 'acquisition_name')
143+
# Creates dual handlers:
144+
# - Console: INFO level
145+
# - File: DEBUG level (saved to logs/ subdirectory)
146+
147+
# Also captures pymmcore-plus logger to same file
148+
```
149+
150+
Use `logger.debug()` for detailed diagnostics (file only) and `logger.info()` for user-facing messages (console + file).
151+
152+
### Configuration Files
153+
154+
Acquisitions are configured using YAML files that define MDASequence parameters plus microscope-specific metadata. Examples in `examples/acquisition_settings/`.
155+
156+
**Key Configuration Sections:**
157+
- `time_plan`: Timepoint intervals and loops
158+
- `channels`: Channel configurations
159+
- `z_plan`: Z-stack range and step size
160+
- `stage_positions`: XY positions (optional)
161+
- `metadata.mantis`: Mantis-specific settings (ROI, autofocus, hardware sequencing)
162+
163+
See `examples/acquisition_settings/example_mda_sequence.yaml` for a minimal example.
164+
165+
### Widget Composition (Qt GUI)
166+
```
167+
MantisAcquisitionWidget (main container)
168+
├── ImagePreview (from pymmcore-widgets)
169+
├── CustomCameraRoiWidget (workaround for camera snap issues)
170+
├── StageWidget (XY and Z stage control)
171+
├── MDAWidget (standard multi-dimensional acquisition configuration)
172+
└── MantisSettingsWidget
173+
├── TriggerScopeSettingsWidget (hardware triggering)
174+
└── MicroscopeSettingsWidget (focus device, autofocus, hardware sequencing)
175+
```
176+
177+
Widgets communicate via Qt signals/slots. Settings are propagated to MDASequence metadata before acquisition starts.
178+
179+
## Key Dependencies
180+
181+
- **pymmcore-plus** (0.17.0): Python bindings for Micro-Manager with MDA engine
182+
- **pymmcore-widgets**: Qt widgets for microscope control
183+
- **useq-schema**: Multi-dimensional acquisition sequence specification
184+
- **PyYAML**: Configuration parsing
185+
- **numpy**: Numerical operations
186+
- **qtpy**: Qt abstraction layer (PyQt5/6, PySide2/6)
187+
188+
Optional (for analysis, not in core package):
189+
- **biahub**: Image analysis library (deskewing, reconstruction, registration)
190+
- **iohub**: OME-Zarr conversion and metadata management
191+
- **recOrder**: Phase and orientation reconstruction
192+
- **VisCy**: Virtual staining
193+
194+
## Code Style
195+
196+
- **Formatter**: black with line length 95, Python 3.11, skip string normalization (`-S`)
197+
- **Import sorting**: isort (black profile)
198+
- **Linter**: flake8 (disabled: C, R, W, import-error, unsubscriptable-object)
199+
- **Pre-commit hooks**: Automatically run style checks on commit
200+
201+
Run `make format` before committing. The pre-commit hooks will catch violations.
202+
203+
## Testing
204+
205+
- Framework: pytest
206+
- Test location: `shrimpy/tests/`
207+
- Ignore: `scripts/`, `**/archive/` (configured in pyproject.toml)
208+
- Run with: `make test` or `pytest . --disable-pytest-warnings`
209+
210+
Current tests focus on logging infrastructure. Add tests for new microscope engines in `shrimpy/tests/test_<microscope>_*.py`.
211+
212+
## Current Development Focus
213+
214+
**Active restructuring** (branch `215-restructure-repository-for-multi-microscope-support`):
215+
- Transitioning from mantis-only to multi-microscope framework
216+
- Archiving legacy CLI and V1/V2 acquisition engines
217+
- Establishing iSIM placeholder for future work
218+
- Maintaining GUI-first approach with programmatic API
219+
220+
**What's stable:**
221+
- Mantis acquisition engine (MantisEngine)
222+
- GUI-based acquisition workflow
223+
- Logging infrastructure
224+
- Configuration via YAML + metadata
225+
226+
**What's in flux:**
227+
- CLI interface (currently empty, being redesigned)
228+
- Cross-microscope abstractions
229+
- iSIM implementation
230+
231+
## Important Implementation Notes
232+
233+
### Mantis-Specific Behavior
234+
- **Autofocus**: Engages Nikon PFS after XY stage movements with retry logic (up to 3 attempts, 0.5s wait between)
235+
- **Stage speed**: Variable speed based on distance (2.0 mm/s for <2000 µm, 5.75 mm/s for longer moves)
236+
- **Hardware sequencing**: TriggerScope DAC/TTL control for synchronized imaging
237+
- **Dual-arm imaging**: Label-free and light-sheet acquired on separate Micro-Manager instances
238+
239+
### Extending to New Microscopes
240+
When adding iSIM or other microscopes:
241+
1. Study `shrimpy/mantis/mantis_engine.py` as the reference implementation
242+
2. Override only the methods that differ from default MDAEngine behavior
243+
3. Document microscope-specific metadata schema in docstrings
244+
4. Create separate logger instance following mantis_logger pattern
245+
5. Keep archived code in `archive/` subdirectory for reference
246+
247+
### Data Output
248+
Raw data follows OME-Zarr or NDTiff format. Reconstruction workflows handled by separate biahub library. See `docs/data_structure.md` for details.

CONTRIBUTING.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# Contributing guide
22

3-
Thanks for your interest in contributing to `mantis`!
3+
Thanks for your interest in contributing to `shrimPy`!
44

55
## Getting started
66

@@ -10,10 +10,10 @@ and how you can install and use the package.
1010
## Making changes
1111

1212
Any change made to the `main` branch or release maintenance branches
13-
need to be proposed in a [pull request](https://github.com/czbiohub/mantis/pulls) (PR).
13+
need to be proposed in a [pull request](https://github.com/czbiohub/shrimPy/pulls) (PR).
1414

1515
Follow [these instructions](https://docs.github.com/en/get-started/quickstart/fork-a-repo)
16-
to [fork](https://github.com/czbiohub/mantis/fork) the repository.
16+
to [fork](https://github.com/czbiohub/shrimPy/fork) the repository.
1717

1818
## Setting up a development environment
1919

Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
PACKAGE_NAME := mantis
1+
PACKAGE_NAME := shrimpy
22

33
.PHONY: setup-develop
44
setup-develop:

README.md

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -7,29 +7,29 @@ The acquisition engine synchronizes data collection using hardware triggering an
77

88
The acquired multidimensional raw datasets are processed with the [biahub](https://github.com/czbiohub-sf/biahub) library to generate registered multimodal data that can be used for analysis. Raw data are first converted to the [OME-Zarr](https://ngff.openmicroscopy.org/) format using [iohub](https://github.com/czbiohub-sf/iohub) to facilitate parallel processing and metadata management. Discrete data volumes then undergo deskewing of fluorescence channels, reconstruction of phase and orientation (using [recOrder](https://github.com/mehta-lab/recOrder)), registration and virtual staining (using [VisCy](https://github.com/mehta-lab/viscy)).
99

10-
This version of the code still uses the legacy name `mantis`, which overlaps with the name of the microscope which is used to acquire data. In a future release we will transition the codebase to the name `shrimPy`.
10+
This version of the code contains an acquisition engine for the `mantis` microscope, including several archived versions. We intend to develop additional acquisition engines for the `iSIM` and `Dragonfly` microscopes within this framework. These acquisition engines are expected to have shared features but also to accommodate differences between the microscope hardware and the acquisition needs on each microscope.
1111

1212
## Installation
1313

1414
We recommend using a virtual conda environment with Python 3.11:
1515

1616
```sh
17-
conda create -y --name mantis python=3.11
18-
conda activate mantis
17+
conda create -y --name shrimpy python=3.11
18+
conda activate shrimpy
1919

2020
git clone https://github.com/czbiohub-sf/shrimPy.git
21-
pip install ./mantis
21+
pip install ./shrimpy
2222
```
2323

2424
Optionally, you can also install the [biahub](https://github.com/czbiohub-sf/biahub) image analysis library in the same environment. `biahub` is currently used when characterizing the microscope point spread function, and will be used for real-time image processing in the future. You can install both libraries in a single step with:
2525

2626
```sh
27-
conda create -y --name mantis python=3.11
28-
conda activate mantis
27+
conda create -y --name shrimpy python=3.11
28+
conda activate shrimpy
2929

3030
git clone https://github.com/czbiohub-sf/shrimPy.git
3131
git clone https://github.com/czbiohub-sf/biahub.git
32-
pip install ./mantis ./biahub
32+
pip install ./shrimpy ./biahub
3333
```
3434

3535
## Setting up the mantis microscope
@@ -44,29 +44,29 @@ Mantis acquisitions and analyses use a command-line interface.
4444

4545
A list of `mantis` commands can be displayed with:
4646
```sh
47-
mantis --help
47+
shrimpy --help
4848
```
4949

50-
Data are acquired using `mantis run-acquisition`, and a list of arguments can be displayed with:
50+
Data are acquired using `shrimpy acquire <microscope_name>`, and a list of arguments can be displayed with:
5151

5252
```sh
53-
mantis run-acquisition --help
53+
shrimpy acquire mantis --help
5454
```
5555

56-
The mantis acquisition is configured using a YAML file. An example of a configuration file can be found [here](examples/acquisition_settings/example_acquisition_settings.yaml).
56+
The shrimPy acquisitions is configured using a YAML file. An example of a configuration file can be found [here](examples/acquisition_settings/example_acquisition_settings.yaml).
5757

58-
This is an example of a command which will start an acquisition on the mantis microscope:
58+
This is an example of a command which will start an acquisition using the mantis acquisition engine:
5959

6060
```pwsh
61-
mantis run-acquisition \
61+
shrimpy acquire mantis \
6262
--config-filepath path/to/config.yaml \
6363
--output-dirpath ./YYYY_MM_DD_experiment_name/acquisition_name
6464
```
6565

6666
The acquisition may also be run in "demo" mode with the Micro-manager `MMConfig_Demo.cfg` config. This does not require any microscope hardware. A demo run can be started with:
6767

6868
```pwsh
69-
mantis run-acquisition \
69+
shrimpy acquire mantis \
7070
--config-filepath path/to/config.yaml \
7171
--output-dirpath ./YYYY_MM_DD_experiment_name/acquisition_name \
7272
--mm-config-filepath path/to/MMConfig_Demo.cfg
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
axis_order:
2+
- t
3+
- c
4+
- z
5+
time_plan:
6+
interval: 1.0
7+
loops: 3
8+
channels:
9+
- config: BF
10+
- config: GFP
11+
# - config: mCherry
12+
# stage_positions:
13+
# - x: 1
14+
# y: 1
15+
# name: pos1
16+
# - x: 0
17+
# y: 0
18+
# name: pos2
19+
z_plan:
20+
range: 200
21+
step: 0.313

0 commit comments

Comments
 (0)