changeset 3:1faa7e3c94ff draft

planemo upload for repository https://github.com/BMCV/galaxy-image-analysis/tree/master/tools/slice_image/ commit c045f067a57e8308308cf6329060c7ccd3fc372f
author imgteam
date Thu, 04 Apr 2024 15:26:38 +0000
parents f312d414f234
children a72590196440
files creators.xml slice_image.py slice_image.xml tests.xml
diffstat 4 files changed, 190 insertions(+), 51 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/creators.xml	Thu Apr 04 15:26:38 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/slice_image.py	Mon Nov 13 22:12:22 2023 +0000
+++ b/slice_image.py	Thu Apr 04 15:26:38 2024 +0000
@@ -9,12 +9,9 @@
 import skimage.util
 
 
-def slice_image(input_file, out_folder, label=None, label_out_folder=None, window_size=64,
-                stride=1, bg_thresh=1, limit_slices=False, n_thresh=5000, seed=None):
-    # TODO NOT Implemented:process labels
-    # --> label and label_out_folder useless so far
+def slice_image(input_file, out_folder, window_size=64, stride=1, bg_thresh=1, limit_slices=False, n_thresh=5000, seed=None):
 
-    # primarily for testing purposes:
+    # Primarily for testing purposes
     if seed is not None:
         random.seed(seed)
 
@@ -40,7 +37,7 @@
                 sum_image = skimage.util.img_as_uint(sum_image)
                 g = skimage.feature.greycomatrix(sum_image, [1, 2], [0, np.pi / 2], nnormed=True, symmetric=True)
                 hom = np.var(skimage.feature.greycoprops(g, prop='homogeneity'))
-                if hom > bg_thresh:  # 0.0005
+                if hom > bg_thresh:
                     continue
 
             if limit_slices:
@@ -54,19 +51,22 @@
 
 if __name__ == "__main__":
     parser = argparse.ArgumentParser()
-    parser.add_argument('input_file', type=argparse.FileType('r'), help='input file')
-    parser.add_argument('out_folder', help='out folder')
-    parser.add_argument('--label', dest='label_file', default=None, help='auxiliary label file to split in the same way')
-    parser.add_argument('--label_out_folder', dest='label_out_folder', default=None, help='label out folder')
-    parser.add_argument('--stride', dest='stride', type=int, default=1, help='applied stride')
-    parser.add_argument('--window_size', dest='window_size', type=int, default=64, help='size of resulting patches')
-    parser.add_argument('--bg_thresh', dest='bg_thresh', type=float, default=0, help='skip patches without information using a treshold')
-    parser.add_argument('--limit_slices', dest='limit_slices', type=bool, default=False, help='limit amount of slices')
-    parser.add_argument('--n_thresh', dest='n_thresh', type=int, default=5000, help='amount of slices')
-    parser.add_argument('--seed', dest='seed', type=int, default=None, help='seed for random choice of limited slices')
+    parser.add_argument('input_file', type=argparse.FileType('r'), help='Input file')
+    parser.add_argument('out_folder', help='Output directory')
+    parser.add_argument('--stride', dest='stride', type=int, default=1, help='Applied stride')
+    parser.add_argument('--window_size', dest='window_size', type=int, default=64, help='Size of resulting patches')
+    parser.add_argument('--bg_thresh', dest='bg_thresh', type=float, default=0, help='Skip background patches without information using a treshold')
+    parser.add_argument('--n_thresh', dest='n_thresh', type=int, default=5000, help='Maximum number of slices to retain')
+    parser.add_argument('--seed', dest='seed', type=int, default=None, help='Seed for random choice of slices')
     args = parser.parse_args()
 
-    slice_image(args.input_file.name, args.out_folder,
-                label=args.label_file, label_out_folder=args.label_out_folder,
-                stride=args.stride, window_size=args.window_size, bg_thresh=args.bg_thresh,
-                limit_slices=args.limit_slices, n_thresh=args.n_thresh, seed=args.seed)
+    slice_image(
+        args.input_file.name,
+        args.out_folder,
+        stride=args.stride,
+        window_size=args.window_size,
+        bg_thresh=args.bg_thresh,
+        limit_slices=args.n_thresh > 0,
+        n_thresh=args.n_thresh,
+        seed=args.seed,
+    )
--- a/slice_image.xml	Mon Nov 13 22:12:22 2023 +0000
+++ b/slice_image.xml	Thu Apr 04 15:26:38 2024 +0000
@@ -1,5 +1,12 @@
-<tool id="ip_slice_image" name="Slice image" version="0.3-2">
+<tool id="ip_slice_image" name="Slice image into patches" version="0.3-3">
     <description></description>
+    <macros>
+        <import>creators.xml</import>
+        <import>tests.xml</import>
+    </macros>
+    <creator>
+        <expand macro="creators/bmcv" />
+    </creator>
     <edam_operations>
         <edam_operation>operation_3443</edam_operation>
     </edam_operations>
@@ -12,34 +19,35 @@
         <requirement type="package" version="1.1.0">scipy</requirement>
         <requirement type="package" version="0.15.1">tifffile</requirement>
     </requirements>
