changeset 1:f183d9de4622 draft

planemo upload for repository https://github.com/ohsu-comp-bio/ashlar commit 95998c84e130c9f3d2183591957464df7d90dd53
author goeckslab
date Wed, 24 Aug 2022 19:19:40 +0000
parents b3054f3d42b2
children 33ab2058c6d9
files ashlar.xml macros.xml pyramid_upgrade.py test-data/ashlar_test_c0.tiff test-data/ashlar_test_c1.tiff
diffstat 5 files changed, 116 insertions(+), 136 deletions(-) [+]
line wrap: on
line diff
--- a/ashlar.xml	Fri Mar 12 00:14:49 2021 +0000
+++ b/ashlar.xml	Wed Aug 24 19:19:40 2022 +0000
@@ -1,11 +1,11 @@
-<tool id="ashlar" name="ASHLAR" version="@VERSION@.6" profile="17.09">
+<tool id="ashlar" name="ASHLAR" version="@TOOL_VERSION@+galaxy@VERSION_SUFFIX@" profile="19.01">
     <description>Alignment by Simultaneous Harmonization of Layer/Adjacency Registration</description>
     <macros>
         <import>macros.xml</import>
     </macros>
  
     <expand macro="requirements"/>
-    @VERSION_CMD@
+    <expand macro="version_cmd"/>
 
     <command detect_errors="exit_code"><![CDATA[
 
@@ -13,41 +13,41 @@
           #set name_clean = str($file.element_identifier).replace('.ome.tiff','').replace('.tiff','').replace('.tiff.','')
 
           #if $type == "raw"
-            #set file_clean = $name_clean + ".ome.tiff"
+            #set file_clean = $name_clean + '.ome.tiff'
           #elif $type == "ffp"
-            #set file_clean = $name_clean + "_ffp.ome.tiff"
+            #set file_clean = $name_clean + '_ffp.ome.tiff'
           #elif $type == "dfp"
-            #set file_clean = $name_clean + "_dfp.ome.tiff"
+            #set file_clean = $name_clean + '_dfp.ome.tiff'
           #end if
 
           #return $file_clean
         #end def
 
         ## Link the illumination files to appropriate file extension
-        #for $dfp in $ldfp:
-            ln -s "$dfp" "$clean($dfp,"dfp")" &&
-        #end for
-        #for $ffp in $lffp:
-            ln -s "$ffp" "$clean($ffp,"ffp")" &&
-        #end for
+        #if $ldfp
+            #for $dfp in $ldfp:
+                ln -s '$dfp' '$clean($dfp,"dfp")' &&
+            #end for
+        #end if
+
+        #if $lffp
+            #for $ffp in $lffp:
+                ln -s '$ffp' '$clean($ffp,"ffp")' &&
+            #end for
+        #end if
 
         @CMD_BEGIN@
 
         ## Supply the raw images
         #for $raw in $lraw:
-            "$raw"
+            '$raw'
         #end for
 
         ## Additional arguments
         -m $max_shift
 
-        #if $flip_x
-        --flip-x
-        #end if
-
-        #if $flip_y
-        --flip-y
-        #end if
+        $flip_x
+        $flip_y
 
         -c $adv.align_channel
 
@@ -59,50 +59,43 @@
         --tile-size $adv.tile_size
         #end if
 
+        #if $lffp
         --ffp
-        #for $ffp in $lffp:
-            "$clean($ffp,"ffp")"
-        #end for
+            #for $ffp in $lffp:
+                '$clean($ffp,"ffp")'
+            #end for
+        #end if
+
+        #if $ldfp
         --dfp
-        #for $dfp in $ldfp:
-            "$clean($dfp,"dfp")"
-        #end for
-        --pyramid
+            #for $dfp in $ldfp:
+                '$clean($dfp,"dfp")'
+            #end for
+        #end if
+
+        $adv.pyramid
+        $adv.flip_mosaic_x
+        $adv.flip_mosaic_y
+
         -f registered.ome.tif;
 
         #if $upgrade.decide == "do_upgrade"
-        python ${__tool_directory__}/pyramid_upgrade.py
-        registered.ome.tif
+            python3 '${__tool_directory__}/pyramid_upgrade.py'
+            registered.ome.tif
 
-        #if $upgrade.markers_file
-        -n `python "$get_markers" "${upgrade.markers_file}"`
-        #end if
+            #if $upgrade.markers_file
+                -n `echo \$(cat $upgrade.markers_file | tail -n +2 | awk -F, '{print \$3}')`;
+            #end if
         #end if
     ]]></command>
 
