B2 · Manual mode — dual-camera + laser-preset browser + timelapse form#75
Closed
pskeshu wants to merge 11 commits into
Closed
B2 · Manual mode — dual-camera + laser-preset browser + timelapse form#75pskeshu wants to merge 11 commits into
pskeshu wants to merge 11 commits into
Conversation
…tasks; live parts rig-deferred)
Add POST /api/devices/laser/config proxy (require_control, 400 on missing/empty config, mirrors /laser/off client+error pattern). Add <select id="devices-laser-preset"> in the Illumination group; populateLaserPresets() fetches the 7 presets on manual-view entry and wires onchange → setLaserPreset(). Entry-safety I3 guard (setLaserOff) fires before populate — preset selection is an explicit post-entry override. CSS styles for ls-laser-row/label/select added to main.css. 7 TDD tests; node --check clean; Chrome-MCP harness verified.
Register DiSPIMCamera("HamCam2") as devices["camera_b"] defensively in
device_factory — only when HamCam2 is in core.getLoadedDevices(); single-
camera rigs skip and log a warning.
Add "side" ('A'|'B', default 'A') to _ls_params; _ensure_lightsheet_sequence_sync
selects camera/camera_b by side and restarts the sequence on side change
(mirrors the exposure-change restart path). Side B without camera_b falls
back to A. New GET /api/cameras endpoint (device-layer + UI proxy) lists
available camera roles. UI: #devices-ls-side select in the manual rail,
hidden on single-camera rigs, shown when GET /api/devices/cameras lists 'B'.
postLightsheetParams includes side on every call. populateCameraRoles()
called on manual-view entry alongside populateLaserPresets.
RIG-DEFERRED: live Multi-Camera dual view + dual-side acquisition.
TDD: 16 tests, all pass; node --check exit 0; no new suite failures.
Adds POST /api/devices/timelapse/start (require_control) that validates params and calls orchestrator.start via server.agent_bridge.agent.timelapse_orchestrator. Adds a collapsible Timelapse panel to #devices-view-manual with cadence, stop condition, embryo IDs, monitoring mode, and volume geometry fields. devices.js populates defaults from GET /api/devices/scan_geometry + /api/devices/laser/configs on manual-view entry and POSTs on submit. 16 TDD tests; node --check passes; galvo/piezo motion is rig-deferred.
… app CSS)
Add 8 CSS classes to main.css that the timelapse panel (#devices-view-manual)
references but were never defined in the app: ls-collapsible-head/body/arrow,
ls-sub-row/label/section/section-label, ls-tl-status. Panel was rendering
unstyled in the real app; scratchpad harness had masked this with inline CSS.
Classes mirror the existing .ls-row/.ls-group/.ls-label pattern (same CSS
variables, spacing, dark instrument aesthetic). [hidden] fights prevented via
explicit [hidden]{display:none} scoped rules. Verified via Chrome MCP harness
loading the real main.css with no harness-local ls-* overrides.
Also: TODO comment in timelapse_start route noting UI path skips plan auto-linking.
…ton LED, add laser on/off)
…lvo/piezo FIX 1 — buffer hardening: - Add snap-loop mode (default): _grab_lightsheet_frame_sync uses snapImage()+getImage() per frame; no circular buffer, hard memory ceiling. - Continuous mode (opt-in via _ls_params["mode"]="continuous"): cap buffer with setCircularBufferMemoryFootprint(256) before start; drain with clearCircularBuffer() after each getLastImage() peek. - _stop_lightsheet_sequence_sync: always calls clearCircularBuffer() on every exit path (disconnect, error, pause, view-exit via finally block). FIX 2 — side-B galvo/piezo: - device_factory.py: defensively register scanner_b (Scanner:CD:33) and piezo_b (PiezoStage:Q:35) when present in getLoadedDevices(); skip+log on single-side rigs. - _park_lightsheet_sync: select scanner_b/piezo_b for side B, fall back to A with warning when absent; single-camera rigs unaffected. TDD: 12 tests red → green; 40 target tests pass; 0 new failures in full suite.
…ection states Restructure the flat timelapse panel into 3 independently collapsible accordion sections — Schedule (open by default), Targets, Volume geometry. Active/inactive state: - Each section header starts muted (hollow 5-px dot, dimmed label). - Any user input/change event in a section flips it active: dot fills accent cyan, label turns accent, a one-line summary appears inline. - Summaries: "60 s · 5 frames" / "all · Idle (plain imaging)" / "80 sl · 10 ms · ALL OFF". - The outer Timelapse panel header shows an accent dot once any section is set; the Start Timelapse button turns accent-bordered when ready. - Re-entering the manual view (initTlForm) resets all touched state and clears visual active state. Payload unchanged: all field IDs preserved, POST body identical. node --check: exit 0.
- Add Gallery to TABS constant (utils.js) and wire switchTab + hash routing in app.js; lazy-inits GalleryTab.init() on first visit - Add Gallery nav button in the Library group (index.html) and the gallery-content tab panel with embryo/type filter selects - Add GalleryTab controller in gallery.js: fetches /api/snapshots (which already includes volumes), sorts newest-first, renders a responsive thumbnail grid grouped by embryo/type filters; clicking opens existing Lightbox - Add showGentlyToast() in gallery.js: fixed bottom-center toast with optional action button and auto-dismiss after 6 s - Show "Volume acquired / View in Gallery" toast in devices.js after successful Snap Volume or Burst — no inline preview to keep manual mode uncluttered; "View in Gallery" calls switchTab(TABS.GALLERY) - Add gallery tab + toast CSS to main.css (gallery-tab-container grid, gently-toast styles); reuses --accent/--bg-card/--border vars
Collaborator
Author
|
Superseded by #72 — the temperature + Operations/tactics suite and the new Operate (bottom-cam→SPIM) surface are consolidated onto |
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.
Sub-project B2 (replaces #70, recovering CI). Laser-preset browser, dual-camera (side A/B) config, manual timelapse form. Includes post-testing fixes: single LED toggle + laser on/off, live-view memory hardening + side-B galvo/piezo, timelapse accordion, Gallery tab + volume-acquired toast. Whole-branch reviewed; ruff+format clean. Live dual-view/acquisition rig-deferred. Stacked on
feature/session-plan-linking.