changeset 3:d45a07063da1 draft default tip

planemo upload for repository https://github.com/BMCV/galaxy-image-analysis/tree/master/tools/split_image/ commit df96ae15da34285b0a9d435a48924665fff37d6a
author imgteam
date Sat, 04 Apr 2026 21:22:07 +0000
parents 227e8928af6e
children
files split.py split_image.xml test-data/multiseries_series6.tiff test-data/zcyx_slice01.tiff test-data/zcyx_slice10.tiff test-data/zcyx_slice18.tiff test-data/zcyx_slice25.tiff
diffstat 7 files changed, 87 insertions(+), 76 deletions(-) [+]
line wrap: on
line diff
--- a/split.py	Fri Dec 12 21:02:25 2025 +0000
+++ b/split.py	Sat Apr 04 21:22:07 2026 +0000
@@ -1,33 +1,45 @@
 import argparse
 import math
-import os
 import pathlib
-import shutil
 
 import giatools
+import giatools.io
 import numpy as np
-import tifffile
 
 
 class OutputWriter:
 
-    def __init__(self, dir_path: pathlib.Path, num_images: int, squeeze: bool, verbose: bool):
-        print(f'Writing {num_images} image(s)')
+    def __init__(
+        self,
+        dir_path: pathlib.Path,
+        num_images: int,
+        squeeze: bool,
+        verbose: bool,
+        offset: int = 0,
+        step: int = 1,
+        count: int | None = None,
+    ):
+        self.positions = np.arange(num_images)[offset::step] + 1
+        if count is not None:
+            self.positions = self.positions[:count]
+
+        print(f'Writing {len(self.positions)} out of {num_images} image(s)')
         decimals = math.ceil(math.log10(1 + num_images))
         self.output_filepath_pattern = str(dir_path / f'%0{decimals}d.tiff')
-        self.last_idx = 0
+        self.last_pos = 0
         self.squeeze = squeeze
         self.verbose = verbose
 
     def write(self, img: giatools.Image):
-        self.last_idx += 1
-        if self.squeeze:
-            img = img.squeeze()
-        if self.last_idx == 1 or self.verbose:
-            prefix = f'Output {self.last_idx}' if self.verbose else 'Output'
-            print(f'{prefix} axes:', img.axes)
-            print(f'{prefix} shape:', img.data.shape)
-        img.write(self.output_filepath_pattern % self.last_idx)
+        self.last_pos += 1
+        if self.last_pos in self.positions:
+            if self.squeeze:
+                img = img.squeeze()
+            if self.last_pos == self.positions[0] or self.verbose:
+                prefix = f'Output {self.last_pos}' if self.verbose else 'Output'
+                print(f'{prefix} axes:', img.axes)
+                print(f'{prefix} shape:', img.data.shape)
+            img.write(self.output_filepath_pattern % self.last_pos)
 
 
 if __name__ == '__main__':
@@ -37,52 +49,31 @@
     parser.add_argument('axis', type=str, choices=list(giatools.default_normalized_axes) + ['S', ''])
     parser.add_argument('output', type=pathlib.Path)
     parser.add_argument('--squeeze', action='store_true', default=False)
+    parser.add_argument('offset', type=int)
+    parser.add_argument('step', type=int)
+    parser.add_argument('--count', type=int)
     args = parser.parse_args()
 
     # If splitting a file that contains multiple images...
     if args.axis == '':
 
-        # Peek the number of series in the input file (if it is a TIFF)
-        try:
-            with tifffile.TiffFile(args.input) as tiff:
-                num_tiff_series = len(tiff.series)
-                print(f'Found TIFF with {num_tiff_series} series')
-        except tifffile.TiffFileError:
-            num_tiff_series = 0  # not a TIFF file
-            print('Not a TIFF file')
+        # Peek the number of images
+        num_images = giatools.io.peek_num_images_in_file(args.input)
+        print(f'Found {num_images} image(s) in file')
 