-    <configfiles>
-        <configfile name="get_markers">
-import pandas as pd
-import sys
-
-marker_file = sys.argv[1]
-df = pd.read_csv(marker_file)
-print(' '.join(df['marker_name'].array)) 
-        </configfile>
-    </configfiles>
-
-
-
     <inputs>
-        <param name="lraw" type="data_collection" format="tiff" collection_type="list" label="Raw Images"/>
-        <param name="ldfp" type="data_collection" format="tiff" collection_type="list" label="Deep Field Profile Images"/>
-        <param name="lffp" type="data_collection" format="tiff" collection_type="list" label="Flat Field Profile Images"/>
-
-        <param name="flip_x" type="boolean" value="false" label="Flip X-axis"/>
-        <param name="flip_y" type="boolean" value="false" label="Flip Y-axis"/>
-
+        <param name="lraw" type="data_collection" format="ome.tiff,tiff" collection_type="list" label="Raw Images"/>
+        <param name="ldfp" type="data_collection" format="ome.tiff,tiff" collection_type="list" optional="true" label="Deep Field Profile Images"/>
+        <param name="lffp" type="data_collection" format="ome.tiff,tiff" collection_type="list" optional="true" label="Flat Field Profile Images"/>
+        <param name="flip_x" type="boolean" truevalue="--flip-x" falsevalue="" label="Flip X-axis"/>
+        <param name="flip_y" type="boolean" truevalue="--flip-y" falsevalue="" label="Flip Y-axis"/>
         <param name="max_shift" type="integer" value="30" label="Maximum allowed per-tile corrective shift" help="In micros"/>
-
         <conditional name="upgrade">
             <param name="decide" type="select" label="Upgrade to BF6-Compliant OME-TIFF Pyramid">
                 <option value="do_upgrade">Upgrade Pyramid</option>
@@ -118,63 +111,48 @@
             <param name="align_channel" type="integer" value="0" label="Align Channel Number"/>
             <param name="filter_sigma" type="float" optional="true" label="Sigma"/>
             <param name="tile_size" type="integer"  optional="true" label="Cyto Mask Channel"/>
+            <param name="flip_mosaic_x" type="boolean" truevalue="--flip-mosaic-x" falsevalue="" label="Flip output image horizontally"/>
+            <param name="flip_mosaic_y" type="boolean" truevalue="--flip-mosaic-y" falsevalue="" label="Flip output image vertically"/>
+            <param name="pyramid" type="boolean" checked="true" truevalue="--pyramid" falsevalue="" label="Write output as a single pyramidal TIFF"/>
         </section>
     </inputs>
 
     <outputs>
-        <data format="tiff" name="output" from_work_dir="registered.ome.tif" label="${tool.name} on ${on_string}"/>
+        <data format="ome.tiff" name="output" from_work_dir="registered.ome.tif" label="${tool.name} on ${on_string}"/>
     </outputs>
