Skip to content
Open
Show file tree
Hide file tree
Changes from 31 commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
3a30883
Add maximum operation in volume_math
CHrlS98 Jan 6, 2026
40bbc7a
Merge branch 'master' into volume-operation
CHrlS98 Jan 6, 2026
e83596a
Transfert functions for reorient
frheault Jan 6, 2026
c55dd1b
Add pathspec==0.12.* to dependencies
arnaudbore Jan 7, 2026
0588741
Update paper figures with better resolution
EmmaRenauld Jan 8, 2026
d2558c1
Merge branch 'master' into volume-operation
CHrlS98 Jan 8, 2026
b4555cc
Merge pull request #1296 from EmmaRenauld/update_figs
arnaudbore Jan 8, 2026
30304ea
Small fix in checking files in explore_bundleseg
EmmaRenauld Jan 8, 2026
5bcba00
Option -v did nothing in compute_density_map. Added loggings
EmmaRenauld Jan 8, 2026
ecc0388
Verify dir exists in bundleseg
EmmaRenauld Jan 8, 2026
f950a6f
Value args.tractogram_clustering_thr was never used in recobundles
EmmaRenauld Jan 8, 2026
c6a8a5e
Merge pull request #1293 from CHrlS98/volume-operation
arnaudbore Jan 8, 2026
ff44804
Merge pull request #1297 from EmmaRenauld/small_changes_from_my_tests
arnaudbore Jan 8, 2026
97b440b
Merge branch 'master' of https://github.com/scilus/scilpy into fix_in…
frheault Jan 14, 2026
60e5dbb
Conversion to to state class
frheault Jan 14, 2026
dc30357
New attribtutes
frheault Jan 14, 2026
d4485fe
Fix tests 3.12
frheault Jan 15, 2026
bda03f4
fix install and tests
arnaudbore Jan 15, 2026
0ba0902
Merge pull request #1299 from arnaudbore/fix_test_
arnaudbore Jan 16, 2026
c7c26d2
Merge branch 'master' of https://github.com/scilus/scilpy into fix_in…
frheault Jan 16, 2026
c260249
Added basic tests to verify SFI behaves normally
frheault Jan 16, 2026
efd61de
Improved tests
frheault Jan 16, 2026
7eb3311
Additionnal tests and flake8
frheault Jan 16, 2026
a23efeb
Update src/scilpy/io/tests/test_stateful_image.py
frheault Jan 17, 2026
9d420b9
Update src/scilpy/io/tests/test_stateful_image.py
frheault Jan 17, 2026
917901e
Copilot comments
frheault Jan 19, 2026
a6c4fae
Remove hasattr check
frheault Jan 22, 2026
26e4ff5
Incorporation to scripts
frheault Jan 25, 2026
cc1ff82
Fix conflict
frheault Jan 25, 2026
262c527
Fix conflict
frheault Jan 25, 2026
52d5617
allequal to allclose
frheault Jan 25, 2026
44e4d3a
New voxels order modification script
frheault Jan 27, 2026
efbd0a8
feat: Add 4D support for voxel order modification
frheault Jan 27, 2026
4cc1860
Fixes due to switch to static functions and changes apply_transform s…
frheault Jan 28, 2026
37ae49b
Last fixes for comments and full testing with Arnaud
frheault Jan 28, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .github/workflows/test-ml.yml
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,8 @@ jobs:
libfreetype6-dev \
libdrm-dev \
libgl1-mesa-dev \
libosmesa6-dev
libosmesa6-dev \
python3-dev \

- name: stdlib checkout
if: ${{ !contains(steps.python-selector.outputs.python-version, '3.12') }}
Expand Down
3 changes: 2 additions & 1 deletion .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,8 @@ jobs:
libfreetype6-dev \
libdrm-dev \
libgl1-mesa-dev \
libosmesa6-dev
libosmesa6-dev \
python3-dev \

- name: stdlib checkout
if: ${{ !contains(steps.python-selector.outputs.python-version, '3.12') }}
Expand Down
5 changes: 3 additions & 2 deletions .github/workflows/test_tutorials.yml
Original file line number Diff line number Diff line change
Expand Up @@ -50,8 +50,9 @@ jobs:
libfreetype6-dev \
libdrm-dev \
libgl1-mesa-dev \
libosmesa6-dev \
wget
libosmesa6-dev \
python3-dev \
wget

