Skip to content

Commit 2876825

Browse files
authored
Add To transform (#1345)
1 parent c95fa1b commit 2876825

5 files changed

Lines changed: 82 additions & 8 deletions

File tree

docs/source/transforms/preprocessing.rst

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,13 @@ Intensity
4646
:show-inheritance:
4747

4848

49+
:class:`To`
50+
~~~~~~~~~~~
51+
52+
.. autoclass:: To
53+
:show-inheritance:
54+
55+
4956
.. currentmodule:: torchio.transforms.preprocessing.intensity
5057

5158

@@ -56,23 +63,20 @@ Intensity
5663
:show-inheritance:
5764

5865

59-
60-
61-
6266
Spatial
6367
-------
6468

6569
.. currentmodule:: torchio.transforms
6670

6771
:class:`CropOrPad`
68-
~~~~~~~~~~~~~~~~~~~~~~~~
72+
~~~~~~~~~~~~~~~~~~
6973

7074
.. autoclass:: CropOrPad
7175
:show-inheritance:
7276
:members: _get_six_bounds_parameters
7377

7478
:class:`ToOrientation`
75-
~~~~~~~~~~~~~~~~~~~~~~~~~
79+
~~~~~~~~~~~~~~~~~~~~~~
7680

7781
.. autoclass:: ToOrientation
7882
:show-inheritance:
@@ -106,7 +110,7 @@ Spatial
106110

107111

108112
:class:`CopyAffine`
109-
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
113+
~~~~~~~~~~~~~~~~~~~
110114

111115
.. autoclass:: CopyAffine
112116
:show-inheritance:
@@ -131,14 +135,14 @@ Label
131135

132136

133137
:class:`RemapLabels`
134-
~~~~~~~~~~~~~~~~~~~~~~~~~
138+
~~~~~~~~~~~~~~~~~~~~
135139

136140
.. autoclass:: RemapLabels
137141
:show-inheritance:
138142

139143

140144
:class:`RemoveLabels`
141-
~~~~~~~~~~~~~~~~~~~~~~~~~
145+
~~~~~~~~~~~~~~~~~~~~~
142146

143147
.. autoclass:: RemoveLabels
144148
:show-inheritance:

src/torchio/transforms/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@
5353
from .preprocessing import RescaleIntensity
5454
from .preprocessing import Resize
5555
from .preprocessing import SequentialLabels
56+
from .preprocessing import To
5657
from .preprocessing import ToCanonical
5758
from .preprocessing import ToOrientation
5859
from .preprocessing import ZNormalization
@@ -101,6 +102,7 @@
101102
'Crop',
102103
'Resize',
103104
'Resample',
105+
'To',
104106
'ToCanonical',
105107
'ToOrientation',
106108
'ZNormalization',

src/torchio/transforms/preprocessing/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
from .intensity.histogram_standardization import HistogramStandardization
33
from .intensity.mask import Mask
44
from .intensity.rescale import RescaleIntensity
5+
from .intensity.to import To
56
from .intensity.z_normalization import ZNormalization
67
from .label.contour import Contour
78
from .label.keep_largest_component import KeepLargestComponent
@@ -31,6 +32,7 @@
3132
'EnsureShapeMultiple',
3233
'Mask',
3334
'RescaleIntensity',
35+
'To',
3436
'Clamp',
3537
'ZNormalization',
3638
'HistogramStandardization',
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
from __future__ import annotations
2+
3+
from typing import Any
4+
5+
import torch
6+
7+
from ....data.image import ScalarImage
8+
from ....data.subject import Subject
9+
from ...intensity_transform import IntensityTransform
10+
11+
12+
class To(IntensityTransform):
13+
"""Convert the image tensor data type and/or device.
14+
15+
This transform is a thin wrapper around :func:`torch.Tensor.to`.
16+
17+
Args:
18+
target: First argument to :func:`torch.Tensor.to`.
19+
to_kwargs: Additional keyword arguments to pass to :func:`torch.Tensor.to`.
20+
21+
Example:
22+
>>> import torchio as tio
23+
>>> ct = tio.datasets.Slicer('CTChest').CT_chest
24+
>>> clamp = tio.Clamp(out_min=-1000, out_max=1000)
25+
>>> ct_clamped = clamp(ct)
26+
>>> rescale = tio.RescaleIntensity(in_min_max=(-1000, 1000), out_min_max=(0, 255))
27+
>>> ct_rescaled = rescale(ct_clamped)
28+
>>> to_uint8 = tio.To(torch.uint8)
29+
>>> ct_uint8 = to_uint8(ct_rescaled)
30+
"""
31+
32+
def __init__(
33+
self,
34+
target: str | torch.dtype | torch.device,
35+
to_kwargs: dict[str, Any] | None = None,
36+
**kwargs,
37+
):
38+
super().__init__(**kwargs)
39+
self.target = target
40+
if to_kwargs is None:
41+
to_kwargs = {}
42+
self.to_kwargs = to_kwargs
43+
self.args_names = ['target', 'to_kwargs']
44+
45+
def apply_transform(self, subject: Subject) -> Subject:
46+
for image in self.get_images(subject):
47+
assert isinstance(image, ScalarImage)
48+
image.set_data(image.data.to(self.target, **self.to_kwargs))
49+
return subject
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import torch
2+
3+
import torchio as tio
4+
5+
from ...utils import TorchioTestCase
6+
7+
8+
class TestTo(TorchioTestCase):
9+
"""Tests for :class:`tio.To` class."""
10+
11+
def test_to(self):
12+
transform = tio.To(torch.int)
13+
tensor = 10 * torch.rand(2, 3, 4, 5)
14+
image = tio.ScalarImage(tensor=tensor)
15+
transformed = transform(image)
16+
assert image.data.dtype == torch.float32
17+
assert transformed.data.dtype == torch.int

0 commit comments

Comments
 (0)