+    <tests>
+        <test>
+            <param name="lraw">
+                <collection type="list">
+                    <element name="rR1" value="ashlar_test_c0.tiff" />
+                    <element name="rR2" value="ashlar_test_c1.tiff" />
+                </collection>
+            </param>
+            <output name="output" ftype="ome.tiff">
+                <assert_contents>
+                    <has_size value="4000000" delta="1000000" />
+                </assert_contents>
+            </output>
+        </test>
+    </tests>
     <help><![CDATA[
-Ashlar python package for microscopy registration, developed by HMS (repo: https://github.com/labsyspharm/ashlar)
-        ashlar [-h] [-o DIR] [-c [CHANNEL]]
-       [--output-channels [CHANNEL [CHANNEL ...]]] [-m SHIFT]
-       [--filter-sigma SIGMA] [-f FORMAT] [--pyramid]
-       [--tile-size PIXELS] [--ffp [FILE [FILE ...]]]
-       [--dfp [FILE [FILE ...]]] [--plates] [-q] [--version]
-       [FILE [FILE ...]]
-
-Stitch and align one or more multi-series images
-
-positional arguments:
-  FILE                  an image file to be processed (one file per cycle)
+--------------------------------------------------------------------------------
+ASHLAR: Alignment by Simultaneous Harmonization of Layer/Adjacency Registration
+--------------------------------------------------------------------------------
 
-optional arguments:
-  -h, --help            show this help message and exit
-  -o DIR, --output DIR  write output image files to DIR; default is the
-                        current directory
-  -c [CHANNEL], --align-channel [CHANNEL]
-                        align images using channel number CHANNEL; numbering
-                        starts at 0
-  --output-channels [CHANNEL [CHANNEL ...]]
-                        output only channels listed in CHANNELS; numbering
-                        starts at 0
-  -m SHIFT, --maximum-shift SHIFT
-                        maximum allowed per-tile corrective shift in microns
-  --filter-sigma SIGMA  width in pixels of Gaussian filter to apply to images
-                        before alignment; default is 0 which disables
-                        filtering
-  -f FORMAT, --filename-format FORMAT
-                        use FORMAT to generate output filenames, with {cycle}
-                        and {channel} as required placeholders for the cycle
-                        and channel numbers; default is
-                        cycle_{cycle}_channel_{channel}.tif
-  --pyramid             write output as a single pyramidal TIFF
-  --tile-size PIXELS    set tile width and height to PIXELS (pyramid output
-                        only); default is 1024
-  --ffp [FILE [FILE ...]]
-                        read flat field profile image from FILES; if specified
-                        must be one common file for all cycles or one file for
-                        each cycle
-  --dfp [FILE [FILE ...]]
-                        read dark field profile image from FILES; if specified
-                        must be one common file for all cycles or one file for
-                        each cycle
-  --plates              enable plate mode for HTS data
-  -q, --quiet           suppress progress display
-  --version             print version
+**Whole-slide microscopy image stitching and registration in Python**
 
-OHSU Wrapper Repo: https://github.com/ohsu-comp-bio/ashlar
-Conda Package Available From: https://anaconda.org/ohsu-comp-bio/ashlar
+**Ashlar** performs fast, high-quality stitching of microscopy images. It also
+co-registers multiple rounds of cyclic imaging for methods such as CyCIF and
+CODEX. Ashlar can read image data directly from BioFormats-supported microscope
+vendor file formats as well as a directory of plain TIFF files. Output is saved
+as pyramidal, tiled OME-TIFF.
+
+Note that Ashlar requires unstitched individual "tile" images as input, so it is
+not suitable for microscopes or slide scanners that only provide pre-stitched
+images.
+
+*Visit https://labsyspharm.github.io/ashlar/ for the most up-to-date information on ASHLAR.*
     ]]></help>
     <expand macro="citations" />
 </tool>
--- a/macros.xml	Fri Mar 12 00:14:49 2021 +0000
+++ b/macros.xml	Wed Aug 24 19:19:40 2022 +0000
@@ -2,19 +2,21 @@
 <macros>
     <xml name="requirements">
         <requirements>
-            <requirement type="package" version="@VERSION@">ashlar</requirement>
-            <requirement type="package" version="1.1.5">pandas</requirement>
+            <requirement type="package" version="@TOOL_VERSION@">ashlar</requirement>
+            <container type="docker">labsyspharm/ashlar:@TOOL_VERSION@</container>
         </requirements>
     </xml>
 
     <xml name="version_cmd">
-        <version_command>echo @VERSION@</version_command>
+        <version_command>echo @TOOL_VERSION@</version_command>
     </xml>
     <xml name="citations">
         <citations>
+            <citation type="doi">10.1101/2021.04.20.440625</citation>
         </citations>
     </xml>
 
-    <token name="@VERSION@">1.13.0</token>
+    <token name="@TOOL_VERSION@">1.14.0</token>
+    <token name="@VERSION_SUFFIX@">0</token>
     <token name="@CMD_BEGIN@">ashlar</token>
 </macros>
--- a/pyramid_upgrade.py	Fri Mar 12 00:14:49 2021 +0000
+++ b/pyramid_upgrade.py	Wed Aug 24 19:19:40 2022 +0000
@@ -1,34 +1,33 @@
-import sys
-import os
 import argparse
-import struct
-import re
+import dataclasses
 import fractions
 import io
-import xml.etree.ElementTree
-import collections
+import os
+import re
 import reprlib
-import dataclasses
-from typing import List, Any
+import struct
+import sys
+import xml.etree.ElementTree
+from typing import Any, List
 
 
 datatype_formats = {
-    1: "B", # BYTE
-    2: "s", # ASCII
-    3: "H", # SHORT
-    4: "I", # LONG
-    5: "I", # RATIONAL (pairs)
-    6: "b", # SBYTE
-    7: "B", # UNDEFINED
-    8: "h", # SSHORT
-    9: "i", # SLONG
-    10: "i", # SRATIONAL (pairs)
-    11: "f", # FLOAT
-    12: "d", # DOUBLE
-    13: "I", # IFD
-    16: "Q", # LONG8
-    17: "q", # SLONG8
-    18: "Q", # IFD8
+    1: "B",  # BYTE
+    2: "s",  # ASCII
+    3: "H",  # SHORT
+    4: "I",  # LONG
+    5: "I",  # RATIONAL (pairs)
+    6: "b",  # SBYTE
+    7: "B",  # UNDEFINED
+    8: "h",  # SSHORT
+    9: "i",  # SLONG
+    10: "i",  # SRATIONAL (pairs)
+    11: "f",  # FLOAT
+    12: "d",  # DOUBLE
+    13: "I",  # IFD
+    16: "Q",  # LONG8
+    17: "q",  # SLONG8
+    18: "Q",  # IFD8
 }
 rational_datatypes = {5, 10}
 
@@ -253,6 +252,7 @@
             + ")"
         )
 