-        # If the file is a multi-series TIFF, extract the individual series
-        # (for consistency, also accept only a single series if squeezing is requested)
-        if num_tiff_series >= 2 or (num_tiff_series == 1 and args.squeeze):
-            output = OutputWriter(
-                dir_path=args.output,
-                num_images=num_tiff_series,
-                squeeze=args.squeeze,
-                verbose=True,
-            )
-            for series in range(num_tiff_series):
-                img = giatools.Image.read(args.input, series=series)
-                output.write(
-                    img.squeeze_like(img.original_axes),
-                )
-
-        # Otherwise, there is nothing to be split (or squeeze)
-        # (the input is either a single-series TIFF or not a TIFF at all)
-        elif num_tiff_series == 1:  # input is a single-series TIFF (output = input)
-            try:
-                os.symlink(args.input, args.output / '1.tiff')
-            except OSError:
-                shutil.copyfile(args.input, args.output / '1.tiff')
-        else:  # input is not a TIFF, conversion needed
-            img = giatools.Image.read(args.input)
-            OutputWriter(
-                dir_path=args.output,
-                num_images=1,
-                squeeze=args.squeeze,
-                verbose=False,
-            ).write(
-                img.squeeze_like(img.original_axes),
-            )
+        # Extract the individual images
+        output = OutputWriter(
+            dir_path=args.output,
+            num_images=num_images,
+            squeeze=args.squeeze,
+            verbose=(num_images > 1),
+            offset=args.offset,
+            step=args.step,
+            count=args.count,
+        )
+        for position in range(num_images):
+            img = giatools.Image.read(args.input, position=position, normalize_axes=None)
+            output.write(img)
 
     # If splitting along an image axes...
     else:
@@ -105,6 +96,9 @@
             num_images=arr.shape[0],
             squeeze=args.squeeze,
             verbose=False,
+            offset=args.offset,
+            step=args.step,
+            count=args.count,
         )
         for img_idx, img in enumerate(arr):
             img = np.moveaxis(img[None], 0, axis_pos)
--- a/split_image.xml	Fri Dec 12 21:02:25 2025 +0000
+++ b/split_image.xml	Sat Apr 04 21:22:07 2026 +0000
@@ -4,7 +4,7 @@
         <import>creators.xml</import>
         <import>tests.xml</import>
         <token name="@TOOL_VERSION@">2.3.5</token>
-        <token name="@VERSION_SUFFIX@">0</token>
+        <token name="@VERSION_SUFFIX@">1</token>
     </macros>
     <creator>
         <expand macro="creators/bmcv"/>
@@ -18,9 +18,11 @@
     </xrefs>
     <requirements>
         <requirement type="package" version="@TOOL_VERSION@">numpy</requirement>
-        <requirement type="package" version="0.5.2">giatools</requirement>
-        <requirement type="package" version="2025.10.16">tifffile</requirement>
+        <requirement type="package" version="0.7.3">giatools</requirement>
     </requirements>
+    <required_files>
+        <include type="glob" path="*.py"/>
+    </required_files>
     <command detect_errors="aggressive"><![CDATA[
 
         mkdir output &&
@@ -30,11 +32,17 @@
         '$axis'
         output
 
+        $offset
+        $step
         $squeeze
 
+        #if str($count) != ""
+            --count $count
+        #end if
+
     ]]></command>
     <inputs>
-        <param name="input" type="data" format="tiff,png" label="Image to split" />
+        <param name="input" type="data" format="tiff,png" label="Image to split"/>
         <param name="axis" type="select" label="Axis to split along">
             <option value="T">T-axis (split the frames of a temporal image sequence)</option>
             <option value="Z">Z-axis (split the slices of a 3-D image or image sequence)</option>
@@ -44,11 +52,17 @@
             <option value="">Split dataset that contains multiple images (e.g., multi-series TIFF)</option>
         </param>
         <param name="squeeze" type="boolean" checked="false" truevalue="--squeeze" falsevalue="" label="Squeeze result images"
-               help="Only non-singleton axes (axes with more than one element) will be retained in the result images. This does not apply for the X and Y axes which always are retained." />
+               help="Only non-singleton axes (axes with more than one element) will be retained in the result images. This does not apply for the X and Y axes which always are retained."/>
+        <param name="offset" type="integer" value="0" min="0" label="Offset"
+               help="Number of slices to skip at the beginning."/>
+        <param name="step" type="integer" value="1" min="1" label="Step"
+               help="Number of slices between extracted images (each slice is extracted for a value of 1, each second slice is extracted for a value of two, and so on)."/>
+        <param name="count" type="integer" optional="true" min="1" label="Count"
+               help="Maximum number of slices to extract."/>
     </inputs>
     <outputs>
         <collection type="list" name="output" label="Split ${on_string} along ${axis} axis">
-            <discover_datasets directory="output" pattern="__name__" format="tiff" />
+            <discover_datasets directory="output" pattern="__name__" format="tiff"/>
         </collection>
     </outputs>
     <tests>
@@ -66,7 +80,7 @@
             <assert_stdout>
                 <has_line line="Input image axes: YXC"/>
                 <has_line line="Input image shape: (32, 32, 3)"/>
-                <has_line line="Writing 3 image(s)"/>
+                <has_line line="Writing 3 out of 3 image(s)"/>
                 <has_line line="Output axes: YXC"/>
                 <has_line line="Output shape: (32, 32, 1)"/>
             </assert_stdout>
@@ -79,8 +93,8 @@
                 <expand macro="tests/intensity_image_diff/element" name="1.tiff" value="rgb1.tiff" ftype="tiff"/>
             </output_collection>
             <assert_stdout>
