Skip to content

Fix BundleSeg second search space reduction ignoring the local SLR - #1373

Open
CSimon-A wants to merge 2 commits into
scilus:masterfrom
CSimon-A:fix-bundleseg-reduce-search-space
Open

CSimon-A wants to merge 2 commits into
scilus:masterfrom
CSimon-A:fix-bundleseg-reduce-search-space

Conversation

@CSimon-A

@CSimon-A CSimon-A commented Nov 3, 2026

Copy link
Copy Markdown
Contributor

Quick description

Fixes #1371. In BundleSeg.recognize(), _reduce_search_space uses the model centroids, while prune_far_from_model uses the full model streamlines. _register_model_to_neighb transformed the streamlines but not the centroids, so the second _reduce_search_space (14 mm) selected candidates around the model before the local SLR, while the pruning compared them to the model after the SLR.

Type of change

  • bundleseg.py: also apply the SLR transform to model_centroids, so the 14 mm search and the pruning use the same (registered) model.
  • test_bundleseg.py (was an empty stub): synthetic bundles, with the model shifted by 15 mm (between the 14 and 16 mm thresholds). Fails before the fix (0/50 streamlines recognized), passes after. Plus a basic recognition test with a 5 mm shift.

Check the relevant options.

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • This change requires a documentation update

Validation

  • test_tractogram_segment_with_bundleseg.py passes. On the fibercup test data, the outputs are identical before and after the fix.
  • HCP test-retest: 3 subjects x 2 sessions, Zenodo BundleSeg atlas, seed 0, same code before/after except this fix.
    • Runs are reproducible, and the local SLR gives the same result with and without the fix, so all differences come from the 14 mm search.
    • Overall (51 bundles × 6 sessions): 34,829 streamlines gained and 4,897 lost, a net increase of ~1.0%. Streamline Dice between the outputs before and after the fix: 0.993.
    • Most bundles barely change. The largest changes are in small bundles (fewer than ~1,000 streamlines) that the SLR moved by more than ~5 mm.
    • In one session, the 14 mm search found no candidate for AC before the fix (133 after).
    • Test-retest voxel Dice unchanged (median over bundles 0.764 -> 0.765).
    • Similar run times before and after, even though 2.1% more candidates reach the pruning step.

Selected bundles (the most changed, two that barely change, the largest loss and the largest gain):

Bundle Mean streamlines, before -> after Mean Dice Gained Lost Mean SLR (mm)
FX_R 96 -> 180 0.697 522 16 9.0
FX_L 104 -> 124 0.735 133 10 10.7
CG_R_curve 271 -> 304 0.846 378 177 6.8
CG_L_curve 607 -> 673 0.870 570 174 6.0
IFOF_R 6,333 -> 6,335 1.000 15 4 4.1
AF_L 9,788 -> 9,802 0.999 85 5 7.6
PYT_R 24,530 -> 24,280 0.993 79 1,574 3.7
CC_Fr_2 26,801 -> 29,302 0.963 15,011 1 6.3
All 51 bundles 2,979,511 -> 3,009,443 0.993 34,829 4,897  
  • Mean streamlines, Mean Dice, Mean SLR: averaged over the 6 sessions.
  • Gained / Lost: summed over the 6 sessions.
  • Dice: overlap of the recognized streamlines before and after the fix (1 = identical).
  • Mean SLR: average distance the local SLR moved the model points (measured with temporary logging, not part of this PR).
  • All 51 bundles: streamline counts summed over all bundles and sessions; Dice computed on all streamlines together.

As there is no ground truth, these numbers show how much the output changes, not which one is better. Gains and losses both come from the 14 mm search keeping or dropping whole tractogram clusters based on their centroid. The candidate search and the pruning now use the same (registered) model.

Full table (51 bundles)

Columns (each row combines the 6 sessions, bundles sorted by size):

  • Mean before / Mean after, Mean Dice: averaged over the sessions. Min Dice: lowest session.
  • Gained / Lost: summed over the sessions.
  • Sessions changed: sessions where the output differs.
  • Mean SLR: average distance the local SLR moved the model points, averaged over the sessions. Max SLR: largest distance moved by a single model point.
  • 14 mm empty: sessions where the 14 mm search found no candidate (before -> after).
