Skip to content

Fix anat-to-tpl xfm grabbed#293

Merged
nx10 merged 6 commits into
mainfrom
maint/ants-transforms
Apr 10, 2026
Merged

Fix anat-to-tpl xfm grabbed#293
nx10 merged 6 commits into
mainfrom
maint/ants-transforms

Conversation

@kaitj
Copy link
Copy Markdown
Contributor

@kaitj kaitj commented Apr 9, 2026

Fixes #288

Summary

  • resolve_functional queried the inverse warp (from-MNI152NLin6Asym_to-T1w) for anat_to_template, but resample_bold_to_template expects the forward warp (from-T1w_to-MNI152NLin6Asym) since ANTs applies transforms in reverse list order
  • Same bug in orchestration/all.py where anat_outputs.inverse_xfm was passed as anat_to_template for the in-memory (non-resolved) code path
  • Renamed forward_xfm/inverse_xfm to direction-explicit names (anat_to_template_xfm, template_to_anat_xfm, etc.) across all NamedTuples, exports, and tests
  • Fixed incorrect BIDS labels in longitudinal exports (previously labeled as T1w<->longitudinal, actually longitudinal<->MNI152NLin6Asym)
  • Fixed test mock attribute names that silently diverged from the real NamedTuple fields (Mock() auto-creates any attribute)
  • Fixed stat overlay misalignment in CI report: _render_stat_overlay was computing slice indices independently for background and overlay, causing different axial slices to be selected (z-scored maps have a different non-zero extent than the template BOLD)

Test plan

  • Unit tests pass (729 passed)
  • Run resample_bold_to_template on real data with both forward and inverse warps to confirm the forward warp produces correct results
  • Verify CI report shows correctly aligned fALFF/ReHo overlays

@github-actions
Copy link
Copy Markdown

github-actions Bot commented Apr 9, 2026

Coverage

Coverage Report
FileStmtsMissCoverMissing
rbc
   __init__.py10100% 
   context.py25868%70, 75–77, 79–80, 93–94
   metadata.py560100% 
rbc/bids
   __init__.py90100% 
   _schema.py585499%776, 782, 790, 1101
   anatomical.py24387%44, 47–48
   builder.py72790%233–235, 362, 364–365, 386
   functional.py42588%46–49, 84
   longitudinal.py250100% 
   metrics.py23195%44
   qc.py170100% 
   query.py674237%103–107, 121–125, 127–128, 130–135, 137, 139, 153, 159–165, 198, 207, 209–216, 225, 257, 266–267
   session.py470100% 
rbc/cli
   __init__.py10100% 
   all.py49295%84, 109
   anatomical.py25292%47, 63
   base.py71987%56, 62, 123–125, 131–133, 156
   functional.py33293%67, 87
   longitudinal.py27292%46, 63
   main.py420100% 
   metrics.py42295%77, 95
   qc.py25292%45, 61
rbc/core
   __init__.py30100% 
   common.py261253%43–45, 62–70
   fileops.py27485%69–72
   fsl2itk.py420100% 
   nifti.py192597%236–237, 244–245, 524
   niwrap.py56198%58
rbc/core/anatomical
   __init__.py40100% 
   registration.py15473%59, 151, 166, 183
   segmentation.py24866%64, 74–76, 92, 114, 125, 141
