Skip to content

Commit

Permalink
Add map/reduce methods to ImageStack (#1539)
Browse files Browse the repository at this point in the history
This is syntactic sugar to simplify single map / reduce operations.  Right now, we would need to instantiate the filter and then run it against the stack, e.g.,

```
max_projector = Filter.Reduce((Axes.CH, Axes.ROUND, Axes.ZPLANE))
max_projected = max_projector.run(stack)
```

With this, it simplifies to:

```
max_projected = stack.reduce((Axes.CH, Axes.ROUND, Axes.ZPLANE), "max")
```

Test plan: Converted imagestack/test/test_max_proj.py to use this idiom.
Depends on #1540
  • Loading branch information
Tony Tung authored Oct 10, 2019
1 parent c9957ea commit a958db6
Show file tree
Hide file tree
Showing 3 changed files with 54 additions and 7 deletions.
6 changes: 2 additions & 4 deletions starfish/core/image/Filter/reduce.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
cast,
Iterable,
MutableMapping,
Optional,
Sequence,
Union
)
Expand Down Expand Up @@ -97,7 +96,7 @@ def run(
self,
stack: ImageStack,
*args,
) -> Optional[ImageStack]:
) -> ImageStack:
"""Performs the dimension reduction with the specifed function
Parameters
Expand All @@ -108,8 +107,7 @@ def run(
Returns
-------
ImageStack :
If in-place is False, return the results of filter as a new stack. Otherwise return the
original stack.
Return the results of filter as a new stack.
"""

Expand Down
49 changes: 49 additions & 0 deletions starfish/core/imagestack/imagestack.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
Any,
Callable,
Hashable,
Iterable,
Iterator,
List,
Mapping,
Expand Down Expand Up @@ -50,6 +51,7 @@
Clip,
Coordinates,
CoordinateValue,
FunctionSource,
Number,
STARFISH_EXTRAS_KEY
)
Expand Down Expand Up @@ -1175,3 +1177,50 @@ def max_proj(self, *dims: Axes) -> "ImageStack":
def _squeezed_numpy(self, *dims: Axes):
"""return this ImageStack's data as a squeezed numpy array"""
return self.xarray.squeeze(tuple(dim.value for dim in dims)).values

def reduce(
self,
dims: Iterable[Union[Axes, str]],
func: str,
module: FunctionSource = FunctionSource.np,
clip_method: Clip = Clip.CLIP,
*args,
**kwargs) -> "ImageStack":
"""
Reduces the dimensionality of the ImageStack and returns a new ImageStack with the result.
This is a shortcut for :py:class:`starfish.image.Filter.Reduce`.
See Also
--------
starfish.image.Filter.Reduce
"""
from starfish.core.image import Filter

reducer = Filter.Reduce(dims, func, module, clip_method, **kwargs)
return reducer.run(self, *args)

def map(
self,
func: str,
module: FunctionSource = FunctionSource.np,
in_place: bool = False,
group_by: Optional[Set[Union[Axes, str]]] = None,
clip_method: Clip = Clip.CLIP,
*args,
**kwargs) -> Optional["ImageStack"]:
"""
Maps the contents of the ImageStack to produce another image. This can be done in-place or
can produce a new ImageStack. This is a shortcut for
:py:class:`starfish.image.Filter.Map`.
See Also
--------
starfish.image.Filter.Map
"""
from starfish.core.image import Filter

mapper = Filter.Map(
func, *args,
module=module, in_place=in_place, group_by=group_by, clip_method=clip_method,
**kwargs)
return mapper.run(self, *args)
6 changes: 3 additions & 3 deletions starfish/core/imagestack/test/test_max_proj.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ def test_max_projection_preserves_dtype():
array = np.ones((2, 2, 2), dtype=original_dtype)
image = ImageStack.from_numpy(array.reshape((1, 1, 2, 2, 2)))

max_projection = image.max_proj(Axes.CH, Axes.ROUND, Axes.ZPLANE)
max_projection = image.reduce((Axes.CH, Axes.ROUND, Axes.ZPLANE), "max")
assert max_projection.xarray.dtype == original_dtype


Expand All @@ -26,7 +26,7 @@ def test_max_projection_preserves_dtype():
def test_max_projection_preserves_coordinates():
e = data.ISS(use_test_data=True)
nuclei = e.fov().get_image('nuclei')
nuclei_proj = nuclei.max_proj(Axes.ROUND, Axes.CH, Axes.ZPLANE)
nuclei_proj = nuclei.reduce((Axes.CH, Axes.ROUND, Axes.ZPLANE), "max")
# Since this data already has only 1 round, 1 ch, 1 zplane
# let's just assert that the max_proj operation didn't change anything
assert nuclei.xarray.equals(nuclei_proj.xarray)
Expand All @@ -44,6 +44,6 @@ def test_max_projection_preserves_coordinates():

stack = imagestack_with_coords_factory(stack_shape, physical_coords)

stack_proj = stack.max_proj(Axes.ROUND, Axes.CH, Axes.ZPLANE)
stack_proj = stack.reduce((Axes.CH, Axes.ROUND, Axes.ZPLANE), "max")
expected_z = np.average(Z_COORDS)
verify_physical_coordinates(stack_proj, X_COORDS, Y_COORDS, expected_z)

0 comments on commit a958db6

Please sign in to comment.