diff --git a/docs/source/dev.md b/docs/source/dev.md index fe392f18..19153466 100644 --- a/docs/source/dev.md +++ b/docs/source/dev.md @@ -268,7 +268,6 @@ trx-python/ │ ├── streamlines_ops.py # Streamline operations │ ├── trx_file_memmap.py # Core TrxFile class │ ├── utils.py # Utility functions -│ ├── viz.py # Visualization (optional) │ ├── workflows.py # High-level workflows │ └── tests/ # Test suite ├── docs/ # Documentation diff --git a/trx/cli.py b/trx/cli.py index 4579543f..9ffade0d 100644 --- a/trx/cli.py +++ b/trx/cli.py @@ -19,7 +19,6 @@ generate_trx_from_scratch, manipulate_trx_datatype, tractogram_simple_compare, - tractogram_visualize_overlap, validate_tractogram, verify_header_compatibility, ) @@ -920,47 +919,6 @@ def verify_header( verify_header_compatibility([str(f) for f in in_files]) -@app.command("visualize") -def visualize( - in_tractogram: Annotated[ - Path, - typer.Argument(help="Input tractogram. Format: trk, tck, vtk, fib, dpy, trx."), - ], - reference: Annotated[ - Path, - typer.Argument(help="Reference anatomy (.nii or .nii.gz)."), - ], - remove_invalid: Annotated[ - bool, - typer.Option( - "--remove-invalid", - help="Remove invalid streamlines to avoid density_map crash.", - ), - ] = False, -) -> None: - """Display tractogram and density map with bounding box. - - Parameters - ---------- - in_tractogram : Path - Input tractogram (.trk, .tck, .vtk, .fib, .dpy, .trx). - reference : Path - Reference anatomy (.nii or .nii.gz). - remove_invalid : bool, optional - Remove invalid streamlines to avoid density map crashes. - - Returns - ------- - None - Opens visualization windows when fury is available. - """ - tractogram_visualize_overlap( - str(in_tractogram), - str(reference), - remove_invalid, - ) - - def _format_size(size_bytes: int) -> str: """Format byte size to human readable string. @@ -1150,12 +1108,6 @@ def _create_standalone_app(command_func, name: str, help_text: str): "Compare spatial attributes of input files.", ) -visualize_cmd = _create_standalone_app( - visualize, - "trx_visualize_overlap", - "Display tractogram and density map with bounding box.", -) - info_cmd = _create_standalone_app( info, "trx_info", diff --git a/trx/tests/test_cli.py b/trx/tests/test_cli.py index 35b78d39..71a70a54 100644 --- a/trx/tests/test_cli.py +++ b/trx/tests/test_cli.py @@ -90,10 +90,6 @@ def test_help_option_verify_header(self, script_runner): ret = script_runner.run(["trx_verify_header_compatibility", "--help"]) assert ret.success - def test_help_option_visualize(self, script_runner): - ret = script_runner.run(["trx_visualize_overlap", "--help"]) - assert ret.success - def test_help_option_info(self, script_runner): ret = script_runner.run(["trx_info", "--help"]) assert ret.success @@ -139,10 +135,6 @@ def test_trx_verify_header_help(self, script_runner): ret = script_runner.run(["trx", "verify-header", "--help"]) assert ret.success - def test_trx_visualize_help(self, script_runner): - ret = script_runner.run(["trx", "visualize", "--help"]) - assert ret.success - def test_trx_info_help(self, script_runner): ret = script_runner.run(["trx", "info", "--help"]) assert ret.success diff --git a/trx/workflows.py b/trx/workflows.py index 2efbd1f5..bdea9c72 100644 --- a/trx/workflows.py +++ b/trx/workflows.py @@ -9,7 +9,6 @@ import os import tempfile -import nibabel as nib from nibabel.streamlines.array_sequence import ArraySequence import numpy as np @@ -32,7 +31,6 @@ load_matrix_in_any_format, split_name_with_gz, ) -from trx.viz import display def convert_dsi_studio( @@ -273,81 +271,6 @@ def verify_header_compatibility(in_files): print("All input files have compatible headers.") -def tractogram_visualize_overlap(in_tractogram, reference, remove_invalid=True): - """Visualize overlap between tractogram density maps in different spaces. - - Parameters - ---------- - in_tractogram : str - Input tractogram path. - reference : str - Reference anatomy (.nii or .nii.gz). - remove_invalid : bool, optional - Remove streamlines outside bounding box before visualization. - - Returns - ------- - None - Opens interactive windows when fury is available. - """ - if not dipy_available: - logging.error("Dipy library is missing, scripts are not available.") - return None - from dipy.io.stateful_tractogram import StatefulTractogram - from dipy.tracking.streamline import set_number_of_points - from dipy.tracking.utils import density_map - - tractogram_obj = load(in_tractogram, reference) - if not isinstance(tractogram_obj, StatefulTractogram): - sft = tractogram_obj.to_sft() - tractogram_obj.close() - else: - sft = tractogram_obj - sft.streamlines._data = sft.streamlines._data.astype(float) - - sft.data_per_point = None - sft.streamlines = set_number_of_points(sft.streamlines, 200) - - if remove_invalid: - sft.remove_invalid_streamlines() - - # Approach (1) - density_1 = density_map(sft.streamlines, sft.affine, sft.dimensions) - img = nib.load(reference) - display( - img.get_fdata(), - volume_affine=img.affine, - streamlines=sft.streamlines, - title="RASMM", - ) - - # Approach (2) - sft.to_vox() - density_2 = density_map(sft.streamlines, np.eye(4), sft.dimensions) - - # Small difference due to casting of the affine as float32 or float64 - diff = density_1 - density_2 - print( - "Total difference of {} voxels with total value of {}".format( - np.count_nonzero(diff), np.sum(np.abs(diff)) - ) - ) - - display(img.get_fdata(), streamlines=sft.streamlines, title="VOX") - - # Try VOXMM - sft.to_voxmm() - affine = np.eye(4) - affine[0:3, 0:3] *= sft.voxel_sizes - - display( - img.get_fdata(), - volume_affine=affine, - streamlines=sft.streamlines, - title="VOXMM", - ) - - def validate_tractogram( in_tractogram, reference,