| Previous changeset 2:33ab2058c6d9 (2022-09-20) Next changeset 4:0b8423c7ee3e (2025-02-26) |
|
Commit message:
planemo upload for repository https://github.com/ohsu-comp-bio/ashlar commit 69f200fcfa0b1d17de50466c51d8c5468fdeb54c |
|
modified:
ashlar.xml macros.xml |
|
removed:
pyramid_upgrade.py |
| b |
| diff -r 33ab2058c6d9 -r ef68bc2a4dbc ashlar.xml --- a/ashlar.xml Tue Sep 20 17:33:50 2022 +0000 +++ b/ashlar.xml Fri Feb 09 22:48:46 2024 +0000 |
| b |
| @@ -51,6 +51,10 @@ -c $adv.align_channel + #if $adv.stitch_alpha + --stitch-alpha $adv.stitch_alpha + #end if + #if $adv.filter_sigma --filter-sigma $adv.filter_sigma #end if @@ -73,20 +77,10 @@ #end for #end if - $adv.pyramid $adv.flip_mosaic_x $adv.flip_mosaic_y - -f registered.ome.tif; - - #if $upgrade.decide == "do_upgrade" - python3 '${__tool_directory__}/pyramid_upgrade.py' - registered.ome.tif - - #if $upgrade.markers_file - -n `echo \$(cat $upgrade.markers_file | tail -n +2 | awk -F, '{print \$3}')`; - #end if - #end if + -o registered.ome.tif; ]]></command> <inputs> @@ -96,24 +90,13 @@ <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> - <option value="dont_upgrade">Leave Legacy Pyramid</option> - </param> - <when value="do_upgrade"> - <param name="markers_file" type="data" format="csv,tabular" optional="true" label="Markers File (optional)"/> - </when> - <when value="dont_upgrade"> - </when> - </conditional> <section name="adv" title="Advanced Options" expanded="false"> <param name="align_channel" type="integer" value="0" label="Align Channel Number"/> + <param name="stitch_alpha" type="float" optional="true" label="Alpha"/> <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> @@ -130,7 +113,7 @@ </param> <output name="output" ftype="ome.tiff"> <assert_contents> - <has_size value="4000000" delta="1000000" /> + <has_size value="500000" delta="400000" /> </assert_contents> </output> </test> |
| b |
| diff -r 33ab2058c6d9 -r ef68bc2a4dbc macros.xml --- a/macros.xml Tue Sep 20 17:33:50 2022 +0000 +++ b/macros.xml Fri Feb 09 22:48:46 2024 +0000 |
| b |
| @@ -12,11 +12,11 @@ </xml> <xml name="citations"> <citations> - <citation type="doi">10.1101/2021.04.20.440625</citation> + <citation type="doi">10.1093/bioinformatics/btac544</citation> </citations> </xml> - <token name="@TOOL_VERSION@">1.14.0</token> - <token name="@VERSION_SUFFIX@">1</token> + <token name="@TOOL_VERSION@">1.18.0</token> + <token name="@VERSION_SUFFIX@">0</token> <token name="@CMD_BEGIN@">ashlar</token> </macros> |
| b |
| diff -r 33ab2058c6d9 -r ef68bc2a4dbc pyramid_upgrade.py --- a/pyramid_upgrade.py Tue Sep 20 17:33:50 2022 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 |
| [ |
| b'@@ -1,566 +0,0 @@\n-import argparse\n-import dataclasses\n-import fractions\n-import io\n-import os\n-import re\n-import reprlib\n-import struct\n-import sys\n-import xml.etree.ElementTree\n-from typing import Any, List\n-\n-\n-datatype_formats = {\n- 1: "B", # BYTE\n- 2: "s", # ASCII\n- 3: "H", # SHORT\n- 4: "I", # LONG\n- 5: "I", # RATIONAL (pairs)\n- 6: "b", # SBYTE\n- 7: "B", # UNDEFINED\n- 8: "h", # SSHORT\n- 9: "i", # SLONG\n- 10: "i", # SRATIONAL (pairs)\n- 11: "f", # FLOAT\n- 12: "d", # DOUBLE\n- 13: "I", # IFD\n- 16: "Q", # LONG8\n- 17: "q", # SLONG8\n- 18: "Q", # IFD8\n-}\n-rational_datatypes = {5, 10}\n-\n-\n-class TiffSurgeon:\n- """Read, manipulate and write IFDs in BigTIFF files."""\n-\n- def __init__(self, path, *, writeable=False, encoding=None):\n- self.path = path\n- self.writeable = writeable\n- self.encoding = encoding\n- self.endian = ""\n- self.ifds = None\n- self.file = open(self.path, "r+b" if self.writeable else "rb")\n- self._validate()\n-\n- def _validate(self):\n- signature = self.read("2s")\n- signature = signature.decode("ascii", errors="ignore")\n- if signature == "II":\n- self.endian = "<"\n- elif signature == "MM":\n- self.endian = ">"\n- else:\n- raise FormatError(f"Not a TIFF file (signature is \'{signature}\').")\n- version = self.read("H")\n- if version == 42:\n- raise FormatError("Cannot process classic TIFF, only BigTIFF.")\n- offset_size, reserved, first_ifd_offset = self.read("H H Q")\n- if version != 43 or offset_size != 8 or reserved != 0:\n- raise FormatError("Malformed TIFF, giving up!")\n- self.first_ifd_offset = first_ifd_offset\n-\n- def read(self, fmt, *, file=None):\n- if file is None:\n- file = self.file\n- endian = self.endian or "="\n- size = struct.calcsize(endian + fmt)\n- raw = file.read(size)\n- value = self.unpack(fmt, raw)\n- return value\n-\n- def write(self, fmt, *values):\n- if not self.writeable:\n- raise ValueError("File is opened as read-only.")\n- raw = self.pack(fmt, *values)\n- self.file.write(raw)\n-\n- def unpack(self, fmt, raw):\n- assert self.endian or re.match(r"\\d+s", fmt), \\\n- "can\'t unpack non-string before endianness is detected"\n- fmt = self.endian + fmt\n- size = struct.calcsize(fmt)\n- values = struct.unpack(fmt, raw[:size])\n- if len(values) == 1:\n- return values[0]\n- else:\n- return values\n-\n- def pack(self, fmt, *values):\n- assert self.endian, "can\'t pack without endian set"\n- fmt = self.endian + fmt\n- raw = struct.pack(fmt, *values)\n- return raw\n-\n- def read_ifds(self):\n- ifds = [self.read_ifd(self.first_ifd_offset)]\n- while ifds[-1].offset_next:\n- ifds.append(self.read_ifd(ifds[-1].offset_next))\n- self.ifds = ifds\n-\n- def read_ifd(self, offset):\n- self.file.seek(offset)\n- num_tags = self.read("Q")\n- buf = io.BytesIO(self.file.read(num_tags * 20))\n- offset_next = self.read("Q")\n- try:\n- tags = TagSet([self.read_tag(buf) for i in range(num_tags)])\n- except FormatError as e:\n- raise FormatError(f"IFD at offset {offset}, {e}") from None\n- ifd = Ifd(tags, offset, offset_next)\n- return ifd\n-\n- def read_tag(self, buf):\n- tag = Tag(*self.read("H H Q 8s", file=buf))\n- value, offset_range = self.tag_value(tag)\n- tag = dataclasses.replace(tag, value=value, offset_range=offset_range)\n- return tag\n-\n- def append_ifd_sequence(self, ifds):\n- """Write list of IFDs as a chained sequence at the end of the file.\n-\n- Returns a list of new Ifd objects with updated offsets.\n-\n- """\n- self.file.seek(0, os.SEEK_END)\n- new_ifds = ['..b'f"Number of channels: {size_c}")\n- print(f"Pyramid sub-resolutions ({num_levels - 1} total):")\n- for dim_x, dim_y in page_dims[size_c::size_c]:\n- print(f" {dim_x} x {dim_y}")\n- software = tiff.ifds[0].tags.get_value(305, "<not set>")\n- print(f"Software: {software}")\n- print()\n-\n- print("Updating OME-XML metadata...")\n- # We already verified there is nothing but Image elements under the root.\n- for other_image in root[1:]:\n- root.remove(other_image)\n- for tiffdata in pixels.findall("ome:TiffData", xml_ns):\n- pixels.remove(tiffdata)\n- new_tiffdata = xml.etree.ElementTree.Element(\n- f"{{{xml_ns[\'ome\']}}}TiffData",\n- attrib={"IFD": "0", "PlaneCount": str(size_c)},\n- )\n- # A valid OME-XML Pixels begins with size_c Channels; then comes TiffData.\n- pixels.insert(size_c, new_tiffdata)\n-\n- if args.channel_names:\n- print("Renaming channels...")\n- channels = pixels.findall("ome:Channel", xml_ns)\n- for channel, name in zip(channels, args.channel_names):\n- channel.attrib["Name"] = name\n-\n- fix_attrib_namespace(root)\n- # ElementTree.tostring would have been simpler but it only supports\n- # xml_declaration and default_namespace starting with Python 3.8.\n- xml_file = io.BytesIO()\n- tree = xml.etree.ElementTree.ElementTree(root)\n- tree.write(\n- xml_file,\n- encoding="utf-8",\n- xml_declaration=True,\n- default_namespace=xml_ns["ome"],\n- )\n- new_omexml = xml_file.getvalue()\n-\n- print("Writing new TIFF headers...")\n- stale_ranges = [ifd.offset_range for ifd in tiff.ifds]\n- main_ifds = tiff.ifds[:size_c]\n- channel_sub_ifds = [tiff.ifds[c + size_c::size_c] for c in range(size_c)]\n- for i, (main_ifd, sub_ifds) in enumerate(zip(main_ifds, channel_sub_ifds)):\n- for ifd in sub_ifds:\n- if 305 in ifd.tags:\n- stale_ranges.append(ifd.tags[305].offset_range)\n- del ifd.tags[305]\n- ifd.tags.insert(tiff.append_tag_data(254, 3, 1))\n- if i == 0:\n- stale_ranges.append(main_ifd.tags[305].offset_range)\n- stale_ranges.append(main_ifd.tags[270].offset_range)\n- old_software = main_ifd.tags[305].value.replace("Faas", "F*a*a*s")\n- new_software = f"pyramid_upgrade.py (was {old_software})"\n- main_ifd.tags.insert(tiff.append_tag_data(305, 2, new_software))\n- main_ifd.tags.insert(tiff.append_tag_data(270, 2, new_omexml))\n- else:\n- if 305 in main_ifd.tags:\n- stale_ranges.append(main_ifd.tags[305].offset_range)\n- del main_ifd.tags[305]\n- sub_ifds[:] = tiff.append_ifd_sequence(sub_ifds)\n- offsets = [ifd.offset for ifd in sub_ifds]\n- main_ifd.tags.insert(tiff.append_tag_data(330, 16, offsets))\n- main_ifds = tiff.append_ifd_sequence(main_ifds)\n- tiff.write_first_ifd_offset(main_ifds[0].offset)\n-\n- print("Clearing old headers and tag values...")\n- # We overwrite all the old IFDs and referenced data values with obvious\n- # "filler" as a courtesy to anyone who might need to poke around in the TIFF\n- # structure down the road. A real TIFF parser wouldn\'t see the stale data,\n- # but a human might just scan for the first thing that looks like a run of\n- # OME-XML and not realize it\'s been replaced with something else. The filler\n- # content is the repeated string "unused " with square brackets at the\n- # beginning and end of each filled IFD or data value.\n- filler = b"unused "\n- f_len = len(filler)\n- for r in stale_ranges:\n- tiff.file.seek(r.start)\n- tiff.file.write(b"[")\n- f_total = len(r) - 2\n- for i in range(f_total // f_len):\n- tiff.file.write(filler)\n- tiff.file.write(b" " * (f_total % f_len))\n- tiff.file.write(b"]")\n-\n- tiff.close()\n-\n- print()\n- print("Success!")\n-\n-\n-if __name__ == "__main__":\n- main()\n' |