Skip to content

Use Aravis camera driver instead of PySpin for Cytation#985

Merged
rickwierenga merged 13 commits intoPyLabRobot:v1b1from
vcjdeboer:aravis-pr
Apr 11, 2026
Merged

Use Aravis camera driver instead of PySpin for Cytation#985
rickwierenga merged 13 commits intoPyLabRobot:v1b1from
vcjdeboer:aravis-pr

Conversation

@vcjdeboer
Copy link
Copy Markdown
Contributor

@vcjdeboer vcjdeboer commented Apr 3, 2026

Summary

  • Adds an Aravis-based camera driver (AravisCamera) as a drop-in alternative to PySpin for FLIR BlackFly cameras on the Cytation. Eliminates the Spinnaker SDK dependency and the Python 3.10 version cap that PySpin imposes.
  • Splits cytation.py into cytation1.py and cytation5.py — each device creates its own driver internally based on a camera parameter ("aravis" or "pyspin").
  • Adds CytationAravisDriver (connection + optics + camera) and CytationAravisMicroscopyBackend (capture orchestration) following the STARDriver pattern.

New files

File Role
aravis_camera.py Standalone BlackFly driver using Aravis/GenICam via PyGObject
aravis_simulated.py Simulated camera for testing without hardware
cytation_aravis_driver.py Driver layer: BioTekBackend serial + AravisCamera, owns connections and optics
cytation_aravis_microscopy.py MicroscopyBackend: capture orchestration, calls driver methods
cytation1.py Cytation 1 device class (split from cytation.py)
cytation5.py Cytation 5 device class (split from cytation.py)

Modified files

File Change
cytation.py Keeps CytationBackend (PySpin), re-exports device classes for backwards compat
__init__.py Updated exports

Test plan

  • Hardware-tested on Cytation 1 with BlackFly BFLY-U3-13S2M via Aravis on macOS
  • Camera connect/disconnect, exposure, gain, image capture verified
  • Single capture (brightfield 2.5x) and multi-image tiling (2x2) working
  • Filter/objective discovery matches firmware (DAPI, GFP, RFP + objectives)
  • CI: Aravis is an optional dependency (PyGObject + system library) — no import at module level, guarded by HAS_ARAVIS
  • PySpin path unchanged — existing users unaffected

Note: Some CI checks may fail due to pre-existing lint issues on v1b1 (e.g., EL406 unused import) that are not from this PR.

vcjdeboer and others added 6 commits April 5, 2026 09:27
Adds a pure-Aravis alternative to PySpin for controlling BlackFly cameras
in the BioTek Cytation. Eliminates the Spinnaker SDK dependency and the
Python 3.10 version cap that PySpin imposes.

New files:
- aravis_camera.py: standalone BlackFly driver using Aravis/GenICam via PyGObject
- aravis_simulated.py: simulated camera for testing without hardware
- cytation_aravis.py: CytationAravisBackend — drop-in replacement for
  CytationBackend using AravisCamera instead of PySpin. Same serial protocol
  for optics (filters, objectives, focus, LED), different camera driver.
  capture() signature matches MicroscopyBackend ABC with backend_params.
- ARAVIS_README.md: installation and usage guide
- test_aravis_connection.ipynb: hardware test notebook

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Move Cytation5 to cytation5.py — takes backend param (PySpin or Aravis)
- Move Cytation1 to cytation1.py — takes backend param, fixes bug where
  BioTekBackend (no capture()) was wired to Microscopy capability
- cytation.py keeps CytationBackend + re-exports devices for backwards compat
- __init__.py updated to import from new files

Both device classes now accept a backend parameter instead of creating
one internally, so users can choose CytationBackend (PySpin) or
CytationAravisBackend (Aravis).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…rdware-tested

Architecture refactor following STAR pattern:
- cytation_aravis_driver.py: CytationAravisDriver (BioTekBackend + AravisCamera)
  owns connections, optics control, camera control
- cytation_aravis_microscopy.py: CytationAravisMicroscopyBackend (MicroscopyBackend)
  orchestrates capture by calling driver methods
- cytation1.py/cytation5.py: device classes with camera="aravis"|"pyspin" switch
- Removed monolithic cytation_aravis.py

Bugs fixed during hardware testing:
- aravis_camera.py: trigger() no longer starts/stops acquisition per frame —
  matches PySpin pattern where acquisition brackets the capture loop
- cytation_aravis_driver.py: led_on intensity zfill(3) → zfill(2)
- cytation_aravis_driver.py: _load_filters/_load_objectives use Rick's actual
  firmware protocol (per-slot query) instead of made-up regex parsing
