# HG changeset patch
# User imgteam
# Date 1765574284 0
# Node ID b2d9c92bc431e742432ef0879c7259190726b73c
# Parent e2542d0ac64f51093897808c8f74c8c929b0b019
planemo upload for repository https://github.com/BMCV/galaxy-image-analysis/tree/master/tools/2d_simple_filter/ commit a6fd77be465068f709a71d377900da99becf94d8
diff -r e2542d0ac64f -r b2d9c92bc431 creators.xml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/creators.xml Fri Dec 12 21:18:04 2025 +0000
@@ -0,0 +1,43 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff -r e2542d0ac64f -r b2d9c92bc431 filter.py
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/filter.py Fri Dec 12 21:18:04 2025 +0000
@@ -0,0 +1,110 @@
+import argparse
+import json
+from typing import (
+ Any,
+ Callable,
+)
+
+import giatools
+import numpy as np
+import scipy.ndimage as ndi
+from skimage.morphology import disk
+
+
+def image_astype(img: giatools.Image, dtype: np.dtype) -> giatools.Image:
+ return giatools.Image(
+ data=img.data.astype(dtype),
+ axes=img.axes,
+ original_axes=img.original_axes,
+ metadata=img.metadata,
+ )
+
+
+filters = {
+ 'gaussian': lambda img, sigma, order=0, axis=None: (
+ apply_2d_filter(
+ ndi.gaussian_filter,
+ img if order == 0 else image_astype(img, float),
+ sigma=sigma,
+ order=order,
+ axes=axis,
+ )
+ ),
+ 'uniform': lambda img, size: (
+ apply_2d_filter(ndi.uniform_filter, img, size=size)
+ ),
+ 'median': lambda img, radius: (
+ apply_2d_filter(ndi.median_filter, img, footprint=disk(radius))
+ ),
+ 'prewitt': lambda img, axis: (
+ apply_2d_filter(ndi.prewitt, img, axis=axis)
+ ),
+ 'sobel': lambda img, axis: (
+ apply_2d_filter(ndi.sobel, img, axis=axis)
+ ),
+}
+
+
+def apply_2d_filter(
+ filter_impl: Callable[[np.ndarray, Any, ...], np.ndarray],
+ img: giatools.Image,
+ **kwargs: Any,
+) -> giatools.Image:
+ """
+ Apply the 2-D filter to the 2-D/3-D, potentially multi-frame and multi-channel image.
+ """
+ result_data = None
+ for qtzc in np.ndindex(
+ img.data.shape[ 0], # Q axis
+ img.data.shape[ 1], # T axis
+ img.data.shape[ 2], # Z axis
+ img.data.shape[-1], # C axis
+ ):
+ sl = np.s_[*qtzc[:3], ..., qtzc[3]] # noqa: E999
+ arr = img.data[sl]
+ assert arr.ndim == 2 # sanity check, should always be True
+
+ # Perform 2-D filtering
+ res = filter_impl(arr, **kwargs)
+ if result_data is None:
+ result_data = np.empty(img.data.shape, res.dtype)
+ result_data[sl] = res
+
+ # Return results
+ return giatools.Image(result_data, img.axes)
+
+
+def apply_filter(
+ input_filepath: str,
+ output_filepath: str,
+ filter_type: str,
+ **kwargs: Any,
+):
+ # Read the input image
+ img = giatools.Image.read(input_filepath)
+
+ # Perform filtering
+ filter_impl = filters[filter_type]
+ res = filter_impl(img, **kwargs).normalize_axes_like(img.original_axes)
+
+ # Adopt metadata and write the result
+ res.metadata = img.metadata
+ res.write(output_filepath, backend='tifffile')
+
+
+if __name__ == "__main__":
+ parser = argparse.ArgumentParser()
+ parser.add_argument('input', type=str, help='Input image filepath')
+ parser.add_argument('output', type=str, help='Output image filepath (TIFF)')
+ parser.add_argument('params', type=str)
+ args = parser.parse_args()
+
+ # Read the config file
+ with open(args.params) as cfgf:
+ cfg = json.load(cfgf)
+
+ apply_filter(
+ args.input,
+ args.output,
+ **cfg,
+ )
diff -r e2542d0ac64f -r b2d9c92bc431 filter.xml
--- a/filter.xml Thu Jul 18 08:51:37 2019 -0400
+++ b/filter.xml Fri Dec 12 21:18:04 2025 +0000
@@ -1,42 +1,249 @@
-
- applies a standard filter to an image
+
+ with scipy
+
+ creators.xml
+ tests.xml
+ 1.16.3
+ 0
+
+
+
+
+
+
+
+
+
+
+
+
+ operation_3443
+
+
+ galaxy_image_analysis
+ scipy
+
- scikit-image
- numpy
- pillow
- tifffile
+ scipy
+ numpy
+ scikit-image
+ tifffile
+ giatools
-
-
-
+
+
+
+
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
- **What it does**
+
+ **Applies a standard, general-purpose 2-D filter to an image.**
+
+ Support for different image types:
- Applies a standard filter to an image.
+ - For 3-D images, the filter is applied to all z-slices of the image.
+ - For multi-channel images, the filter is applied to all channels of the image.
+ - For time-series images, the filter is also applied for all time steps.
+
+ Mean filters like the Gaussian filter, the box filter, or the median filter preserve both the brightness of the image, and
+ the range of values. This does not hold for the derivative variants of the Gaussian filter, which may produce negative values.
+
10.1016/j.jbiotec.2017.07.019
diff -r e2542d0ac64f -r b2d9c92bc431 filter_image.py
--- a/filter_image.py Thu Jul 18 08:51:37 2019 -0400
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,29 +0,0 @@
-import argparse
-import sys
-import warnings
-import numpy as np
-import skimage.io
-import skimage.filters
-import skimage.util
-from skimage.morphology import disk
-from skimage import img_as_uint
-
-filterOptions = {
- 'median' : lambda img_raw, radius: skimage.filters.median(img_raw, disk(radius)),
- 'gaussian' : lambda img_raw, radius: skimage.filters.gaussian(img_raw, sigma=radius),
- 'prewitt' : lambda img_raw, radius: skimage.filters.prewitt(img_raw),
- 'sobel' : lambda img_raw, radius: skimage.filters.sobel(img_raw),
- 'scharr' : lambda img_raw, radius: skimage.filters.scharr(img_raw),
-}
-
-if __name__ == "__main__":
- parser = argparse.ArgumentParser()
- parser.add_argument('input_file', type=argparse.FileType('r'), default=sys.stdin, help='input file')
- parser.add_argument('out_file', type=argparse.FileType('w'), default=sys.stdin, help='out file (TIFF)')
- parser.add_argument('filter_type', choices=filterOptions.keys(), help='conversion type')
- parser.add_argument('radius', default=3.0, type=float, help='Radius/Sigma')
- args = parser.parse_args()
-
- img_in = skimage.io.imread(args.input_file.name)
- res = img_as_uint(filterOptions[args.filter_type](img_in, args.radius))
- skimage.io.imsave(args.out_file.name, res, plugin='tifffile')
diff -r e2542d0ac64f -r b2d9c92bc431 test-data/input1_gaussian.tiff
Binary file test-data/input1_gaussian.tiff has changed
diff -r e2542d0ac64f -r b2d9c92bc431 test-data/input1_median.tiff
Binary file test-data/input1_median.tiff has changed
diff -r e2542d0ac64f -r b2d9c92bc431 test-data/input1_prewitt_h.tiff
Binary file test-data/input1_prewitt_h.tiff has changed
diff -r e2542d0ac64f -r b2d9c92bc431 test-data/input1_prewitt_v.tiff
Binary file test-data/input1_prewitt_v.tiff has changed
diff -r e2542d0ac64f -r b2d9c92bc431 test-data/input1_sobel_h.tiff
Binary file test-data/input1_sobel_h.tiff has changed
diff -r e2542d0ac64f -r b2d9c92bc431 test-data/input1_sobel_v.tiff
Binary file test-data/input1_sobel_v.tiff has changed
diff -r e2542d0ac64f -r b2d9c92bc431 test-data/input1_uint8.tiff
Binary file test-data/input1_uint8.tiff has changed
diff -r e2542d0ac64f -r b2d9c92bc431 test-data/input2_float.tiff
Binary file test-data/input2_float.tiff has changed
diff -r e2542d0ac64f -r b2d9c92bc431 test-data/input2_gaussian.tiff
Binary file test-data/input2_gaussian.tiff has changed
diff -r e2542d0ac64f -r b2d9c92bc431 test-data/input2_uniform.tiff
Binary file test-data/input2_uniform.tiff has changed
diff -r e2542d0ac64f -r b2d9c92bc431 test-data/res.tif
Binary file test-data/res.tif has changed
diff -r e2542d0ac64f -r b2d9c92bc431 test-data/retina_gaussian_order0.tiff
Binary file test-data/retina_gaussian_order0.tiff has changed
diff -r e2542d0ac64f -r b2d9c92bc431 test-data/retina_gaussian_order2_axis0.tiff
Binary file test-data/retina_gaussian_order2_axis0.tiff has changed
diff -r e2542d0ac64f -r b2d9c92bc431 test-data/sample.tif
Binary file test-data/sample.tif has changed
diff -r e2542d0ac64f -r b2d9c92bc431 test-data/scikit-image/LICENSE.txt
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test-data/scikit-image/LICENSE.txt Fri Dec 12 21:18:04 2025 +0000
@@ -0,0 +1,28 @@
+Files: *
+Copyright: 2009-2022 the scikit-image team
+License: BSD-3-Clause
+
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+3. Neither the name of the University nor the names of its contributors
+ may be used to endorse or promote products derived from this software
+ without specific prior written permission.
+.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE HOLDERS OR
+CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff -r e2542d0ac64f -r b2d9c92bc431 test-data/scikit-image/retina.png
Binary file test-data/scikit-image/retina.png has changed
diff -r e2542d0ac64f -r b2d9c92bc431 tests.xml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/tests.xml Fri Dec 12 21:18:04 2025 +0000
@@ -0,0 +1,95 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+