Add noise-aware stitching, min_rows, concat, and calcium imaging config#155
Conversation
BlackAreaDetector now supports a min_rows parameter (default=1, preserving backward compatibility) that requires multiple flagged rows before marking a frame as invalid. This eliminates false positives from naturally dark regions in calcium imaging data. Stitch now supports --match-by=timestamp which matches frames across recordings by nearest buffer_recv_unix_time (within configurable threshold), instead of by device frame_num. This handles DAQs with offset frame numbering, different start/stop times, and mid-recording gaps automatically. Also adds denoise_calcium_imaging.yml example config with recommended parameters for calcium imaging (consecutive_threshold=30, value_threshold=0, min_rows=10). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
New `mio process concat -d /path/to/daq1/` command discovers all .avi files (with companion .csv) in a directory, sorts by filename, and concatenates them into a single video + CSV with contiguous reconstructed_frame_index. This is needed when a DAQ produces multiple segment files that must be combined before cross-DAQ stitching. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Alphabetical sort puts long-10 before long-2. Natural sort correctly orders segments by their numeric suffix (2, 3, ..., 9, 10, 12, 13). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
AVI files like long-8-002.avi have CSVs named long-8.csv (without the extra numeric suffix). The concat command now strips trailing -NNN suffixes when looking for companion CSVs, and shows the mapping in output. Also quiets per-frame debug messages to logger only. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…masking The FrequencyMaskingConfig requires id, mio_model, and mio_version fields from its MiniscopeConfig base class. Without these, the config fails Pydantic validation at runtime. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…tch diagnostics - Add --selection-mode noise_aware to stitch/workflow: uses InvalidFrameDetector during stitching to pick clean frames and skip both-broken pairs - Vectorize BlackAreaDetector with numpy cumsum sliding window (~100x faster) - Skip Sobel edge scoring in noise_aware mode for additional speedup - Add --max-frames flag for quick test runs - Add terminal noise summary (per-DAQ noisy counts, both-broken percentage) - Add noise_report.png (timeline, run length distribution, drop density) - Add both_broken.avi debug output for manual inspection of skipped frames - Fix denoise_calcium_imaging.yml: add interactive_display section Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
Nice that it seems to do what we want. But I also think some parts are a bit redundant/excessive for what we want to do. Some quick thoughts before looking into the details of the code:
|
so good comments. Makes total sense. Thanks!!! |
|
To-DO safeguard:
-seperate two steps noise filter and stitch as discussed above |
sneakers-the-rat
left a comment
There was a problem hiding this comment.
let's merge #133 first and then change the base of this to main. I'll handle restructuring this to match the changes i made there. a few questions and notes, but i get the need for this and can handle tidying up
|
OK pushing what i have for the day. things i still need to do
the diff got extremely fucked up from the removal of the MSE detector, but basically i simplified the noise-aware part of the stitching into that still TODO is to figure out what to do with the denoise processor classes, because they don't use the |
Coverage Report for CI Build 24915631375Warning Build has drifted: This PR's base is out of sync with its target branch, so coverage data may include unrelated changes. Coverage decreased (-0.6%) to 83.793%Details
Uncovered Changes
Coverage Regressions27 previously-covered lines in 4 files lost coverage.
Coverage Stats
💛 - Coveralls |




Summary
Adds several features for processing dual-DAQ wireless miniscope recordings, motivated by a 9-hour calcium imaging session with two DAQs.
Noise-aware frame selection (
--selection-mode noise_aware)InvalidFrameDetector(gradient + black_area) on each candidate framenoise_report.png(timeline, run length distribution, drop density plots)both_broken.avifor manual inspection of skipped framesmin_rowsparameter forBlackAreaDetectormin_rowsfield onBlackAreaDetectorConfig(default=1, preserves existing behavior)min_rows=10)Vectorized
BlackAreaDetectorTimestamp-based frame matching (
--match-by timestamp)buffer_recv_unix_timewithin configurable threshold (default 25ms)frame_nummatching (which remains the default)mio process concatcommandlong-8-002.avi→long-8.csv)reconstructed_frame_indexto be contiguous across segments--max-framesflagdenoise_calcium_imagingconfigconsecutive_threshold: 30,value_threshold: 0,min_rows: 10New output files
These are additional outputs created by the new features (on top of mio's existing outputs):
noise_report.pngstitch --selection-mode noise_awareboth_broken.avistitch --selection-mode noise_aware<dir>_combined.aviconcat<dir>_combined.csvconcatreconstructed_frame_indexExample usage
Backward compatibility
frame_num, default selection remainsmetadatamin_rowsdefaults to 1 (existing behavior)Test plan
pytest tests/test_process/test_frame_helper.py -v— min_rows + vectorized detectionpytest tests/test_process/test_stitch.py -v— timestamp matching + concat--selection-mode noise_aware🤖 Generated with Claude Code