# HG changeset patch
# User greg
# Date 1563971437 14400
# Node ID 0729a4b20e67120c695962e5891de2cad91b642d
Uploaded
diff -r 000000000000 -r 0729a4b20e67 .shed.yml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/.shed.yml Wed Jul 24 08:30:37 2019 -0400
@@ -0,0 +1,19 @@
+name: imagej2_adjust_threshold_binary
+owner: greg
+homepage_url: http://fiji.sc
+long_description: |
+ ImageJ2 is a new version of ImageJ for the next generation of multidimensional
+ image data, with a focus on scientific imaging. Its central goal is to broaden
+ the paradigm of ImageJ beyond the limitations of ImageJ 1.x, to support the next
+ generation of multidimensional scientific imaging.
+
+ ImageJ2 is also a collection of reusable software libraries built on the SciJava
+ software stack, using a powerful plugin framework to facilitate rapid development
+ and painless user customization.
+
+ The Fiji distribution of ImageJ has shipped with beta versions of ImageJ2 for
+ quite some time.
+remote_repository_url: https://github.com/bgruening/galaxytools/tree/master/tools/image_processing/imagej2
+type: unrestricted
+categories:
+ - Imaging
diff -r 000000000000 -r 0729a4b20e67 imagej2_adjust_threshold_binary.py
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/imagej2_adjust_threshold_binary.py Wed Jul 24 08:30:37 2019 -0400
@@ -0,0 +1,63 @@
+#!/usr/bin/env python
+import argparse
+import os
+import shutil
+import subprocess
+import tempfile
+import imagej2_base_utils
+
+parser = argparse.ArgumentParser()
+parser.add_argument( '--input', dest='input', help='Path to the input file' )
+parser.add_argument( '--input_datatype', dest='input_datatype', help='Datatype of the input image' )
+parser.add_argument( '--threshold_min', dest='threshold_min', type=float, help='Minimum threshold value' )
+parser.add_argument( '--threshold_max', dest='threshold_max', type=float, help='Maximum threshold value' )
+parser.add_argument( '--method', dest='method', help='Threshold method' )
+parser.add_argument( '--display', dest='display', help='Display mode' )
+parser.add_argument( '--black_background', dest='black_background', help='Black background' )
+parser.add_argument( '--stack_histogram', dest='stack_histogram', help='Stack histogram' )
+parser.add_argument( '--jython_script', dest='jython_script', help='Path to the Jython script' )
+parser.add_argument( '--output', dest='output', help='Path to the output file' )
+parser.add_argument( '--output_datatype', dest='output_datatype', help='Datatype of the output image' )
+args = parser.parse_args()
+
+tmp_dir = imagej2_base_utils.get_temp_dir()
+# ImageJ expects valid image file extensions, so the Galaxy .dat extension does not
+# work for some features. The following creates a symlink with an appropriate file
+# extension that points to the Galaxy dataset. This symlink is used by ImageJ.
+tmp_input_path = imagej2_base_utils.get_input_image_path( tmp_dir, args.input, args.input_datatype )
+tmp_output_path = imagej2_base_utils.get_temporary_image_path( tmp_dir, args.output_datatype )
+# Define command response buffers.
+tmp_out = tempfile.NamedTemporaryFile().name
+tmp_stdout = open( tmp_out, 'wb' )
+tmp_err = tempfile.NamedTemporaryFile().name
+tmp_stderr = open( tmp_err, 'wb' )
+# Java writes a lot of stuff to stderr, so we'll specify a file for handling actual errors.
+error_log = tempfile.NamedTemporaryFile( delete=False ).name
+# Build the command line.
+cmd = imagej2_base_utils.get_base_command_imagej2( None, jython_script=args.jython_script )
+if cmd is None:
+ imagej2_base_utils.stop_err( "ImageJ not found!" )
+cmd += ' %s' % error_log
+cmd += ' %s' % tmp_input_path
+cmd += ' %.3f' % args.threshold_min
+cmd += ' %.3f' % args.threshold_max
+cmd += ' %s' % args.method
+cmd += ' %s' % args.display
+cmd += ' %s' % args.black_background
+cmd += ' %s' % args.stack_histogram
+cmd += ' %s' % tmp_output_path
+cmd += ' %s' % args.output_datatype
+# Run the command.
+proc = subprocess.Popen( args=cmd, stderr=tmp_stderr, stdout=tmp_stdout, shell=True )
+rc = proc.wait()
+# Handle execution errors.
+if rc != 0:
+ error_message = imagej2_base_utils.get_stderr_exception( tmp_err, tmp_stderr, tmp_out, tmp_stdout )
+ imagej2_base_utils.stop_err( error_message )
+# Handle processing errors.
+if os.path.getsize( error_log ) > 0:
+ error_message = open( error_log, 'r' ).read()
+ imagej2_base_utils.stop_err( error_message )
+# Save the output image.
+shutil.move( tmp_output_path, args.output )
+imagej2_base_utils.cleanup_before_exit( tmp_dir )
diff -r 000000000000 -r 0729a4b20e67 imagej2_adjust_threshold_binary.xml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/imagej2_adjust_threshold_binary.xml Wed Jul 24 08:30:37 2019 -0400
@@ -0,0 +1,115 @@
+
+
+ of binary image
+
+ imagej2_macros.xml
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+@requires_binary_input@
+
+**What it does**
+
+
+
+
+
+
diff -r 000000000000 -r 0729a4b20e67 imagej2_adjust_threshold_binary_jython_script.py
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/imagej2_adjust_threshold_binary_jython_script.py Wed Jul 24 08:30:37 2019 -0400
@@ -0,0 +1,49 @@
+import jython_utils
+import sys
+from ij import IJ
+
+# Fiji Jython interpreter implements Python 2.5 which does not
+# provide support for argparse.
+error_log = sys.argv[ -10 ]
+input = sys.argv[ -9 ]
+threshold_min = float( sys.argv[ -8 ] )
+threshold_max = float( sys.argv[ -7 ] )
+method = sys.argv[ -6 ]
+display = sys.argv[ -5 ]
+black_background = jython_utils.asbool( sys.argv[ -4 ] )
+# TODO: this is not being used.
+stack_histogram = jython_utils.asbool( sys.argv[ -3 ] )
+tmp_output_path = sys.argv[ -2 ]
+output_datatype = sys.argv[ -1 ]
+
+# Open the input image file.
+input_image_plus = IJ.openImage( input )
+
+# Create a copy of the image.
+input_image_plus_copy = input_image_plus.duplicate()
+image_processor_copy = input_image_plus_copy.getProcessor()
+
+try:
+ # Convert image to binary if necessary.
+ if not image_processor_copy.isBinary():
+ # Convert the image to binary grayscale.
+ IJ.run( input_image_plus_copy, "Make Binary","iterations=1 count=1 edm=Overwrite do=Nothing" )
+ # Set the options.
+ if black_background:
+ method_str = "%s dark" % method
+ else:
+ method_str = method
+ IJ.setAutoThreshold( input_image_plus_copy, method_str )
+ if display == "red":
+ display_mode = "Red"
+ elif display == "bw":
+ display_mode = "Black & White"
+ elif display == "over_under":
+ display_mode = "Over/Under"
+ IJ.setThreshold( input_image_plus_copy, threshold_min, threshold_max, display_mode )
+ # Run the command.
+ IJ.run( input_image_plus_copy, "threshold", "" )
+ # Save the ImagePlus object as a new image.
+ IJ.saveAs( input_image_plus_copy, output_datatype, tmp_output_path )
+except Exception, e:
+ jython_utils.handle_error( error_log, str( e ) )
diff -r 000000000000 -r 0729a4b20e67 imagej2_base_utils.py
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/imagej2_base_utils.py Wed Jul 24 08:30:37 2019 -0400
@@ -0,0 +1,169 @@
+import os
+import shutil
+import sys
+import tempfile
+
+BUFF_SIZE = 1048576
+
+
+def cleanup_before_exit(tmp_dir):
+ """
+ Remove temporary files and directories prior to tool exit.
+ """
+ if tmp_dir and os.path.exists(tmp_dir):
+ shutil.rmtree(tmp_dir)
+
+
+def get_base_cmd_bunwarpj(jvm_memory):
+ if jvm_memory in [None, 'None']:
+ jvm_memory_str = ''
+ else:
+ jvm_memory_str = '-Xmx%s' % jvm_memory
+ # The following bunwarpj_base_cmd string will look something like this:
+ # "java %s -cp $JAR_DIR/ij-1.49k.jar:$PLUGINS_DIR/bUnwarpJ_-2.6.1.jar \
+ # bunwarpj.bUnwarpJ_" % (jvm_memory_str)
+ # See the bunwarpj.sh script for the fiji 20151222
+ # bioconda recipe in github.
+ bunwarpj_base_cmd = "bunwarpj %s" % jvm_memory_str
+ return bunwarpj_base_cmd
+
+
+def get_base_command_imagej2(memory_size=None, macro=None, jython_script=None):
+ imagej2_executable = get_imagej2_executable()
+ if imagej2_executable is None:
+ return None
+ cmd = '%s --ij2 --headless --debug' % imagej2_executable
+ if memory_size is not None:
+ memory_size_cmd = ' -DXms=%s -DXmx=%s' % (memory_size, memory_size)
+ cmd += memory_size_cmd
+ if macro is not None:
+ cmd += ' --macro %s' % os.path.abspath(macro)
+ if jython_script is not None:
+ cmd += ' --jython %s' % os.path.abspath(jython_script)
+ return cmd
+
+
+def get_file_extension(image_format):
+ """
+ Return a valid bioformats file extension based on the received
+ value of image_format(e.g., "gif" is returned as ".gif".
+ """
+ return '.%s' % image_format
+
+
+def get_file_name_without_extension(file_path):
+ """
+ Eliminate the .ext from the received file name, assuming that
+ the file name consists of only a single '.'.
+ """
+ if os.path.exists(file_path):
+ path, name = os.path.split(file_path)
+ name_items = name.split('.')
+ return name_items[0]
+ return None
+
+
+def get_imagej2_executable():
+ """
+ Fiji names the ImageJ executable different names for different
+ architectures, but our bioconda recipe allows us to do this.
+ """
+ return 'ImageJ'
+
+
+def get_input_image_path(tmp_dir, input_file, image_format):
+ """
+ Bioformats uses file extensions (e.g., .job, .gif, etc)
+ when reading and writing image files, so the Galaxy dataset
+ naming convention of setting all file extensions as .dat
+ must be handled.
+ """
+ image_path = get_temporary_image_path(tmp_dir, image_format)
+ # Remove the file so we can create a symlink.
+ os.remove(image_path)
+ os.symlink(input_file, image_path)
+ return image_path
+
+
+def get_platform_info_dict():
+ '''Return a dict with information about the current platform.'''
+ platform_dict = {}
+ sysname, nodename, release, version, machine = os.uname()
+ platform_dict['os'] = sysname.lower()
+ platform_dict['architecture'] = machine.lower()
+ return platform_dict
+
+
+def get_stderr_exception(tmp_err, tmp_stderr, tmp_out, tmp_stdout, include_stdout=False):
+ tmp_stderr.close()
+ """
+ Return a stderr string of reasonable size.
+ """
+ # Get stderr, allowing for case where it's very large.
+ tmp_stderr = open(tmp_err, 'rb')
+ stderr_str = ''
+ buffsize = BUFF_SIZE
+ try:
+ while True:
+ stderr_str += tmp_stderr.read(buffsize)
+ if not stderr_str or len(stderr_str) % buffsize != 0:
+ break
+ except OverflowError:
+ pass
+ tmp_stderr.close()
+ if include_stdout:
+ tmp_stdout = open(tmp_out, 'rb')
+ stdout_str = ''
+ buffsize = BUFF_SIZE
+ try:
+ while True:
+ stdout_str += tmp_stdout.read(buffsize)
+ if not stdout_str or len(stdout_str) % buffsize != 0:
+ break
+ except OverflowError:
+ pass
+ tmp_stdout.close()
+ if include_stdout:
+ return 'STDOUT\n%s\n\nSTDERR\n%s\n' % (stdout_str, stderr_str)
+ return stderr_str
+
+
+def get_temp_dir(prefix='tmp-imagej-', dir=None):
+ """
+ Return a temporary directory.
+ """
+ return tempfile.mkdtemp(prefix=prefix, dir=dir)
+
+
+def get_tempfilename(dir=None, suffix=None):
+ """
+ Return a temporary file name.
+ """
+ fd, name = tempfile.mkstemp(suffix=suffix, dir=dir)
+ os.close(fd)
+ return name
+
+
+def get_temporary_image_path(tmp_dir, image_format):
+ """
+ Return the path to a temporary file with a valid image format
+ file extension that can be used with bioformats.
+ """
+ file_extension = get_file_extension(image_format)
+ return get_tempfilename(tmp_dir, file_extension)
+
+
+def handle_none_type(val, val_type='float'):
+ if val is None:
+ return ' None'
+ else:
+ if val_type == 'float':
+ return ' %.3f' % val
+ elif val_type == 'int':
+ return ' %d' % val
+ return ' %s' % val
+
+
+def stop_err(msg):
+ sys.stderr.write(msg)
+ sys.exit(1)
diff -r 000000000000 -r 0729a4b20e67 imagej2_base_utils.pyc
Binary file imagej2_base_utils.pyc has changed
diff -r 000000000000 -r 0729a4b20e67 imagej2_macros.xml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/imagej2_macros.xml Wed Jul 24 08:30:37 2019 -0400
@@ -0,0 +1,106 @@
+
+
+ 20170530
+
+
+ fiji
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ --iterations $iterations
+ --count $count
+ --black_background $black_background
+ --pad_edges_when_eroding $pad_edges_when_eroding
+
+
+.. class:: warningmark
+
+This tool works on binary images, so other image types will automatically be converted to binary
+before they are analyzed. This step is performed using the ImageJ2 **Make Binary** command with
+the following settings: **Iterations:** 1, **Count:** 1, **Pad edges when eroding:** No. The tool
+allows you to choose the **Black background** setting. If these settings are not appropriate,
+first manually convert the image to binary using the **Convert to binary (black and white)**
+tool, which allows you to change them.
+
+
+
+
+
+
+
+
+
+
+
+ @InProceedings(Arganda-Carreras2006,
+ author = "Ignacio Arganda-Carreras and
+ Carlos Oscar S{\'a}nchez Sorzano and
+ Roberto Marabini and
+ Jos{\'e} Mar\'{\i}a Carazo and
+ Carlos Ortiz-de-Solorzano and
+ Jan Kybic",
+ title = "Consistent and Elastic Registration of Histological Sections Using Vector-Spline Regularization",
+ publisher = "Springer Berlin / Heidelberg",
+ booktitle = "Computer Vision Approaches to Medical Image Analysis",
+ series = "Lecture Notes in Computer Science",
+ year = "2006",
+ volume = "4241",
+ pages = "85-95",
+ month = "May",
+ city = "Graz, Austria")
+
+ 10.1038/nmeth.2019
+
+
+
+
+ 10.1038/nmeth.2102
+
+
+
diff -r 000000000000 -r 0729a4b20e67 jython_utils.py
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jython_utils.py Wed Jul 24 08:30:37 2019 -0400
@@ -0,0 +1,48 @@
+import imagej2_base_utils
+from ij import IJ
+
+IMAGE_PLUS_IMAGE_TYPE_FIELD_VALUES = { '0':'GRAY8', '1':'GRAY16', '2':'GRAY32',
+ '3':'COLOR_256', '4':'COLOR_RGB' }
+
+def asbool( val ):
+ return str( val ).lower() in [ 'yes', 'true' ]
+
+def convert_before_saving_as_tiff( image_plus ):
+ # The bUnwarpJ plug-in produces TIFF image stacks consisting of 3
+ # slices which can be viewed in ImageJ. The 3 slices are: 1) the
+ # registered image, 2) the target image and 3) the black/white warp
+ # image. When running bUnwarpJ from the command line (as these
+ # Galaxy wrappers do) the initial call to IJ.openImage() (to open the
+ # registered source and target images produced by bUnwarpJ) in the
+ # tool's jython_script.py returns an ImagePlus object with a single
+ # slice which is the "generally undesired" slice 3 discussed above.
+ # However, a call to IJ.saveAs() will convert the single-slice TIFF
+ # into a 3-slice TIFF image stack (as described above) if the selected
+ # format for saving is TIFF. Galaxy supports only single-layered
+ # images, so to work around this behavior, we have to convert the
+ # image to something other than TIFF so that slices are eliminated.
+ # We can then convert back to TIFF for saving. There might be a way
+ # to do this without converting twice, but I spent a lot of time looking
+ # and I have yet to discover it.
+ tmp_dir = imagej2_base_utils.get_temp_dir()
+ tmp_out_png_path = imagej2_base_utils.get_temporary_image_path( tmp_dir, 'png' )
+ IJ.saveAs( image_plus, 'png', tmp_out_png_path )
+ return IJ.openImage( tmp_out_png_path )
+
+def get_binary_options( black_background, iterations=1, count=1, pad_edges_when_eroding='no' ):
+ options = [ 'edm=Overwrite', 'iterations=%d' % iterations, 'count=%d' % count ]
+ if asbool( pad_edges_when_eroding ):
+ options.append( 'pad' )
+ if asbool( black_background ):
+ options.append( "black" )
+ return " ".join( options )
+
+def get_display_image_type( image_type ):
+ return IMAGE_PLUS_IMAGE_TYPE_FIELD_VALUES.get( str( image_type ), None )
+
+def handle_error( error_log, msg ):
+ # Java writes a lot of stuff to stderr, so the received error_log
+ # will log actual errors.
+ elh = open( error_log, 'wb' )
+ elh.write( msg )
+ elh.close()
diff -r 000000000000 -r 0729a4b20e67 test-data/blobs.gif
Binary file test-data/blobs.gif has changed
diff -r 000000000000 -r 0729a4b20e67 test-data/blobs_threshold_default.gif
Binary file test-data/blobs_threshold_default.gif has changed
diff -r 000000000000 -r 0729a4b20e67 test-data/blobs_threshold_huang_dark.gif
Binary file test-data/blobs_threshold_huang_dark.gif has changed
diff -r 000000000000 -r 0729a4b20e67 test-data/blobs_threshold_ijiso.gif
Binary file test-data/blobs_threshold_ijiso.gif has changed