Part of #50 (device-layer refactor). Depends on the shared wire contract (#79).
Problem
gently/hardware/dispim/device_layer.py is a ~3,000-line monolith mixing
hardware-agnostic plumbing with diSPIM-specific device code. A second hardware plugin
would have to reimplement the plumbing.
Goal
Hoist the reusable scaffolding into a hardware-agnostic BaseDeviceLayer (in
core/harness, building on core/service.py:Service). diSPIM subclasses it and
supplies only device/plan specifics. Pure refactor — behavior identical, so it can
be validated on the real diSPIM before anything new is built on top.
Generic — hoists up
Based on the current routes/machinery in device_layer.py:
- aiohttp routing /
Service lifecycle wiring
- SSE device-state streaming (position/property pollers + broadcast/debounce):
/api/devices/state, /api/devices/stream, /api/devices/callbacks/stream
- plan queue +
_plan_executor: /api/queue/item/add, /api/history, /api/plans,
/api/status
/api/microscope + /api/microscope/execute plan-dispatch translation
- SAM / detection endpoint scaffolding
Stays in the diSPIM plugin
MMCore init, Ophyd device definitions, Bluesky plans, dual-view/galvo specifics, the
concrete SAM detector, and accessory endpoints (/api/led, /api/temperature,
/api/room_light, /api/camera/*, /api/light_source/*, /api/bottom_camera/stream).
Also in this issue (#50 item 4): purge dead RPyC references
Stale comments/handling from the old RPyC transfer path:
gently/hardware/dispim/devices/acquisition.py:216
gently/hardware/dispim/plans/calibration.py:524
Acceptance
- diSPIM boots on
BaseDeviceLayer with no behavioral change; @pskeshu validates on-scope.
- The AO-adiSPIM offline profile (#PROFILE) can boot against
BaseDeviceLayer without
importing anything diSPIM-specific — that's the real test that the seam is in the right
place.
Scope guard (from #50)
Extract only the obviously generic plumbing. Defer a "universal" device-layer
abstraction until a real second hardware validates the seams (rule of three).
Part of #50 (device-layer refactor). Depends on the shared wire contract (#79).
Problem
gently/hardware/dispim/device_layer.pyis a ~3,000-line monolith mixinghardware-agnostic plumbing with diSPIM-specific device code. A second hardware plugin
would have to reimplement the plumbing.
Goal
Hoist the reusable scaffolding into a hardware-agnostic
BaseDeviceLayer(incore/harness, building oncore/service.py:Service). diSPIM subclasses it andsupplies only device/plan specifics. Pure refactor — behavior identical, so it can
be validated on the real diSPIM before anything new is built on top.
Generic — hoists up
Based on the current routes/machinery in
device_layer.py:Servicelifecycle wiring/api/devices/state,/api/devices/stream,/api/devices/callbacks/stream_plan_executor:/api/queue/item/add,/api/history,/api/plans,/api/status/api/microscope+/api/microscope/executeplan-dispatch translationStays in the diSPIM plugin
MMCore init, Ophyd device definitions, Bluesky plans, dual-view/galvo specifics, the
concrete SAM detector, and accessory endpoints (
/api/led,/api/temperature,/api/room_light,/api/camera/*,/api/light_source/*,/api/bottom_camera/stream).Also in this issue (#50 item 4): purge dead RPyC references
Stale comments/handling from the old RPyC transfer path:
gently/hardware/dispim/devices/acquisition.py:216gently/hardware/dispim/plans/calibration.py:524Acceptance
BaseDeviceLayerwith no behavioral change; @pskeshu validates on-scope.BaseDeviceLayerwithoutimporting anything diSPIM-specific — that's the real test that the seam is in the right
place.
Scope guard (from #50)
Extract only the obviously generic plumbing. Defer a "universal" device-layer
abstraction until a real second hardware validates the seams (rule of three).