Conversation
This was referenced Sep 20, 2026
mvdoc
added this pull request to stack #744
September 20, 2026 01:08
Contributor
There was a problem hiding this comment.
Copilot review overview
🟡 Changes recommended
Unresolved identity, metadata, dataset integration, validation, and empty-selection issues can break normal tractogram workflows.
Get a fresh assessment by requesting another Copilot review.
Review effort: Balanced
Findings: 3
Open (7)
Implement empty uniques iterator for tractograms · New Include streamline offsets in tractogram identity hash · New Preserve base Dataview metadata in tractogram packages · New Retain Python 3.10 coverage in the test matrix · New Reject multidimensional group index arrays · New Validate boolean selection mask length · New Handle empty selections in vertex_colors · New
What changed in this PR
Adds a Tractogram dataview for storing, selecting, coloring, and transporting streamline data.
Changes:
- Adds TRX and raw-streamline constructors with grouping and coloring support.
- Exposes
Tractogrampublicly and documents its API. - Adds tractogram tests and an optional dependency while updating CI.
| File | Description |
|---|---|
| pyproject.toml | Adds the tractography dependency extra. |
| docs/dataset.rst | Documents the new dataview and constructors. |
| cortex/tests/test_tractogram.py | Tests construction, selection, coloring, and TRX loading. |
| cortex/dataset/tractogram.py | Implements the tractogram container. |
| cortex/dataset/__init__.py | Exports Tractogram from the dataset package. |
| cortex/__init__.py | Exposes Tractogram through the public API. |
| .github/workflows/run_tests.yml | Removes Python 3.10 from the test matrix. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
mvdoc
force-pushed
the
tractography/2-dataview
branch
from
September 20, 2026 21:54
5d5a4ed to
4b3e733
Compare
cortex.Tractogram holds a bundle of streamlines -- diffusion tractography
output such as pyAFQ or DIPY bundles -- as a Dataview, so it travels through
Dataset and the viewer machinery like any other data. It is the odd one out
among the dataviews in that it is not braindata: the geometry is a flat (N, 3)
array of points plus an (M+1,) offset table delimiting the M streamlines,
which is the TRX convention.
tract = cortex.Tractogram.from_trx("bundles.trx", "S1")
tract = cortex.Tractogram.from_streamlines(list_of_arrays, "S1")
Per-point and per-streamline scalars and named groups of streamlines (pyAFQ
writes one per bundle) come across from the file, and select/get_group/
subsample return new tractograms with the group memberships remapped.
Coloring is resolved in Python by vertex_colors: by local tangent direction,
by a constant color, or through a colormap from a named scalar.
Reading TRX needs trx-python, a new optional `tractography` extra. The import
is lazy, so pycortex works normally without it, and the tests importorskip.
trx-python requires Python 3.11, and the test dependency group pulls the extra
in, so the CI matrix drops its 3.10 row -- on 3.10 the install fails outright
rather than the TRX tests quietly skipping.
This is a container only. Rendering comes next; HDF5 persistence is
deliberately NotImplementedError, since a Dataset carrying one cannot be
saved, and the TRX file stays the source of truth.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Its two groups now go in in reverse alphabetical order. The viewer lists bundles alphabetically rather than in wire order, and with the two agreeing no test could tell the difference. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Seven fixes from the review of the Tractogram container, each with a regression test: - `uniques()` was missing. `Dataset.uniques()` calls it on every view it holds, so `Dataset(tract=tract).uniques()` raised `AttributeError` and a dataset carrying a tractogram could not be packaged or saved at all. A tractogram wraps no BrainData, so it yields nothing. - `name` hashed `points` alone, giving the same identity to two tractograms whose point buffers match but whose streamline boundaries differ. `offsets` now goes into the digest too. - `to_json()` dropped the base Dataview keys `state`, `attrs` and `desc`, losing custom state on the way to the viewer and breaking any consumer that reads them off a view's metadata. - Group index arrays were only range-checked, so a 2-D array was accepted and reached `select()` and `groups_wire()`, whose `(K,)` buffer contract it breaks. Groups must now be 1-D, and a boolean mask is converted rather than silently reinterpreted as the indices 0/1. - `select()` accepted a boolean mask of any length: `select([True])` on a larger tractogram quietly kept only streamline 0. Masks must now have one entry per streamline, indices must be 1-D, and an out-of-range index raises instead of wrapping (a negative index sliced `points` from the end yet never matched when remapping `groups`). - `vertex_colors()` raised on an empty tractogram in the `dpv:`/`dps:` colour modes, where `reshape(0, -1)` cannot be inferred. Empty tractograms are legitimate -- an empty named group, or a `select` that matched nothing -- and now return the documented `(0, 3)` array. - `from_trx(xfm=...)` did not check the affine's shape, failing later inside the matmul. Also restore the Python 3.10 row in the test matrix. The incompatibility is confined to trx-python, an optional test dependency, so gating it with `python_version >= '3.11'` in the test group keeps 3.10 installable (the TRX tests skip themselves there) rather than dropping core 3.10 coverage for a version the wheel-install workflow still exercises. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UWULoz8DLUFHHio66eTCgh
mvdoc
force-pushed
the
tractography/2-dataview
branch
from
September 21, 2026 01:42
4b3e733 to
8f793d0
Compare
This branch has not been deployed
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.


Stack
Merge bottom-up; each PR is based on the one above it.
cortex.Tractogramholds a bundle of streamlines — diffusion tractographyoutput such as pyAFQ or DIPY bundles — as a
Dataview, so it travels throughDatasetand the viewer machinery like any other data. It is the odd one outamong the dataviews in that it is not braindata: the geometry is a flat
(N, 3)array of points plus an(M+1,)offset table delimiting theMstreamlines, which is the TRX convention.
Per-point and per-streamline scalars and named groups of streamlines (pyAFQ
writes one per bundle) come across from the file, and
select,get_groupandsubsamplereturn new tractograms with the group memberships remapped.Colouring is resolved in Python by
vertex_colors: by local tangent direction,by a constant colour, or through a colormap from a named scalar.
This is a container only — nothing renders it yet. HDF5 persistence is
deliberately
NotImplementedError: aDatasetcarrying a tractogram cannot besaved, and the TRX file stays the source of truth.
Dependency and CI
Reading TRX needs
trx-python, a new optionaltractographyextra. The importis lazy, so pycortex works normally without it, and the tests
importorskip.trx-pythonrequires Python 3.11 and the test dependency group pulls the extrain, so the CI matrix drops its 3.10 row. On 3.10 the install step fails
outright rather than the TRX tests quietly skipping. Note that the project
declares no
requires-python, so this changes what is tested without changingwhat the package claims to support; making the two agree is a separate
decision.
Testing
cortex/tests/test_tractogram.py, 30 tests: construction and validation,round-tripping a hand-built TRX file, the
xfm, every colour mode,select/get_group/subsampleinvariants including overlapping groups, and thewire-format
to_jsonkeys.🤖 Generated with Claude Code