diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 94a9d52b0..e1b518610 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -18,7 +18,7 @@ jobs: strategy: matrix: os: [ubuntu-latest, macos-latest, windows-latest] - python: ["3.9", "3.10", "3.11", "3.12", "3.13"] + python: ["3.10", "3.11", "3.12", "3.13"] fail-fast: false runs-on: ${{ matrix.os }} diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 341864924..e03a8c5f7 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -35,7 +35,7 @@ repos: rev: v3.20.0 hooks: - id: pyupgrade - args: ['--py39-plus'] + args: ['--py310-plus'] ci: autoupdate_commit_msg: Autoupdate pre-commit hooks diff --git a/docs/examples/plot_3d_to_2d.py b/docs/examples/plot_3d_to_2d.py index bd897e202..8d04ed25f 100644 --- a/docs/examples/plot_3d_to_2d.py +++ b/docs/examples/plot_3d_to_2d.py @@ -37,7 +37,7 @@ def plot_batch(sampler): batch = tio.utils.get_first_item(loader) _, axes = plt.subplots(4, 4, figsize=(12, 10)) - for ax, im in zip(axes.flatten(), batch['t1']['data']): + for ax, im in zip(axes.flatten(), batch['t1']['data'], strict=True): ax.imshow(im.squeeze(), cmap='gray') plt.suptitle(sampler.__class__.__name__) plt.tight_layout() diff --git a/justfile b/justfile index 90d3541c2..ccb3096b7 100644 --- a/justfile +++ b/justfile @@ -73,7 +73,7 @@ bump-python: ) pyproject_path.write_text(pyproject_text) -deprecate-python: +deprecate-python-in-files: #!/usr/bin/env -S uv run --script # /// script # dependencies = [ @@ -121,11 +121,15 @@ deprecate-python: ) tests_workflow_path.write_text(tests_workflow) +quality_cmd := "uv run --group quality" + +deprecate-python: deprecate-python-in-files + uv run pre-commit run --all-files pyupgrade + {{quality_cmd}} -- ruff check --fix src docs tests + push: git push && git push --tags -quality_cmd := "uv run --group quality" - types: {{quality_cmd}} -- tox -e types diff --git a/pyproject.toml b/pyproject.toml index 4bf247473..68c0357f8 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -19,7 +19,6 @@ classifiers = [ "Programming Language :: Python", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3 :: Only", - "Programming Language :: Python :: 3.9", "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.12", @@ -31,7 +30,7 @@ classifiers = [ "Typing :: Typed", ] keywords = ["medical", "image processing", "pytorch", "augmentation", "mri"] -requires-python = ">=3.9" +requires-python = ">=3.10" dependencies = [ "deprecated>=1.2", "einops>=0.3", diff --git a/src/torchio/data/dataset.py b/src/torchio/data/dataset.py index d7a8a4f8e..05744f5f9 100644 --- a/src/torchio/data/dataset.py +++ b/src/torchio/data/dataset.py @@ -1,9 +1,9 @@ from __future__ import annotations import copy +from collections.abc import Callable from collections.abc import Iterable from collections.abc import Sequence -from typing import Callable from torch.utils.data import Dataset diff --git a/src/torchio/data/image.py b/src/torchio/data/image.py index cba3850ca..d8f74c320 100644 --- a/src/torchio/data/image.py +++ b/src/torchio/data/image.py @@ -2,10 +2,10 @@ import warnings from collections import Counter +from collections.abc import Callable from collections.abc import Sequence from pathlib import Path from typing import Any -from typing import Callable import humanize import nibabel as nib @@ -424,7 +424,7 @@ def flip_axis(axis: str) -> str: labels = 'LRPAISTBDV' first = labels[::2] last = labels[1::2] - flip_dict = dict(zip(first + last, last + first)) + flip_dict = dict(zip(first + last, last + first, strict=True)) axis = axis[0].upper() flipped_axis = flip_dict.get(axis) if flipped_axis is None: diff --git a/src/torchio/data/inference/aggregator.py b/src/torchio/data/inference/aggregator.py index c6d5961be..69bf84bbd 100644 --- a/src/torchio/data/inference/aggregator.py +++ b/src/torchio/data/inference/aggregator.py @@ -163,7 +163,7 @@ def add_batch( self._initialize_output_tensor(batch) assert isinstance(self._output_tensor, torch.Tensor) if self.overlap_mode == 'crop': - for patch, location in zip(batch, locations_array): + for patch, location in zip(batch, locations_array, strict=True): cropped_patch, new_location = self._crop_patch( patch, location, @@ -179,7 +179,7 @@ def add_batch( elif self.overlap_mode == 'average': self._initialize_avgmask_tensor(batch) assert isinstance(self._avgmask_tensor, torch.Tensor) - for patch, location in zip(batch, locations): + for patch, location in zip(batch, locations, strict=True): i_ini, j_ini, k_ini, i_fin, j_fin, k_fin = location self._output_tensor[ :, @@ -210,7 +210,7 @@ def add_batch( if self._avgmask_tensor.dtype != torch.float32: self._avgmask_tensor = self._avgmask_tensor.float() - for patch, location in zip(batch, locations): + for patch, location in zip(batch, locations, strict=True): i_ini, j_ini, k_ini, i_fin, j_fin, k_fin = location patch = patch * self._hann_window diff --git a/src/torchio/data/loader.py b/src/torchio/data/loader.py index 60db2866b..7c69af695 100644 --- a/src/torchio/data/loader.py +++ b/src/torchio/data/loader.py @@ -1,7 +1,7 @@ from __future__ import annotations +from collections.abc import Callable from typing import Any -from typing import Callable from typing import TypeVar import numpy as np diff --git a/src/torchio/data/sampler/grid.py b/src/torchio/data/sampler/grid.py index 312a91eb2..41e31b964 100644 --- a/src/torchio/data/sampler/grid.py +++ b/src/torchio/data/sampler/grid.py @@ -159,7 +159,7 @@ def _get_patches_locations( # [3, 8], # [5, 10]] indices = [] - zipped = zip(image_size, patch_size, patch_overlap) + zipped = zip(image_size, patch_size, patch_overlap, strict=True) for im_size_dim, patch_size_dim, patch_overlap_dim in zipped: end = im_size_dim + 1 - patch_size_dim step = patch_size_dim - patch_overlap_dim diff --git a/src/torchio/data/sampler/label.py b/src/torchio/data/sampler/label.py index a5cfd698f..f40452837 100644 --- a/src/torchio/data/sampler/label.py +++ b/src/torchio/data/sampler/label.py @@ -124,7 +124,7 @@ def get_probabilities_from_label_map( probability_map = torch.zeros_like(label_map) label_probs = torch.Tensor(list(label_probabilities_dict.values())) normalized_probs = label_probs / label_probs.sum() - iterable = zip(label_probabilities_dict, normalized_probs) + iterable = zip(label_probabilities_dict, normalized_probs, strict=True) for label, label_probability in iterable: if multichannel: mask = label_map[label] diff --git a/src/torchio/data/sampler/sampler.py b/src/torchio/data/sampler/sampler.py index 16d82da88..8625c0a67 100644 --- a/src/torchio/data/sampler/sampler.py +++ b/src/torchio/data/sampler/sampler.py @@ -77,7 +77,7 @@ def _get_crop_transform( crop_ini = index_ini_array.tolist() crop_fin = (shape - index_fin).tolist() start = () - cropping = sum(zip(crop_ini, crop_fin), start) # type: ignore[arg-type] + cropping = sum(zip(crop_ini, crop_fin, strict=True), start) # type: ignore[arg-type] return Crop(cropping) # type: ignore[arg-type] def __call__( diff --git a/src/torchio/datasets/ixi.py b/src/torchio/datasets/ixi.py index a6186da4d..ad67222d3 100644 --- a/src/torchio/datasets/ixi.py +++ b/src/torchio/datasets/ixi.py @@ -205,7 +205,7 @@ def _get_subjects_list(root): raise FileNotFoundError(message) subjects = [] - for image_path, label_path in zip(image_paths, label_paths): + for image_path, label_path in zip(image_paths, label_paths, strict=True): subject_id = get_subject_id(image_path) subject_dict = {} subject_dict['image'] = ScalarImage(image_path) diff --git a/src/torchio/datasets/medmnist.py b/src/torchio/datasets/medmnist.py index bad491ffd..61fd7ce06 100644 --- a/src/torchio/datasets/medmnist.py +++ b/src/torchio/datasets/medmnist.py @@ -42,7 +42,7 @@ def __init__(self, split, **kwargs): images = npz_file[f'{split}_images'] labels = npz_file[f'{split}_labels'] subjects = [] - for image, label in zip(images, labels): + for image, label in zip(images, labels, strict=True): image = ScalarImage(tensor=image[np.newaxis]) subject = Subject(image=image, labels=torch.from_numpy(label)) subjects.append(subject) diff --git a/src/torchio/datasets/slicer.py b/src/torchio/datasets/slicer.py index d3c94eb43..7b595f1d5 100644 --- a/src/torchio/datasets/slicer.py +++ b/src/torchio/datasets/slicer.py @@ -55,7 +55,7 @@ def __init__(self, name='MRHead'): except KeyError as e: message = f'Invalid name "{name}". Valid names are: {", ".join(URLS_DICT)}' raise ValueError(message) from e - for filename, url_file in zip(filenames, url_files): + for filename, url_file in zip(filenames, url_files, strict=True): filename = filename.replace('-', '_') url = urllib.parse.urljoin(SLICER_URL, url_file) download_root = get_torchio_cache_dir() / 'slicer' diff --git a/src/torchio/transforms/augmentation/intensity/random_bias_field.py b/src/torchio/transforms/augmentation/intensity/random_bias_field.py index 25c83e928..47e3ce0c2 100644 --- a/src/torchio/transforms/augmentation/intensity/random_bias_field.py +++ b/src/torchio/transforms/augmentation/intensity/random_bias_field.py @@ -1,5 +1,4 @@ from collections import defaultdict -from typing import Union import numpy as np import torch @@ -36,7 +35,7 @@ class RandomBiasField(RandomTransform, IntensityTransform): def __init__( self, - coefficients: Union[float, tuple[float, float]] = 0.5, + coefficients: float | tuple[float, float] = 0.5, order: int = 3, **kwargs, ): @@ -89,8 +88,8 @@ class BiasField(IntensityTransform): def __init__( self, - coefficients: Union[list[float], dict[str, list[float]]], - order: Union[int, dict[str, int]], + coefficients: list[float] | dict[str, list[float]], + order: int | dict[str, int], **kwargs, ): super().__init__(**kwargs) diff --git a/src/torchio/transforms/augmentation/intensity/random_blur.py b/src/torchio/transforms/augmentation/intensity/random_blur.py index 940513460..506e99339 100644 --- a/src/torchio/transforms/augmentation/intensity/random_blur.py +++ b/src/torchio/transforms/augmentation/intensity/random_blur.py @@ -1,5 +1,4 @@ from collections import defaultdict -from typing import Union import numpy as np import scipy.ndimage as ndi @@ -32,7 +31,7 @@ class RandomBlur(RandomTransform, IntensityTransform): keyword arguments. """ - def __init__(self, std: Union[float, tuple[float, float]] = (0, 2), **kwargs): + def __init__(self, std: float | tuple[float, float] = (0, 2), **kwargs): super().__init__(**kwargs) self.std_ranges = self.parse_params(std, None, 'std', min_constraint=0) @@ -68,7 +67,7 @@ class Blur(IntensityTransform): def __init__( self, - std: Union[TypeTripletFloat, dict[str, TypeTripletFloat]], + std: TypeTripletFloat | dict[str, TypeTripletFloat], **kwargs, ): super().__init__(**kwargs) @@ -85,7 +84,7 @@ def apply_transform(self, subject: Subject) -> Subject: stds_channels: np.ndarray stds_channels = np.tile(stds, repets) # type: ignore[arg-type] transformed_tensors = [] - for std, channel in zip(stds_channels, image.data): + for std, channel in zip(stds_channels, image.data, strict=True): transformed_tensor = blur( channel, image.spacing, diff --git a/src/torchio/transforms/augmentation/intensity/random_gamma.py b/src/torchio/transforms/augmentation/intensity/random_gamma.py index b62ddb356..c825cb63e 100644 --- a/src/torchio/transforms/augmentation/intensity/random_gamma.py +++ b/src/torchio/transforms/augmentation/intensity/random_gamma.py @@ -134,7 +134,7 @@ def apply_transform(self, subject: Subject) -> Subject: gammas = to_tuple(gamma, length=len(image.data)) transformed_tensors = [] image.set_data(image.data.float()) - for gamma, tensor in zip(gammas, image.data): + for gamma, tensor in zip(gammas, image.data, strict=True): if self.invert_transform: correction = power(tensor, 1 - gamma) transformed_tensor = tensor * correction diff --git a/src/torchio/transforms/augmentation/intensity/random_motion.py b/src/torchio/transforms/augmentation/intensity/random_motion.py index 33b12dcee..579b9f7e6 100644 --- a/src/torchio/transforms/augmentation/intensity/random_motion.py +++ b/src/torchio/transforms/augmentation/intensity/random_motion.py @@ -1,6 +1,5 @@ from collections import defaultdict from collections.abc import Sequence -from typing import Union import numpy as np import SimpleITK as sitk @@ -49,8 +48,8 @@ class RandomMotion(RandomTransform, IntensityTransform, FourierTransform): def __init__( self, - degrees: Union[float, tuple[float, float]] = 10, - translation: Union[float, tuple[float, float]] = 10, # in mm + degrees: float | tuple[float, float] = 10, + translation: float | tuple[float, float] = 10, # in mm num_transforms: int = 2, image_interpolation: str = 'linear', **kwargs, @@ -145,10 +144,10 @@ class Motion(IntensityTransform, FourierTransform): def __init__( self, - degrees: Union[TypeTripletFloat, dict[str, TypeTripletFloat]], - translation: Union[TypeTripletFloat, dict[str, TypeTripletFloat]], - times: Union[Sequence[float], dict[str, Sequence[float]]], - image_interpolation: Union[Sequence[str], dict[str, Sequence[str]]], + degrees: TypeTripletFloat | dict[str, TypeTripletFloat], + translation: TypeTripletFloat | dict[str, TypeTripletFloat], + times: Sequence[float] | dict[str, Sequence[float]], + image_interpolation: Sequence[str] | dict[str, Sequence[str]], **kwargs, ): super().__init__(**kwargs) @@ -212,7 +211,8 @@ def get_rigid_transforms( center_lps = image.TransformContinuousIndexToPhysicalPoint(center_ijk) identity = np.eye(4) matrices = [identity] - for degrees, translation in zip(degrees_params, translation_params): + zipped = zip(degrees_params, translation_params, strict=True) + for degrees, translation in zipped: radians = np.radians(degrees).tolist() motion = sitk.Euler3DTransform() motion.SetCenter(center_lps) @@ -291,7 +291,7 @@ def add_artifact( indices: list[int] = indices_array.tolist() # type: ignore[assignment] indices.append(last_index) ini = 0 - for spectrum, fin in zip(spectra, indices): + for spectrum, fin in zip(spectra, indices, strict=True): result_spectrum[..., ini:fin] = spectrum[..., ini:fin] ini = fin result_image = self.inv_fourier_transform(result_spectrum).real.float() diff --git a/src/torchio/transforms/augmentation/intensity/random_noise.py b/src/torchio/transforms/augmentation/intensity/random_noise.py index f14c0d1f5..5047cd952 100644 --- a/src/torchio/transforms/augmentation/intensity/random_noise.py +++ b/src/torchio/transforms/augmentation/intensity/random_noise.py @@ -1,6 +1,5 @@ from collections import defaultdict from collections.abc import Sequence -from typing import Union import torch @@ -33,8 +32,8 @@ class RandomNoise(RandomTransform, IntensityTransform): def __init__( self, - mean: Union[float, tuple[float, float]] = 0, - std: Union[float, tuple[float, float]] = (0, 0.25), + mean: float | tuple[float, float] = 0, + std: float | tuple[float, float] = (0, 0.25), **kwargs, ): super().__init__(**kwargs) @@ -85,9 +84,9 @@ class Noise(IntensityTransform): def __init__( self, - mean: Union[float, dict[str, float]], - std: Union[float, dict[str, float]], - seed: Union[int, Sequence[int]], + mean: float | dict[str, float], + std: float | dict[str, float], + seed: int | Sequence[int], **kwargs, ): super().__init__(**kwargs) diff --git a/src/torchio/transforms/augmentation/intensity/random_spike.py b/src/torchio/transforms/augmentation/intensity/random_spike.py index c20e1fcb7..982a0bd78 100644 --- a/src/torchio/transforms/augmentation/intensity/random_spike.py +++ b/src/torchio/transforms/augmentation/intensity/random_spike.py @@ -1,6 +1,5 @@ from collections import defaultdict from numbers import Number -from typing import Union import numpy as np import torch @@ -42,8 +41,8 @@ class RandomSpike(RandomTransform, IntensityTransform, FourierTransform): def __init__( self, - num_spikes: Union[int, tuple[int, int]] = 1, - intensity: Union[float, tuple[float, float]] = (1, 3), + num_spikes: int | tuple[int, int] = 1, + intensity: float | tuple[float, float] = (1, 3), **kwargs, ): super().__init__(**kwargs) @@ -109,8 +108,8 @@ class Spike(IntensityTransform, FourierTransform): def __init__( self, - spikes_positions: Union[np.ndarray, dict[str, np.ndarray]], - intensity: Union[float, dict[str, float]], + spikes_positions: np.ndarray | dict[str, np.ndarray], + intensity: float | dict[str, float], **kwargs, ): super().__init__(**kwargs) diff --git a/src/torchio/transforms/augmentation/random_transform.py b/src/torchio/transforms/augmentation/random_transform.py index e6137beb6..0cbfdc246 100644 --- a/src/torchio/transforms/augmentation/random_transform.py +++ b/src/torchio/transforms/augmentation/random_transform.py @@ -47,7 +47,7 @@ def _get_random_seed() -> int: @staticmethod def sample_uniform_sextet(params: TypeSextetFloat) -> TypeTripletFloat: results = [] - for a, b in zip(params[::2], params[1::2]): + for a, b in zip(params[::2], params[1::2], strict=True): results.append(RandomTransform.sample_uniform(a, b)) sx, sy, sz = results return sx, sy, sz diff --git a/src/torchio/transforms/augmentation/spatial/random_anisotropy.py b/src/torchio/transforms/augmentation/spatial/random_anisotropy.py index e1d2c8e74..324ce3f41 100644 --- a/src/torchio/transforms/augmentation/spatial/random_anisotropy.py +++ b/src/torchio/transforms/augmentation/spatial/random_anisotropy.py @@ -1,5 +1,4 @@ import warnings -from typing import Union import torch @@ -47,7 +46,7 @@ class RandomAnisotropy(RandomTransform): def __init__( self, - axes: Union[int, tuple[int, ...]] = (0, 1, 2), + axes: int | tuple[int, ...] = (0, 1, 2), downsampling: TypeRangeFloat = (1.5, 5), image_interpolation: str = 'linear', scalars_only: bool = True, @@ -74,7 +73,7 @@ def get_params( return axis, downsampling @staticmethod - def parse_axes(axes: Union[int, tuple[int, ...]]): + def parse_axes(axes: int | tuple[int, ...]): axes_tuple = to_tuple(axes) for axis in axes_tuple: is_int = isinstance(axis, int) diff --git a/src/torchio/transforms/augmentation/spatial/random_elastic_deformation.py b/src/torchio/transforms/augmentation/spatial/random_elastic_deformation.py index 2f221a85e..da2cb2943 100644 --- a/src/torchio/transforms/augmentation/spatial/random_elastic_deformation.py +++ b/src/torchio/transforms/augmentation/spatial/random_elastic_deformation.py @@ -1,6 +1,5 @@ import warnings from numbers import Number -from typing import Union import numpy as np import SimpleITK as sitk @@ -119,8 +118,8 @@ class RandomElasticDeformation(RandomTransform, SpatialTransform): def __init__( self, - num_control_points: Union[int, TypeTripletInt] = 7, - max_displacement: Union[float, TypeTripletFloat] = 7.5, + num_control_points: int | TypeTripletInt = 7, + max_displacement: float | TypeTripletFloat = 7.5, locked_borders: int = 2, image_interpolation: str = 'linear', label_interpolation: str = 'nearest', diff --git a/src/torchio/transforms/augmentation/spatial/random_flip.py b/src/torchio/transforms/augmentation/spatial/random_flip.py index dcfa08ad7..eb1546247 100644 --- a/src/torchio/transforms/augmentation/spatial/random_flip.py +++ b/src/torchio/transforms/augmentation/spatial/random_flip.py @@ -1,5 +1,3 @@ -from typing import Union - import numpy as np import torch @@ -38,7 +36,7 @@ class RandomFlip(RandomTransform, SpatialTransform): def __init__( self, - axes: Union[int, tuple[int, ...]] = 0, + axes: int | tuple[int, ...] = 0, flip_probability: float = 0.5, **kwargs, ): @@ -101,7 +99,7 @@ def inverse(self): return self -def _parse_axes(axes: Union[int, tuple[int, ...]]): +def _parse_axes(axes: int | tuple[int, ...]): axes_tuple = to_tuple(axes) for axis in axes_tuple: is_int = isinstance(axis, int) diff --git a/src/torchio/transforms/preprocessing/intensity/histogram_standardization.py b/src/torchio/transforms/preprocessing/intensity/histogram_standardization.py index 7741ff434..2749541b8 100644 --- a/src/torchio/transforms/preprocessing/intensity/histogram_standardization.py +++ b/src/torchio/transforms/preprocessing/intensity/histogram_standardization.py @@ -1,9 +1,9 @@ from __future__ import annotations +from collections.abc import Callable from collections.abc import Iterable from collections.abc import Sequence from pathlib import Path -from typing import Callable from typing import Union import numpy as np diff --git a/src/torchio/transforms/preprocessing/spatial/ensure_shape_multiple.py b/src/torchio/transforms/preprocessing/spatial/ensure_shape_multiple.py index b850c2f77..df151a31d 100644 --- a/src/torchio/transforms/preprocessing/spatial/ensure_shape_multiple.py +++ b/src/torchio/transforms/preprocessing/spatial/ensure_shape_multiple.py @@ -1,6 +1,6 @@ from __future__ import annotations -from typing import Callable +from collections.abc import Callable import numpy as np diff --git a/src/torchio/transforms/preprocessing/spatial/pad.py b/src/torchio/transforms/preprocessing/spatial/pad.py index 7b9db6d2c..70cf35d65 100644 --- a/src/torchio/transforms/preprocessing/spatial/pad.py +++ b/src/torchio/transforms/preprocessing/spatial/pad.py @@ -1,6 +1,5 @@ import warnings from numbers import Number -from typing import Union import numpy as np import torch @@ -61,7 +60,7 @@ class Pad(BoundsTransform): def __init__( self, padding: TypeBounds, - padding_mode: Union[str, float] = 0, + padding_mode: str | float = 0, **kwargs, ): super().__init__(padding, **kwargs) @@ -81,7 +80,7 @@ def check_padding_mode(cls, padding_mode): ) raise KeyError(message) - def _check_truncation(self, image: Image, mode: Union[str, float]) -> None: + def _check_truncation(self, image: Image, mode: str | float) -> None: if mode not in ('mean', 'median'): return if torch.is_floating_point(image.data): diff --git a/src/torchio/transforms/transform.py b/src/torchio/transforms/transform.py index 5c271c77e..93b4f8f76 100644 --- a/src/torchio/transforms/transform.py +++ b/src/torchio/transforms/transform.py @@ -266,7 +266,7 @@ def parse_params(self, params, around, name, make_ranges=True, **kwargs): f' 6, not {len(params)}' ) raise ValueError(message) - for param_range in zip(params[::2], params[1::2]): + for param_range in zip(params[::2], params[1::2], strict=True): self._parse_range(param_range, name, **kwargs) return tuple(params) diff --git a/src/torchio/types.py b/src/torchio/types.py index 4d7c5f9b9..4ce503997 100755 --- a/src/torchio/types.py +++ b/src/torchio/types.py @@ -1,8 +1,8 @@ from __future__ import annotations +from collections.abc import Callable from collections.abc import Sequence from pathlib import Path -from typing import Callable from typing import Optional from typing import Union diff --git a/src/torchio/utils.py b/src/torchio/utils.py index 1d40e9a3d..32c4fdfba 100644 --- a/src/torchio/utils.py +++ b/src/torchio/utils.py @@ -330,7 +330,7 @@ def add_images_from_batch( from . import ScalarImage class_ = ScalarImage - for subject, data in zip(subjects, tensor): + for subject, data in zip(subjects, tensor, strict=True): one_image = subject.get_first_image() kwargs = {'tensor': data, 'affine': one_image.affine} if 'filename' in one_image: diff --git a/src/torchio/visualization.py b/src/torchio/visualization.py index edfa356df..f177862a4 100644 --- a/src/torchio/visualization.py +++ b/src/torchio/visualization.py @@ -240,7 +240,7 @@ def plot_subject( xlabels=last_row, **plot_volume_kwargs, ) - for axis, axis_name in zip(image_axes, axes_names): + for axis, axis_name in zip(image_axes, axes_names, strict=True): axis.set_title(f'{name} ({axis_name})') plt.tight_layout() if output_path is not None: diff --git a/tests/data/inference/test_aggregator.py b/tests/data/inference/test_aggregator.py index 199879744..5220dd485 100644 --- a/tests/data/inference/test_aggregator.py +++ b/tests/data/inference/test_aggregator.py @@ -27,8 +27,10 @@ def aggregate(self, mode, fixture): (1, 1): 6, } for batch in loader: - iterable = zip(batch[tio.LOCATION], batch[image_name][tio.DATA]) - for location, data in iterable: + location = batch[tio.LOCATION] + data = batch[image_name][tio.DATA] + locations_and_channels = zip(location, data, strict=True) + for location, data in locations_and_channels: coords_2d = tuple(location[1:3].tolist()) data *= values_dict[coords_2d] batch_data = batch[image_name][tio.DATA] diff --git a/tests/transforms/preprocessing/test_crop_pad.py b/tests/transforms/preprocessing/test_crop_pad.py index cb9cadb36..81cc75b3b 100644 --- a/tests/transforms/preprocessing/test_crop_pad.py +++ b/tests/transforms/preprocessing/test_crop_pad.py @@ -128,7 +128,11 @@ def test_center_mask(self): mask[0, 4:6, 9:11, 14:16] = 1 transformed_center = transform_center(self.sample_subject) transformed_mask = transform_mask(self.sample_subject) - zipped = zip(transformed_center.values(), transformed_mask.values()) + zipped = zip( + transformed_center.values(), + transformed_mask.values(), + strict=True, + ) for image_center, image_mask in zipped: self.assert_tensor_equal( image_center.data, @@ -149,13 +153,17 @@ def test_mask_corners(self): target_shape, mask_name='label', ) - mask = self.sample_subject['label'].data + mask = self.sample_subject['label'][tio.DATA] mask *= 0 mask[0, 0, 0, 0] = 1 mask[0, -1, -1, -1] = 1 transformed_center = transform_center(self.sample_subject) transformed_mask = transform_mask(self.sample_subject) - zipped = zip(transformed_center.values(), transformed_mask.values()) + zipped = zip( + transformed_center.values(), + transformed_mask.values(), + strict=True, + ) for image_center, image_mask in zipped: self.assert_tensor_equal( image_center.data, @@ -221,7 +229,7 @@ def test_only_pad_true(self): target_shape = 9, 21, 30 orig_shape = self.sample_subject['t1'].spatial_shape expected_shape = tuple( - t if t > o else o for o, t in zip(orig_shape, target_shape) + t if t > o else o for o, t in zip(orig_shape, target_shape, strict=True) ) transform = tio.CropOrPad(target_shape, only_pad=True) transformed = transform(self.sample_subject) @@ -233,7 +241,7 @@ def test_only_crop_true(self): target_shape = 9, 21, 30 orig_shape = self.sample_subject['t1'].spatial_shape expected_shape = tuple( - t if t < o else o for o, t in zip(orig_shape, target_shape) + t if t < o else o for o, t in zip(orig_shape, target_shape, strict=True) ) transform = tio.CropOrPad(target_shape, only_crop=True) transformed = transform(self.sample_subject) diff --git a/tests/transforms/test_transforms.py b/tests/transforms/test_transforms.py index 4e078142e..be99c185d 100644 --- a/tests/transforms/test_transforms.py +++ b/tests/transforms/test_transforms.py @@ -305,7 +305,7 @@ def test_batch_history(self): inverse = transformed.apply_inverse_transform() images1 = subject.get_images(intensity_only=False) images2 = inverse.get_images(intensity_only=False) - for image1, image2 in zip(images1, images2): + for image1, image2 in zip(images1, images2, strict=True): assert image1.shape == image2.shape def test_bad_bounds_mask(self): diff --git a/tox.ini b/tox.ini index 678407946..54122daa9 100644 --- a/tox.ini +++ b/tox.ini @@ -24,13 +24,13 @@ commands = description = Run code linter skip_install = True deps = ruff -commands = ruff check +commands = ruff check src/ tests/ docs/ [testenv:format] description = Run code formatter skip_install = True deps = ruff -commands = ruff format --diff +commands = ruff format --diff src/ tests/ docs/ [testenv:types] dependency_groups =