Mercurial > repos > iuc > imagej2_analyze_skeleton
comparison jython_script.py @ 0:a989ca433027 draft
planemo upload commit 8f8692e83217a072a3ed928469621f1f606ab28a-dirty
| author | iuc |
|---|---|
| date | Tue, 04 Aug 2015 11:14:30 -0400 |
| parents | |
| children | dd8e4e000d2f |
comparison
equal
deleted
inserted
replaced
| -1:000000000000 | 0:a989ca433027 |
|---|---|
| 1 import jython_utils | |
| 2 import math | |
| 3 import sys | |
| 4 from ij import IJ | |
| 5 from ij import ImagePlus | |
| 6 from skeleton_analysis import AnalyzeSkeleton_ | |
| 7 | |
| 8 BASIC_NAMES = [ 'Branches', 'Junctions', 'End-point Voxels', | |
| 9 'Junction Voxels', 'Slab Voxels', 'Average branch length', | |
| 10 'Triple Points', 'Quadruple Points', 'Maximum Branch Length' ] | |
| 11 DETAIL_NAMES = [ 'Skeleton ID', 'Branch length', 'V1 x', 'V1 y', 'V1 z', 'V2 x', | |
| 12 'V2 y', 'V2 z', 'Euclidean distance' ] | |
| 13 VALID_IMAGE_TYPES = [ ImagePlus.GRAY8 ] | |
| 14 | |
| 15 def asbool( val ): | |
| 16 return val == 'yes' | |
| 17 | |
| 18 def get_euclidean_distance( vertex1, vertex2 ): | |
| 19 x1, y1, z1 = get_points( vertex1 ) | |
| 20 x2, y2, z2 = get_points( vertex2 ) | |
| 21 return math.sqrt( math.pow( ( x2 - x1 ), 2 ) + | |
| 22 math.pow( ( y2 - y1 ), 2 ) + | |
| 23 math.pow( ( z2 - z1 ), 2 ) ) | |
| 24 | |
| 25 def get_graph_length( graph ): | |
| 26 length = 0 | |
| 27 for edge in graph.getEdges(): | |
| 28 length = length + edge.getLength() | |
| 29 return length | |
| 30 | |
| 31 def get_points( vertex ): | |
| 32 # An array of Point, which has attributes x,y,z. | |
| 33 point = vertex.getPoints()[ 0 ] | |
| 34 return point.x, point.y, point.z | |
| 35 | |
| 36 def get_sorted_edge_lengths( graph ): | |
| 37 # Return graph edges sorted from longest to shortest. | |
| 38 edges = graph.getEdges() | |
| 39 edges = sorted( edges, key=lambda edge: edge.getLength(), reverse=True ) | |
| 40 return edges | |
| 41 | |
| 42 def get_sorted_graph_lengths( result ): | |
| 43 # Get the separate graphs (skeletons). | |
| 44 graphs = result.getGraph() | |
| 45 # Sort graphs from longest to shortest. | |
| 46 graphs = sorted( graphs, key=lambda g: get_graph_length( g ), reverse=True ) | |
| 47 return graphs | |
| 48 | |
| 49 def save( result, output, show_detailed_info, calculate_largest_shortest_path, sep='\t' ): | |
| 50 num_trees = int( result.getNumOfTrees() ) | |
| 51 outf = open( output, 'wb' ) | |
| 52 outf.write( '# %s\n' % sep.join( BASIC_NAMES ) ) | |
| 53 for index in range( num_trees ): | |
| 54 outf.write( '%d%s' % ( result.getBranches()[ index ], sep ) ) | |
| 55 outf.write( '%d%s' % ( result.getJunctions()[ index ], sep ) ) | |
| 56 outf.write( '%d%s' % ( result.getEndPoints()[ index ], sep ) ) | |
| 57 outf.write( '%d%s' % ( result.getJunctionVoxels()[ index ], sep ) ) | |
| 58 outf.write( '%d%s' % ( len( result.getListOfSlabVoxels() ), sep ) ) | |
| 59 outf.write( '%.3f%s' % ( result.getAverageBranchLength()[ index ], sep ) ) | |
| 60 outf.write( '%d%s' % ( result.getTriples()[ index ], sep ) ) | |
| 61 outf.write( '%d%s' % ( result.getQuadruples()[ index ], sep ) ) | |
| 62 outf.write( '%.3f' % result.getMaximumBranchLength()[ index ] ) | |
| 63 if calculate_largest_shortest_path: | |
| 64 outf.write( '%s%.3f%s' % ( sep, result.shortestPathList.get( index ), sep ) ) | |
| 65 outf.write( '%d%s' % ( result.spStartPosition[ index ][ 0 ], sep ) ) | |
| 66 outf.write( '%d%s' % ( result.spStartPosition[ index ][ 1 ], sep ) ) | |
| 67 outf.write( '%d\n' % result.spStartPosition[ index ][ 2 ] ) | |
| 68 else: | |
| 69 outf.write( '\n' ) | |
| 70 if show_detailed_info: | |
| 71 outf.write( '# %s\n' % sep.join( DETAIL_NAMES ) ) | |
| 72 # The following index is a placeholder for the skeleton ID. | |
| 73 # The terms "graph" and "skeleton" refer to the same thing. | |
| 74 # Also, the SkeletonResult.java code states that the | |
| 75 # private Graph[] graph object is an array of graphs (one | |
| 76 # per tree). | |
| 77 for index, graph in enumerate( get_sorted_graph_lengths( result ) ): | |
| 78 for edge in get_sorted_edge_lengths( graph ): | |
| 79 vertex1 = edge.getV1() | |
| 80 x1, y1, z1 = get_points( vertex1 ) | |
| 81 vertex2 = edge.getV2() | |
| 82 x2, y2, z2 = get_points( vertex2 ) | |
| 83 outf.write( '%d%s' % ( index+1, sep ) ) | |
| 84 outf.write( '%.3f%s' % ( edge.getLength(), sep ) ) | |
| 85 outf.write( '%d%s' % ( x1, sep ) ) | |
| 86 outf.write( '%d%s' % ( y1, sep ) ) | |
| 87 outf.write( '%d%s' % ( z1, sep ) ) | |
| 88 outf.write( '%d%s' % ( x2, sep ) ) | |
| 89 outf.write( '%d%s' % ( y2, sep ) ) | |
| 90 outf.write( '%d%s' % ( z2, sep ) ) | |
| 91 outf.write( '%.3f' % get_euclidean_distance( vertex1, vertex2 ) ) | |
| 92 if calculate_largest_shortest_path: | |
| 93 # Keep number of separated items the same for each line. | |
| 94 outf.write( '%s %s' % ( sep, sep ) ) | |
| 95 outf.write( ' %s' % sep ) | |
| 96 outf.write( ' %s' % sep ) | |
| 97 outf.write( ' \n' ) | |
| 98 else: | |
| 99 outf.write( '\n' ) | |
| 100 outf.close() | |
| 101 | |
| 102 # Fiji Jython interpreter implements Python 2.5 which does not | |
| 103 # provide support for argparse. | |
| 104 error_log = sys.argv[ -7 ] | |
| 105 input = sys.argv[ -6 ] | |
| 106 prune_cycle_method = sys.argv[ -5 ] | |
| 107 prune_ends = asbool( sys.argv[ -4 ] ) | |
| 108 calculate_largest_shortest_path = asbool( sys.argv[ -3 ] ) | |
| 109 if calculate_largest_shortest_path: | |
| 110 BASIC_NAMES.extend( [ 'Longest Shortest Path', 'spx', 'spy', 'spz' ] ) | |
| 111 DETAIL_NAMES.extend( [ ' ', ' ', ' ', ' ' ] ) | |
| 112 show_detailed_info = asbool( sys.argv[ -2 ] ) | |
| 113 output = sys.argv[ -1 ] | |
| 114 | |
| 115 # Open the input image file. | |
| 116 input_image_plus = IJ.openImage( input ) | |
| 117 bit_depth = input_image_plus.getBitDepth() | |
| 118 image_type = input_image_plus.getType() | |
| 119 | |
| 120 # Create a copy of the image. | |
| 121 input_image_plus_copy = input_image_plus.createImagePlus() | |
| 122 image_processor_copy = input_image_plus.getProcessor().duplicate() | |
| 123 input_image_plus_copy.setProcessor( "iCopy", image_processor_copy ) | |
| 124 | |
| 125 try: | |
| 126 if image_type not in VALID_IMAGE_TYPES: | |
| 127 # Convert the image to binary grayscale. | |
| 128 IJ.run( input_image_plus_copy, "Make Binary","" ) | |
| 129 # Run AnalyzeSkeleton | |
| 130 analyze_skeleton = AnalyzeSkeleton_() | |
| 131 analyze_skeleton.setup( "", input_image_plus_copy ) | |
| 132 if prune_cycle_method == 'none': | |
| 133 prune_index = analyze_skeleton.NONE | |
| 134 elif prune_cycle_method == 'shortest_branch': | |
| 135 prune_index = analyze_skeleton.SHORTEST_BRANCH | |
| 136 elif prune_cycle_method == 'lowest_intensity_voxel': | |
| 137 prune_index = analyze_skeleton.LOWEST_INTENSITY_VOXEL | |
| 138 elif prune_cycle_method == 'lowest_intensity_branch': | |
| 139 prune_index = analyze_skeleton.LOWEST_INTENSITY_BRANCH | |
| 140 result = analyze_skeleton.run( prune_index, | |
| 141 prune_ends, | |
| 142 calculate_largest_shortest_path, | |
| 143 input_image_plus_copy, | |
| 144 True, | |
| 145 True ) | |
| 146 # Save the results. | |
| 147 save( result, output, show_detailed_info, calculate_largest_shortest_path ) | |
| 148 except Exception, e: | |
| 149 jython_utils.handle_error( error_log, str( e ) ) |
