Skip to content

Commit

Permalink
Move preserve_float_range (#1041)
Browse files Browse the repository at this point in the history
  • Loading branch information
ambrosejcarr authored Mar 2, 2019
1 parent 35021df commit ae5311a
Show file tree
Hide file tree
Showing 22 changed files with 363 additions and 158 deletions.
3 changes: 2 additions & 1 deletion notebooks/MERFISH_Pipeline_-_U2O2_Cell_Culture_-_1_FOV.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,8 @@
"metadata": {},
"outputs": [],
"source": [
"dpsf = Filter.DeconvolvePSF(num_iter=15, sigma=2, clip=True)\n",
"from starfish.types import Clip\n",
"dpsf = Filter.DeconvolvePSF(num_iter=15, sigma=2, clip_method=Clip.SCALE_BY_CHUNK)\n",
"deconvolved = dpsf.run(high_passed, verbose=True, in_place=False)"
]
},
Expand Down
3 changes: 2 additions & 1 deletion notebooks/py/MERFISH_Pipeline_-_U2O2_Cell_Culture_-_1_FOV.py
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,8 @@
# EPY: END markdown

# EPY: START code
dpsf = Filter.DeconvolvePSF(num_iter=15, sigma=2, clip=True)
from starfish.types import Clip
dpsf = Filter.DeconvolvePSF(num_iter=15, sigma=2, clip_method=Clip.SCALE_BY_CHUNK)
deconvolved = dpsf.run(high_passed, verbose=True, in_place=False)
# EPY: END code

Expand Down
33 changes: 26 additions & 7 deletions starfish/image/_filter/bandpass.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,18 @@
from trackpy import bandpass

from starfish.imagestack.imagestack import ImageStack
from starfish.types import Number
from starfish.types import Clip, Number
from starfish.util import click
from ._base import FilterAlgorithmBase
from .util import determine_axes_to_group_by, preserve_float_range
from .util import determine_axes_to_group_by


class Bandpass(FilterAlgorithmBase):

