Open
Conversation
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…ntics Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add a convenience method that runs a brief (default 1 s) scan with camera mask 0xFF on both modules, collects contact-quality warnings via a callback, and returns a ContactQualityResult. Thread the new contact_quality_callback kwarg through ScanWorkflow.start_scan into the create_science_pipeline call so the monitor's warnings reach the caller. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…ill alive
If _stream_loop is blocked in dev.read when stop_streaming's 2s join
times out, the old teardown unconditionally nulled expected_size and
data_queue. When dev.read then returned, the next loop iteration passed
expected_size=None into dev.read and pyusb raised TypeError from
array.array('B', length * b"\x00"). This was first hit by the 1 s
run_contact_quality_check quick-check, where LEFT histo never receives
a chunk before scan-end and the read loop is stuck.
Only null the buffers after confirming the thread has exited; if it is
still alive, log a warning and leave them intact so the leaked thread
exits cleanly once dev.read errors out. Also add an explicit
stop_event check at the top of _stream_loop so teardown is deterministic
and does not depend on a dev.read timeout firing.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Adds an ``error`` field to ``ContactQualityResult`` and populates it from ``run_contact_quality_check``: - ``start_scan`` returning False -> ok=False, error="Failed to start scan" - All connected sides received 0 USB chunks -> ok=False, error notes the likely cabling/FPGA cause - One side received 0 chunks -> ok=True with a per-side note (single-side scenarios remain valid) Also raises the quick-check minimum duration from 1 s to 3 s; the previous default couldn't survive scan-teardown overhead + camera-enable + warmup- discard and frequently produced empty acquisitions. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…ed contention Observed worst-case response latency was ~1.08 s when streaming on IF1 has just been armed — the MCU's IF0 command handler takes noticeably longer to service the request under that contention. The previous 0.3 s timeout caused ``_send`` to return as "no response", and the eventual stale response then poisoned the next packet ID, breaking subsequent commands. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Previously run_contact_quality_check skipped the camera-configure step that the play-button path performs via startConfigureCameraSensors, which could leave cameras in a state that caused flaky enable_camera timeouts during the quick-check scan. Now always run a ConfigureRequest(0xFF, 0xFF) first, block on the configure worker via on_complete_fn + _config_thread.join(), and abort with a descriptive error if configuration fails. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
the app auto-flashes at startup; reconfiguring mid-session fails with not-READY errors. Quick-check should follow the same contract as normal scans — cameras must already be configured.
ContactQualityMonitor now emits an INFO log line whenever a warning latches, including the raw value, the absolute threshold compared against, the pedestal + named constant that make up that threshold, and the streak counter (for POOR_CONTACT) or "immediate" marker (for AMBIENT_LIGHT). Latch clears are logged at DEBUG. run_contact_quality_check now logs a summary block after the scan thread joins with elapsed time, requested duration, absolute thresholds, per-side chunk counts, a bullet list of each warning, and the final ok/error decision. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Contact-quality INFO log lines now show L1..L8 / R1..R8 instead of L0..L7 / R0..R7 to match how cameras are numbered in clinical docs and the app UI. The raw camera_id field on ContactQualityWarning stays 0-indexed; only the formatted string label is shifted. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…o 1s; log per-camera status Replaces per-frame streak-based POOR_CONTACT logic with an average-based evaluation. ContactQualityMonitor.update_light now accumulates each light-frame raw_light_mean; a new finalize() method computes the per-camera average and emits one POOR_CONTACT warning per camera whose average falls below pedestal + LIGHT_MEAN_THRESHOLD_DN. Ambient-light per-frame latching behavior is unchanged. run_contact_quality_check now constructs the monitor explicitly and plumbs it through ScanWorkflow.start_scan and create_science_pipeline via a new contact_quality_monitor kwarg, so it can call finalize() and per_camera_summary() after the scan thread joins. The returned warnings list merges live ambient warnings (from the callback) with averaged poor-contact warnings (from finalize), de-duped by (camera_id, warning_type). An INFO line is logged for each camera with light_frames, avg_light_mean, ambient_latched, and a status of OK / AMBIENT_LIGHT / POOR_CONTACT / AMBIENT_LIGHT, POOR_CONTACT / NO DATA. Default duration_s drops back to 1.0 and the floor to 1 s; the app now pushes trigger config before invoking the check so 1 s acquisitions are viable. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…w=10) ContactQualityMonitor.update_light now maintains a per-camera rolling window of the last LIVE_LIGHT_WINDOW_FRAMES (=10) raw_light_mean values in addition to the existing cumulative light_sum/light_count. Once the window is full, the rolling average is compared against pedestal + LIGHT_MEAN_THRESHOLD_DN on every new frame. A single latching POOR_CONTACT warning is returned when the rolling average dips below threshold; the latch clears when the average recovers, so subsequent dips can re-fire. The cumulative finalize() path is untouched, keeping the quick-check behavior exactly as before, and the dedup-by- (camera_id, warning_type) in Interface.run_contact_quality_check continues to suppress duplicate POOR_CONTACT between the live callback and finalize() paths. per_camera_summary() now additionally reports rolling_avg_light_mean and contact_latched for end-of-check diagnostics. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
… don't collide Previously _state_for(camera_id) keyed state by cam_id alone, which caused left cam 0 and right cam 0 to share a single _CameraState. Whichever side updated last overwrote the other in per_camera_summary() and ambient-latch suppressed the second side's warnings. State is now keyed by (side, cam_id); finalize() and per_camera_summary() iterate over the tuple keys, and reset() accepts optional side/camera_id to clear all / a side / a specific entry. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Accumulate dark_sum/dark_count per (side, cam_id) in update_dark() and surface dark_frames/dark_mean_avg in per_camera_summary(). The end-of- check INFO log in run_contact_quality_check now reports dark-frame count and average alongside light-frame stats, and a camera seen only via dark frames still produces a summary row. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…g window The rolling-window check is for live continuous scans where transient dips matter. For the 1s quick-check, drop live POOR_CONTACT warnings and use finalize()'s cumulative average so the warning value matches the per-camera summary log. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
….py, gitignore superpowers docs Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
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.
No description provided.