# HG changeset patch # User imgteam # Date 1712244203 0 # Node ID 2436a8807ad1a4b6195a3a7510290d1e4f96175c # Parent 0a53256b48c6a596fb7800c783b60753bd7bd55d planemo upload for repository https://github.com/BMCV/galaxy-image-analysis/tree/master/tools/2d_feature_extraction/ commit c045f067a57e8308308cf6329060c7ccd3fc372f diff -r 0a53256b48c6 -r 2436a8807ad1 2d_feature_extraction.py --- a/2d_feature_extraction.py Fri Nov 10 14:23:12 2023 +0000 +++ b/2d_feature_extraction.py Thu Apr 04 15:23:23 2024 +0000 @@ -8,119 +8,120 @@ import skimage.morphology import skimage.segmentation -# TODO make importable by python script -parser = argparse.ArgumentParser(description='Extract Features 2D') +if __name__ == '__main__': + + parser = argparse.ArgumentParser(description='Extract image features') -# 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') + # 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('--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() + 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 + 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_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) + 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 = 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)) + 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()) + 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) + # 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 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: - perimeter = df['it'].map(lambda ait: regions[ait].perimeter) - area = df['it'].map(lambda ait: regions[ait].area) - df['convexity'] = area / (perimeter * perimeter) + 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: + perimeter = df['it'].map(lambda ait: regions[ait].perimeter) + area = df['it'].map(lambda ait: regions[ait].area) + df['convexity'] = area / (perimeter * perimeter) -del df['it'] -df.to_csv(out_file, sep='\t', line_terminator='\n', index=False) + del df['it'] + df.to_csv(out_file, sep='\t', line_terminator='\n', index=False) diff -r 0a53256b48c6 -r 2436a8807ad1 2d_feature_extraction.xml --- a/2d_feature_extraction.xml Fri Nov 10 14:23:12 2023 +0000 +++ b/2d_feature_extraction.xml Thu Apr 04 15:23:23 2024 +0000 @@ -1,5 +1,13 @@ - + with scikit-image + + creators.xml + 0.14.2 + 0 + + + + operation_3443 @@ -8,8 +16,8 @@ scikit-image + scikit-image pandas - scikit-image numpy tifffile @@ -28,15 +36,15 @@ ]]> - + - - - + + + - + @@ -47,25 +55,25 @@ - + - + - - + + - - - - - + + + + + @@ -81,14 +89,19 @@ - + - **What it does** + + **Computes features of a label map.** - This tool computes several features of a 2D label image and optionally more features using the original image. + The computed features are computed based solely on the properties of the labels in the label map, + or, optionally, by also taking the intensities from a corresponding intensity image into account. + + The label map must be a 2-D or 3-D single-channel image. + 10.1016/j.jbiotec.2017.07.019 diff -r 0a53256b48c6 -r 2436a8807ad1 creators.xml --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/creators.xml Thu Apr 04 15:23:23 2024 +0000 @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + + + + + + + + + diff -r 0a53256b48c6 -r 2436a8807ad1 test-data/input.tiff Binary file test-data/input.tiff has changed diff -r 0a53256b48c6 -r 2436a8807ad1 test-data/out.tsv --- a/test-data/out.tsv Fri Nov 10 14:23:12 2023 +0000 +++ b/test-data/out.tsv Thu Apr 04 15:23:23 2024 +0000 @@ -1,12 +1,3 @@ -area -612 -612 -375 -375 -729 -729 -399 -399 -3 -3 -434042 +label area +1 8 +2 9