def __init__(
self, lshort: Number, llong: int, threshold: Number=0, truncate: Number=4,
is_volume: bool=False) -> None:
self, lshort: Number, llong: int, threshold: Number=0, truncate: Number=4,
is_volume: bool=False, clip_method: Union[str, Clip]=Clip.CLIP
) -> None:
"""
Parameters
Expand All @@ -32,6 +33,15 @@ def __init__(
deviations (default 4)
is_volume : bool
If True, 3d (z, y, x) volumes will be filtered. By default, filter 2-d (y, x) planes
clip_method : Union[str, Clip]
(Default Clip.CLIP) Controls the way that data are scaled to retain skimage dtype
requirements that float data fall in [0, 1].
Clip.CLIP: data above 1 are set to 1, and below 0 are set to 0
Clip.SCALE_BY_IMAGE: data above 1 are scaled by the maximum value, with the maximum
value calculated over the entire ImageStack
Clip.SCALE_BY_CHUNK: data above 1 are scaled by the maximum value, with the maximum
value calculated over each slice, where slice shapes are determined by the group_by
parameters
"""
self.lshort = lshort
self.llong = llong
Expand All @@ -42,6 +52,7 @@ def __init__(
self.threshold = threshold
self.truncate = truncate
self.is_volume = is_volume
self.clip_method = clip_method

_DEFAULT_TESTING_PARAMETERS = {"lshort": 1, "llong": 3, "threshold": 0.01}

Expand Down Expand Up @@ -75,7 +86,7 @@ def _bandpass(
image, lshort=lshort, llong=llong, threshold=threshold,
truncate=truncate
)
return preserve_float_range(bandpassed)
return bandpassed

def run(
self, stack: ImageStack, in_place: bool = False, verbose: bool = False,
Expand Down Expand Up @@ -113,6 +124,7 @@ def run(
group_by=group_by,
in_place=in_place,
n_processes=n_processes,
clip_method=self.clip_method,
)
return result

Expand All @@ -127,6 +139,13 @@ def run(
@click.option(
"--truncate", default=4, type=float,
help="truncate the filter at this many standard deviations")
@click.option(
"--clip-method", default=Clip.CLIP, type=Clip,
help="method to constrain data to [0,1]. options: 'clip', 'scale_by_image', "
"'scale_by_chunk'")
@click.pass_context
def _cli(ctx, lshort, llong, threshold, truncate):
ctx.obj["component"]._cli_run(ctx, Bandpass(lshort, llong, threshold, truncate))
def _cli(ctx, lshort, llong, threshold, truncate, clip_method):
ctx.obj["component"]._cli_run(
ctx,
Bandpass(lshort, llong, threshold, truncate, clip_method)
)
29 changes: 22 additions & 7 deletions starfish/image/_filter/gaussian_high_pass.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,20 +6,21 @@

from starfish.image._filter.gaussian_low_pass import GaussianLowPass
from starfish.imagestack.imagestack import ImageStack
from starfish.types import Number
from starfish.types import Clip, Number
from starfish.util import click
from starfish.util.dtype import preserve_float_range
from ._base import FilterAlgorithmBase
from .util import (
determine_axes_to_group_by,
preserve_float_range,
validate_and_broadcast_kernel_size,
)


class GaussianHighPass(FilterAlgorithmBase):

def __init__(
self, sigma: Union[Number, Tuple[Number]], is_volume: bool=False,
self, sigma: Union[Number, Tuple[Number]], is_volume: bool=False,
clip_method: Union[str, Clip]=Clip.CLIP
) -> None:
"""Gaussian high pass filter
Expand All @@ -30,10 +31,19 @@ def __init__(
is_volume : bool
If True, 3d (z, y, x) volumes will be filtered, otherwise, filter 2d tiles
independently.
clip_method : Union[str, Clip]
(Default Clip.CLIP) Controls the way that data are scaled to retain skimage dtype
requirements that float data fall in [0, 1].
Clip.CLIP: data above 1 are set to 1, and below 0 are set to 0
Clip.SCALE_BY_IMAGE: data above 1 are scaled by the maximum value, with the maximum
value calculated over the entire ImageStack
Clip.SCALE_BY_CHUNK: data above 1 are scaled by the maximum value, with the maximum
value calculated over each slice, where slice shapes are determined by the group_by
parameters
"""
self.sigma = validate_and_broadcast_kernel_size(sigma, is_volume)
self.is_volume = is_volume
self.clip_method = clip_method

_DEFAULT_TESTING_PARAMETERS = {"sigma": 3}

Expand Down Expand Up @@ -95,7 +105,8 @@ def run(
high_pass: Callable = partial(self._high_pass, sigma=self.sigma)
result = stack.apply(
high_pass,
group_by=group_by, verbose=verbose, in_place=in_place, n_processes=n_processes
group_by=group_by, verbose=verbose, in_place=in_place, n_processes=n_processes,
clip_method=self.clip_method
)
return result

Expand All @@ -104,6 +115,10 @@ def run(
@click.option("--sigma", type=float, help="standard deviation of gaussian kernel")
@click.option("--is-volume", is_flag=True,
help="indicates that the image stack should be filtered in 3d")
@click.option(
"--clip-method", default=Clip.CLIP, type=Clip,
help="method to constrain data to [0,1]. options: 'clip', 'scale_by_image', "
"'scale_by_chunk'")
@click.pass_context
def _cli(ctx, sigma, is_volume):
ctx.obj["component"]._cli_run(ctx, GaussianHighPass(sigma, is_volume))
def _cli(ctx, sigma, is_volume, clip_method):
ctx.obj["component"]._cli_run(ctx, GaussianHighPass(sigma, is_volume, clip_method))
30 changes: 23 additions & 7 deletions starfish/image/_filter/gaussian_low_pass.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,20 +6,22 @@
from skimage.filters import gaussian

from starfish.imagestack.imagestack import ImageStack
from starfish.types import Number
from starfish.types import Clip, Number
from starfish.util import click
from starfish.util.dtype import preserve_float_range
from ._base import FilterAlgorithmBase
from .util import (
determine_axes_to_group_by,
preserve_float_range,
validate_and_broadcast_kernel_size,
)


class GaussianLowPass(FilterAlgorithmBase):

def __init__(
self, sigma: Union[Number, Tuple[Number]], is_volume: bool=False) -> None:
self, sigma: Union[Number, Tuple[Number]], is_volume: bool=False,
clip_method: Union[str, Clip]=Clip.CLIP
) -> None:
"""Multi-dimensional low-pass gaussian filter.
Parameters
Expand All @@ -29,10 +31,19 @@ def __init__(
is_volume : bool
If True, 3d (z, y, x) volumes will be filtered, otherwise, filter 2d tiles
independently.
clip_method : Union[str, Clip]
(Default Clip.CLIP) Controls the way that data are scaled to retain skimage dtype
requirements that float data fall in [0, 1].
Clip.CLIP: data above 1 are set to 1, and below 0 are set to 0
Clip.SCALE_BY_IMAGE: data above 1 are scaled by the maximum value, with the maximum
value calculated over the entire ImageStack
Clip.SCALE_BY_CHUNK: data above 1 are scaled by the maximum value, with the maximum
value calculated over each slice, where slice shapes are determined by the group_by
parameters
"""
self.sigma = validate_and_broadcast_kernel_size(sigma, is_volume)
self.is_volume = is_volume
self.clip_method = clip_method

_DEFAULT_TESTING_PARAMETERS = {"sigma": 1}

Expand Down Expand Up @@ -99,7 +110,8 @@ def run(
low_pass: Callable = partial(self._low_pass, sigma=self.sigma)
result = stack.apply(
low_pass,
group_by=group_by, verbose=verbose, in_place=in_place, n_processes=n_processes
group_by=group_by, verbose=verbose, in_place=in_place, n_processes=n_processes,
clip_method=self.clip_method
)
return result

Expand All @@ -108,6 +120,10 @@ def run(
@click.option("--sigma", type=float, help="standard deviation of gaussian kernel")
@click.option("--is-volume", is_flag=True,
help="indicates that the image stack should be filtered in 3d")
@click.option(
"--clip-method", default=Clip.CLIP, type=Clip,
help="method to constrain data to [0,1]. options: 'clip', 'scale_by_image', "
"'scale_by_chunk'")
@click.pass_context
def _cli(ctx, sigma, is_volume):
ctx.obj["component"]._cli_run(ctx, GaussianLowPass(sigma, is_volume))
def _cli(ctx, sigma, is_volume, clip_method):
ctx.obj["component"]._cli_run(ctx, GaussianLowPass(sigma, is_volume, clip_method))
56 changes: 28 additions & 28 deletions starfish/image/_filter/laplace.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,42 +9,30 @@
from starfish.image._filter._base import FilterAlgorithmBase
from starfish.image._filter.util import (
determine_axes_to_group_by,
preserve_float_range,
validate_and_broadcast_kernel_size,
)
from starfish.imagestack.imagestack import ImageStack
from starfish.types import Number
from starfish.types import Clip, Number
from starfish.util import click


class Laplace(FilterAlgorithmBase):
"""
Multi-dimensional Laplace filter, using Gaussian second derivatives.
This filter wraps scipy.ndimage.gaussian_laplace
Parameters
----------
sigma : Union[Number, Tuple[Number]]
Standard deviation for Gaussian kernel.
is_volume : bool
If True, 3d (z, y, x) volumes will be filtered, otherwise, filter 2d tiles
independently.
"""

def __init__(
self,
sigma: Union[Number, Tuple[Number]], mode: str='reflect',
cval: float=0.0, is_volume: bool=False,
self,
sigma: Union[Number, Tuple[Number]], mode: str='reflect',
cval: float=0.0, is_volume: bool=False, clip_method: Union[str, Clip]=Clip.CLIP,
) -> None:
"""Multi-dimensional gaussian-laplacian filter used to enhance dots against background
This filter wraps scipy.ndimage.gaussian_laplace
Parameters
----------
sigma_gauss : Union[Number, Tuple[Number]]
sigma : Union[Number, Tuple[Number]]
Standard deviation for Gaussian kernel to enhance dots.
mode: The mode parameter determines how the input array is extended when
mode : str
The mode parameter determines how the input array is extended when
the filter overlaps a border. By passing a sequence of modes with
length equal to the number of dimensions of the input array,
different modes can be specified along each axis. Default value
Expand All @@ -66,18 +54,26 @@ def __init__(
‘wrap’ (a b c d | a b c d | a b c d)
The input is extended by wrapping around to the opposite edge.
cval : scalar, optional
Value to fill past edges of input if mode is ‘constant’. Default is 0.0.
(Default 0) Value to fill past edges of input if mode is ‘constant’.
is_volume: bool
True is the image is a stack
If True, 3d (z, y, x) volumes will be filtered. By default, filter 2-d (y, x) planes
clip_method : Union[str, Clip]
(Default Clip.CLIP) Controls the way that data are scaled to retain skimage dtype
requirements that float data fall in [0, 1].
Clip.CLIP: data above 1 are set to 1, and below 0 are set to 0
Clip.SCALE_BY_IMAGE: data above 1 are scaled by the maximum value, with the maximum
value calculated over the entire ImageStack
Clip.SCALE_BY_CHUNK: data above 1 are scaled by the maximum value, with the maximum
value calculated over each slice, where slice shapes are determined by the group_by
parameters
"""

self.sigma = validate_and_broadcast_kernel_size(sigma, is_volume=is_volume)
self.mode = mode
self.cval = cval
self.is_volume = is_volume
self.clip_method = clip_method

_DEFAULT_TESTING_PARAMETERS = {"sigma": 0.5}

Expand All @@ -90,7 +86,6 @@ def _gaussian_laplace(
image, sigma=sigma, mode=mode, cval=cval)

filtered = -filtered # the peaks are negative so invert the signal
filtered = preserve_float_range(filtered)

return filtered

Expand All @@ -117,6 +112,7 @@ def run(
return stack.apply(
apply_filtering,
group_by=group_by, verbose=verbose, in_place=in_place, n_processes=n_processes,
clip_method=self.clip_method
)

@staticmethod
Expand All @@ -133,6 +129,10 @@ def run(
@click.option(
"--is-volume", is_flag=True,
help="indicates that the image stack should be filtered in 3d")
@click.option(
"--clip-method", default=Clip.CLIP, type=Clip,
help="method to constrain data to [0,1]. options: 'clip', 'scale_by_image', "
"'scale_by_chunk'")
@click.pass_context
def _cli(ctx, sigma, mode, cval, is_volume):
ctx.obj["component"]._cli_run(ctx, Laplace(sigma, mode, cval, is_volume))
def _cli(ctx, sigma, mode, cval, is_volume, clip_method):
ctx.obj["component"]._cli_run(ctx, Laplace(sigma, mode, cval, is_volume, clip_method))
Loading

0 comments on commit ae5311a

Please sign in to comment.