-                <has_line line="Not a TIFF file"/>
-                <has_line line="Writing 1 image(s)"/>
+                <has_line line="Found 1 image(s) in file"/>
+                <has_line line="Writing 1 out of 1 image(s)"/>
                 <has_line line="Output axes: YXC"/>
                 <has_line line="Output shape: (32, 32, 3)"/>
             </assert_stdout>
@@ -88,17 +102,20 @@
 
         <!-- TIFF tests -->
         <test>
-            <param name="input" value="zcyx.tiff" />
-            <param name="axis" value="Z" />
-            <param name="squeeze" value="false" />
-            <output_collection name="output" type="list" count="25">
-                <expand macro="tests/intensity_image_diff/element" name="01.tiff" value="zcyx_slice01.tiff" ftype="tiff"/>
-                <expand macro="tests/intensity_image_diff/element" name="25.tiff" value="zcyx_slice25.tiff" ftype="tiff"/>
+            <param name="input" value="zcyx.tiff"/>
+            <param name="axis" value="Z"/>
+            <param name="squeeze" value="false"/>
+            <param name="offset" value="9"/>
+            <param name="step" value="2"/>
+            <param name="count" value="5"/>
+            <output_collection name="output" type="list" count="5">
+                <expand macro="tests/intensity_image_diff/element" name="10.tiff" value="zcyx_slice10.tiff" ftype="tiff"/>
+                <expand macro="tests/intensity_image_diff/element" name="18.tiff" value="zcyx_slice18.tiff" ftype="tiff"/>
             </output_collection>
             <assert_stdout>
                 <has_line line="Input image axes: ZCYX"/>
                 <has_line line="Input image shape: (25, 2, 50, 50)"/>
-                <has_line line="Writing 25 image(s)"/>
+                <has_line line="Writing 5 out of 25 image(s)"/>
                 <has_line line="Output axes: ZCYX"/>
                 <has_line line="Output shape: (1, 2, 50, 50)"/>
             </assert_stdout>
@@ -114,7 +131,7 @@
             <assert_stdout>
                 <has_line line="Input image axes: QYX"/>
                 <has_line line="Input image shape: (2, 256, 256)"/>
-                <has_line line="Writing 2 image(s)"/>
+                <has_line line="Writing 2 out of 2 image(s)"/>
                 <has_line line="Output axes: QYX"/>
                 <has_line line="Output shape: (1, 256, 256)"/>
             </assert_stdout>
@@ -127,7 +144,7 @@
                 <expand macro="tests/intensity_image_diff/element" name="1.tiff" value="qyx.tiff" ftype="tiff"/>
             </output_collection>
             <assert_stdout>
-                <has_line line="Found TIFF with 1 series"/>
+                <has_line line="Found 1 image(s) in file"/>
             </assert_stdout>
         </test>
 
@@ -141,8 +158,8 @@
                 <expand macro="tests/intensity_image_diff/element" name="6.tiff" value="multiseries_series6.tiff" ftype="tiff"/>
             </output_collection>
             <assert_stdout>
-                <has_line line="Found TIFF with 6 series"/>
-                <has_line line="Writing 6 image(s)"/>
+                <has_line line="Found 6 image(s) in file"/>
+                <has_line line="Writing 6 out of 6 image(s)"/>
                 <has_line line="Output 1 axes: CYX"/>
                 <has_line line="Output 1 shape: (4, 5, 5)"/>
                 <has_line line="Output 2 axes: CYX"/>
@@ -171,7 +188,7 @@
             <assert_stdout>
                 <has_line line="Input image axes: YXC"/>
                 <has_line line="Input image shape: (32, 32, 3)"/>
-                <has_line line="Writing 3 image(s)"/>
+                <has_line line="Writing 3 out of 3 image(s)"/>
                 <has_line line="Output axes: YX"/>
                 <has_line line="Output shape: (32, 32)"/>
             </assert_stdout>
@@ -188,7 +205,7 @@
             <assert_stdout>
                 <has_line line="Input image axes: YXC"/>
                 <has_line line="Input image shape: (32, 32, 3)"/>
-                <has_line line="Writing 1 image(s)"/>
+                <has_line line="Writing 1 out of 1 image(s)"/>
                 <has_line line="Output axes: YXC"/>
                 <has_line line="Output shape: (32, 32, 3)"/>
             </assert_stdout>
Binary file test-data/multiseries_series6.tiff has changed
Binary file test-data/zcyx_slice01.tiff has changed
Binary file test-data/zcyx_slice10.tiff has changed
Binary file test-data/zcyx_slice18.tiff has changed
Binary file test-data/zcyx_slice25.tiff has changed