changeset 3:6c4b22ef2b81 draft

planemo upload for repository https://github.com/BMCV/galaxy-image-analysis/tree/master/tools/2d_simple_filter/ commit c045f067a57e8308308cf6329060c7ccd3fc372f
author imgteam
date Thu, 04 Apr 2024 15:23:42 +0000
parents f70b215d155c
children d51310ab328a
files creators.xml filter.xml filter_image.py test-data/input1_gaussian.tif test-data/input1_median.tif test-data/input1_prewitt_h.tif test-data/input1_prewitt_v.tif test-data/input1_sobel_h.tif test-data/input1_sobel_v.tif test-data/input1_uint8.tif test-data/input2_float.tif test-data/input2_gaussian.tif test-data/res.tif test-data/sample.tif tests.xml
diffstat 15 files changed, 249 insertions(+), 46 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/creators.xml	Thu Apr 04 15:23:42 2024 +0000
@@ -0,0 +1,23 @@
+<macros>
+
+    <xml name="creators/bmcv">
+        <organization name="Biomedical Computer Vision Group, Heidelberg Universtiy" alternateName="BMCV" url="http://www.bioquant.uni-heidelberg.de/research/groups/biomedical_computer_vision.html" />
+        <yield />
+    </xml>
+
+    <xml name="creators/alliecreason">
+        <person givenName="Allison" familyName="Creason"/>
+        <yield/>
+    </xml>
+
+    <xml name="creators/bugraoezdemir">
+        <person givenName="Bugra" familyName="Oezdemir"/>
+        <yield/>
+    </xml>
+
+    <xml name="creators/thawn">
+        <person givenName="Till" familyName="Korten"/>
+        <yield/>
+    </xml>
+    
+</macros>
--- a/filter.xml	Fri Nov 10 13:44:57 2023 +0000
+++ b/filter.xml	Thu Apr 04 15:23:42 2024 +0000
@@ -1,49 +1,135 @@
-<tool id="ip_filter_standard" name="Filter 2D image" version="0.0.3-3">
-    <description>with scikit-image</description>
+<tool id="ip_filter_standard" name="Filter 2-D image" version="@TOOL_VERSION@+galaxy@VERSION_SUFFIX@" profile="20.05">
+    <description>with scipy</description>
+    <macros>
+        <import>creators.xml</import>
+        <import>tests.xml</import>
+        <token name="@TOOL_VERSION@">1.12.0</token>
+        <token name="@VERSION_SUFFIX@">0</token>
+    </macros>
+    <creator>
+        <expand macro="creators/bmcv" />
+    </creator>
     <edam_operations>
         <edam_operation>operation_3443</edam_operation>
     </edam_operations>
     <xrefs>
-        <xref type="bio.tools">scikit-image</xref>
-        <xref type="biii">scikit-image</xref>
+        <xref type="biii">scipy</xref>
     </xrefs>
     <requirements>
-        <requirement type="package" version="0.14.2">scikit-image</requirement>
-        <requirement type="package" version="1.15.4">numpy</requirement>
-        <requirement type="package" version="5.3.0">pillow</requirement>
-        <requirement type="package" version="0.15.1">tifffile</requirement>
+        <requirement type="package" version="@TOOL_VERSION@">scipy</requirement>
+        <requirement type="package" version="1.26.4">numpy</requirement>
+        <requirement type="package" version="0.22.0">scikit-image</requirement>
+        <requirement type="package" version="2024.2.12">tifffile</requirement>
     </requirements>
-    <command detect_errors="aggressive">
-      <![CDATA[
-        python '$__tool_directory__/filter_image.py' '$input' '$output' $filter_type $radius
-      ]]>
-    </command>
+    <command detect_errors="aggressive"><![CDATA[
+
+        python '$__tool_directory__/filter_image.py'
+
+        '$input'
+        '$output'
+
+        $filter_type
+        $size
+
+    ]]></command>
     <inputs>