+
 @dataclasses.dataclass(frozen=True)
 class TagSet:
     """Container for Tag objects as stored in a TIFF IFD.
@@ -293,7 +293,7 @@
             i = self.codes.index(code)
         except ValueError:
             raise KeyError(code) from None
-        self.tags[:] = self.tags[:i] + self.tags[i+1:]
+        self.tags[:] = self.tags[:i] + self.tags[i + 1:]
 
     def __contains__(self, code):
         return code in self.codes
@@ -328,7 +328,7 @@
         else:
             i = len(self.tags)
         n = len(self.tags)
-        self.tags[i:n+1] = [tag] + self.tags[i:n]
+        self.tags[i:n + 1] = [tag] + self.tags[i:n]
 
 
 @dataclasses.dataclass(frozen=True)
@@ -372,7 +372,7 @@
 def parse_args():
     parser = argparse.ArgumentParser(
         description="Convert an OME-TIFF legacy pyramid to the BioFormats 6"
-            " OME-TIFF pyramid format in-place.",
+                    " OME-TIFF pyramid format in-place.",
     )
     parser.add_argument("image", help="OME-TIFF file to convert")
     parser.add_argument(
@@ -382,8 +382,8 @@
         default=[],
         metavar="NAME",
         help="Channel names to be inserted into OME metadata. Number of names"
-            " must match number of channels in image. Be sure to put quotes"
-            " around names containing spaces or other special shell characters."
+             " must match number of channels in image. Be sure to put quotes"
+             " around names containing spaces or other special shell characters."
     )
     args = parser.parse_args()
     return args
@@ -451,7 +451,7 @@
         print(f"TIFF does not begin with SizeC={size_c} full-size pages.")
         sys.exit(1)
     for level in range(1, num_levels):
-        level_dims = page_dims[level * size_c : (level + 1) * size_c]
+        level_dims = page_dims[level * size_c: (level + 1) * size_c]
         if len(set(level_dims)) != 1:
             print(
                 f"Pyramid level {level + 1} out of {num_levels} has inconsistent"
@@ -513,7 +513,7 @@
     print("Writing new TIFF headers...")
     stale_ranges = [ifd.offset_range for ifd in tiff.ifds]
     main_ifds = tiff.ifds[:size_c]
-    channel_sub_ifds = [tiff.ifds[c + size_c : : size_c] for c in range(size_c)]
+    channel_sub_ifds = [tiff.ifds[c + size_c::size_c] for c in range(size_c)]
     for i, (main_ifd, sub_ifds) in enumerate(zip(main_ifds, channel_sub_ifds)):
         for ifd in sub_ifds:
             if 305 in ifd.tags:
Binary file test-data/ashlar_test_c0.tiff has changed
Binary file test-data/ashlar_test_c1.tiff has changed