Mercurial > repos > iuc > imagej2_bunwarpj_elastic_transform
changeset 0:0219a764e425 draft
planemo upload commit 7195716d447effc5bc32154279de4b84369eccdb-dirty
| author | iuc |
|---|---|
| date | Fri, 19 Jun 2015 17:00:07 -0400 |
| parents | |
| children | 9e8524cf6c84 |
| files | imagej2_base_utils.py imagej2_bunwarpj_elastic_transform.py imagej2_bunwarpj_elastic_transform.xml imagej2_macros.xml jython_script.py jython_utils.py test-data/blobs.gif test-data/blobs_direct_transf.txt test-data/dotblot.jpg test-data/registered_source1.png tool_dependencies.xml |
| diffstat | 11 files changed, 465 insertions(+), 0 deletions(-) [+] |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/imagej2_base_utils.py Fri Jun 19 17:00:07 2015 -0400 @@ -0,0 +1,156 @@ +import os +import shutil +import sys +import tempfile + +FIJI_JAR_DIR = os.environ.get( 'FIJI_JAR_DIR', None ) +FIJI_OSX_JAVA3D_DIR = os.environ.get( 'FIJI_OSX_JAVA3D_DIR', None ) +FIJI_PLUGIN_DIR = os.environ.get( 'FIJI_PLUGIN_DIR', None ) +FIJI_ROOT_DIR = os.environ.get( 'FIJI_ROOT_DIR', None ) + +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 FIJI_JAR_DIR is not None and FIJI_PLUGIN_DIR is not None: + if jvm_memory in [ None, 'None' ]: + jvm_memory_str = '' + else: + jvm_memory_str = '-Xmx%s' % jvm_memory + bunwarpj_base_cmd = "java %s -cp %s/ij-1.49k.jar:%s/bUnwarpJ_-2.6.1.jar bunwarpj.bUnwarpJ_" % \ + ( jvm_memory_str, FIJI_JAR_DIR, FIJI_PLUGIN_DIR ) + return bunwarpj_base_cmd + return None + +def get_base_command_imagej2( memory_size=None, macro=None, jython_script=None ): + imagej2_executable = get_imagej2_executable() + if imagej2_executable: + cmd = '%s --headless -DXincgc' % 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 -u %s' % os.path.abspath( jython_script ) + return cmd + return None + +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, so figure out which name we need. + """ + platform_dict = get_platform_info_dict() + if platform_dict.get( 'architecture', None ) in [ 'x86_64' ]: + if platform_dict.get( 'os', None ) in [ 'darwin' ]: + return 'ImageJ-macosx' + if platform_dict.get( 'os', None ) in [ 'linux' ]: + return 'ImageJ-linux64' + return None + +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_max_heap_size_value( max_heap_size_type, max_heap_size ): + """ + Return a string that can be used by the javabridge to set the size + of the memory allocation pool used by the JVM. The value must be + determined to be a multiple of 1024 or it will be ignored. + """ + if max_heap_size_type == 'default': + return None + if max_heap_size_type == 'megabytes': + if max_heap_size % 1024 not in [ 0, 256, 512 ]: + return None + return '%sm' % str( max_heap_size ) + if max_heap_size_type == 'gigabytes': + return '%sg' % str( max_heap_size ) + +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_stdout ): + 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() + tmp_stdout.close() + return str( 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 stop_err( msg ): + sys.stderr.write( msg ) + sys.exit( 1 )
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/imagej2_bunwarpj_elastic_transform.py Fri Jun 19 17:00:07 2015 -0400 @@ -0,0 +1,79 @@ +#!/usr/bin/env python +import argparse +import os +import shutil +import subprocess +import tempfile +import imagej2_base_utils + +# Parse Command Line. +parser = argparse.ArgumentParser() +parser.add_argument( '--source_image', dest='source_image', help='Source image' ) +parser.add_argument( '--source_image_format', dest='source_image_format', help='Source image format' ) +parser.add_argument( '--target_image', dest='target_image', help='Target image' ) +parser.add_argument( '--target_image_format', dest='target_image_format', help='Target image format' ) +parser.add_argument( '--elastic_transformation', dest='elastic_transformation', default=None, help='Elastic transformation as saved by bUnwarpJ in elastic format' ) +parser.add_argument( '--source_out', help='Output source image' ) +parser.add_argument( '--source_out_datatype', help='Output registered source image format' ) +parser.add_argument( '--jython_script', dest='jython_script', help='Path to the Jython script' ) +parser.add_argument( '--max_heap_size_type', dest='max_heap_size_type', help='Type (default or megabytes) of max_heap_size value' ) +parser.add_argument( '--max_heap_size', dest='max_heap_size', help='Maximum size of the memory allocation pool used by the JVM.' ) + +args = parser.parse_args() + +tmp_dir = imagej2_base_utils.get_temp_dir() +source_image_path = imagej2_base_utils.get_input_image_path( tmp_dir, args.source_image, args.source_image_format ) +tmp_source_out_tiff_path = imagej2_base_utils.get_temporary_image_path( tmp_dir, 'tiff' ) +tmp_source_out_path = imagej2_base_utils.get_temporary_image_path( tmp_dir, args.source_out_datatype ) +target_image_path = imagej2_base_utils.get_input_image_path( tmp_dir, args.target_image, args.target_image_format ) +elastic_transformation_path = imagej2_base_utils.get_input_image_path( tmp_dir, args.elastic_transformation, 'txt' ) + +# Set the size of the memory allocation pool used by the JVM. +memory_size = imagej2_base_utils.get_max_heap_size_value( args.max_heap_size_type, args.max_heap_size ) + +# 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' ) + +# Build the command line to align the two images. +cmd = imagej2_base_utils.get_base_cmd_bunwarpj( memory_size ) +if cmd is None: + imagej2_base_utils.stop_err( "bUnwarpJ not found!" ) +cmd += ' -elastic_transform' +# Target is sent before source. +cmd += ' %s' % target_image_path +cmd += ' %s' % source_image_path +cmd += ' %s' % elastic_transformation_path +cmd += ' %s' % tmp_source_out_tiff_path + +# Apply the elastic transformation using bUnwarpJ. +proc = subprocess.Popen( args=cmd, stderr=tmp_stderr, stdout=tmp_stdout, shell=True ) +rc = proc.wait() +if rc != 0: + error_message = imagej2_base_utils.get_stderr_exception( tmp_err, tmp_stderr, tmp_stdout ) + imagej2_base_utils.stop_err( error_message ) + +# Convert the registered image to the specified output format. +tmp_out = tempfile.NamedTemporaryFile().name +tmp_stdout = open( tmp_out, 'wb' ) +tmp_err = tempfile.NamedTemporaryFile().name +tmp_stderr = open( tmp_err, 'wb' ) + +cmd = imagej2_base_utils.get_base_command_imagej2( memory_size, jython_script=args.jython_script ) +if cmd is None: + imagej2_base_utils.stop_err( "ImageJ not found!" ) +cmd += ' %s %s %s' % ( tmp_source_out_tiff_path, + args.source_out_datatype, + tmp_source_out_path ) + +proc = subprocess.Popen( args=cmd, stderr=tmp_stderr, stdout=tmp_stdout, shell=True ) +rc = proc.wait() +if rc != 0: + error_message = imagej2_base_utils.get_stderr_exception( tmp_err, tmp_stderr, tmp_stdout ) + imagej2_base_utils.stop_err( error_message ) + +# Save the Registered Source Image to the defined output. +shutil.move( tmp_source_out_path, args.source_out ) +imagej2_base_utils.cleanup_before_exit( tmp_dir )
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/imagej2_bunwarpj_elastic_transform.xml Fri Jun 19 17:00:07 2015 -0400 @@ -0,0 +1,84 @@ +<?xml version='1.0' encoding='UTF-8'?> +<tool id="imagej2_bunwarpj_elastic_transform" name="Apply elastic transformation" version="1.0.0"> + <description>with bUnwarpJ</description> + <macros> + <import>imagej2_macros.xml</import> + </macros> + <expand macro="fiji_headless_requirements" /> + <command> +<![CDATA[ + python $__tool_directory__/imagej2_bunwarpj_elastic_transform.py + --target_image "$target_image" + --target_image_format $target_image.ext + --source_image "$source_image" + --source_image_format $source_image.ext + --elastic_transformation $elastic_transformation + --source_out "$source_out" + --source_out_datatype $source_out_datatype + --jython_script $__tool_directory__/jython_script.py + --max_heap_size_type $set_max_heap_size.max_heap_size_type + --max_heap_size $set_max_heap_size.max_heap_size +]]> + </command> + <inputs> + <param format="bmp,eps,gif,jpg,pcx,pgm,png,psd,tiff" name="target_image" type="data" label="Target image"/> + <param format="bmp,eps,gif,jpg,pcx,pgm,png,psd,tiff" name="source_image" type="data" label="Source image"/> + <!-- Support for a bUnwarpJ elastic transformation datatype should be added to Galaxy --> + <param format="txt" name="elastic_transformation" type="data" label="Elastic transformation" help="As saved by bUnwarpJ in elastic format"/> + <param name="source_out_datatype" type="select" label="Save registered source image as format"> + <expand macro="image_datatypes" /> + </param> + <expand macro="max_heap_size_type_conditional" /> + </inputs> + <outputs> + <data name="source_out" format="png" label="${tool.name} on ${on_string}: Registered source image"> + <actions> + <action type="format"> + <option type="from_param" name="source_out_datatype" /> + </action> + </actions> + </data> + </outputs> + <tests> + <test> + <param name="target_image" value="dotblot.jpg" /> + <param name="source_image" value="blobs.gif" /> + <param name="elastic_transformation" value="blobs_direct_transf.txt" /> + <param name="source_out_datatype" value="png" /> + <output name="source_out" file="registered_source1.png" compare="sim_size" /> + </test> + </tests> + <help> +**What it does** + +<![CDATA[ +Applies an elastic transformation to an image, producing another image which is elastically +deformed according to the transformation. The transformation file must be in the same format +as the files created with the **Save Transformation** option in the **Align two images with bUnwarpJ** +tool. + +]]> + + </help> + <citations> + <citation type="bibtex"> + @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") + </citation> + <citation type="doi">10.1038/nmeth.2019</citation> + </citations> +</tool>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/imagej2_macros.xml Fri Jun 19 17:00:07 2015 -0400 @@ -0,0 +1,81 @@ +<?xml version='1.0' encoding='UTF-8'?> +<macros> + <xml name="fiji_headless_requirements"> + <requirements> + <requirement type="package" version="20141125">fiji</requirement> + </requirements> + </xml> + <xml name="python_bioformats_requirements"> + <requirements> + <requirement type="package" version="20141125">fiji</requirement> + <requirement type="package" version="1.0.11">javabridge</requirement> + <requirement type="package" version="1.9">numpy</requirement> + <requirement type="package" version="1.0.4">python_bioformats</requirement> + </requirements> + </xml> + <xml name="stdio"> + <stdio> + <exit_code range="1:"/> + <exit_code range=":-1"/> + <regex match="Error:"/> + <regex match="Exception:"/> + </stdio> + </xml> + <xml name="image_type"> + <param name="image_type" type="select" label="Image type"> + <option value="8-bit_white" selected="True">8-bit white</option> + <option value="8-bit_black">8-bit black</option> + <option value="8-bit_random">8-bit random</option> + <option value="8-bit_ramp">8-bit ramp</option> + <option value="16-bit_white">16-bit white</option> + <option value="16-bit_black">16-bit black</option> + <option value="16-bit_random">16-bit random</option> + <option value="16-bit_ramp">16-bit ramp</option> + <option value="32-bit_white">32-bit white</option> + <option value="32-bit_black">32-bit black</option> + <option value="32-bit_random">32-bit random</option> + <option value="32-bit_ramp">32-bit ramp</option> + <option value="RGB_white">RGB white</option> + <option value="RGB_black">RGB black</option> + <option value="RGB_random">RGB random</option> + <option value="RGB_ramp">RGB ramp</option> + </param> + </xml> + <xml name="max_heap_size_type_conditional"> + <conditional name="set_max_heap_size"> + <param name="max_heap_size_type" type="select" label="Maximum size of the memory allocation pool used by the JVM" help="This value must be a multiple of 1024 or it will be ignored and the system default will be used."> + <option value="default" selected="True">Do not set</option> + <option value="megabytes">Set in megabytes</option> + <option value="gigabytes">Set in gigabytes</option> + </param> + <when value="default"> + <param name="max_heap_size" type="integer" value="0" label="Do not set" help="Use system default"/> + </when> + <when value="megabytes"> + <param name="max_heap_size" type="integer" value="512" min="256" label="Maximum size, in megabytes, of the memory allocation pool" help="Examples: 256, 512, etc."/> + </when> + <when value="gigabytes"> + <param name="max_heap_size" type="integer" value="1" min="1" label="Maximum size, in gigabytes, of the memory allocation pool" help="Examples: 1, 2, etc."/> + </when> + </conditional> + </xml> + <xml name="image_datatypes"> + <option value="bmp">bmp</option> + <option value="gif">gif</option> + <option value="jpg">jpg</option> + <option value="png" selected="true">png</option> + <option value="tiff">tiff</option> + </xml> + <xml name="fiji_headless_citations"> + <citations> + <citation type="doi">10.1038/nmeth.2102</citation> + </citations> + </xml> + <xml name="citations"> + <citations> + <citation type="doi">10.1038/nmeth.2102</citation> + <citation type="doi">10.1038/nmeth.2019</citation> + <citation type="doi">10.1083/jcb.201004104</citation> + </citations> + </xml> +</macros>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jython_script.py Fri Jun 19 17:00:07 2015 -0400 @@ -0,0 +1,16 @@ +import sys +import jython_utils +from ij import IJ + +# Fiji Jython interpreter implements Python 2.5 which does not +# provide support for argparse. + +source_tiff_path = sys.argv[ -3 ] +source_datatype = sys.argv[ -2 ] +source_path = sys.argv[ -1 ] + +# Save the Registered Source Image. +registered_source_image = IJ.openImage( source_tiff_path ) +if source_datatype == 'tiff': + registered_source_image = jython_utils.convert_before_saving_as_tiff( registered_source_image ) +IJ.saveAs( registered_source_image, source_datatype, source_path )
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jython_utils.py Fri Jun 19 17:00:07 2015 -0400 @@ -0,0 +1,24 @@ +import imagej2_base_utils +from ij import IJ + +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 )
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test-data/blobs_direct_transf.txt Fri Jun 19 17:00:07 2015 -0400 @@ -0,0 +1,19 @@ +Intervals=4 + +X Coeffs ----------------------------------- + -34.14981674286569 3.144052189417975 44.74398427283767 72.62900018057132 111.3348086331012 134.27021754923854 171.74048996962574 + -46.475609806523806 -28.37507243951631 71.19906566193379 30.10778479539863 122.71885776990422 109.9563576074076 171.94005579124322 + -57.04494430952696 1.8032931596380026 61.404945193416715 42.75919945626539 148.2715738833391 126.39195563069309 116.8758739961032 + -26.50696765072751 24.133275156317662 45.18779137671111 49.91727740928712 130.5425749032711 160.35055773949284 186.2385413131219 + 30.36695633747302 -3.333376652604397 35.957597759623795 86.8060703274396 102.5208634329241 126.298277744805 243.1342175649626 + -2.831201175463878 -4.836159041803193 36.263197544298954 77.65977608215381 98.47306066697166 149.98143182373533 193.72941653859635 + -33.88117649278133 7.9003473752729985 41.603347919804314 72.11109321021485 111.05849721622616 148.16049042863358 181.51669289966162 + +Y Coeffs ----------------------------------- + -32.99874935645494 -10.853014366833959 -18.11337422707787 120.45933796140201 -11.717505555260894 -42.65980408275417 -41.34878020779432 + 11.306632136922623 42.01572254879719 -18.137465736571315 41.67904406737918 -9.059457409112 -63.14804168936847 -7.646807909694754 + 20.638424092275454 35.302620259132304 1.8587715711200654 2.065183621887666 13.47064662534885 8.966817348422527 65.74329336525717 + 79.92027086396175 117.61262084713007 78.2409336472003 102.3526144171297 97.29273111510625 48.80095761073018 89.32772899111102 + 121.0699654326738 114.38154300759474 23.57251043213103 101.87328690674049 115.94282218472065 106.18526585145909 111.14979545782822 + 140.58687592247674 130.54971240393465 177.05271414686374 150.48052118800214 150.41722526235608 156.3116913517668 146.21075369002716 + 175.51191703543347 174.9228152249439 173.31675176966468 181.87538254503764 170.81399893021742 186.14994867024973 185.85560874061068
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tool_dependencies.xml Fri Jun 19 17:00:07 2015 -0400 @@ -0,0 +1,6 @@ +<?xml version="1.0"?> +<tool_dependency> + <package name="fiji" version="20141125"> + <repository changeset_revision="7121a1ea4839" name="package_fiji_20141125" owner="iuc" toolshed="https://testtoolshed.g2.bx.psu.edu" /> + </package> +</tool_dependency>