- name: stdlib checkout
if: ${{ !contains(steps.python-selector.outputs.python-version, '3.12') }}
Expand Down
Binary file modified docs/source/_static/images/scilpy_paper_figure1.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified docs/source/_static/images/scilpy_paper_figure2.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified docs/source/_static/images/scilpy_paper_figure3.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified docs/source/_static/images/scilpy_paper_figure4.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified docs/source/_static/images/scilpy_paper_figure5.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ dependencies = [
"numpy==1.26.*",
"openpyxl==3.1.*",
"packaging==24.*",
"pathspec==0.12.*",
"pybids==0.18.*",
"PyMCubes==0.1.*",
"pyparsing==3.2.*",
Expand Down
13 changes: 9 additions & 4 deletions src/scilpy/cli/scil_bundle_explore_bundleseg.py
Original file line number Diff line number Diff line change
Expand Up @@ -478,11 +478,16 @@ def main():
offset = 0
count = 0
for bundle in mapping.keys():
filename = glob.glob(f'{os.path.join(args.in_folder, bundle)}.t?k')[0]

if not os.path.exists(filename):
logging.warning(f'File {filename} not found.')
files = glob.glob(f'{os.path.join(args.in_folder, bundle)}.t?k')
if len(files) == 0:
logging.warning("Could not find any file fitting pattern {}"
.format(os.path.join(args.in_folder, bundle)))
continue
elif len(files) > 1:
logging.warning("Found two files for bundle {}. Selecting the "
"first one. Verify your files!".format(bundle))

filename = files[0]
count += 1

tmp_sft = load_tractogram(filename, ref_img)
Expand Down
2 changes: 2 additions & 0 deletions src/scilpy/cli/scil_tractogram_compute_density_map.py
Original file line number Diff line number Diff line change
Expand Up @@ -77,13 +77,15 @@ def main():
transformation, dimensions, _, _ = sft.space_attributes

# Processing
logging.info("Computing density map...")
if args.endpoints_only:
streamline_count = get_endpoints_density_map(sft)
else:
streamline_count = compute_tract_counts_map(sft.streamlines,
dimensions)

# Saving
logging.info("Saving density map {}".format(args.out_img))
dtype_to_use = np.int32
if args.binary is not None:
if args.binary == 1:
Expand Down
4 changes: 3 additions & 1 deletion src/scilpy/cli/scil_tractogram_segment_with_bundleseg.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,8 @@
add_reference_arg, add_verbose_arg,
assert_inputs_exist,
assert_output_dirs_exist_and_empty,
load_matrix_in_any_format, ranged_type)
load_matrix_in_any_format, ranged_type,
assert_inputs_dirs_exist)
from scilpy.segment.voting_scheme import VotingScheme
from scilpy.version import version_string

Expand Down Expand Up @@ -136,6 +137,7 @@ def main():
logging.getLogger().setLevel(logging.getLevelName('INFO'))