rbc/core/functional
   __init__.py130100% 
   coregistration.py7271%44, 55
   despiking.py7357%32, 36–37
   distortion.py1304069%269–271, 321, 324, 332–335, 341–346, 349, 352–353, 356, 365–369, 375–376, 387–388, 391, 397, 443–444, 447, 455, 461, 470–471, 474, 484, 491
   erosion.py32196%50
   initialization.py9455%35, 42–43, 63
   masking.py342526%53, 55–56, 58–59, 62–65, 69, 91, 134, 183, 197, 208, 223, 233, 249, 258, 271, 285, 296, 306, 319, 328
   motion.py573735%62, 64–67, 69, 71, 73, 76–77, 83–84, 86–87, 95–97, 99, 102, 105, 107, 124–125, 135–138, 159, 169, 171–172, 175, 177–179, 181, 183
   nuisance.py816025%78, 80–85, 87, 89–90, 93, 96–98, 100–102, 104–110, 112–116, 118, 163, 165, 167, 170–171, 173–175, 178, 181–182, 185–187, 190–193, 197, 203–205, 207, 235, 243, 269, 278, 307, 316, 322
   regressors.py89693%163, 193, 325–328
   resampling.py544320%37–42, 74–76, 78, 80–81, 85–87, 90, 93, 105, 107–108, 112, 114, 150–152, 154–155, 159, 161–162, 167–169, 173–174, 177, 180, 187, 199, 201–202, 207, 209
   timing.py161131%46–47, 49–53, 58, 60, 66–67
rbc/core/longitudinal
   __init__.py10100% 
   transform.py46784%106–107, 165–168, 170
rbc/core/metrics
   __init__.py30100% 
   alff.py90198%265
   reho.py660100% 
   smoothing.py7357%36, 42–43
   standardization.py271159%64, 66–68, 70, 72–75, 77–78
   timeseries.py57198%120
rbc/core/qc
   __init__.py60100% 
   dvars.py260100% 
   motion.py310100% 
   registration.py410100% 
   xcp.py410100% 
rbc/orchestration
   __init__.py32293%90, 93
   all.py41978%131–132, 137, 145, 153–154, 171, 173–174
   anatomical.py372240%49–52, 57–58, 60–63, 85–87, 89–90, 94, 101, 104, 109–110, 116, 118
   functional.py411270%124–126, 128–129, 133, 139, 142, 147–148, 157, 159
   longitudinal.py56198%150
   metrics.py463034%32–35, 38–40, 67, 75–76, 100–102, 104–106, 110, 118–121, 123–124, 130–132, 137, 145, 152, 154
   qc.py340100% 
rbc/workflows
   __init__.py100100% 
   anatomical.py471959%90–93, 97–102, 107, 177–180, 182–184, 188
   functional.py985642%113–114, 122, 127–128, 136, 207–208, 211–212, 215–216, 219, 222–225, 235–237, 247–248, 251, 254, 257–258, 266–267, 274–275, 282–283, 290–291, 294–296, 299–302, 314–315, 327, 329–332, 335–336, 345–346, 354, 361, 430, 436
   metrics.py391756%80–81, 86–87, 90–93, 96–99, 103–106, 108
   qc.py533337%87, 89–90, 93, 96, 99–104, 107, 116–118, 122–125, 127–131, 133–134, 136–138, 141, 158, 165, 167
rbc_resources
   __init__.py380100% 
TOTAL324058182% 

Tests Skipped Failures Errors Time
730 0 💤 0 ❌ 0 🔥 10.496s ⏱️

kaitj and others added 4 commits April 9, 2026 15:17
The self-hosted runner's network blocks raw.githubusercontent.com,
causing setup-uv to fail when fetching the version manifest. Pinning
the version skips the network lookup entirely.
The mocks used `long_to_anat_xfm`/`anat_to_long_xfm` but the actual
NamedTuple fields are `long_to_template_xfm`/`template_to_long_xfm`.
Mock() silently creates any attribute, so this mismatch was invisible.
@nx10 nx10 marked this pull request as ready for review April 9, 2026 23:13
_render_stat_overlay was calling _build_mosaic independently for the
background and stat map. Since _axial_slices picks slices based on
non-zero extent, the z-scored maps (which have zeros outside the mask
and negative values) computed different slice indices than the template
BOLD underlay, causing visible misalignment in the overlay.

Now computes slice indices once from the background volume and reuses
them for the stat map.
@nx10 nx10 merged commit 9ea91af into main Apr 10, 2026
8 checks passed
@nx10 nx10 deleted the maint/ants-transforms branch April 10, 2026 07:02
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.

Investigate anat_to_template transform direction in resolve_functional

2 participants