-    <command detect_errors="aggressive"> 
-        <![CDATA[
+    <command detect_errors="aggressive"><![CDATA[
+
         mkdir ./out &&
+
         python '$__tool_directory__/slice_image.py'
         '$input_file' ./out
-        --stride $stride --window_size $patch_size --bg_thresh $bg_thresh
-        --limit_slices $limit_slices 
-        #if $limit_slices:
-          --n_thresh $n_thresh
+
+        --stride '$stride'
+        --window_size '$patch_size'
+        --bg_thresh '$bg_thresh'
+
+        #if $n_thresh > 0:
+            --n_thresh '$n_thresh'
         #end if
-        #if $control_rng:
-          --seed $seed
+
+        #if len('$seed') > 0:
+            --seed '$seed'
         #end if
+
         && ls -l ./out
-        ]]> 
-    </command>
+
+    ]]></command>
     <inputs>
-        <param name="input_file" type="data" format="tiff,png,jpg,bmp" label="Input image"/> 
-        <!--<param name="out_folder" type="text" label="Output folder for image slices"/> 
-        <param name="label_file" type="data" format="tiff,png,jpg,bmp" label="Auxiliary label file to split in the same way"/>--> 
-        <param name="stride" type="integer" optional="true" value="16"/>
-        <param name="patch_size" type="integer" optional="true" value="64" label="Size of resulting (quadratic-shaped) slices"/>
-        <param name="bg_thresh" type="float" optional="true" value="0" label="Threshold to not be considered background"/>
-        <param name="limit_slices" type="boolean" checked="true" label="Should the number of slices be limited?"/>
-        <param name="n_thresh" type="integer" optional="true" label="Maximum amount of slices; only needed if limit_slices is selected"/>  
-        <param name="control_rng" type="boolean" checked="false" label="Boolean that controls if a certain seed should be selected for the random number generator"/>
-        <param name="seed" type="integer" value="1"
-            label="Seed chosen for the random number generator of the random choice of limited slices. Only required if cotrol_rng is selected"/>
+        <param name="input_file" type="data" format="tiff,png" label="Input image"/> 
+        <param name="stride" type="integer" optional="true" value="16" min="1" label="Stride" help="Minimum offset between any two patches in pixels."/>
+        <param name="patch_size" type="integer" optional="true" value="64" label="Patch size" help="Width of the patches in pixels (the height is identical)."/>
+        <param name="bg_thresh" type="float" optional="true" value="0" min="0" label="Maximum patch homogeneity" help="If larger than 0, patches with a homogeneity above this threshold will be considered as purely background and discarded."/>
+        <param name="n_thresh" type="integer" optional="true" label="Maximum number of patches" value="0" min="0" help="If larger than 0, only the specified number of patches will be retained (or less). Those will be selected randomly."/>
+        <param name="seed" type="hidden" value=""/>
     </inputs>
     <outputs>
         <collection name="slices" type="list" label="Slices obtained from input">
@@ -47,25 +55,38 @@
         </collection>
     </outputs>
     <tests>
+        <!-- Tests for TIFF input -->
         <test>
             <param name="input_file" value="input.tiff"/>
-            <param name="limit_slices" value="true"/>
             <param name="n_thresh" value="5"/>
-            <param name="control_rng" value="true"/>
             <param name="seed" value="17"/>
             <output_collection name="slices" type="list">
-                <element name="148.tiff" file="input_148.tiff" ftype="tiff" compare="sim_size"/>
-                <element name="155.tiff" file="input_155.tiff" ftype="tiff" compare="sim_size"/>
-                <element name="187.tiff" file="input_187.tiff" ftype="tiff" compare="sim_size"/>
-                <element name="212.tiff" file="input_212.tiff" ftype="tiff" compare="sim_size"/>
-                <element name="267.tiff" file="input_267.tiff" ftype="tiff" compare="sim_size"/>
+                <expand macro="tests/intensity_image_diff/element" name="148.tiff" value="input_148.tiff" ftype="tiff"/>
+                <expand macro="tests/intensity_image_diff/element" name="155.tiff" value="input_155.tiff" ftype="tiff"/>
+                <expand macro="tests/intensity_image_diff/element" name="187.tiff" value="input_187.tiff" ftype="tiff"/>
+                <expand macro="tests/intensity_image_diff/element" name="212.tiff" value="input_212.tiff" ftype="tiff"/>
+                <expand macro="tests/intensity_image_diff/element" name="267.tiff" value="input_267.tiff" ftype="tiff"/>
             </output_collection>
         </test>
+        <!-- TODO: Add tests for PNG input -->
     </tests>
     <help>
-    **What it does**
+
+        **Slices an image into multiple smaller, square-shaped patches.**
+
+        For overlapping patches, set the stride to a value smaller than the patch size.
+        For non-overlapping patches, set the stride to a value identical to the patch size (or larger).
+        If the stride is set to a value larger than the patch size, parts of the original image will be skipped.
 
-    Slices image into multiple smaller patches.
+        Optionally, patches entirely corresponding to image background are discarded.
+        To decide whether a patch corresponds to image background, the `homogeneity`_ of its `gray-level co-occurrence matrix`_ is considered.
+
+        .. _homogeneity: https://scikit-image.org/docs/stable/api/skimage.feature.html#skimage.feature.graycoprops
+        .. _gray-level co-occurrence matrix: https://scikit-image.org/docs/stable/api/skimage.feature.html#skimage.feature.graycomatrix
+
+        In addition, the number of the remaining patches can be reduced by specifying a maximum number of patches to retain.
+        Those will be selected randomly.
+
     </help>
     <citations>
         <citation type="doi">10.1016/j.jbiotec.2017.07.019</citation>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests.xml	Thu Apr 04 15:26:38 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>