# HG changeset patch # User imgteam # Date 1549740506 18000 # Node ID 96909b9d1df128feb9e6594a279c8567d2654701 planemo upload for repository https://github.com/BMCV/galaxy-image-analysis/tools/2d_feature_extraction/ commit c3f4b766f03770f094fda6bda0a5882c0ebd4581 diff -r 000000000000 -r 96909b9d1df1 2d_feature_extraction.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/2d_feature_extraction.py Sat Feb 09 14:28:26 2019 -0500 @@ -0,0 +1,124 @@ +import argparse +import numpy as np +import pandas as pd +import tifffile +import skimage.io +import skimage.measure +import skimage.feature +import skimage.segmentation +import skimage.morphology + +#TODO make importable by python script + +parser = argparse.ArgumentParser(description='Extract Features 2D') + +#TODO create factory for boilerplate code +features = parser.add_argument_group('compute features') +features.add_argument('--all', dest='all_features', action='store_true') +features.add_argument('--label', dest='add_label', action='store_true') +features.add_argument('--patches', dest='add_roi_patches', action='store_true') +features.add_argument('--max_intensity', dest='max_intensity', action='store_true') +features.add_argument('--mean_intensity', dest='mean_intensity', action='store_true') +features.add_argument('--min_intensity', dest='min_intensity', action='store_true') +features.add_argument('--moments_hu', dest='moments_hu', action='store_true') +features.add_argument('--centroid', dest='centroid', action='store_true') +features.add_argument('--bbox', dest='bbox', action='store_true') +features.add_argument('--area', dest='area', action='store_true') +features.add_argument('--filled_area', dest='filled_area', action='store_true') +features.add_argument('--convex_area', dest='convex_area', action='store_true') +features.add_argument('--perimeter', dest='perimeter', action='store_true') +features.add_argument('--extent', dest='extent', action='store_true') +features.add_argument('--eccentricity', dest='eccentricity', action='store_true') +features.add_argument('--equivalent_diameter', dest='equivalent_diameter', action='store_true') +features.add_argument('--euler_number', dest='euler_number', action='store_true') +features.add_argument('--inertia_tensor_eigvals', dest='inertia_tensor_eigvals', action='store_true') +features.add_argument('--major_axis_length', dest='major_axis_length', action='store_true') +features.add_argument('--minor_axis_length', dest='minor_axis_length', action='store_true') +features.add_argument('--orientation', dest='orientation', action='store_true') +features.add_argument('--solidity', dest='solidity', action='store_true') +features.add_argument('--moments', dest='moments', action='store_true') +features.add_argument('--convexity', dest='convexity', action='store_true') + +parser.add_argument('--label_file_binary', dest='label_file_binary', action='store_true') + +parser.add_argument('--raw', dest='raw_file', type=argparse.FileType('r'), + help='Original input file', required=False) +parser.add_argument('label_file', type=argparse.FileType('r'), + help='Label input file') +parser.add_argument('output_file', type=argparse.FileType('w'), + help='Tabular output file') +args = parser.parse_args() + +label_file_binary = args.label_file_binary +label_file = args.label_file.name +out_file = args.output_file.name +add_patch = args.add_roi_patches + +raw_image = None +if args.raw_file is not None: + raw_image = skimage.io.imread(args.raw_file.name) + +raw_label_image = skimage.io.imread(label_file) + +df = pd.DataFrame() +if label_file_binary: + raw_label_image = skimage.measure.label(raw_label_image) +regions = skimage.measure.regionprops(raw_label_image, intensity_image=raw_image) + +df['it'] = np.arange(len(regions)) + +if add_patch: + df['image'] = df['it'].map(lambda ait: regions[ait].image.astype(np.float).tolist()) + df['intensity_image'] = df['it'].map(lambda ait: regions[ait].intensity_image.astype(np.float).tolist()) + +#TODO no matrix features, but split in own rows? +if args.add_label or args.all_features: + df['label'] = df['it'].map(lambda ait: regions[ait].label) + +if raw_image is not None: + if args.max_intensity or args.all_features: + df['max_intensity'] = df['it'].map(lambda ait: regions[ait].max_intensity) + if args.mean_intensity or args.all_features: + df['mean_intensity'] = df['it'].map(lambda ait: regions[ait].mean_intensity) + if args.min_intensity or args.all_features: + df['min_intensity'] = df['it'].map(lambda ait: regions[ait].min_intensity) + if args.moments_hu or args.all_features: + df['moments_hu'] = df['it'].map(lambda ait: regions[ait].moments_hu) + +if args.centroid or args.all_features: + df['centroid'] = df['it'].map(lambda ait: regions[ait].centroid) +if args.bbox or args.all_features: + df['bbox'] = df['it'].map(lambda ait: regions[ait].bbox) +if args.area or args.all_features: + df['area'] = df['it'].map(lambda ait: regions[ait].area) +if args.filled_area or args.all_features: + df['filled_area'] = df['it'].map(lambda ait: regions[ait].filled_area) +if args.convex_area or args.all_features: + df['convex_area'] = df['it'].map(lambda ait: regions[ait].convex_area) +if args.perimeter or args.all_features: + df['perimeter'] = df['it'].map(lambda ait: regions[ait].perimeter) +if args.extent or args.all_features: + df['extent'] = df['it'].map(lambda ait: regions[ait].extent) +if args.eccentricity or args.all_features: + df['eccentricity'] = df['it'].map(lambda ait: regions[ait].eccentricity) +if args.equivalent_diameter or args.all_features: + df['equivalent_diameter'] = df['it'].map(lambda ait: regions[ait].equivalent_diameter) +if args.euler_number or args.all_features: + df['euler_number'] = df['it'].map(lambda ait: regions[ait].euler_number) +if args.inertia_tensor_eigvals or args.all_features: + df['inertia_tensor_eigvals'] = df['it'].map(lambda ait: regions[ait].inertia_tensor_eigvals) +if args.major_axis_length or args.all_features: + df['major_axis_length'] = df['it'].map(lambda ait: regions[ait].major_axis_length) +if args.minor_axis_length or args.all_features: + df['minor_axis_length'] = df['it'].map(lambda ait: regions[ait].minor_axis_length) +if args.orientation or args.all_features: + df['orientation'] = df['it'].map(lambda ait: regions[ait].orientation) +if args.solidity or args.all_features: + df['solidity'] = df['it'].map(lambda ait: regions[ait].solidity) +if args.moments or args.all_features: + df['moments'] = df['it'].map(lambda ait: regions[ait].moments) +if args.convexity or args.all_features: + df['convexity'] = df.area/(df.perimeter*df.perimeter) + +del df['it'] +df.to_csv(out_file, sep='\t', line_terminator='\n', index=False) diff -r 000000000000 -r 96909b9d1df1 2d_feature_extraction.xml --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/2d_feature_extraction.xml Sat Feb 09 14:28:26 2019 -0500 @@ -0,0 +1,89 @@ + + Feature Extraction + + pandas + scikit-image + numpy + tifffile + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + **What it does** + + This tool computes several features of a 2D label image and optionally more features using the original image. + + + 10.1016/j.jbiotec.2017.07.019 + + diff -r 000000000000 -r 96909b9d1df1 test-data/input.tiff Binary file test-data/input.tiff has changed diff -r 000000000000 -r 96909b9d1df1 test-data/out.tsv --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test-data/out.tsv Sat Feb 09 14:28:26 2019 -0500 @@ -0,0 +1,12 @@ +area +612 +612 +375 +375 +729 +729 +399 +399 +3 +3 +434042