Metrics, QC & all pipeline in longitudinal space (Stage 6 of #301)#317
Merged
Conversation
Implement rbc longitudinal metrics: resolve per-regressor regressed_bold/cleaned_bold + brain mask from space-longitudinal functional derivatives, read TR from NIfTI header, and call single_session_metrics unchanged. Reuse cross-sectional export_metrics for BIDS output naming. Co-authored-by: Janhavi Pillai <janhavipillai3@gmail.com>
QC: Dice/Jaccard overlap between anatomical and BOLD brain masks in longitudinal space with pass/fail threshold (Dice >= 0.85). Minimal scope per plan; viz tracked in #303/#304. All: rbc longitudinal all chains template -> anat -> func -> metrics -> qc. Template writes to disk (cross-session), then per-session stages pass func outputs in-memory to metrics and QC. CLI: Add --regressor and --task to rbc longitudinal all. Update descriptions for metrics/qc (no longer placeholders). Update unit tests to match (dispatch tests use mocks instead of NotImplementedError). Tests: Tier-4 full_pipeline tests for longitudinal metrics, QC, and the all-vs-sequential equivalence test under tests/full_pipeline/longitudinal/. process_anat/process_func now return their workflow outputs for in-memory handoff.
The T1w suffix filter in run() excluded mask files from the DataFrame passed to process_anat, so resolve_longitudinal_anat could never find the brain mask. Remove the filter so both T1w and mask rows are grouped together. Pre-existing bug from Stage 4 exposed by the new full_pipeline tests.
Replace fragile DataFrame-based regressor discovery (which queried a non-existent 'reg' column) with an explicit --regressor parameter, matching the cross-sectional metrics CLI pattern.
The all fixture ran cross-sectional functional only for ses-test but invoked rbc longitudinal all without --session-label, causing it to iterate ses-retest (which has no functional derivatives) and crash on an empty BOLD DataFrame.
Template generation needs all sessions to find multi-session subjects. The session/task filters should only apply to per-session stages (anat, func, metrics, qc), not to discover_template_inputs which requires the full cross-session view.
TR handling: - Promote resolve_tr/warn_implausible_tr to public API in metadata.py - Replace bare _read_header_tr with _read_derivative_tr that pipes through resolve_tr for validation and plausibility warnings - Add --tr override to rbc longitudinal metrics CLI, matching cross-sectional FreeSurfer auth: - Rename _setup_freesurfer_auth -> setup_freesurfer_auth and add to __all__ in template.py - Import at module level in all.py instead of lazy private import QC DataFrame assembly: - Replace manual concat of session.anat + session.func + tpl_df with load_table call, matching cross-sectional qc.py pattern
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.
Summary
rbc longitudinal metricsresolves per-regressorregressed_bold/cleaned_bold+ brain mask fromspace-longitudinalfunctional derivatives, reads TR from the NIfTI header, and callssingle_session_metricsunchanged. Reuses cross-sectionalexport_metricsfor BIDS output naming (ALFF, fALFF, ReHo, atlas timeseries/correlations). CLI mirrors cross-sectional with--atlas(default schaefer_200) and--fwhm(default 6.0).rbc longitudinal qccomputes Dice/Jaccard overlap between the anatomical brain mask and BOLD brain mask in longitudinal template space. Pass/fail threshold at Dice >= 0.85. Minimal scope per plan; no visualizations (tracked in Cross-sectional QC visualization pipeline #303/Longitudinal QC visualization pipeline #304).rbc longitudinal allchains template -> anat -> func -> metrics -> qc. Template step writes to disk (cross-session), then per-session stages pass functional outputs in-memory to metrics and QC. CLI gains--regressorand--taskflags.process_anat/process_funcnow return their workflow outputs (AnatomicalLongOutputs/FunctionalLongOutputs) for in-memory handoff.full_pipelinetests for metrics, QC, and the all-vs-sequential equivalence test undertests/full_pipeline/longitudinal/. Unit test dispatch tests updated fromNotImplementedErrorchecks to mock-based routing verification.Ports metrics work from closed #297.
Closes the Stage 6 checkbox on #301.
Test plan
uv run ruff checkpasses on all changed filesuv run mypypasses on all changed modulesuv run pytest -m unitpasses (780 passed)uv run pytest -m integration --runner docker(nightly lane)uv run pytest -m full_pipeline --runner dockerfortests/full_pipeline/longitudinal/(release lane)