Skip to content

Commit

Permalink
Merge pull request #700 from ANTsX/ants_image_import
Browse files Browse the repository at this point in the history
ENH: Add ants.ANTsImage back to namespace
  • Loading branch information
cookpa authored Aug 21, 2024
2 parents 5f550b8 + 16592be commit c311c08
Show file tree
Hide file tree
Showing 2 changed files with 31 additions and 29 deletions.
3 changes: 2 additions & 1 deletion ants/core/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@
from_numpy,
from_numpy_like,
new_image_like)
from .ants_image import (copy_image_info,
from .ants_image import (ANTsImage,
copy_image_info,
set_origin,
get_origin,
set_direction,
Expand Down
57 changes: 29 additions & 28 deletions ants/core/ants_image.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@


__all__ = ['copy_image_info',
__all__ = ['ANTsImage',
'copy_image_info',
'set_origin',
'get_origin',
'set_direction',
Expand Down Expand Up @@ -40,7 +41,7 @@ class ANTsImage(object):
def __init__(self, pointer):
"""
Initialize an ANTsImage.
Creating an ANTsImage requires a pointer to an underlying ITK image that
is stored via a nanobind class wrapping a AntsImage struct.
Expand All @@ -57,31 +58,31 @@ def __init__(self, pointer):
@property
def _libsuffix(self):
return str(type(self.pointer)).split('AntsImage')[-1].split("'")[0]

@property
def shape(self):
return tuple(get_lib_fn('getShape')(self.pointer))

@property
def physical_shape(self):
return tuple([round(sh*sp,3) for sh,sp in zip(self.shape, self.spacing)])

@property
def is_rgb(self):
return 'RGB' in self._libsuffix

@property
def has_components(self):
suffix = self._libsuffix
return suffix.startswith('V') or suffix.startswith('RGB')

@property
def components(self):
if not self.has_components:
return 1

return get_lib_fn('getComponents')(self.pointer)

@property
def pixeltype(self):
ptype = self._libsuffix[:-1]
Expand All @@ -90,17 +91,17 @@ def pixeltype(self):
ptype = ptype[3:]
else:
ptype = ptype[1:]

ptype_map = {'UC': 'unsigned char',
'UI': 'unsigned int',
'F': 'float',
'D': 'double'}
return ptype_map[ptype]

@property
def dtype(self):
return _itk_to_npy_map[self.pixeltype]

@property
def dimension(self):
return int(self._libsuffix[-1])
Expand Down Expand Up @@ -369,9 +370,9 @@ def __add__(self, other):

new_array = this_array + other
return self.new_image_like(new_array)

__radd__ = __add__

def __sub__(self, other):
this_array = self.numpy()

Expand All @@ -382,7 +383,7 @@ def __sub__(self, other):

new_array = this_array - other
return self.new_image_like(new_array)

def __rsub__(self, other):
this_array = self.numpy()

Expand All @@ -393,7 +394,7 @@ def __rsub__(self, other):

new_array = other - this_array
return self.new_image_like(new_array)

def __mul__(self, other):
this_array = self.numpy()

Expand Down Expand Up @@ -500,16 +501,16 @@ def __getitem__(self, idx):
return ants.merge_channels([
img[idx] for img in ants.split_channels(self)
])

if isinstance(idx, ANTsImage):
if not ants.image_physical_space_consistency(self, idx):
raise ValueError('images do not occupy same physical space')
return self.numpy().__getitem__(idx.numpy().astype('bool'))

ndim = len(idx)
sizes = list(self.shape)
starts = [0] * ndim

for i in range(ndim):
ti = idx[i]
if isinstance(ti, slice):
Expand All @@ -519,32 +520,32 @@ def __getitem__(self, idx):
sizes[i] = ti.stop - starts[i]
else:
sizes[i] = self.shape[i] - starts[i]

if ti.stop and ti.start:
if ti.stop < ti.start:
raise Exception('Reverse indexing is not supported.')

elif isinstance(ti, int):
starts[i] = ti
sizes[i] = 0

if sizes[i] == 0:
ndim -= 1

if ndim < 2:
return self.numpy().__getitem__(idx)

libfn = get_lib_fn('getItem%i' % ndim)
new_ptr = libfn(self.pointer, starts, sizes)
new_image = from_pointer(new_ptr)
return new_image

def __setitem__(self, idx, value):
arr = self.view()

if is_image(value):
value = value.numpy()

if is_image(idx):
if not ants.image_physical_space_consistency(self, idx):
raise ValueError('images do not occupy same physical space')
Expand All @@ -565,7 +566,7 @@ def __repr__(self):
'\t {:<10} : {}\n'.format('Origin', tuple([round(o,4) for o in self.origin]))+\
'\t {:<10} : {}\n'.format('Direction', np.round(self.direction.flatten(),4))
return s

def __getstate__(self):
"""
import ants
Expand All @@ -580,7 +581,7 @@ def __getstate__(self):
print(img.mean(), img3.mean())
"""
return self.numpy(), self.origin, self.spacing, self.direction, self.has_components, self.is_rgb

def __setstate__(self, state):
data, origin, spacing, direction, has_components, is_rgb = state
image = ants.from_numpy(np.copy(data), origin=origin, spacing=spacing, direction=direction, has_components=has_components, is_rgb=is_rgb)
Expand Down

0 comments on commit c311c08

Please sign in to comment.