class SegmentationPluginOutside(_SegmentationPlugin): LABEL = 'Ring around primary region' NAME = 'outside' COLOR = '#00FF00' DOC = ":additional_segmentation_plugins" REQUIRES = ['primary_segmentation'] PARAMS = [('expansion_size', IntTrait(10, 0, 4000, label='Expansion size')), ('separation_size', IntTrait(5, 0, 4000, label='Separation size')), ] @stopwatch() def _run(self, meta_image, container): image = meta_image.image if self.params['expansion_size'] > 0 and self.params['expansion_size'] > self.params['separation_size']: nr_objects = container.img_labels.getMinmax()[1] + 1 img_labels = ccore.seeded_region_expansion(image, container.img_labels, ccore.SrgType.KeepContours, nr_objects, 0, self.params['expansion_size'], self.params['separation_size']) img_labels = ccore.substractImages(img_labels, container.img_labels) return ccore.ImageMaskContainer(image, img_labels, False, True, True) else: raise ValueError("Parameters are not valid. Requirements: 'expansion_size' > 0 and " "'expansion_size' > 'separation_size'")
class SegmentationPluginPropagate(_SegmentationPlugin): LABEL = 'Propagate region from primary' NAME = 'propagate' COLOR = '#FFFF99' DOC = ":additional_segmentation_plugins" REQUIRES = ['primary_segmentation'] PARAMS = [('presegmentation_median_radius', IntTrait(1, 0, 100, label='Median radius')), ('presegmentation_alpha', FloatTrait(1.0, 0, 4000, label='Otsu factor', digits=2)), ('lambda', FloatTrait(0.05, 0, 4000, label='Lambda', digits=2)), ('delta_width', IntTrait(1, 1, 4, label='Delta width')), ] @stopwatch() def _run(self, meta_image, container): image = meta_image.image img_prefiltered = ccore.disc_median(image, self.params['presegmentation_median_radius']) t = int(ccore.get_otsu_threshold(img_prefiltered) * self.params['presegmentation_alpha']) img_bin = ccore.threshold_image(img_prefiltered, t) img_labels = ccore.segmentation_propagate(img_prefiltered, img_bin, container.img_labels, self.params['lambda'], self.params['delta_width']) return ccore.ImageMaskContainer(image, img_labels, False, True, True)
class SectionTracking(SectionCore): SECTION_NAME = SECTION_NAME_TRACKING OPTIONS = [ ('tracking', [ ('region', SelectionTrait2(None, [], label='Region name')), ('tracking_maxobjectdistance', IntTrait(0, 0, 4000, label='Max object x-y distance')), ('tracking_maxtrackinggap', IntTrait(0, 0, 4000, label='Max time-point gap')), ('tracking_maxsplitobjects', IntTrait(0, 0, 4000, label='Max split events')), ('tracking_exporttrackfeatures', BooleanTrait(True, label='Export tracks')), ('tracking_compressiontrackfeatures', SelectionTrait(COMPRESSION_FORMATS[0], COMPRESSION_FORMATS, label='Compression')), ]), ('visualization', [ ('tracking_visualization', BooleanTrait(False, label='Visualization')), ('tracking_visualize_track_length', IntTrait(5, -1, 10000, label='Max. time-points')), ('tracking_centroid_radius', IntTrait(3, -1, 50, label='Centroid radius')), ]), ]
class SectionEventSelection(SectionCore): SECTION_NAME = SECTION_NAME_EVENT_SELECTION OPTIONS = [ ('event_selection', [('eventchannel', SelectionTrait2(None, [], label='Channel')), ('event_selection', BooleanTrait(True, label='Event Selection')), ('backwardrange', FloatTrait(0, -1, 4000, label='Duration [pre]')), ('forwardrange', FloatTrait(0, -1, 4000, label='Duration [post]')), ('duration_unit', SelectionTrait2(TimeConverter.FRAMES, TimeConverter.units, label='Duration unit')), ('backwardrange_min', BooleanTrait(False, label='Min.')), ('forwardrange_min', BooleanTrait(False, label='Min.')), ('maxindegree', IntTrait(1, 0, 4000, label='Max in-degree')), ('maxoutdegree', IntTrait(2, 0, 4000, label='Max out-degree')), ]), ('supervised_event_selection', [('supervised_event_selection', BooleanTrait(True, label='Supervised', widget_info=BooleanTrait.RADIOBUTTON)), ('labeltransitions', StringTrait('', 200, label='Class transition motif(s)')), ('backwardlabels', StringTrait('', 200, label='Class filter [pre]', mask='(\d+,)*\d+')), ('forwardlabels', StringTrait('', 200, label='Class filter [post]', mask='(\d+,)*\d+')), ('backwardcheck', FloatTrait(2, 0, 4000, label='Filter duration [pre]')), ('forwardcheck', FloatTrait(2, 0, 4000, label='Filter duration [post]')), ]), ('unsupervised_event_selection', [('unsupervised_event_selection', BooleanTrait(False, label='Unsupervised', widget_info=BooleanTrait.RADIOBUTTON)), ('min_event_duration', IntTrait(3, 1, 100, label='Min. event duration')), ('num_clusters', IntTrait(6, 2, 15, label='Number of clusters',)), ('min_cluster_size', IntTrait(2, 1, 10, label='Min. cluster size',)), ]) ]
class SectionTracking(SectionCore): SECTION_NAME = SECTION_NAME_TRACKING OPTIONS = [ ('tracking', [ ('region', SelectionTrait2(None, [], label='Region name')), ('tracking_maxobjectdistance', IntTrait(0, 0, 4000, label='Max object x-y distance')), ('tracking_maxtrackinggap', IntTrait(0, 0, 4000, label='Max time-point gap')), ('tracking_maxsplitobjects', IntTrait(0, 0, 4000, label='Max split events')), ]), ]
class SegmentationPluginExpanded(_SegmentationPlugin): LABEL = 'Expanded region from primary' NAME = 'expanded' COLOR = '#00FFFF' DOC = ":additional_segmentation_plugins" REQUIRES = ['primary_segmentation'] PARAMS = [('expansion_size', IntTrait(10, 0, 4000, label='Expansion size')), ] @stopwatch() def _run(self, meta_image, container): image = meta_image.image if self.params['expansion_size'] > 0: nr_objects = container.img_labels.getMinmax()[1] + 1 img_labels = ccore.seeded_region_expansion(image, container.img_labels, ccore.SrgType.KeepContours, nr_objects, 0, self.params['expansion_size'], 0) else: img_labels = container.img_labels return ccore.ImageMaskContainer(image, img_labels, False, True, True)
class SegmentationPluginInside(_SegmentationPlugin): LABEL = 'Shrinked region from primary' NAME = 'inside' COLOR = '#FFFF00' DOC = ":additional_segmentation_plugins" REQUIRES = ['primary_segmentation'] PARAMS = [('shrinking_size', IntTrait(5, 0, 4000, label='Shrinking size')), ] @stopwatch() def _run(self, meta_image, container): image = meta_image.image if self.params['shrinking_size'] > 0: nr_objects = container.img_labels.getMinmax()[1] + 1 img_labels = ccore.seeded_region_shrinking(image, container.img_labels, nr_objects, self.params['shrinking_size']) else: img_labels = container.img_labels return ccore.ImageMaskContainer(image, img_labels, False, True, True)
class SectionCluster(SectionCore): SECTION_NAME = SECTION_NAME_CLUSTER OPTIONS = [('cluster', [ ('position_granularity', IntTrait(1, 1, 1000, label='Batch size (non-timelapse)')), ])]
class SegmentationPluginModification(_SegmentationPlugin): LABEL = 'Expansion/shrinking of primary region' NAME = 'modification' COLOR = '#FF00FF' DOC = ":additional_segmentation_plugins" REQUIRES = ['primary_segmentation'] PARAMS = [('expansion_size', IntTrait(5, 0, 4000, label='Expansion size')), ('shrinking_size', IntTrait(5, 0, 4000, label='Shrinking size')), ] @stopwatch() def _run(self, meta_image, container): image = meta_image.image if self.params['expansion_size'] > 0 or self.params['shrinking_size'] > 0: nr_objects = container.img_labels.getMinmax()[1] + 1 if self.params['shrinking_size'] > 0: img_labelsA = ccore.seeded_region_shrinking(image, container.img_labels, nr_objects, self.params['shrinking_size']) else: img_labelsA = container.img_labels if self.params['expansion_size'] > 0: img_labelsB = ccore.seeded_region_expansion(image, container.img_labels, ccore.SrgType.KeepContours, nr_objects, 0, self.params['expansion_size'], 0) else: img_labelsB = container.img_labels img_labels = ccore.substractImages(img_labelsB, img_labelsA) return ccore.ImageMaskContainer(image, img_labels, False, True, True) else: raise ValueError("Parameters are not valid. Requirements: 'expansion_size' > 0 and/or " "'shrinking_size' > 0")
class SectionGeneral(SectionCore): SECTION_NAME = SECTION_NAME_GENERAL OPTIONS = [('general', [ ('pathin', StringTrait('', label='Image Directory', widget_info=StringTrait.STRING_PATH)), ('has_multiple_plates', BooleanTrait(False, label='Multiple Plates')), ('pathout', StringTrait('', label='Output Directory', widget_info=StringTrait.STRING_PATH)), ('plate_layout', StringTrait('', label='Plate Layout', widget_info=StringTrait.STRING_PATH)), ('namingscheme', SelectionTrait(CecogEnvironment.naming_schema.sections()[0], CecogEnvironment.naming_schema.sections(), label='Image Naming Scheme')), ('framerange', BooleanTrait(False, label='Timelapse')), ('framerange_begin', IntTrait(1, 0, 10000, label='first')), ('framerange_end', IntTrait(1, 0, 1000, label='last')), ('frameincrement', IntTrait(1, 1, 100, label='increment')), ('skip_finished', BooleanTrait(False, label='Skip finished positions')), ('constrain_positions', BooleanTrait(False, label='Positions')), ('positions', StringTrait('', 1000, label="", mask='(\w+,)*\w+')), ('process_primary', BooleanTrait(True, label='primary')), ('process_secondary', BooleanTrait(False, label='secondary')), ('process_tertiary', BooleanTrait(False, label='tertiary')), ('process_merged', BooleanTrait(False, label='merged')), ('crop_image', BooleanTrait(False, label='Image cropping')), ('crop_image_x0', IntTrait(-1, -1, 4000, label='upper left x:')), ('crop_image_y0', IntTrait(-1, -1, 4000, label='upper left y')), ('crop_image_x1', IntTrait(-1, -1, 4000, label='lower right x')), ('crop_image_y1', IntTrait(-1, -1, 4000, label='lower right y')), ('crop_image', BooleanTrait(False, label='Image cropping')), ('rendering', DictTrait({}, label='Rendering')), ('version', StringTrait('', 6, label='Cecog %s, file version:' % version, widget_info=StringTrait.STRING_GRAYED)), ('rendering_class', DictTrait({}, label='Rendering class')), ('primary_featureextraction_exportfeaturenames', ListTrait(['n2_avg', 'n2_stddev', 'roisize'], label='Primary channel')), ('secondary_featureextraction_exportfeaturenames', ListTrait(['n2_avg', 'n2_stddev', 'roisize'], label='Secondary channel')), ('tertiary_featureextraction_exportfeaturenames', ListTrait(['n2_avg', 'n2_stddev', 'roisize'], label='Tertiary channel')), ])]
class SegmentationPluginConstrainedWatershed(_SegmentationPlugin): LABEL = 'Constrained watershed from primary' NAME = 'constrained_watershed' COLOR = '#FF99FF' REQUIRES = ['primary_segmentation'] PARAMS = [ ('gauss_filter_size', IntTrait(2, 1, 4, label='Gauss filter size')), ] @stopwatch() def _run(self, meta_image, container): image = meta_image.image img_labels = self._constrained_watershed( image, container.img_labels, filter_size=self.params['gauss_filter_size']) return ccore.ImageMaskContainer(image, img_labels, False, True, True) def _constrained_watershed(self, img_in, img_labels, filter_size=2): maxlabel = img_labels.getMinmax()[1] img_bin = ccore.threshold(img_labels, 1, maxlabel, 0, 255) # internal marker img_ero = ccore.erode(img_bin, 3, 8) img_internal_marker = ccore.anchoredSkeleton(img_bin, img_ero) # external marker img_inv = ccore.linearRangeMapping(img_bin, 255, 0, 0, 255) img_voronoi = ccore.watershed(img_inv) img_external_marker = ccore.threshold(img_voronoi, 0, 0, 0, 255) # full marker image img_marker = ccore.supremum(img_internal_marker, img_external_marker) # gradient image img_filtered = ccore.gaussianFilter(img_in, filter_size) img_grad = ccore.morphoGradient(img_filtered, 1, 8) # Watershed result: 0 is WSL, 1 is Background, all other values correspond to labels. img_grad_watershed = ccore.constrainedWatershed(img_grad, img_marker) # we first get the regions maxreslab = img_grad_watershed.getMinmax()[1] img_bin2 = ccore.threshold(img_grad_watershed, 2, maxreslab, 0, 255) img_temp = ccore.copyImageIf(img_labels, img_bin2) img_out = ccore.relabelImage(img_bin2, img_temp) return img_out
class SectionFeatureExtraction(SectionCore): SECTION_NAME = SECTION_NAME_FEATURE_EXTRACTION OPTIONS = [ ('primary_features', [('primary_featurecategory_%s' % name, BooleanTrait(True, label=desc)) for name, desc in zip(FEATURE_CATEGORIES, FEATURE_CATEGORY_DESC)] + [ ('primary_dist_haralick', StringTrait('1,2,4,8', 200, label='Haralick: Distances for cooccurence')), ('primary_se_granugrey', StringTrait('1,2,3,5,7', 200, label='Granulometry Sizes (Structuring Element)')), ('primary_diameter_spotfeatures', IntTrait(5, 1, 30, label="Diameter")), ('primary_thresh_spotfeatures', IntTrait(8, 1, 255, label="Threshold")), ]), ('secondary_features', [('secondary_featurecategory_%s' % name, BooleanTrait(True, label=desc)) for name, desc in zip(FEATURE_CATEGORIES, FEATURE_CATEGORY_DESC)] + [ ('secondary_dist_haralick', StringTrait('1,2,4,8', 200, label='Haralick: Distances for cooccurence')), ('secondary_se_granugrey', StringTrait('1,2,3,5,7', 200, label='Granulometry Sizes (Structuring Element)')), ('secondary_diameter_spotfeatures', IntTrait(5, 1, 30, label="Diameter")), ('secondary_thresh_spotfeatures', IntTrait(8, 1, 255, label="Threshold")), ]), ('tertiary_features', [('tertiary_featurecategory_%s' % name, BooleanTrait(True, label=desc)) for name, desc in zip(FEATURE_CATEGORIES, FEATURE_CATEGORY_DESC)] + [ ('tertiary_dist_haralick', StringTrait('1,2,4,8', 200, label='Haralick: Distances for cooccurence')), ('tertiary_se_granugrey', StringTrait('1,2,3,5,7', 200, label='Granulometry Sizes (Structuring Element)')), ('tertiary_diameter_spotfeatures', IntTrait(5, 1, 30, label="Diameter")), ('tertiary_thresh_spotfeatures', IntTrait(8, 1, 255, label="Threshold")), ]), ]
class SectionFeatureExtraction(SectionCore): SECTION_NAME = SECTION_NAME_FEATURE_EXTRACTION OPTIONS = [ ('primary_features', [ ('primary_%s' % name, BooleanTrait(val, label=desc)) for name, (desc, val) in GUI_LABELS.iteritems() ] + [ ('primary_dist_haralick', StringTrait( '1,2,4,8', 200, label='Haralick: Distances for cooccurence')), ('primary_se_granulometry', StringTrait('1,2,3,5,7', 200, label='Granulometry Sizes (Structuring Element)')), ('primary_diameter_spotfeatures', IntTrait(5, 1, 30, label="Diameter")), ('primary_thresh_spotfeatures', IntTrait(8, 1, 255, label="Threshold")), ]), ('secondary_features', [ ('secondary_%s' % name, BooleanTrait(val, label=desc)) for name, (desc, val) in GUI_LABELS.iteritems() ] + [ ('secondary_dist_haralick', StringTrait( '1,2,4,8', 200, label='Haralick: Distances for cooccurence')), ('secondary_se_granulometry', StringTrait('1,2,3,5,7', 200, label='Granulometry Sizes (Structuring Element)')), ('secondary_diameter_spotfeatures', IntTrait(5, 1, 30, label="Diameter")), ('secondary_thresh_spotfeatures', IntTrait(8, 1, 255, label="Threshold")), ]), ('tertiary_features', [ ('tertiary_%s' % name, BooleanTrait(val, label=desc)) for name, (desc, val) in GUI_LABELS.iteritems() ] + [ ('tertiary_dist_haralick', StringTrait( '1,2,4,8', 200, label='Haralick: Distances for cooccurence')), ('tertiary_se_granulometry', StringTrait('1,2,3,5,7', 200, label='Granulometry Sizes (Structuring Element)')), ('tertiary_diameter_spotfeatures', IntTrait(5, 1, 30, label="Diameter")), ('tertiary_thresh_spotfeatures', IntTrait(8, 1, 255, label="Threshold")), ]), ]
class SectionErrorcorrection(SectionCore): SECTION_NAME = SECTION_NAME_ERRORCORRECTION OPTIONS = [ ('error_correction', [('primary', BooleanTrait(True, label='primary')), ('secondary', BooleanTrait(False, label='secondary')), ('tertiary', BooleanTrait(False, label='tertiary')), ('merged', BooleanTrait(False, label='merged')), ('constrain_graph', BooleanTrait(True, label='Constrain graph')), ('primary_graph', StringTrait('', 1000, label='Primary file', widget_info=StringTrait.STRING_FILE)), ('secondary_graph', StringTrait('', 1000, label='Secondary file', widget_info=StringTrait.STRING_FILE)), ('tertiary_graph', StringTrait('', 1000, label='Tertiary file', widget_info=StringTrait.STRING_FILE)), ('merged_graph', StringTrait('', 1000, label='Merged ch. file', widget_info=StringTrait.STRING_FILE)), ('groupby_position', BooleanTrait(True, label='Position', widget_info=BooleanTrait.RADIOBUTTON)), ('groupby_sirna', BooleanTrait(False, label='siRNA', widget_info=BooleanTrait.RADIOBUTTON)), ('hmm_smoothing', BooleanTrait(True, label='Smoothing Model', widget_info=BooleanTrait.RADIOBUTTON)), ('hmm_baumwelch', BooleanTrait(False, label='Baum-Welch', widget_info=BooleanTrait.RADIOBUTTON)), ('groupby_genesymbol', BooleanTrait(False, label='Gene Symbol', widget_info=BooleanTrait.RADIOBUTTON)), ('overwrite_time_lapse', BooleanTrait(False, label='Overwrite time-lapse')), ('timelapse', FloatTrait(1, 0, 2000, digits=2, label='Time-lapse [min]')), ('max_time', FloatTrait(-1, -1, 2000, digits=2, label='Max. time in plot [min]')), ('ignore_tracking_branches', BooleanTrait(False, label='Ignore tracking branches')), ('enable_sorting', BooleanTrait(False, label='Sort by phase duration')), ('sorting_sequence', StringTrait('', 1000, label='Label sequence', mask='(\w+,)*\w+')), ('primary_sort', StringTrait('', 100)), ('secondary_sort', StringTrait('', 100)), ('compose_galleries', BooleanTrait(False, label='Compose gallery images')), ('compose_galleries_sample', IntTrait(-1, -1, 10000, label='Max. number of random samples')), ('resampling_factor', FloatTrait(0.4, 0.01, 1.0, label="Resampling factor")), ('size_gallery_image', IntTrait(60, 1, 1000, label='Size of gallery images (px)')) ]) ]
class SectionPostProcessing(SectionCore): SECTION_NAME = SECTION_NAME_POST_PROCESSING OPTIONS = [('post_processing', [ ('ibb_analysis', BooleanTrait(True, label='IBB analysis')), ('mappingfile_path', StringTrait('', 1000, label='Mapping file path', widget_info=StringTrait.STRING_PATH)), ('single_plot', BooleanTrait( True, label='Export single event', )), ('single_plot_max_plots', IntTrait( 1, 1, 2000, label='Max. number', )), ('ibb_ratio_signal_threshold', FloatTrait( 1.2, 0.5, 5, label='IBB minimum ratio signal threshold', )), ('ibb_range_signal_threshold', FloatTrait( 3, 0.5, 5, label='IBB minimum range threshold', )), ('ibb_onset_factor_threshold', FloatTrait( 1.2, 1, 5, label='IBB onset slope threshold', )), ('nebd_onset_factor_threshold', FloatTrait( 1.2, 1, 5, label='NEBD onset slope threshold', )), ('plot_ylim1_low', IntTrait( 0, 0, 2000, label='Y-axis limit (low)', )), ('plot_ylim1_high', IntTrait( 100, 1, 4000, label='Y-axis limit (high)', )), ('single_plot_ylim_low', FloatTrait( 1, 0, 10, label='Y-axis ratio range (low)', )), ('single_plot_ylim_high', IntTrait( 5, 1, 30, label='Y-axis ratio range (high)', )), ('group_by_position', BooleanTrait(True, label='Position', widget_info=BooleanTrait.RADIOBUTTON)), ('group_by_oligoid', BooleanTrait(False, label='Oligo ID', widget_info=BooleanTrait.RADIOBUTTON)), ('group_by_genesymbol', BooleanTrait(False, label='Gene symbol', widget_info=BooleanTrait.RADIOBUTTON)), ('group_by_group', BooleanTrait(False, label='Group', widget_info=BooleanTrait.RADIOBUTTON)), ('color_sort_by_position', BooleanTrait(False, label='Position', widget_info=BooleanTrait.RADIOBUTTON)), ('color_sort_by_oligoid', BooleanTrait(True, label='Oligo ID', widget_info=BooleanTrait.RADIOBUTTON)), ('color_sort_by_genesymbol', BooleanTrait(False, label='Gene symbol', widget_info=BooleanTrait.RADIOBUTTON)), ('color_sort_by_group', BooleanTrait(False, label='Group', widget_info=BooleanTrait.RADIOBUTTON)), ('securin_analysis', BooleanTrait(True, label='Securin analysis')), ])]
class SectionTracking(SectionCore): SECTION_NAME = SECTION_NAME_TRACKING OPTIONS = [ ('tracking', [ ('tracking_regionname', SelectionTrait2(None, [], label='Region name')), ('tracking_maxobjectdistance', IntTrait(0, 0, 4000, label='Max object x-y distance')), ('tracking_maxtrackinggap', IntTrait(0, 0, 4000, label='Max time-point gap')), ('tracking_maxsplitobjects', IntTrait(0, 0, 4000, label='Max split events')), ('tracking_maxindegree', IntTrait(1, 0, 4000, label='Max in-degree')), ('tracking_maxoutdegree', IntTrait(2, 0, 4000, label='Max out-degree')), ('tracking_exporttrackfeatures', BooleanTrait(True, label='Export tracks')), ('tracking_compressiontrackfeatures', SelectionTrait(COMPRESSION_FORMATS[0], COMPRESSION_FORMATS, label='Compression')), ]), ('event_selection', [ ('tracking_labeltransitions', StringTrait('', 200, label='Class transition motif(s)', mask='(\(\d+,\d+\),)*\(\d+,\d+\)')), ('tracking_backwardrange', FloatTrait(0, -1, 4000, label='Duration [pre]')), ('tracking_forwardrange', FloatTrait(0, -1, 4000, label='Duration [post]')), ('tracking_backwardlabels', StringTrait('', 200, label='Class filter [pre]', mask='(\d+,)*\d+')), ('tracking_forwardlabels', StringTrait('', 200, label='Class filter [post]', mask='(\d+,)*\d+')), ('tracking_backwardcheck', FloatTrait(2, 0, 4000, label='Filter duration [pre]')), ('tracking_forwardcheck', FloatTrait(2, 0, 4000, label='Filter duration [post]')), ('tracking_duration_unit', SelectionTrait2(TRACKING_DURATION_UNITS_DEFAULT[0], TRACKING_DURATION_UNITS_DEFAULT, label='Duration unit')), ('tracking_backwardrange_min', BooleanTrait(False, label='Min.')), ('tracking_forwardrange_min', BooleanTrait(False, label='Min.')), ]), ('visualization', [ ('tracking_visualization', BooleanTrait(False, label='Visualization')), ('tracking_visualize_track_length', IntTrait(5, -1, 10000, label='Max. time-points')), ('tracking_centroid_radius', IntTrait(3, -1, 50, label='Centroid radius')), ]), ]
class SectionOutput(SectionCore): SECTION_NAME = SECTION_NAME_OUTPUT OPTIONS = [ ('output', [ ('text_output', BooleanTrait(False, label='Text Output', widget_info=BooleanTrait.RADIOBUTTON)), ('rendering_labels_discwrite', BooleanTrait(False, label='Label images')), ('rendering_contours_discwrite', BooleanTrait(False, label='Contour images')), ('rendering_contours_showids', BooleanTrait(False, label='Show object IDs')), ('rendering_class_discwrite', BooleanTrait(False, label='Classification images')), ('rendering_class_showids', BooleanTrait(False, label='Show object IDs')), ('rendering_channel_gallery', BooleanTrait(False, label='Merged channel gallery')), ('export_object_counts', BooleanTrait(False, label='Export object counts')), ('export_object_counts_ylim_max', IntTrait(-1, -1, 1000, label='Max. count in plot')), ('export_object_details', BooleanTrait(False, label='Export detailed object data')), ('export_file_names', BooleanTrait(False, label='Export raw image file names')), ('export_tracking_as_dot', BooleanTrait(False, label='Export tracking as GraphViz .dot')), ('export_track_data', BooleanTrait(False, label='Export tracks for head nodes')), ('export_events', BooleanTrait(False, label='Export event data')), ('events_export_all_features', BooleanTrait(False, label='Export all features per event')), ('events_export_gallery_images', BooleanTrait(False, label='Export gallery images')), ('events_gallery_image_size', IntTrait(50, 1, 1000, label='Gallery image size (pixel)')), ]), ('hdf5', [ ('hdf5_create_file', BooleanTrait(True, label='Create CellH5', widget_info=BooleanTrait.RADIOBUTTON)), ('hdf5_reuse', BooleanTrait(False, label='Reuse CellH5')), ('minimal_effort', BooleanTrait(False, label='Only necessary steps')), ('hdf5_include_raw_images', BooleanTrait(False, label='Include 8-bit image data')), ('hdf5_include_label_images', BooleanTrait(False, label='Include segmentation images')), ('hdf5_include_crack', BooleanTrait(False, label='Include crack contours')), ('hdf5_include_features', BooleanTrait(False, label='Include features')), ('hdf5_include_classification', BooleanTrait(False, label='Include classification')), ('hdf5_include_tracking', BooleanTrait(False, label='Include tracking')), ('hdf5_include_events', BooleanTrait(False, label='Include events')), ('hdf5_compression', BooleanTrait(True, label='Enable gzip compression (recommended!)')), ('hdf5_merge_positions', BooleanTrait(True, label='Merge positions into one file')), ]), ]
class SectionGeneral(SectionCore): SECTION_NAME = SECTION_NAME_GENERAL OPTIONS = [('general', [ ('pathin', StringTrait('', 1000, label='Image folder', widget_info=StringTrait.STRING_PATH)), ('has_multiple_plates', BooleanTrait(False, label='Multiple plates')), ('pathout', StringTrait('', 1000, label='Analysis folder', widget_info=StringTrait.STRING_PATH)), ('image_import_namingschema', BooleanTrait(True, label='Import via naming schema', widget_info=BooleanTrait.RADIOBUTTON)), ('image_import_structurefile', BooleanTrait(False, label='Import via coordinate file', widget_info=BooleanTrait.RADIOBUTTON)), ('namingscheme', SelectionTrait(CecogEnvironment.naming_schema.sections()[0], CecogEnvironment.naming_schema.sections(), label='Naming scheme')), ('structure_filename', StringTrait('', 1000, label='Coordinate filename', widget_info=StringTrait.STRING_FILE)), ('structure_file_pathin', BooleanTrait(True, label='Image folder', widget_info=BooleanTrait.RADIOBUTTON)), ('structure_file_pathout', BooleanTrait(False, label='Analysis folder', widget_info=BooleanTrait.RADIOBUTTON)), ('structure_file_extra_path', BooleanTrait(False, label='Different location', widget_info=BooleanTrait.RADIOBUTTON)), ('structure_file_extra_path_name', StringTrait('', 1000, label='Path', widget_info=StringTrait.STRING_PATH)), ('constrain_positions', BooleanTrait(False, label='Constrain positions')), ('positions', StringTrait('', 1000, label='Positions', mask='(\w+,)*\w+')), ('crop_image', BooleanTrait(False, label='Crop image')), ('crop_image_x0', IntTrait(-1, -1, 4000, label='Upper left X')), ('crop_image_y0', IntTrait(-1, -1, 4000, label='Upper left Y')), ('crop_image_x1', IntTrait(-1, -1, 4000, label='Lower right X')), ('crop_image_y1', IntTrait(-1, -1, 4000, label='Lower right Y')), ('crop_image', BooleanTrait(False, label='Crop image')), ('redofailedonly', BooleanTrait(True, label='Skip processed positions')), ('framerange', BooleanTrait(False, label='Constrain timepoints')), ('framerange_begin', IntTrait(1, 0, 10000, label='Begin')), ('framerange_end', IntTrait(1, 0, 1000, label='End')), ('frameincrement', IntTrait(1, 1, 100, label='Timepoint increment')), ('rendering', DictTrait({}, label='Rendering')), ('version', StringTrait('', 6, label='Cecog %s, file version:' % VERSION, widget_info=StringTrait.STRING_GRAYED)), ('rendering_class', DictTrait({}, label='Rendering class')), ('primary_featureextraction_exportfeaturenames', ListTrait(['n2_avg', 'n2_stddev', 'roisize'], label='Primary channel')), ('secondary_featureextraction_exportfeaturenames', ListTrait(['n2_avg', 'n2_stddev', 'roisize'], label='Secondary channel')), ('tertiary_featureextraction_exportfeaturenames', ListTrait(['n2_avg', 'n2_stddev', 'roisize'], label='Tertiary channel')), ])]
class SectionObjectdetection(SectionCore): SECTION_NAME = SECTION_NAME_OBJECTDETECTION OPTIONS = [ ('primary_image', [('primary_channelid', SelectionTrait2(None, [], label='Primary channel ID')), ('primary_normalizemin', IntTrait(0, -2**16, 2**16, label='Min.')), ('primary_normalizemax', IntTrait(255, -2**16, 2**16, label='Max.')), ('primary_zslice_selection', BooleanTrait(True, label='Z-slice selection', widget_info=BooleanTrait.RADIOBUTTON)), ('primary_flat_field_correction', BooleanTrait(False, label='Z-slice flat field correction', widget_info=BooleanTrait.CHECKBOX)), ('primary_flat_field_correction_image_dir', StringTrait('', 1000, label='Correction image directory', widget_info=StringTrait.STRING_PATH)), ('primary_zslice_selection_slice', IntTrait(1, 0, 1000, label='Slice')), ('primary_zslice_projection', BooleanTrait(False, label='Z-slice projection', widget_info=BooleanTrait.RADIOBUTTON)), ('primary_zslice_projection_method', SelectionTrait(ZSLICE_PROJECTION_METHODS[0], ZSLICE_PROJECTION_METHODS, label='Method')), ('primary_zslice_projection_begin', IntTrait(1, 0, 1000, label='Begin')), ('primary_zslice_projection_end', IntTrait(1, 0, 1000, label='End')), ('primary_zslice_projection_step', IntTrait(1, 1, 1000, label='Step')), # these two options are nopes, just to have no # special casing in channel classes ('primary_channelregistration_x', IntTrait(0, -99999, 99999, label='Shift X')), ('primary_channelregistration_y', IntTrait(0, -99999, 99999, label='Shift Y')), ]), ] + \ unlist( [[('%s_image' % prefix, [('%s_channelid' % prefix, SelectionTrait2(None, [], label='%s channel ID' % name)), ('%s_normalizemin' % prefix, IntTrait(0, -2**16, 2**16, label='Min.')), ('%s_normalizemax' % prefix, IntTrait(255, -2**16, 2**16, label='Max.')), ('%s_zslice_selection' % prefix, BooleanTrait(True, label='Z-slice selection', widget_info=BooleanTrait.RADIOBUTTON)), ('%s_flat_field_correction' % prefix, BooleanTrait(False, label='Z-slice flat field correction', widget_info=BooleanTrait.CHECKBOX)), ('%s_flat_field_correction_image_dir' % prefix, StringTrait('', 1000, label='Correction image directory', widget_info=StringTrait.STRING_PATH)), ('%s_zslice_selection_slice' % prefix, IntTrait(1, 0, 1000, label='Slice')), ('%s_zslice_projection' % prefix, BooleanTrait(False, label='Z-slice projection', widget_info=BooleanTrait.RADIOBUTTON)), ('%s_zslice_projection_method' % prefix, SelectionTrait(ZSLICE_PROJECTION_METHODS[0], ZSLICE_PROJECTION_METHODS, label='Method')), ('%s_zslice_projection_begin' % prefix, IntTrait(1, 0, 1000, label='Begin')), ('%s_zslice_projection_end' % prefix, IntTrait(1, 0, 1000, label='End')), ('%s_zslice_projection_step' % prefix, IntTrait(1, 1, 1000, label='Step')), ]), ('%s_registration' % prefix, [('%s_channelregistration_x' % prefix, IntTrait(0, -99999, 99999, label='Shift X')), ('%s_channelregistration_y' % prefix, IntTrait(0, -99999, 99999, label='Shift Y')), ]), ] for name, prefix in [('Secondary', 'secondary'), ('Tertiary', 'tertiary'), # moste merged channel options are nopes # to avoid special casing ('Merged', 'merged') ]] )
class SectionErrorcorrection(SectionCore): SECTION_NAME = SECTION_NAME_ERRORCORRECTION OPTIONS = [('error_correction', [ ('filename_to_r', StringTrait('', 1000, label='R-project executable', widget_info=StringTrait.STRING_FILE)), ('constrain_graph', BooleanTrait(True, label='Constrain graph')), ('primary_graph', StringTrait('', 1000, label='Primary file', widget_info=StringTrait.STRING_FILE)), ('secondary_graph', StringTrait('', 1000, label='Secondary file', widget_info=StringTrait.STRING_FILE)), ('skip_processed_plates', BooleanTrait(False, label='Skip processed plates')), ('position_labels', BooleanTrait(False, label='Position labels')), ('mappingfile_path', StringTrait('', 1000, label='Path', widget_info=StringTrait.STRING_PATH)), ('groupby_position', BooleanTrait(True, label='Position', widget_info=BooleanTrait.RADIOBUTTON)), ('groupby_oligoid', BooleanTrait(False, label='Oligo ID', widget_info=BooleanTrait.RADIOBUTTON)), ('groupby_genesymbol', BooleanTrait(False, label='Gene symbol', widget_info=BooleanTrait.RADIOBUTTON)), ('overwrite_time_lapse', BooleanTrait(False, label='Overwrite time-lapse')), ('timelapse', FloatTrait(1, 0, 2000, digits=2, label='Time-lapse [min]')), ('max_time', FloatTrait(100, 1, 2000, digits=2, label='Max. time in plot [min]')), ('ignore_tracking_branches', BooleanTrait(False, label='Ignore tracking branches')), ('show_html', BooleanTrait(True, label='Open in browser')), ('enable_sorting', BooleanTrait(False, label='Sort by phase duration')), ('sorting_sequence', StringTrait('', 1000, label='Label sequence', mask='(\w+,)*\w+')), ('primary_sort', StringTrait('', 100)), ('secondary_sort', StringTrait('', 100)), ('compose_galleries', BooleanTrait(False, label='Compose gallery images')), ('compose_galleries_sample', IntTrait(-1, -1, 10000, label='Max. number of random samples')), ])]
class SegmentationPluginPrimary(_SegmentationPlugin): LABEL = 'Local adaptive threshold w/ split&merge' NAME = 'primary' COLOR = '#FF0000' REQUIRES = None PARAMS = [('medianradius', IntTrait(2, 0, 1000, label='Median radius')), ('latwindowsize', IntTrait(20, 1, 1000, label='Window size')), ('latlimit', IntTrait(1, 0, 255, label='Min. contrast')), ('lat2', BooleanTrait(False, label='Local adaptive threshold 2')), ('latwindowsize2', IntTrait(20, 1, 1000, label='Window size')), ('latlimit2', IntTrait(1, 0, 255, label='Min. contrast')), ('shapewatershed', BooleanTrait(False, label='Split & merge by shape')), ('shapewatershed_gausssize', IntTrait(1, 0, 1000000, label='Gauss radius')), ('shapewatershed_maximasize', IntTrait(1, 0, 1000000, label='Min. seed distance')), ('shapewatershed_minmergesize', IntTrait(1, 0, 1000000, label='Object size threshold')), ('intensitywatershed', BooleanTrait(False, label='Split & merge by intensity')), ('intensitywatershed_gausssize', IntTrait(1, 0, 1000000, label='Gauss radius')), ('intensitywatershed_maximasize', IntTrait(1, 0, 1000000, label='Min. seed distance')), ('intensitywatershed_minmergesize', IntTrait(1, 0, 1000000, label='Object size threshold')), ('postprocessing', BooleanTrait(False, label='Object filter')), ('postprocessing_roisize_min', IntTrait(-1, -1, 1000000, label='Min. object size')), ('postprocessing_roisize_max', IntTrait(-1, -1, 1000000, label='Max. object size')), ('postprocessing_intensity_min', IntTrait(-1, -1, 1000000, label='Min. average intensity')), ('postprocessing_intensity_max', IntTrait(-1, -1, 1000000, label='Max. average intensity')), ('removeborderobjects', BooleanTrait(True, label='Remove border objects')), ('holefilling', BooleanTrait(True, label='Fill holes')), ] # the : at the beginning indicates a QRC link with alias 'plugins/segmentation/local_adaptive_threshold' DOC = ':local_adaptive_threshold' def render_to_gui(self, panel): panel.add_group(None, [('medianradius', (0, 0, 1, 1)), ('latwindowsize', (0, 1, 1, 1)), ('latlimit', (0, 2, 1, 1)), ], link='lat', label='Local adaptive threshold') panel.add_group('lat2', [('latwindowsize2', (0, 0, 1, 1)), ('latlimit2', (0, 1, 1, 1)), ]) panel.add_input('holefilling') panel.add_input('removeborderobjects') panel.add_group('shapewatershed', [('shapewatershed_gausssize', (0, 0, 1, 1)), ('shapewatershed_maximasize', (0, 1, 1, 1)), ('shapewatershed_minmergesize', (1, 0, 1, 1)), ]) panel.add_group('postprocessing', [('postprocessing_roisize_min', (0, 0, 1, 1)), ('postprocessing_roisize_max', (0, 1, 1, 1)), ('postprocessing_intensity_min', (1, 0, 1, 1)), ('postprocessing_intensity_max', (1, 1, 1, 1)), ]) @stopwatch() def prefilter(self, img_in, radius=None): if radius is None: radius = self.params['medianradius'] img_out = ccore.disc_median(img_in, radius) return img_out @stopwatch() def threshold(self, img_in, size, limit): img_out = ccore.window_average_threshold(img_in, size, limit) return img_out @stopwatch() def correct_segmetation(self, img_in, img_bin, border, gauss_size, max_dist, min_merge_size, kind='shape'): if kind == 'shape': f = ccore.segmentation_correction_shape else: f = ccore.segmentation_correction_intensity return f(img_in, img_bin, border, gauss_size, max_dist, min_merge_size) @stopwatch() def postprocessing(self, container, is_active, roisize_minmax, intensity_minmax, delete_objects=True): valid_ids = container.getObjects().keys() rejected_ids = [] if is_active: feature_categories = set() conditions = [] for idx, (roisize, intensity) in enumerate( \ zip(roisize_minmax, intensity_minmax)): cmprt = '>=' if idx == 0 else '<=' if roisize > -1: feature_categories.add('roisize') conditions.append('roisize %s %d' % (cmprt, roisize)) if intensity > -1: feature_categories.add('normbase2') conditions.append('n2_avg %s %d' % (cmprt, intensity)) if len(conditions) > 0: conditions_str = ' and '.join(conditions) # extract features needed for the filter # FIXME: features are currently kept in the ObjectContainer and used for classification automatically for feature in feature_categories: container.applyFeature(feature) valid_ids = [] rejected_ids = [] # get a dict copy, because we delete elements from the dict objects = container.getObjects() for obj_id, obj in objects.iteritems(): # eval condition string based on the feature dict (provides values for the features above) if not eval(conditions_str, obj.getFeatures()): if delete_objects: container.delObject(obj_id) rejected_ids.append(obj_id) else: valid_ids.append(obj_id) # store valid and rejected object IDs to the container container.valid_ids = valid_ids container.rejected_ids = rejected_ids @stopwatch() def _run(self, meta_image): image = meta_image.image img_prefiltered = self.prefilter(image) img_bin1 = self.threshold(img_prefiltered, self.params['latwindowsize'], self.params['latlimit']) if self.params['holefilling']: ccore.fill_holes(img_bin1, False) if self.params['lat2']: img_bin2 = self.threshold(img_prefiltered, self.params['latwindowsize2'], self.params['latlimit2']) # replacement for not working ccore.projectImage img_bin = numpy.zeros((img_bin2.height, img_bin2.width), dtype=meta_image.format) img_bin = ccore.numpy_to_image(img_bin, copy=True) ccore.zproject(img_bin, [img_bin1, img_bin2], ccore.ProjectionType.MaxProjection) else: img_bin = img_bin1 if self.params['shapewatershed']: img_bin = self.correct_segmetation(img_prefiltered, img_bin, self.params['latwindowsize'], self.params['shapewatershed_gausssize'], self.params['shapewatershed_maximasize'], self.params['shapewatershed_minmergesize'], kind='shape') if self.params['intensitywatershed']: img_bin = self.correct_segmetation(img_prefiltered, img_bin, self.params['latwindowsize'], self.params['intensitywatershed_gausssize'], self.params['intensitywatershed_maximasize'], self.params['intensitywatershed_minmergesize'], kind='intensity') container = ccore.ImageMaskContainer(image, img_bin, self.params['removeborderobjects']) self.postprocessing(container, self.params['postprocessing'], (self.params['postprocessing_roisize_min'], self.params['postprocessing_roisize_max']), (self.params['postprocessing_intensity_min'], self.params['postprocessing_intensity_max'])) return container
class SegmentationPluginPrimary3(_SegmentationPlugin): LABEL = 'Local adaptive threshold, togglemappings, split by minima depth, background corrected object filter' NAME = 'primary3' COLOR = '#FF0000' REQUIRES = None PARAMS = [('medianradius', IntTrait(2, 0, 1000, label='Median radius')), ('togglemappings', BooleanTrait(False, label='Toggle Mappings')), ('tm_size', IntTrait(1, 0, 20, label='Toggle Mappings Size')), ('latwindowsize', IntTrait(20, 1, 1000, label='Window size')), ('latlimit', IntTrait(1, 0, 255, label='Min. contrast')), ('lat2', BooleanTrait(False, label='Local adaptive threshold 2')), ('latwindowsize2', IntTrait(20, 1, 1000, label='Window size')), ('latlimit2', IntTrait(1, 0, 255, label='Min. contrast')), ('watershed_distance', BooleanTrait(False, label='Watershed (Distance)')), ('watershed_dynamic', IntTrait(2, 0, 1000, label='Minimal depth')), ('watershed_used_distance', IntTrait(2, 0, 2, label='Distance Metric (0: chessboard, 1: L1, 2: L2)')), ('postprocessing', BooleanTrait(False, label='Object filter')), ('postprocessing_roisize_min', IntTrait(-1, -1, 1000000, label='Min. object size')), ('postprocessing_roisize_max', IntTrait(-1, -1, 1000000, label='Max. object size')), ('postprocessing_intensity_min', IntTrait(-1, -1, 1000000, label='Min. average intensity above background')), ('postprocessing_intensity_max', IntTrait(-1, -1, 1000000, label='Max. average intensity above background')), ('removeborderobjects', BooleanTrait(True, label='Remove border objects')), ('holefilling', BooleanTrait(True, label='Fill holes')), ] # the : at the beginning indicates a QRC link with alias 'plugins/segmentation/local_adaptive_threshold' DOC = ':local_adaptive_threshold' def render_to_gui(self, panel): panel.add_group('togglemappings', [('tm_size', (0, 0, 1, 1)), ]) panel.add_group(None, [('medianradius', (0, 0, 1, 1)), ('latwindowsize', (0, 1, 1, 1)), ('latlimit', (0, 2, 1, 1)), ], link='lat', label='Local adaptive threshold') panel.add_group('lat2', [('latwindowsize2', (0, 0, 1, 1)), ('latlimit2', (0, 1, 1, 1)), ]) panel.add_input('holefilling') panel.add_input('removeborderobjects') panel.add_group('watershed_distance', [('watershed_dynamic', (0, 0, 1, 1)), ('watershed_used_distance', (0, 1, 1, 1)), ]) # panel.add_group('shapewatershed', # [('shapewatershed_gausssize', (0, 0, 1, 1)), # ('shapewatershed_maximasize', (0, 1, 1, 1)), # ('shapewatershed_minmergesize', (1, 0, 1, 1)), # ]) panel.add_group('postprocessing', [('postprocessing_roisize_min', (0, 0, 1, 1)), ('postprocessing_roisize_max', (0, 1, 1, 1)), ('postprocessing_intensity_min', (1, 0, 1, 1)), ('postprocessing_intensity_max', (1, 1, 1, 1)), ]) @stopwatch() def prefilter(self, img_in, radius=None): img_temp = img_in if self.params['togglemappings']: img_temp = ccore.toggle_mapping(img_in, self.params['tm_size']) if radius is None: radius = self.params['medianradius'] img_out = ccore.disc_median(img_temp, radius) return img_out @stopwatch() def threshold(self, img_in, size, limit): img_out = ccore.window_average_threshold(img_in, size, limit) return img_out @stopwatch() def OLD_correct_segmetation(self, img_in, img_bin, border, gauss_size, max_dist, min_merge_size, kind='shape'): if kind == 'shape': f = ccore.segmentation_correction_shape else: f = ccore.segmentation_correction_intensity return f(img_in, img_bin, border, gauss_size, max_dist, min_merge_size) @stopwatch() def correct_segmetation(self, img_in, img_bin, dyn, distance=2): if distance==2: # Euclidean distance res = ccore.watershed_dynamic_split(img_bin, dyn, 4, 2) elif distance==1: # we use connectivity 4 (for the watershed) and distance mode 1 (which # corresponds to the L1 norm which corresponds to the graph distance # of a 4-neighborhood graph res = ccore.watershed_dynamic_split(img_bin, dyn, 4, 1) elif distance==0: # the chessboard distance and 8 connectivity for the watershed algorithm. # However, the distances are "deeper" for 4-connectivity. res = ccore.watershed_dynamic_split(img_bin, dyn, 8, 0) else: print 'not implemented' res = img_bin return res @stopwatch() def postprocessing(self, container, is_active, roisize_minmax, intensity_minmax, delete_objects=True, offset=0): valid_ids = container.getObjects().keys() rejected_ids = [] if is_active: feature_categories = set() conditions = [] for idx, (roisize, intensity) in enumerate( \ zip(roisize_minmax, intensity_minmax)): cmprt = '>=' if idx == 0 else '<=' if roisize > -1: feature_categories.add('roisize') conditions.append('roisize %s %d' % (cmprt, roisize)) if intensity > -1: feature_categories.add('normbase2') conditions.append('n2_avg %s %d' % (cmprt, intensity+offset)) if len(conditions) > 0: conditions_str = ' and '.join(conditions) # extract features needed for the filter # FIXME: features are currently kept in the ObjectContainer and used for classification automatically # Features can be removed from the container, but it remains much better a choice # to restrict the feature sets used for classification. for feature in feature_categories: container.applyFeature(feature) valid_ids = [] rejected_ids = [] # get a dict copy, because we delete elements from the dict objects = container.getObjects() for obj_id, obj in objects.iteritems(): # eval condition string based on the feature dict (provides values for the features above) if not eval(conditions_str, obj.getFeatures()): if delete_objects: container.delObject(obj_id) rejected_ids.append(obj_id) else: valid_ids.append(obj_id) #pdb.set_trace() #img_v = container.img. # delete features that were added by the object filter for feature in ['roisize', 'normbase2']: container.deleteFeatureCategory(feature) # store valid and rejected object IDs to the container container.valid_ids = valid_ids container.rejected_ids = rejected_ids @stopwatch() def _run(self, meta_image): image = meta_image.image img_prefiltered = self.prefilter(image) img_bin1 = self.threshold(img_prefiltered, self.params['latwindowsize'], self.params['latlimit']) if self.params['holefilling']: ccore.fill_holes(img_bin1, False) if self.params['lat2']: img_bin2 = self.threshold(img_prefiltered, self.params['latwindowsize2'], self.params['latlimit2']) # replacement for not working ccore.projectImage img_bin = numpy.zeros((img_bin2.height, img_bin2.width), dtype=meta_image.format) img_bin = ccore.numpy_to_image(img_bin, copy=True) ccore.zproject(img_bin, [img_bin1, img_bin2], ccore.ProjectionType.MaxProjection) else: img_bin = img_bin1 if self.params['watershed_distance']: img_bin = self.correct_segmetation(img_prefiltered, img_bin, self.params['watershed_dynamic'], self.params['watershed_used_distance']) # if self.params['shapewatershed']: # img_bin = self.correct_segmetation(img_prefiltered, img_bin, # self.params['latwindowsize'], # self.params['shapewatershed_gausssize'], # self.params['shapewatershed_maximasize'], # self.params['shapewatershed_minmergesize'], # kind='shape') # if self.params['intensitywatershed']: # img_bin = self.correct_segmetation(img_prefiltered, img_bin, # self.params['latwindowsize'], # self.params['intensitywatershed_gausssize'], # self.params['intensitywatershed_maximasize'], # self.params['intensitywatershed_minmergesize'], # kind='intensity') container = ccore.ImageMaskContainer(image, img_bin, self.params['removeborderobjects']) # calculate offset: mean on the background region, as given by the segmentation result # no locality: simply a global mean on the image. np_image = image.toArray(True) np_img_bin = img_bin.toArray(True) offset = np_image[np_img_bin==0].mean() self.postprocessing(container, self.params['postprocessing'], (self.params['postprocessing_roisize_min'], self.params['postprocessing_roisize_max']), (self.params['postprocessing_intensity_min'], self.params['postprocessing_intensity_max']), offset=offset) return container
class SegmentationPluginIlastik(SegmentationPluginPrimary): LABEL = 'Local adaptive threshold w/ split&merge using trained ilastik classifier' NAME = 'primary_ilastik' COLOR = '#FF0000' REQUIRES = None PARAMS = [('ilastik_classifier', StringTrait('', 1000, label='ilastik Classifier File', widget_info=StringTrait.STRING_FILE)), ('ilastik_class_selector', IntTrait(1, 0, 1000, label='Output class')), ('medianradius', IntTrait(2, 0, 1000, label='Median radius')), ('latwindowsize', IntTrait(20, 1, 1000, label='Window size')), ('latlimit', IntTrait(1, 0, 255, label='Min. contrast')), ('lat2', BooleanTrait(False, label='Local adaptive threshold 2')), ('latwindowsize2', IntTrait(20, 1, 1000, label='Window size')), ('latlimit2', IntTrait(1, 0, 255, label='Min. contrast')), ('shapewatershed', BooleanTrait(False, label='Split & merge by shape')), ('shapewatershed_gausssize', IntTrait(1, 0, 10000, label='Gauss radius')), ('shapewatershed_maximasize', IntTrait(1, 0, 10000, label='Min. seed distance')), ('shapewatershed_minmergesize', IntTrait(1, 0, 10000, label='Object size threshold')), ('intensitywatershed', BooleanTrait(False, label='Split & merge by intensity')), ('intensitywatershed_gausssize', IntTrait(1, 0, 10000, label='Gauss radius')), ('intensitywatershed_maximasize', IntTrait(1, 0, 10000, label='Min. seed distance')), ('intensitywatershed_minmergesize', IntTrait(1, 0, 10000, label='Object size threshold')), ('postprocessing', BooleanTrait(False, label='Object filter')), ('postprocessing_roisize_min', IntTrait(-1, -1, 10000, label='Min. object size')), ('postprocessing_roisize_max', IntTrait(-1, -1, 10000, label='Max. object size')), ('postprocessing_intensity_min', IntTrait(-1, -1, 10000, label='Min. average intensity')), ('postprocessing_intensity_max', IntTrait(-1, -1, 10000, label='Max. average intensity')), ('removeborderobjects', BooleanTrait(True, label='Remove border objects')), ('holefilling', BooleanTrait(True, label='Fill holes')), ] # the : at the beginning indicates a QRC link with alias 'plugins/segmentation/local_adaptive_threshold' DOC = ':local_adaptive_threshold' @stopwatch() def prefilter(self, img_in): img = SegmentationPluginPrimary.prefilter(self, img_in) np_img = img.toArray(True) return self._predict_image_with_ilastik(np_img) def threshold(self, img_in, *args): np_img = img_in.toArray(True) return ccore.numpy_to_image((np_img > 128).astype(numpy.uint8), True) def render_to_gui(self, panel): panel.add_group(None, [('ilastik_classifier', (0, 0, 1, 1)), ('ilastik_class_selector', (1, 0, 1, 1)), ], label='ilastik') SegmentationPluginPrimary.render_to_gui(self, panel) def _predict_image_with_ilastik(self, image_): import ilastik from ilastik.core.dataMgr import DataMgr, DataItemImage from ilastik.modules.classification.core.featureMgr import FeatureMgr from ilastik.modules.classification.core.classificationMgr import ClassificationMgr from ilastik.modules.classification.core.features.featureBase import FeatureBase from ilastik.modules.classification.core.classifiers.classifierRandomForest import ClassifierRandomForest from ilastik.modules.classification.core.classificationMgr import ClassifierPredictThread from ilastik.core.volume import DataAccessor import numpy, h5py dataMgr = DataMgr() # Transform input image to ilastik convention s # 3D = (time,x,y,z,channel) # 2D = (time,1,x,y,channel) # Note, this work for 2D images right now. Is there a need for 3D image_.shape = (1,1) + image_.shape # Check if image_ has channels, if not add singelton dimension if len(image_.shape) == 4: image_.shape = image_.shape + (1,) # Add data item di to dataMgr di = DataItemImage('') di.setDataVol(DataAccessor(image_)) dataMgr.append(di, alreadyLoaded=True) fileName = self.params["ilastik_classifier"] ilastik_class = self.params["ilastik_class_selector"] hf = h5py.File(fileName,'r') temp = hf['classifiers'].keys() # If hf is not closed this leads to an error in win64 and mac os x hf.close() del hf classifiers = [] for cid in temp: cidpath = 'classifiers/' + cid classifiers.append(ClassifierRandomForest.loadRFfromFile(fileName, str(cidpath))) dataMgr.module["Classification"]["classificationMgr"].classifiers = classifiers # Restore user selection of feature items from hdf5 featureItems = [] f = h5py.File(fileName,'r') for fgrp in f['features'].values(): featureItems.append(FeatureBase.deserialize(fgrp)) f.close() del f fm = FeatureMgr(dataMgr, featureItems) # Create FeatureMgr # Compute features fm.prepareCompute(dataMgr) fm.triggerCompute() fm.joinCompute(dataMgr) # Predict with loaded classifier classificationPredict = ClassifierPredictThread(dataMgr) classificationPredict.start() classificationPredict.wait() if ilastik_class >= classificationPredict._prediction[0].shape[-1]: raise RuntimeError('ilastik output class not valid...') # Produce output image and select the probability map probMap = (classificationPredict._prediction[0][0,0,:,:, ilastik_class] * 255).astype(numpy.uint8) img_out = ccore.numpy_to_image(probMap, True) return img_out