Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
252 changes: 154 additions & 98 deletions doc/06-Working-with-Images.ipynb

Large diffs are not rendered by default.

23 changes: 12 additions & 11 deletions src/imagej/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -419,7 +419,7 @@ def sync_image(self, imp: "jc.ImagePlus" = None):
pixels = imp.getProcessor().getPixels()
stack.setPixels(pixels, imp.getCurrentSlice())

def to_dataset(self, data):
def to_dataset(self, data, dim_order=None):
"""Convert the data into an ImageJ2 Dataset.

Converts a Python image (e.g. xarray or numpy array) or Java image (e.g.
Expand All @@ -428,7 +428,6 @@ def to_dataset(self, data):
:param data: Image object to be converted to Dataset.
:return: A net.imagej.Dataset.
"""
dim_order = None
if sj.isjava(data):
if dim_order:
_logger.warning(
Expand All @@ -447,7 +446,7 @@ def to_dataset(self, data):

raise TypeError(f"Type not supported: {type(data)}")

def to_img(self, data):
def to_img(self, data, dim_order=None):
"""Convert the data into an ImgLib2 Img.

Converts a Python image (e.g. xarray or numpy array) or Java image (e.g.
Expand All @@ -456,7 +455,6 @@ def to_img(self, data):
:param data: Image object to be converted to Img.
:return: A net.imglib2.img.Img.
"""
dim_order = None
if sj.isjava(data):
if dim_order:
_logger.warning(
Expand Down Expand Up @@ -500,7 +498,7 @@ def to_java(self, data, **hints):

return sj.to_java(data, **hints)

def to_xarray(self, data):
def to_xarray(self, data, dim_order=None):
"""Convert the data into an ImgLib2 Img.

Converts a Python image (e.g. xarray or numpy array) or Java image (e.g.
Expand All @@ -509,21 +507,24 @@ def to_xarray(self, data):
:param data: Image object to be converted to xarray.DataArray.
:return: An xarray.DataArray.
"""
dim_order = None
if sj.isjava(data):
if dim_order:
_logger.warning(f"Conversion hints are not supported for {type(data)}.")
if isinstance(data, jc.ImagePlus):
data = convert.imageplus_to_imgplus(self._ij, data)
if convert.supports_java_to_xarray(self._ij, data):
if dim_order:
_logger.warning(
f"Conversion hints are not supported for {type(data)}."
)
return convert.java_to_xarray(self._ij, data)
if convert.supports_java_to_ndarray(self._ij, data):
return convert.ndarray_to_xarray(
convert.java_to_ndarray(self._ij, data)
)

if images.is_xarraylike(data):
return convert._rename_xarray_dims(data, dim_order)
if images.is_arraylike(data):
return convert.ndarray_to_xarray(data, dim_order)

return TypeError(f"Type not supported: {type(data)}.")
raise TypeError(f"Type not supported: {type(data)}.")

# -- Deprecated methods --

Expand Down
8 changes: 2 additions & 6 deletions src/imagej/convert.py
Original file line number Diff line number Diff line change
Expand Up @@ -143,10 +143,7 @@ def ndarray_to_xarray(narr: np.ndarray, dim_order=None) -> xr.DataArray:
assert images.is_arraylike(narr)
if dim_order:
# check dim length
if narr.ndim != len(dim_order):
raise ValueError(
f"Expected {narr.ndim} dimensions but got {len(dim_order)}."
)
dim_order = dims._validate_dim_order(dim_order, narr.shape)
return xr.DataArray(narr, dims=dim_order)
return xr.DataArray(narr)

Expand Down Expand Up @@ -557,8 +554,7 @@ def _rename_xarray_dims(xarr, new_dims: Sequence[str]):
if not new_dims:
return xarr
# check dim length
if xarr.ndim != len(new_dims):
raise ValueError(f"Expected {xarr.ndim} dimensions but got {len(new_dims)}.")
new_dims = dims._validate_dim_order(new_dims, xarr.shape)
dim_map = {}
for i in range(xarr.ndim):
dim_map[curr_dims[i]] = new_dims[i]
Expand Down
29 changes: 28 additions & 1 deletion src/imagej/dims.py
Original file line number Diff line number Diff line change
Expand Up @@ -284,7 +284,13 @@ def _get_scale(axis):
:return: The scale for this axis or None if it is a non-numeric scale.
"""
try:
return axis.values[1] - axis.values[0]
# HACK: This axis length check is a work around for singleton dimensions.
# You can't calculate the slope of a singleton dimension.
# This section will be removed when axis-scale-logic is merged.
if len(axis) <= 1:
return 1
else:
return axis.values[1] - axis.values[0]
except TypeError:
return None

Expand Down Expand Up @@ -397,6 +403,27 @@ def _convert_dims(dimensions: List[str], direction: str) -> List[str]:
return dimensions


def _validate_dim_order(dim_order: List[str], shape: tuple) -> List[str]:
"""
Validate a List of dimensions. If the dimension list is smaller
fill the rest of the list with "dim_n" (following xarrray convention).

:param dim_order: List of dimensions (e.g. X, Y, Channel, Z, Time)
:param shape: Shape image for the dimension order.
:return: List with "dim_n" dimensions added to match shape length.
"""
dim_len = len(dim_order)
shape_len = len(shape)
if dim_len < shape_len:
d = shape_len - dim_len
for i in range(d):
dim_order.append(f"dim_{i}")
return dim_order
if dim_len > shape_len:
raise ValueError(f"Expected {shape_len} dimensions but got {dim_len}.")
return dim_order


def _has_axis(rai: "jc.RandomAccessibleInterval"):
"""Check if a RandomAccessibleInterval has axes."""
if sj.isjava(rai):
Expand Down
1 change: 0 additions & 1 deletion src/imagej/stack.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@ def rai_slice(rai, imin: Tuple, imax: Tuple, istep: Tuple):
dim_itr = range(len(shape))

for py_dim, j_dim in zip(dim_itr, dim_itr):

# Set minimum
if imin[py_dim] is None:
index = 0
Expand Down
Loading