-        <param name="filter_type" type="select" label="Filter type">
-          <option value="median" selected="True">Median</option>
-          <option value="gaussian">Gaussian Blur</option>
-          <option value="prewitt">Prewitt</option>
-          <option value="sobel">Sobel</option>
-          <option value="scharr">Scharr</option>
-        </param>
-        <param name="radius" type="integer" value="3" label="Radius/Sigma" />
-        <param name="input" type="data" format="tiff" label="Source file" />
+        <param name="input" type="data" format="tiff,png" label="Input image" />
+        <conditional name="filter">
+            <param name="filter_type" type="select" label="Filter type">
+                <option value="gaussian" selected="True">Gaussian</option>
+                <option value="median">Median</option>
+                <option value="prewitt_h">Prewitt horizontal</option>
+                <option value="prewitt_v">Prewitt vertical</option>
+                <option value="sobel_h">Sobel horizontal</option>
+                <option value="sobel_v">Sobel vertical</option>
+            </param>
+            <when value="gaussian">
+                <param name="size" type="float" value="3" min="0.1" label="Sigma" help="The half width of the Gaussian bell (in pixels)." />
+            </when>
+            <when value="median">
+                <param name="size" type="integer" value="3" label="Radius" help="Radius of the neighborhood (in pixels)." />
+            </when>
+            <when value="prewitt_h">
+                <param name="size" type="hidden" value="0" />
+            </when>
+            <when value="prewitt_v">
+                <param name="size" type="hidden" value="0" />
+            </when>
+            <when value="sobel_h">
+                <param name="size" type="hidden" value="0" />
+            </when>
+            <when value="sobel_v">
+                <param name="size" type="hidden" value="0" />
+            </when>
+        </conditional>
     </inputs>
     <outputs>
        <data format="tiff" name="output" />
     </outputs> 
     <tests>
-      <test>
-        <param name="input" value="sample.tif" />
-        <output name="output" value="res.tif" ftype="tiff" compare="sim_size"/>
-        <param name="filter_type" value="prewitt" />
-        <param name="radius" value="4" />
-      </test>
+        <!-- Tests with uint8 TIFF input image -->
+        <test>
+            <param name="input" value="input1_uint8.tif" />
+            <param name="filter_type" value="gaussian" />
+            <expand macro="tests/intensity_image_diff" name="output" value="input1_gaussian.tif" ftype="tiff">
+                <!--
+
+                The input file `input1_uint8.tif` has values ranging between 23 and 254, with a mean value of 63.67.
+
+                Below, we use an assertion in addition to the `image_diff` comparison, to ensure that the range of
+                values is preserved. The motiviation behind this is that the expectation images are usually checked
+                visually, which means that the `image_diff` comparison is likely to ensure that the brightness of
+                the image is correct, thus it's good to double-check the range of values (hence the comparably large
+                value for `eps`). This also concerns the median filter.
+
+                -->
+                <has_image_mean_intensity mean_intensity="63.67" eps="10"/>
+            </expand>
+        </test>
+        <test>
+            <param name="input" value="input1_uint8.tif" />
+            <param name="filter_type" value="median" />
+            <expand macro="tests/intensity_image_diff" name="output" value="input1_median.tif" ftype="tiff">
+                <!-- See note for Gaussian filter above. -->
+                <has_image_mean_intensity mean_intensity="63.67" eps="10"/>
+            </expand>
+        </test>
+        <test>
+            <param name="input" value="input1_uint8.tif" />
+            <param name="filter_type" value="prewitt_h" />
+            <expand macro="tests/intensity_image_diff" name="output" value="input1_prewitt_h.tif" ftype="tiff"/>
+        </test>
+        <test>
+            <param name="input" value="input1_uint8.tif" />
+            <param name="filter_type" value="prewitt_v" />
+            <expand macro="tests/intensity_image_diff" name="output" value="input1_prewitt_v.tif" ftype="tiff"/>
+        </test>
+        <test>
+            <param name="input" value="input1_uint8.tif" />
+            <param name="filter_type" value="sobel_h" />
+            <expand macro="tests/intensity_image_diff" name="output" value="input1_sobel_h.tif" ftype="tiff"/>
+        </test>
+        <test>
+            <param name="input" value="input1_uint8.tif" />
+            <param name="filter_type" value="sobel_v" />
+            <expand macro="tests/intensity_image_diff" name="output" value="input1_sobel_v.tif" ftype="tiff"/>
+        </test>
+        <!-- Tests with float TIFF input image -->
+        <test>
+            <param name="input" value="input2_float.tif" />
+            <param name="filter_type" value="gaussian" />
+            <expand macro="tests/intensity_image_diff" name="output" value="input2_gaussian.tif" ftype="tiff">
+                <!-- See note for Gaussian filter above. -->
+                <has_image_mean_intensity mean_intensity="0.25" eps="0.01"/>
+            </expand>
+        </test>
     </tests>
     <help>
-    **What it does**
+
+        **Applies a standard filter to a single-channel 2-D image.**
 
-    Applies a standard filter to an image.
+        Mean filters like the Gaussian filter or the median filter preserve both the brightness of the image, and the range of values.
+
     </help>
     <citations>
        <citation type="doi">10.1016/j.jbiotec.2017.07.019</citation>
--- a/filter_image.py	Fri Nov 10 13:44:57 2023 +0000
+++ b/filter_image.py	Thu Apr 04 15:23:42 2024 +0000
@@ -1,29 +1,28 @@
 import argparse
-import sys
 
-import skimage.filters
+import scipy.ndimage as ndi
 import skimage.io
 import skimage.util
-from skimage import img_as_uint
 from skimage.morphology import disk
 
 