# Verifications
assert_inputs_dirs_exist(parser, args.in_directory)
in_models_directories = [
os.path.join(args.in_directory, x)
for x in os.listdir(args.in_directory)
Expand Down
4 changes: 2 additions & 2 deletions src/scilpy/cli/scil_tractogram_segment_with_recobundles.py
Original file line number Diff line number Diff line change
Expand Up @@ -112,8 +112,8 @@ def main():
if args.tractogram_clustering_thr and args.in_pickle:
parser.error("Option --tractogram_clustering_thr should not be "
"used with --in_pickle.")
else:
# Setting default value. (Will be ignored in args.in_pickle)
elif args.tractogram_clustering_thr is not None:
# Setting default value. (Will be ignored if args.in_pickle)
args.tractogram_clustering_thr = 8.0

# Loading
Expand Down
12 changes: 6 additions & 6 deletions src/scilpy/cli/scil_volume_crop.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@
import argparse
import logging

import nibabel as nib
import numpy as np

from scilpy.io.utils import (add_overwrite_arg,
Expand All @@ -32,6 +31,7 @@
from scilpy.image.utils import compute_nifti_bounding_box
from scilpy.image.volume_operations import crop_volume
from scilpy.version import version_string
from scilpy.io.stateful_image import StatefulImage


def _build_arg_parser():
Expand Down Expand Up @@ -73,23 +73,23 @@ def main():
assert_inputs_exist(parser, args.in_image, args.input_bbox)
assert_outputs_exist(parser, args, args.out_image, args.output_bbox)

img = nib.load(args.in_image)
simg = StatefulImage.load(args.in_image, to_orientation='RAS')
Copy link
Contributor

Choose a reason for hiding this comment

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

to_orientation='RAS' is your default value, so I would not add it (here and in other calls below)

if args.input_bbox:
wbbox = WorldBoundingBox.load(args.input_bbox,
args.use_deprecated_pickle)
if not args.ignore_voxel_size:
voxel_size = img.header.get_zooms()[0:3]
voxel_size = simg.header.get_zooms()[0:3]
if not np.allclose(voxel_size, wbbox.voxel_size[0:3], atol=1e-03):
raise IOError("Bounding box and data voxel sizes are not "
"compatible. Use option --ignore_voxel_size "
"to ignore this test.")
else:
wbbox = compute_nifti_bounding_box(img)
wbbox = compute_nifti_bounding_box(simg)
if args.output_bbox:
wbbox.dump(args.output_bbox, args.use_deprecated_pickle)

out_nifti_file = crop_volume(img, wbbox)
nib.save(out_nifti_file, args.out_image)
out_simg = crop_volume(simg, wbbox)
out_simg.save(args.out_image)


if __name__ == "__main__":
Expand Down
27 changes: 14 additions & 13 deletions src/scilpy/cli/scil_volume_resample.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
assert_inputs_exist, assert_outputs_exist)
from scilpy.image.volume_operations import resample_volume
from scilpy.version import version_string
from scilpy.io.stateful_image import StatefulImage


def _build_arg_parser():
Expand Down Expand Up @@ -95,39 +96,39 @@ def main():

logging.info('Loading raw data from %s', args.in_image)

img = nib.load(args.in_image)
simg = StatefulImage.load(args.in_image, to_orientation='RAS')

ref_img = None
if args.ref:
ref_img = nib.load(args.ref)

# Must not verify that headers are compatible. But can verify that, at
# least, the first columns of their affines are compatible.
img_zoom_invert = [1 / zoom for zoom in img.header.get_zooms()]
img_zoom_invert = [1 / zoom for zoom in simg.header.get_zooms()]
ref_zoom_invert = [1 / zoom for zoom in ref_img.header.get_zooms()]

img_affine = np.dot(img.affine[:3, :3], img_zoom_invert)
img_affine = np.dot(simg.affine[:3, :3], img_zoom_invert)
ref_affine = np.dot(ref_img.affine[:3, :3], ref_zoom_invert)

if not np.allclose(img_affine, ref_affine):
parser.error("The --ref image should have the same affine as the "
"input image (but with a different sampling).")

# Resampling volume
resampled_img = resample_volume(img, ref_img=ref_img,
volume_shape=args.volume_size,
iso_min=args.iso_min,
voxel_res=args.voxel_size,
interp=args.interp,
enforce_dimensions=args.enforce_dimensions)
resampled_simg = resample_volume(simg, ref_img=ref_img,
volume_shape=args.volume_size,
iso_min=args.iso_min,
voxel_res=args.voxel_size,
interp=args.interp,
enforce_dimensions=args.enforce_dimensions)

# Saving results
zooms = list(resampled_img.header.get_zooms())
zooms = list(resampled_simg.header.get_zooms())
if args.voxel_size:
if len(args.voxel_size) == 1:
args.voxel_size = args.voxel_size * 3

if not np.array_equal(zooms[:3], args.voxel_size):
if not np.allclose(zooms[:3], args.voxel_size, atol=1e-3):
logging.warning('Voxel size is different from expected.'
' Got: %s, expected: %s',
tuple(zooms), tuple(args.voxel_size))
Expand All @@ -137,10 +138,10 @@ def main():
zooms[0] = args.voxel_size[0]
zooms[1] = args.voxel_size[1]
zooms[2] = args.voxel_size[2]
resampled_img.header.set_zooms(tuple(zooms))
resampled_simg.header.set_zooms(tuple(zooms))

logging.info('Saving resampled data to %s', args.out_image)
nib.save(resampled_img, args.out_image)
resampled_simg.save(args.out_image)


if __name__ == '__main__':
Expand Down
13 changes: 7 additions & 6 deletions src/scilpy/cli/scil_volume_reshape.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
assert_inputs_exist, assert_outputs_exist)
from scilpy.image.volume_operations import reshape_volume
from scilpy.version import version_string
from scilpy.io.stateful_image import StatefulImage


def _build_arg_parser():
Expand Down Expand Up @@ -80,7 +81,7 @@ def main():

logging.info('Loading raw data from %s', args.in_image)

img = nib.load(args.in_image)
simg = StatefulImage.load(args.in_image, to_orientation='RAS')

ref_img = None
if args.ref:
Expand All @@ -93,14 +94,14 @@ def main():
volume_shape = args.volume_size

# Resampling volume
reshaped_img = reshape_volume(img, volume_shape,
mode=args.mode,
cval=args.constant_value,
dtype=args.data_type)
reshaped_simg = reshape_volume(simg, volume_shape,
mode=args.mode,
cval=args.constant_value,
dtype=args.data_type)

# Saving results
logging.info('Saving reshaped data to %s', args.out_image)
nib.save(reshaped_img, args.out_image)
reshaped_simg.save(args.out_image)


if __name__ == '__main__':
Expand Down
11 changes: 6 additions & 5 deletions src/scilpy/cli/scil_volume_reslice_to_reference.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
from scilpy.io.utils import (add_overwrite_arg, assert_inputs_exist,
add_verbose_arg, assert_outputs_exist)
from scilpy.version import version_string
from scilpy.io.stateful_image import StatefulImage


def _build_arg_parser():
Expand Down Expand Up @@ -63,14 +64,14 @@ def main():
assert_outputs_exist(parser, args, args.out_file)

# Load images.
in_file = nib.load(args.in_file)
simg = StatefulImage.load(args.in_file, to_orientation='RAS')
ref_file = nib.load(args.in_ref_file)

reshaped_img = apply_transform(np.eye(4), ref_file, in_file,
interp=args.interpolation,
keep_dtype=args.keep_dtype)
reshaped_simg = apply_transform(np.eye(4), ref_file, simg,
interp=args.interpolation,
keep_dtype=args.keep_dtype)

nib.save(reshaped_img, args.out_file)
reshaped_simg.save(args.out_file)


if __name__ == "__main__":
Expand Down
Loading
Loading