Integrate longitudinal template generation (Stage 2 of #301)#306
Merged
Conversation
Ports scripts/build_robust_template.py into the rbc package layout so the
template stage matches the rest of the pipeline and gets test coverage:
- core/longitudinal/freesurfer.py: generate_robust_template +
fs_to_itk_xfm via niwrap freesurfer + rbc.core.fsl2itk (no c3d).
- workflows/longitudinal/template.py: LongitudinalTemplateOutputs +
generate_subject_template().
- bids/longitudinal/template.py: discover_template_inputs +
export_template; xfm output naming switched to
sub-X_ses-longitudinal_from-Y_to-longitudinal_mode-image_xfm.txt.
resolve_longitudinal_{anat,func} updated to query by from+to extras.
- orchestration/longitudinal/template.py: per-subject loop. Fixes #19
(per-subject volume check now inside the loop, not on the whole df).
- cli/longitudinal/ becomes a package with nested subparsers and a
``long`` alias. ``rbc longitudinal template`` is the new subcommand;
the legacy --anatomical/--functional flow lives at
``rbc longitudinal process`` until Stage 3 splits it.
- noit=True ported as-is with TODO referencing #302.
- Drops the FS license requirement entirely: orchestration sets the
documented SURFER_SIDEDOOR bypass on the runner environ, since
mri_robust_template's chklc() returns immediately when the var is set.
- Deletes scripts/build_robust_template.py.
Unit tests cover filename mapping, the per-subject single-volume guard,
template input discovery, BIDS export naming, and the new CLI wiring
(including the ``long`` alias).
Tier-2 integration test for ``rbc longitudinal template`` deferred:
needs the ds000114 multi-session fixture infrastructure (download
script + CI cache + conftest), which is substantial enough to land
in a separate PR. Existing ``pytest -m 'integration and not slow'``
collects 0 tests today, so no regression risk.
- ``--fs-license`` / ``FS_LICENSE`` env var override the SURFER_SIDEDOOR bypass when set; license is mounted into containers via the restored mount_fs_license helper. Bypass remains the default so casual users don't need a license. - ``discover_template_inputs`` now returns ``(inputs, skipped)`` and the orchestrator logs a warning per single-session subject instead of silently dropping them. - ``hasattr(runner, "environ")`` guard around the SURFER_SIDEDOOR assignment for runners that don't expose an environ dict.
nx10
added a commit
that referenced
this pull request
Apr 13, 2026
Adds the download script, conftest fixtures, and CI cache that the Stage 2 longitudinal integration test (deferred from PR #306) and the upcoming Stages 3-6 tier-2 tests need. Pins OpenNeuro snapshot 1.0.2 via sha256 of task-fingerfootlips_bold.json so silent upstream drift (including the old missing-TaskName regression) is caught at fetch time. Also lands the deferred rbc longitudinal template integration test asserting the ses-longitudinal BIDS tree shape (template T1w plus from-test / from-retest ITK xfms). Refs #301, follow-up to #306.
4 tasks
nx10
added a commit
that referenced
this pull request
Apr 14, 2026
Adds the download script, conftest fixtures, and CI cache that the Stage 2 longitudinal integration test (deferred from PR #306) and the upcoming Stages 3-6 tier-2 tests need. Pins OpenNeuro snapshot 1.0.2 via sha256 of task-fingerfootlips_bold.json so silent upstream drift (including the old missing-TaskName regression) is caught at fetch time. Also lands the deferred rbc longitudinal template integration test asserting the ses-longitudinal BIDS tree shape (template T1w plus from-test / from-retest ITK xfms). Refs #301, follow-up to #306.
nx10
added a commit
that referenced
this pull request
Apr 14, 2026
The LTA that mri_robust_template writes embeds /styx_input/... paths to the --mov volumes that only exist inside that container. When lta_convert runs in a fresh container, those paths don't resolve and FreeSurfer fails to emit a valid FSL matrix. Passing src_geometry and trg_geometry explicitly makes niwrap bind-mount the volumes and gives FreeSurfer the geometry it needs. Tightens the existing unit test to assert both kwargs are forwarded so this can't regress silently again. Latent since PR #306; surfaced by the ds000114 fixture in #307.
nx10
added a commit
that referenced
this pull request
Apr 15, 2026
Adds the download script, conftest fixtures, and CI cache that the Stage 2 longitudinal integration test (deferred from PR #306) and the upcoming Stages 3-6 tier-2 tests need. Pins OpenNeuro snapshot 1.0.2 via sha256 of task-fingerfootlips_bold.json so silent upstream drift (including the old missing-TaskName regression) is caught at fetch time. Also lands the deferred rbc longitudinal template integration test asserting the ses-longitudinal BIDS tree shape (template T1w plus from-test / from-retest ITK xfms). Refs #301, follow-up to #306.
nx10
added a commit
that referenced
this pull request
Apr 15, 2026
The LTA that mri_robust_template writes embeds /styx_input/... paths to the --mov volumes that only exist inside that container. When lta_convert runs in a fresh container, those paths don't resolve and FreeSurfer fails to emit a valid FSL matrix. Passing src_geometry and trg_geometry explicitly makes niwrap bind-mount the volumes and gives FreeSurfer the geometry it needs. Tightens the existing unit test to assert both kwargs are forwarded so this can't regress silently again. Latent since PR #306; surfaced by the ds000114 fixture in #307.
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
Stage 2 of the longitudinal refactor (tracker: #301). Ports
scripts/build_robust_template.pyinto the rbc package layout, updates xfm naming, and wires uprbc longitudinal templateas a nested subcommand. The standalone script is deleted.What moved / changed
core/longitudinal/freesurfer.py--generate_robust_template+fs_to_itk_xfmvia niwrap freesurfer +rbc.core.fsl2itk(replacesc3d_affine_tool).workflows/longitudinal/template.py--LongitudinalTemplateOutputs+generate_subject_template.bids/longitudinal/template.py--discover_template_inputs+export_template.orchestration/longitudinal/template.py-- per-subject loop.sub-X_ses-longitudinal_from-Y_to-longitudinal_mode-image_xfm.txt.resolve_longitudinal_{anat,func}now query byextra={"from": ses, "to": "longitudinal"}. The multi-entity-extras spike confirmedBids.expect()ANDs each predicate, so this Just Works.cli/longitudinal/is now a package with nested subparsers and alongalias. New:rbc longitudinal template. Legacy--anatomical/--functionalflow lives atrbc longitudinal processuntil Stage 3 splits it into proper per-stage subcommands. (rbc long templateworks.)chklc(): ifSURFER_SIDEDOORis set, the check returns 1 immediately. Orchestration sets it onrunner.environ, so users don't need--fs-license,FS_LICENSE, or any registration to runmri_robust_template. The original script's license-mounting plumbing is gone.noit=Trueported as-is with a TODO comment referencing Evaluate noit=True in longitudinal robust template generation #302 (quality spike).scripts/build_robust_template.py.Test plan
uv run pytest -m unit(750 passed, 1 skipped)uv run ruff check src/ tests/uv run ruff format src/ tests/uv run mypy src/ tests/uv run rbc longitudinal --helpandrbc long template --helpshow the expected nested subparser outputpytest -m "integration and not slow"lane is unaffected (collects 0 tests today, so the "passes" criterion is trivially satisfied). I'll file a follow-up issue.Follow-ups referenced
noit=Truequality spike (ported as-is here).rbc longitudinal template.rbc longitudinal processinto dedicatedanatomical/functionalsubcommands; remove the legacy--anatomical --functionalflag shape.