- cytation_aravis_driver.py: all serial commands (set_imaging_mode, set_objective,
  set_focus, select, set_position, led_on/off) now match cytation.py exactly
- cytation_aravis_driver.py: bytes→str decode for firmware responses

Hardware-tested on Cytation 1 with BlackFly BFLY-U3-13S2M:
- Single capture: brightfield 2.5x, real images with correct exposure
- Multi-image tiling: 2x2 grid capture working
- Filter/objective discovery: DAPI, GFP, RFP + 4x PL FL, 2.5x FL Zeiss

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…tive

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
… access

Replace all PySpin camera code in CytationBackend with AravisCamera calls.
Simplify Cytation1/Cytation5 to always use CytationAravisDriver. Fix
aravis_camera.py to accept serial_number=None (first available camera).
Update docs notebook to use Microscopy.capture(well=...) API.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@rickwierenga rickwierenga changed the title Add Aravis camera driver as PySpin alternative for Cytation Use Aravis camera driver instead of PySpin for Cytation Apr 9, 2026
rickwierenga and others added 3 commits April 9, 2026 16:24
# Conflicts:
#	docs/user_guide/agilent/biotek/cytation/hello-world.ipynb
#	pylabrobot/agilent/biotek/__init__.py
#	pylabrobot/agilent/biotek/aravis_camera.py
#	pylabrobot/agilent/biotek/cytation.py
…gic to aravis driver

- Remove cytation_aravis.py (duplicate of cytation_aravis_driver.py)
- Remove test_aravis_connection.ipynb (referenced deleted module)
- Port set_imaging_mode version 2 commands from cytation.py to aravis driver
- Port capture orchestration (image_size, tiling, timing) to microscopy backend
- Port acquire_image retry with stop/start recovery to aravis driver
- Add SetupParams to CytationAravisDriver (matches cytation.py pattern)
- Add CaptureParams.overlap to microscopy backend
- Rename CytationAravisMicroscopyBackend -> CytationMicroscopyBackend
- Rename cytation_aravis_microscopy.py -> cytation_microscopy_backend.py

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…d, use BioTekBackend directly

- Delete cytation.py (replaced by microscopy backend)
- CytationMicroscopyBackend now owns AravisCamera, camera_serial, imaging_config
- Device classes use BioTekBackend directly as driver (no more CytationAravisDriver)
- use_cam, camera_serial, imaging_config are device-level params passed to backend
- Extract _CytationBase for shared device logic (Cytation1/5)
- Add loading tray capability to both Cytation models
- Filter/objective loading happens in _on_setup
- CytationAravisDriver kept but no longer used by device classes

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
rickwierenga added a commit that referenced this pull request Apr 10, 2026
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
rickwierenga and others added 4 commits April 9, 2026 17:17
# Conflicts:
#	pylabrobot/agilent/biotek/aravis_camera.py
- Delete cytation_aravis_driver.py (dead code, duplicated CytationImagingConfig)
- Fix set_gain("machine-auto") to actually enable auto-gain on camera
- Make numpy import optional in aravis_camera.py
- Replace assert with NotImplementedError for overlap check
- Fix CaptureParams docstring (LED intensity is 1-10, not 0-100)
- Fix legacy adapter to use BioTekBackend + CytationMicroscopyBackend directly
- Fix tests to use BioTekBackend directly

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Move BioTekBackend -> plate_readers/base.py (shared base)
- Move Cytation code -> plate_readers/cytation/ (base, cytation1, cytation5,
  microscopy_backend, aravis_camera)
- Move SynergyH1 -> plate_readers/synergy/
- Update all internal imports, legacy adapters, and docs (rst + notebooks)

Review fixes:
- Wrap led_off() in try/except inside capture() finally so stop_acquisition
  always runs even if the LED command fails
- Restore asyncio.sleep(0.1) stage settle delay in set_position
- Restore max_image_read_attempts default to 50
- Accept backend_params kwarg in CytationMicroscopyBackend._on_setup
- Add PyGObject to cytation-microscopy extra (needed for Aravis)
- Add autofocus example to cytation hello-world notebook

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Replace Spinnaker SDK / Python 3.10 requirements with Aravis system
library install steps.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@rickwierenga rickwierenga merged commit af69da8 into PyLabRobot:v1b1 Apr 11, 2026
1 of 19 checks passed
@rickwierenga
Copy link
Copy Markdown
Member

thanks @vcjdeboer! works super well. very happy to ditch spinnaker

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