Skip to content

Add weighted artery profile analysis and optimize cross-section processing - #44

Open
micatlan wants to merge 84 commits into
mainfrom
codex/cross-section-memory-gpu
Open

Add weighted artery profile analysis and optimize cross-section processing#44
micatlan wants to merge 84 commits into
mainfrom
codex/cross-section-memory-gpu

Conversation

@micatlan

@micatlan micatlan commented Sep 9, 2026

Copy link
Copy Markdown
Contributor

The artery velocity-profile analysis pipeline now fits one quadratic per (time, beat, branch, radius) from /Processing/VelocityProfiles/Artery/TransverseVelocityProfileMasked/value. Weighted least squares assigns weight 0.5 to the outer 25% at each border and 1.0 to the center, using the complete zero-based input domain even when samples are missing.

Float64 centered/scaled solves run in bounded time blocks and reuse solves for shared finite-sample masks. The existing writer publishes 16 arrays under /Processing/VelocityProfileAnalysis/Artery/<name>/value: coefficients, weighted and unweighted fit diagnostics, sample counts, fractional vertex and roots, and Qv_fit/Qv. Both areas are unweighted signed sums over identical finite observed integer indexes between the roots, clipped to the input domain. Invalid geometry and empty support produce NaNs while preserving counts. Scheduling analysis automatically enables the required upstream computation and profile publication. Fitting is CPU-only; serialized outputs retain float32/int32 conventions. The schema and edge-case behavior are documented in docs/velocity_profile_analysis.md.

Cross-section calculations allocate full movies for absent ring–branch intersections, eagerly prepare temporal windows, and mix radius units when estimating mask orientation. This change stores only measured segment payloads, extracts windows lazily, caches geometry, and uses one half-diagonal radius convention.

A configurable estimated scratch-memory budget (512 MiB by default) bounds workers and batches long temporal windows with one global angle and integration limits. Missing frames remain NaN, empty results have zero branches, centroids use the largest component, and quadratic fits reject unsuitable roots.

GPU arrays stay on-device through resize, rotation and profile reduction. RTX 4090 testing exposed unsupported cupy.divide(..., where=...) calls; these are fixed in the new GPU path and existing helpers. Automatic fallback warns; explicit CuPy mode raises on failure.

Validation

  • 215 tests passed in the full local suite with the CPU backend, including weighted least-squares reference comparisons, border/missing-data cases, geometry and signed sums, HDF5 round trips, and upstream option dependencies.
  • 39 targeted tests passed after import-order cleanup; Ruff passed on changed Python files and Git diff checks passed.
  • Earlier cross-section validation passed all 187 tests, including RTX 4090 hardware parity and batching checks.
  • Five warmed, synchronized host-to-host runs per synthetic case, including transfers:
Case Memory-bounded CPU RTX 4090 Speedup
64 frames, 33×33 258.1 ms 25.6 ms 10.1×
256 frames, 65×65, shared validity 1209.6 ms 116.4 ms 10.4×
256 frames, 65×65, varying validity 1554.8 ms 116.1 ms 13.4×

CPU/GPU signals and profiles agree at rtol=1e-5, atol=1e-5 on the benchmark cases. Script, raw timings and methodology are included in benchmarks/ and docs/cross_section_gpu_benchmark.md. These are single-segment synthetic timings, excluding branch labeling, final profile postprocessing and export.

Compatibility

Large payloads use SegmentArray with the existing logical axes. Integer segment indexing stays sparse; general slicing and np.asarray materialize dense data. Small metadata and rectangular exports remain dense. The scratch budget excludes retained input/output arrays and is not a total-RSS limit. Radius, missing-data and fit corrections intentionally change affected numerical results. The orientation search strategy is unchanged.

AdrienGordon and others added 30 commits July 29, 2026 11:29
… is from h5. some results not outputed anymore but kept in a tmp work h5 for figure and png creation.

Fixed raw arterial signal being filtered. now two fully separate outputs.
Augmented segment ring count from 10 to 16.
…form_shape_metrics and updated wsm with the optimizations done in ae
…d_segments

H5 output Change + Fixes to cycle and bpm + integrated hemifield analysis to waveform_shape_metrics
…ne. First draft of correcting optic disk layer
…tween each.

Added constant to decide whether to use M2 or calculate M2ff
reverted to circle annuli and use segment length frac for distance be…
AdrienGordon and others added 25 commits August 13, 2026 17:01
Unify radius units, retain sparse segment payloads, cache geometry, bound
concurrent scratch memory with temporal batching, and preserve missing data.
Keep GPU calculations resident through profile reduction and fix unsupported
CuPy divide(where=...) calls. Include RTX 4090 parity tests and benchmarks.
@micatlan micatlan changed the title Reduce cross-section memory use and fix GPU execution Add weighted artery profile analysis and optimize cross-section processing Sep 10, 2026
AdrienGordon and others added 4 commits September 11, 2026 13:33
# Conflicts:
#	src/calculations/blood_flow_velocity/cross_section/generate_cross_section_signals.py
#	src/calculations/blood_flow_velocity/cross_section/reusable_cross_section_signals.py
#	src/calculations/blood_flow_velocity/cross_section/segment_velocity_signals.py
#	src/input_output/schema/eyeflow_output.py
#	src/pipelines/waveform_velocity/profiles.py
#	src/pipelines/waveform_velocity/runner.py
#	test/test_waveform_shape_metrics_segment_geometry.py
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.

4 participants