-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),
+filters = {
+    'gaussian': lambda im, sigma: ndi.gaussian_filter(im, sigma),
+    'median': lambda im, radius: ndi.median_filter(im, footprint=disk(radius)),
+    'prewitt_h': lambda im, *args: ndi.prewitt(im, axis=1),
+    'prewitt_v': lambda im, *args: ndi.prewitt(im, axis=0),
+    'sobel_h': lambda im, *args: ndi.sobel(im, axis=1),
+    'sobel_v': lambda im, *args: ndi.sobel(im, axis=0),
 }
 
 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')
+    parser.add_argument('input', type=argparse.FileType('r'), help='Input file')
+    parser.add_argument('output', type=argparse.FileType('w'), help='Output file (TIFF)')
+    parser.add_argument('filter', choices=filters.keys(), help='Filter to be used')
+    parser.add_argument('size', type=float, help='Size of the filter (e.g., 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')
+    im = skimage.io.imread(args.input.name)
+    res = filters[args.filter](im, args.size)
+    skimage.io.imsave(args.output.name, res, plugin='tifffile')
Binary file test-data/input1_gaussian.tif has changed
Binary file test-data/input1_median.tif has changed
Binary file test-data/input1_prewitt_h.tif has changed
Binary file test-data/input1_prewitt_v.tif has changed
Binary file test-data/input1_sobel_h.tif has changed
Binary file test-data/input1_sobel_v.tif has changed
Binary file test-data/input1_uint8.tif has changed
Binary file test-data/input2_float.tif has changed
Binary file test-data/input2_gaussian.tif has changed
Binary file test-data/res.tif has changed
Binary file test-data/sample.tif has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests.xml	Thu Apr 04 15:23:42 2024 +0000
@@ -0,0 +1,95 @@
+<macros>
+
+    <!-- Macros for verification of image outputs -->
+
+    <xml
+        name="tests/binary_image_diff"
+        tokens="name,value,ftype,metric,eps"
+        token_metric="mae"
+        token_eps="0.01">
+
+        <output name="@NAME@" value="@VALUE@" ftype="@FTYPE@" compare="image_diff" metric="@METRIC@" eps="@EPS@" pin_labels="0">
+            <assert_contents>
+                <has_image_n_labels n="2"/>
+                <yield/>
+            </assert_contents>
+        </output>
+
+    </xml>
+
+    <xml
+        name="tests/label_image_diff"
+        tokens="name,value,ftype,metric,eps,pin_labels"
+        token_metric="iou"
+        token_eps="0.01"
+        token_pin_labels="0">
+
+        <output name="@NAME@" value="@VALUE@" ftype="@FTYPE@" compare="image_diff" metric="@METRIC@" eps="@EPS@" pin_labels="@PIN_LABELS@">
+            <assert_contents>
+                <yield/>
+            </assert_contents>
+        </output>
+
+    </xml>
+
+    <xml
+        name="tests/intensity_image_diff"
+        tokens="name,value,ftype,metric,eps"
+        token_metric="rms"
+        token_eps="0.01">
+
+        <output name="@NAME@" value="@VALUE@" ftype="@FTYPE@" compare="image_diff" metric="@METRIC@" eps="@EPS@">
+            <assert_contents>
+                <yield/>
+            </assert_contents>
+        </output>
+
+    </xml>
+
+    <!-- Variants of the above for verification of collection elements -->
+
+    <xml
+        name="tests/binary_image_diff/element"
+        tokens="name,value,ftype,metric,eps"
+        token_metric="mae"
+        token_eps="0.01">
+
+        <element name="@NAME@" value="@VALUE@" ftype="@FTYPE@" compare="image_diff" metric="@METRIC@" eps="@EPS@" pin_labels="0">
+            <assert_contents>
+                <has_image_n_labels n="2"/>
+                <yield/>
+            </assert_contents>
+        </element>
+
+    </xml>
+
+    <xml
+        name="tests/label_image_diff/element"
+        tokens="name,value,ftype,metric,eps"
+        token_metric="iou"
+        token_eps="0.01"
+        token_pin_labels="0">
+
+        <element name="@NAME@" value="@VALUE@" ftype="@FTYPE@" compare="image_diff" metric="@METRIC@" eps="@EPS@" pin_labels="@PIN_LABELS@">
+            <assert_contents>
+                <yield/>
+            </assert_contents>
+        </element>
+
+    </xml>
+
+    <xml
+        name="tests/intensity_image_diff/element"
+        tokens="name,value,ftype,metric,eps"
+        token_metric="rms"
+        token_eps="0.01">
+
+        <element name="@NAME@" value="@VALUE@" ftype="@FTYPE@" compare="image_diff" metric="@METRIC@" eps="@EPS@">
+            <assert_contents>
+                <yield/>
+            </assert_contents>
+        </element>
+
+    </xml>
+
+</macros>