Skip to content

[ENH] Finally, batched bundle recognition#187

Merged
36000 merged 8 commits into
tractometry:mainfrom
36000:batch_recog
May 16, 2026
Merged

[ENH] Finally, batched bundle recognition#187
36000 merged 8 commits into
tractometry:mainfrom
36000:batch_recog

Conversation

@36000

@36000 36000 commented May 11, 2026

Copy link
Copy Markdown
Collaborator

Expect to segment ~100M streamlines in ~1 hour on your PC

Copilot AI review requested due to automatic review settings May 11, 2026 00:46

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR refactors pyAFQ’s bundle recognition pipeline to support batched (chunked) recognition—intended to bound peak memory while segmenting very large tractograms (e.g., TRX) by running “chunk-local” criteria per chunk and then merging survivors for a “global” phase.

Changes:

  • Introduces a chunked recognition flow (recognize_bundles) with per-chunk filtering and a merged global phase.
  • Replaces the prior immlib-based preprocessing plan with a lightweight PreprocPlan using cached properties.
  • Adjusts TRX handling to sometimes pass a TRX path through segmentation/recognition, plus a few error/logging message updates.

Reviewed changes

Copilot reviewed 6 out of 6 changed files in this pull request and generated 6 comments.

Show a summary per file
File Description
AFQ/tasks/tractography.py Updates the “no streamlines generated” error message text.
AFQ/tasks/segmentation.py Adjusts TRX loading behavior to optionally pass a TRX path through to recognition.
AFQ/recognition/utils.py Updates recognition utilities (logging → tqdm.write) and adds chunk-survivor export/merge helpers.
AFQ/recognition/recognize.py Routes recognition through the new batched recognition entrypoint and adds chunk_size.
AFQ/recognition/preprocess.py Replaces the previous preprocessing-plan machinery with PreprocPlan.
AFQ/recognition/criteria.py Major refactor: splits criteria into chunk-local/global phases and implements recognize_bundles chunking/merge logic.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread AFQ/recognition/utils.py Outdated
Comment thread AFQ/recognition/criteria.py
Comment thread AFQ/recognition/criteria.py
Comment thread AFQ/recognition/criteria.py Outdated
Comment thread AFQ/recognition/recognize.py Outdated
Comment thread AFQ/tasks/segmentation.py
@36000 36000 changed the title [WIP/ENH] Finally, batched bundle recognition [ENH] Finally, batched bundle recognition May 15, 2026
@36000
36000 requested a review from Copilot May 15, 2026 21:22

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 11 out of 11 changed files in this pull request and generated 4 comments.

Comment thread AFQ/viz/fury_backend.py Outdated
Comment thread AFQ/recognition/utils.py
Comment thread AFQ/recognition/criteria.py
Comment thread AFQ/tasks/tractography.py Outdated
@36000

36000 commented May 16, 2026

Copy link
Copy Markdown
Collaborator Author

@arokem this is ready for review/merge

@arokem arokem left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is great. I had some small not-so-important comments.

I wonder whether this could be leveraged to parallelize across chunks when memory is available. Could make this even faster?

Comment thread AFQ/recognition/criteria.py
return abu.tolerance_mm_to_vox(img, dist_to_waypoint, input_dist_to_atlas)
@cached_property
def fgarray(self):
return np.asarray(abu.resample_tg(self.tg, 20), dtype=np.float32)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we really hard-code 20 here?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is used for cross_midline, prob_map, and start and end points. For start and end points, the resampling number does not matter; DIPY always puts a point at the exact start and end. For prob map and cross_midline, it could potentially matter; however, we have had this hard-coded in the past, and I have never found a reason to tweak it.

Comment thread AFQ/_fixes.py
@36000
36000 merged commit 17adc83 into tractometry:main May 16, 2026
9 checks passed
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.

3 participants