Bundle Mean before Mean after Mean Dice Min Dice Gained Lost Sessions changed Mean SLR (mm) Max SLR (mm) 14 mm empty
PC 1 1 0.944 0.667 0 1 1/6 8.6 25.7 0 -> 0
FX_R 96 180 0.697 0.220 522 16 6/6 9.0 22.6 0 -> 0
FX_L 104 124 0.735 0.216 133 10 6/6 10.7 23.6 0 -> 0
AC 226 236 0.965 0.836 66 8 2/6 7.7 18.2 1 -> 0
CG_R_curve 271 304 0.846 0.579 378 177 6/6 6.8 23.2 0 -> 0
CG_L_curve 607 673 0.870 0.629 570 174 5/6 6.0 19.0 0 -> 0
CG_L_Po 648 669 0.946 0.733 148 24 4/6 6.8 16.2 0 -> 0
SCP_L 875 875 0.973 0.933 107 108 6/6 6.6 21.4 0 -> 0
CC_Te 1042 1043 0.998 0.994 11 1 4/6 5.3 22.7 0 -> 0
CG_R_Po 1114 1187 0.970 0.832 461 24 5/6 5.9 14.1 0 -> 0
UF_R 1130 1128 0.996 0.986 6 15 4/6 9.8 23.4 0 -> 0
SCP_R 1230 1250 0.978 0.943 156 39 6/6 6.6 22.0 0 -> 0
UF_L 1275 1282 0.997 0.986 41 1 3/6 8.2 17.4 0 -> 0
ICP_R 1476 1480 0.963 0.781 24 4 2/6 5.9 14.1 0 -> 0
ICP_L 2098 2098 0.997 0.991 30 33 5/6 6.6 15.6 0 -> 0
MdLF_R 2699 2697 0.987 0.951 70 85 6/6 8.2 28.8 0 -> 0
MdLF_L 3502 3609 0.958 0.777 694 50 6/6 8.6 29.9 0 -> 0
CG_R_An 3572 3617 0.987 0.961 297 23 5/6 8.8 28.0 0 -> 0
CG_L_An 4872 4886 0.997 0.992 105 24 4/6 8.7 25.4 0 -> 0
OR_ML_R 5487 5527 0.996 0.989 248 5 5/6 10.1 21.1 0 -> 0
CG_L 5782 5787 0.995 0.982 134 103 6/6 7.9 19.9 0 -> 0
CG_R 5840 5809 0.994 0.986 95 284 6/6 7.5 17.0 0 -> 0
CC_Oc 6084 6162 0.994 0.987 472 0 6/6 5.5 12.0 0 -> 0
IFOF_R 6333 6335 1.000 0.999 15 4 5/6 4.1 13.7 0 -> 0
SLF_L 6751 6773 0.996 0.984 173 44 6/6 8.6 23.4 0 -> 0
OR_ML_L 6775 6804 0.998 0.992 180 3 5/6 9.3 23.9 0 -> 0
POPT_R_Brainstem 6945 7207 0.975 0.886 1637 66 5/6 4.2 15.0 0 -> 0
IFOF_L 7433 7420 0.998 0.994 33 110 3/6 3.6 12.3 0 -> 0
AF_L 9788 9802 0.999 0.998 85 5 6/6 7.6 18.8 0 -> 0
POPT_L_Brainstem 10699 10872 0.993 0.969 1099 64 6/6 6.5 17.9 0 -> 0
POPT_R 11489 11479 0.999 0.995 73 134 5/6 5.7 15.5 0 -> 0
FPT_L_Brainstem 12847 13133 0.975 0.860 1793 76 6/6 5.5 16.0 0 -> 0
CC_Pa 13314 13322 0.999 0.998 101 51 5/6 5.8 18.4 0 -> 0
FAT_R 13692 13836 0.991 0.976 1147 284 6/6 8.2 16.3 0 -> 0
POPT_L 14229 14318 0.996 0.990 593 64 6/6 6.1 15.8 0 -> 0
FPT_R_Brainstem 14420 14438 0.996 0.986 376 272 5/6 5.5 15.4 0 -> 0
PYT_L_Brainstem 14487 14531 0.997 0.993 465 200 6/6 4.4 16.1 0 -> 0
PYT_R_Brainstem 16051 16050 1.000 1.000 12 16 4/6 3.2 12.7 0 -> 0
FAT_L 16815 17180 0.990 0.968 2243 54 6/6 9.9 22.4 0 -> 0
FPT_L 18054 18104 0.997 0.986 339 42 5/6 4.2 15.4 0 -> 0
CC_Fr_1 18420 18746 0.991 0.967 1955 0 6/6 7.4 15.7 0 -> 0
CC_Pr_Po 19566 19683 0.997 0.987 716 12 5/6 3.4 10.7 0 -> 0
ILF_L 20604 20652 0.999 0.998 290 0 6/6 8.6 17.8 0 -> 0
MCP 21273 21299 0.999 0.996 157 1 4/6 4.2 10.0 0 -> 0
ILF_R 21667 21764 0.998 0.996 587 1 5/6 8.1 17.8 0 -> 0
PYT_L 21992 21979 1.000 0.999 0 73 2/6 3.5 11.3 0 -> 0
AF_R 22372 22401 0.999 0.996 200 28 6/6 6.2 15.7 0 -> 0
FPT_R 22778 22781 1.000 1.000 20 1 3/6 4.9 16.3 0 -> 0
PYT_R 24530 24280 0.993 0.967 79 1574 5/6 3.7 11.9 0 -> 0
SLF_R 26430 26459 0.996 0.990 682 508 6/6 8.2 22.9 0 -> 0
CC_Fr_2 26801 29302 0.963 0.922 15011 1 6/6 6.3 14.7 0 -> 0

Checklist

  • My code follows the style guidelines of this project (run autopep8)
  • I added relevant citations to scripts, modules and functions docstrings and descriptions
  • I have performed a self-review of my code
  • I have commented my code, particularly in hard-to-understand areas
  • I have made corresponding changes to the documentation
  • My changes generate no new warnings
  • I moved all functions from the script file (except the argparser and main) to scilpy modules
  • I have added tests that prove my fix is effective or that my feature works
  • New and existing unit tests pass locally with my changes

@codecov

codecov Bot commented Nov 3, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 72.85%. Comparing base (c787973) to head (884772b).

Additional details and impacted files
@@            Coverage Diff             @@
##           master    #1373      +/-   ##
==========================================
+ Coverage   72.57%   72.85%   +0.27%     
==========================================
  Files         301      301              
  Lines       26279    26281       +2     
  Branches     3702     3702              
==========================================
+ Hits        19073    19148      +75     
+ Misses       5655     5572      -83     
- Partials     1551     1561      +10     
Flag Coverage Δ
smoketests 69.72% <0.00%> (-0.02%) ⬇️
unittests 14.69% <100.00%> (+0.47%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

Components Coverage Δ
Scripts 75.26% <ø> (-0.02%) ⬇️
Library 69.96% <100.00%> (+0.63%) ⬆️
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

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.

BundleSeg: second _reduce_search_space ignores the local SLR

3 participants