From 2eefaee944d4622451cfb08756b11c1d5027880e Mon Sep 17 00:00:00 2001 From: frheault Date: Thu, 6 Aug 2026 16:50:22 -0400 Subject: [PATCH 1/5] Add current branch to CI triggers --- .github/workflows/codeformat.yml | 2 +- .github/workflows/coverage.yml | 2 +- .github/workflows/docbuild.yml | 2 +- .github/workflows/publish-to-test-pypi.yml | 1 + .github/workflows/test.yml | 2 +- 5 files changed, 5 insertions(+), 4 deletions(-) diff --git a/.github/workflows/codeformat.yml b/.github/workflows/codeformat.yml index 03e3a21b..a486e71b 100644 --- a/.github/workflows/codeformat.yml +++ b/.github/workflows/codeformat.yml @@ -2,7 +2,7 @@ name: Code Format on: push: - branches: [master] + branches: [master, extra_fields_testing] pull_request: branches: [master] diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml index 57381838..073f8d65 100644 --- a/.github/workflows/coverage.yml +++ b/.github/workflows/coverage.yml @@ -2,7 +2,7 @@ name: Coverage on: push: - branches: [master] + branches: [master, extra_fields_testing] pull_request: branches: [master] diff --git a/.github/workflows/docbuild.yml b/.github/workflows/docbuild.yml index 4855bd27..e2c9290e 100644 --- a/.github/workflows/docbuild.yml +++ b/.github/workflows/docbuild.yml @@ -2,7 +2,7 @@ name: Documentation build on: push: - branches: [ master ] + branches: [ master, extra_fields_testing ] tags: - '*' pull_request: diff --git a/.github/workflows/publish-to-test-pypi.yml b/.github/workflows/publish-to-test-pypi.yml index f2164e58..2594e834 100644 --- a/.github/workflows/publish-to-test-pypi.yml +++ b/.github/workflows/publish-to-test-pypi.yml @@ -4,6 +4,7 @@ on: push: branches: - master + - extra_fields_testing tags: - "*" diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 40e83d11..4bf53818 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -2,7 +2,7 @@ name: Tests on: push: - branches: [master] + branches: [master, extra_fields_testing] pull_request: branches: [master] From 2c7825e66be50d9d27397a943daeba668b3ed317 Mon Sep 17 00:00:00 2001 From: frheault Date: Mon, 17 Aug 2026 13:22:28 -0400 Subject: [PATCH 2/5] True fix for the select --- trx/io.py | 28 ++++++++++++++++------------ trx/tests/test_io.py | 35 +++++++++-------------------------- trx/tests/test_memmap.py | 28 +++++++++++++++++++++++++++- trx/trx_file_memmap.py | 4 ++-- 4 files changed, 54 insertions(+), 41 deletions(-) diff --git a/trx/io.py b/trx/io.py index ebf657f2..a2ee117e 100644 --- a/trx/io.py +++ b/trx/io.py @@ -46,7 +46,9 @@ def get_trx_tmp_dir(): return tempfile.TemporaryDirectory(dir=trx_tmp_dir, prefix="trx_") -def load_sft_with_reference(filepath, reference=None, bbox_check=True, **kwargs): +def load_sft_with_reference( + filepath, reference=None, bbox_check=True, from_space=None +): """Load a tractogram as a StatefulTractogram with an explicit reference. Parameters @@ -59,8 +61,8 @@ def load_sft_with_reference(filepath, reference=None, bbox_check=True, **kwargs) bbox_check : bool, optional If True, validate that streamlines lie within the reference bounding box. Defaults to True. - **kwargs - Additional keyword arguments passed to dipy's load_tractogram. + from_space : dipy.io.stateful_tractogram.Space, optional + Space to which the tractogram was transformed before saving. Returns ------- @@ -72,7 +74,7 @@ def load_sft_with_reference(filepath, reference=None, bbox_check=True, **kwargs) IOError If the file format is unsupported or a required reference is missing. """ - if not dipy_available: # pragma: no cover + if not dipy_available: logging.error( "Dipy library is missing, cannot use functions related " "to the StatefulTractogram." @@ -85,13 +87,15 @@ def load_sft_with_reference(filepath, reference=None, bbox_check=True, **kwargs) if ext == ".trk": if reference is not None and reference != "same": logging.warning(f"Reference is discarded for this file format {filepath}.") - sft = load_tractogram(filepath, "same", bbox_valid_check=bbox_check, **kwargs) + sft = load_tractogram( + filepath, "same", bbox_valid_check=bbox_check, from_space=from_space + ) elif ext in [".tck", ".fib", ".vtk", ".dpy"]: if reference is None or reference == "same": raise IOError(f"--reference is required for this file format {filepath}.") else: sft = load_tractogram( - filepath, reference, bbox_valid_check=bbox_check, **kwargs + filepath, reference, bbox_valid_check=bbox_check, from_space=from_space ) else: @@ -100,17 +104,17 @@ def load_sft_with_reference(filepath, reference=None, bbox_check=True, **kwargs) return sft -def load(tractogram_filename, reference, **kwargs): +def load(tractogram_filename, reference=None, from_space=None): """Load a tractogram from disk and return a TRX or StatefulTractogram. Parameters ---------- tractogram_filename : str Path to the input tractogram. TRX directories are supported. - reference : str or nibabel.Nifti1Image + reference : str or nibabel.Nifti1Image, optional Reference image used for formats without embedded affine information. - **kwargs - Additional keyword arguments passed to dipy's load_tractogram. + from_space : dipy.io.stateful_tractogram.Space, optional + Space to which the tractogram was transformed before saving. Returns ------- @@ -122,7 +126,7 @@ def load(tractogram_filename, reference, **kwargs): in_ext = split_name_with_gz(tractogram_filename)[1] if in_ext != ".trx" and not os.path.isdir(tractogram_filename): tractogram_obj = load_sft_with_reference( - tractogram_filename, reference, bbox_check=False, **kwargs + tractogram_filename, reference, bbox_check=False, from_space=from_space ) else: tractogram_obj = tmm.load(tractogram_filename) @@ -151,7 +155,7 @@ def save(tractogram_obj, tractogram_filename, bbox_valid_check=False): The function writes to disk and returns ``None``. Returns ``None`` immediately when ``dipy`` is unavailable. """ - if not dipy_available: # pragma: no cover + if not dipy_available: logging.error( "Dipy library is missing, cannot use functions related " "to the StatefulTractogram." diff --git a/trx/tests/test_io.py b/trx/tests/test_io.py index 11a24fae..8b577b53 100644 --- a/trx/tests/test_io.py +++ b/trx/tests/test_io.py @@ -14,16 +14,9 @@ from dipy.io.streamline import load_tractogram, save_tractogram dipy_available = True -except ImportError: # pragma: no cover +except ImportError: dipy_available = False -try: - import fury # noqa: F401 - - fury_available = True -except ImportError: # pragma: no cover - fury_available = False - from trx.fetcher import fetch_data, get_home, get_testing_files_dict from trx.io import load, save import trx.trx_file_memmap as tmm @@ -35,8 +28,6 @@ @pytest.mark.parametrize("path", [("gs.trk"), ("gs.tck"), ("gs.vtk")]) @pytest.mark.skipif(not dipy_available, reason="Dipy is not installed.") def test_seq_ops_sft(path): - if path.endswith(".vtk") and not fury_available: - pytest.skip("fury is not installed") with TemporaryDirectory() as tmp_dir: gs_dir = os.path.join(get_home(), "gold_standard") path = os.path.join(tmp_dir, path) @@ -65,17 +56,13 @@ def test_seq_ops_trx(): @pytest.mark.parametrize("path", [("gs.trx"), ("gs.trk"), ("gs.tck"), ("gs.vtk")]) @pytest.mark.skipif(not dipy_available, reason="Dipy is not installed.") def test_load_vox(path): - if path.endswith(".vtk") and not fury_available: - pytest.skip("fury is not installed") + from dipy.io.stateful_tractogram import Space + gs_dir = os.path.join(get_home(), "gold_standard") path = os.path.join(gs_dir, path) coord = np.loadtxt(os.path.join(get_home(), "gold_standard", "gs_vox_space.txt")) - if path.endswith(".vtk"): - from dipy.io.stateful_tractogram import Space - - obj = load(path, os.path.join(gs_dir, "gs.nii"), from_space=Space.LPSMM) - else: - obj = load(path, os.path.join(gs_dir, "gs.nii")) + from_space = Space.LPSMM if path.endswith("gs.vtk") else None + obj = load(path, os.path.join(gs_dir, "gs.nii"), from_space=from_space) sft = obj.to_sft() if isinstance(obj, TrxFile) else obj sft.to_vox() @@ -88,17 +75,13 @@ def test_load_vox(path): @pytest.mark.parametrize("path", [("gs.trx"), ("gs.trk"), ("gs.tck"), ("gs.vtk")]) @pytest.mark.skipif(not dipy_available, reason="Dipy is not installed.") def test_load_voxmm(path): - if path.endswith(".vtk") and not fury_available: - pytest.skip("fury is not installed") + from dipy.io.stateful_tractogram import Space + gs_dir = os.path.join(get_home(), "gold_standard") path = os.path.join(gs_dir, path) coord = np.loadtxt(os.path.join(get_home(), "gold_standard", "gs_voxmm_space.txt")) - if path.endswith(".vtk"): - from dipy.io.stateful_tractogram import Space - - obj = load(path, os.path.join(gs_dir, "gs.nii"), from_space=Space.LPSMM) - else: - obj = load(path, os.path.join(gs_dir, "gs.nii")) + from_space = Space.LPSMM if path.endswith("gs.vtk") else None + obj = load(path, os.path.join(gs_dir, "gs.nii"), from_space=from_space) sft = obj.to_sft() if isinstance(obj, TrxFile) else obj sft.to_voxmm() diff --git a/trx/tests/test_memmap.py b/trx/tests/test_memmap.py index 9ef28794..b6110266 100644 --- a/trx/tests/test_memmap.py +++ b/trx/tests/test_memmap.py @@ -387,7 +387,33 @@ def test_trxfile_getgroup(): def test_trxfile_select(): - pass + path = os.path.join(get_home(), "memmap_test_data", "small.trx") + trx = tmm.load(path) + + assert len(trx.select([]).streamlines) == 0 + assert len(trx.select([0]).streamlines) == 1 + + idx = list(range(10)) + sub = trx.select(idx) + assert len(sub.streamlines) == len(idx) + assert not sub._copy_safe + + trx.close() + + +def test_save_after_select(): + path = os.path.join(get_home(), "memmap_test_data", "small.trx") + trx = tmm.load(path) + sub = trx.select(list(range(5))) + with tempfile.TemporaryDirectory() as tmp_dir: + out = os.path.join(tmp_dir, "sub.trx") + tmm.save(sub, out) + loaded = tmm.load(out) + assert len(loaded.streamlines) == 5 + assert len(loaded.streamlines._data) == len(sub.streamlines.copy()._data) + loaded.close() + trx.close() + def test_trxfile_to_memory(): diff --git a/trx/trx_file_memmap.py b/trx/trx_file_memmap.py index 412923d7..665ae7ba 100644 --- a/trx/trx_file_memmap.py +++ b/trx/trx_file_memmap.py @@ -1109,14 +1109,14 @@ def deepcopy(self) -> Type["TrxFile"]: # noqa: C901 if not self._copy_safe: to_dump = _append_last_offsets( - self.streamlines.copy()._offsets, self.header["NB_VERTICES"] + self.streamlines.copy()._offsets, tmp_header["NB_VERTICES"] ) else: to_dump = _append_last_offsets( self.streamlines._offsets, self.header["NB_VERTICES"] ) offsets_filename = _generate_filename_from_data( - self.streamlines._offsets, os.path.join(tmp_dir.name, "offsets") + to_dump, os.path.join(tmp_dir.name, "offsets") ) _ensure_little_endian(to_dump).tofile(offsets_filename) From e1e1d92e5e3b60d40fa0ae605e38c794885aefa8 Mon Sep 17 00:00:00 2001 From: frheault Date: Mon, 17 Aug 2026 13:27:25 -0400 Subject: [PATCH 3/5] Remove extra_fields_testing branch triggers from CI workflows --- .github/workflows/codeformat.yml | 2 +- .github/workflows/coverage.yml | 2 +- .github/workflows/docbuild.yml | 2 +- .github/workflows/publish-to-test-pypi.yml | 1 - .github/workflows/test.yml | 2 +- 5 files changed, 4 insertions(+), 5 deletions(-) diff --git a/.github/workflows/codeformat.yml b/.github/workflows/codeformat.yml index 6086d597..b9879d25 100644 --- a/.github/workflows/codeformat.yml +++ b/.github/workflows/codeformat.yml @@ -2,7 +2,7 @@ name: Code Format on: push: - branches: [master, extra_fields_testing] + branches: [master] pull_request: branches: [master] diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml index b0873dfb..c06256ab 100644 --- a/.github/workflows/coverage.yml +++ b/.github/workflows/coverage.yml @@ -2,7 +2,7 @@ name: Coverage on: push: - branches: [master, extra_fields_testing] + branches: [master] pull_request: branches: [master] diff --git a/.github/workflows/docbuild.yml b/.github/workflows/docbuild.yml index 5eef5bfc..394250c0 100644 --- a/.github/workflows/docbuild.yml +++ b/.github/workflows/docbuild.yml @@ -2,7 +2,7 @@ name: Documentation build on: push: - branches: [ master, extra_fields_testing ] + branches: [ master ] tags: - '*' pull_request: diff --git a/.github/workflows/publish-to-test-pypi.yml b/.github/workflows/publish-to-test-pypi.yml index 2594e834..f2164e58 100644 --- a/.github/workflows/publish-to-test-pypi.yml +++ b/.github/workflows/publish-to-test-pypi.yml @@ -4,7 +4,6 @@ on: push: branches: - master - - extra_fields_testing tags: - "*" diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 16679ada..63c1e964 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -2,7 +2,7 @@ name: Tests on: push: - branches: [master, extra_fields_testing] + branches: [master] pull_request: branches: [master] From 364816a582465bd2c9f76fb85ee06e175f31138c Mon Sep 17 00:00:00 2001 From: frheault Date: Mon, 17 Aug 2026 13:37:25 -0400 Subject: [PATCH 4/5] forgot to run pre-commit --- trx/io.py | 4 +--- trx/tests/test_memmap.py | 1 - 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/trx/io.py b/trx/io.py index a2ee117e..1fdc787b 100644 --- a/trx/io.py +++ b/trx/io.py @@ -46,9 +46,7 @@ def get_trx_tmp_dir(): return tempfile.TemporaryDirectory(dir=trx_tmp_dir, prefix="trx_") -def load_sft_with_reference( - filepath, reference=None, bbox_check=True, from_space=None -): +def load_sft_with_reference(filepath, reference=None, bbox_check=True, from_space=None): """Load a tractogram as a StatefulTractogram with an explicit reference. Parameters diff --git a/trx/tests/test_memmap.py b/trx/tests/test_memmap.py index b6110266..2cc33d73 100644 --- a/trx/tests/test_memmap.py +++ b/trx/tests/test_memmap.py @@ -415,7 +415,6 @@ def test_save_after_select(): trx.close() - def test_trxfile_to_memory(): pass From 9c867adc17a65faa96cc684ba8df61c9d193783b Mon Sep 17 00:00:00 2001 From: frheault Date: Mon, 17 Aug 2026 13:43:36 -0400 Subject: [PATCH 5/5] Fix coverage? --- .github/workflows/coverage.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml index c06256ab..950eab3d 100644 --- a/.github/workflows/coverage.yml +++ b/.github/workflows/coverage.yml @@ -37,7 +37,7 @@ jobs: pytest trx/tests --cov=trx --cov-report=xml --cov-report=term-missing - name: Upload coverage to Codecov - uses: codecov/codecov-action@v4 + uses: codecov/codecov-action@v5 with: files: ./coverage.xml flags: unittests