def display(self, workspace, figure): """Display a visualization of the results""" from matplotlib.axes import Axes from matplotlib.lines import Line2D import matplotlib.cm if self.wants_neuron_graph: figure.set_subplots((2, 1)) else: figure.set_subplots((1, 1)) title = "Branchpoints of %s and %s\nTrunks are red\nBranches are green\nEndpoints are blue" % ( self.seed_objects_name.value, self.image_name.value, ) figure.subplot_imshow(0, 0, workspace.display_data.branchpoint_image, title) if self.wants_neuron_graph: image = workspace.display_data.intensity_image figure.subplot_imshow_grayscale(1, 0, image, title="Neuron graph", sharexy=figure.subplot(0, 0)) axes = figure.subplot(1, 0) assert isinstance(axes, Axes) edge_graph = workspace.display_data.edge_graph vertex_graph = workspace.display_data.vertex_graph i = vertex_graph["i"] j = vertex_graph["j"] kind = vertex_graph["kind"] brightness = edge_graph["total_intensity"] / edge_graph["length"] brightness = (brightness - np.min(brightness)) / (np.max(brightness) - np.min(brightness) + 0.000001) cm = matplotlib.cm.get_cmap(cpprefs.get_default_colormap()) cmap = matplotlib.cm.ScalarMappable(cmap=cm) edge_color = cmap.to_rgba(brightness) for idx in range(len(edge_graph["v1"])): v = np.array([edge_graph["v1"][idx] - 1, edge_graph["v2"][idx] - 1]) line = Line2D(j[v], i[v], color=edge_color[idx]) axes.add_line(line)
def display(self, workspace): '''Display the results of relabeling workspace - workspace containing saved display data ''' from cellprofiler.gui.cpfigure import renumber_labels_for_display import matplotlib.cm as cm figure = workspace.create_or_find_figure(title="UnifyObjectsByShape, image cycle #%d"%( workspace.measurements.image_set_number),subplots=(1,2)) figure.subplot_imshow_labels(0,0, workspace.display_data.orig_labels, title = self.objects_name.value) output_labels = renumber_labels_for_display( workspace.display_data.output_labels) objects = workspace.object_set.get_objects(self.objects_name.value) labels = objects.segmented image = labels.astype(float) / (1.0 if np.max(labels) == 0 else np.max(labels)) image = (stretch(image) * 255).astype(np.uint8) image = np.dstack((image,image,image)) my_cm = cm.get_cmap(cpprefs.get_default_colormap()) my_cm.set_bad((0,0,0)) sm = cm.ScalarMappable(cmap=my_cm) m_output_labels = np.ma.array(output_labels, mask = output_labels == 0) output_image = sm.to_rgba(m_output_labels, bytes=True)[:,:,:3] image[output_labels > 0 ] = ( image[output_labels > 0] / 4 * 3 + output_image[output_labels > 0,:] / 4) figure.subplot_imshow(0,1, image, title = self.output_objects_name.value, sharex = figure.subplot(0,0), sharey = figure.subplot(0,0))
def upgrade_settings(self, setting_values, variable_revision_number, module_name, from_matlab): if from_matlab and (variable_revision_number == 2): object_name, category, feature_nbr, image_name, size_scale, \ display_image, data_image, dpi_to_save, \ saved_image_contents = setting_values objects_or_image = (OI_IMAGE if object_name == cpmeas.IMAGE else OI_OBJECTS) measurement = '_'.join((category, feature_nbr, image_name, size_scale)) setting_values = [ objects_or_image, object_name, measurement, display_image, "red", data_image, dpi_to_save, saved_image_contents] from_matlab = False variable_revision_number = 1 if variable_revision_number == 1: objects_or_image, objects_name, measurement, \ image_name, text_color, display_image, \ dpi, saved_image_contents = setting_values setting_values = [objects_or_image, objects_name, measurement, image_name, text_color, display_image, 10, 2, saved_image_contents] variable_revision_number = 2 if variable_revision_number == 2: '''Added annotation offset''' setting_values = setting_values + ["0"] variable_revision_number = 3 if variable_revision_number == 3: # Added color map mode setting_values = setting_values + [ CT_TEXT, cpprefs.get_default_colormap() ] variable_revision_number = 4 return setting_values, variable_revision_number, from_matlab
def display(self, workspace, figure): '''Show an informative display''' import matplotlib import cellprofiler.gui.cpfigure figure.set_subplots((2, 1)) assert isinstance(figure, cellprofiler.gui.cpfigure.CPFigureFrame) i = workspace.display_data.i j = workspace.display_data.j angles = workspace.display_data.angle mask = workspace.display_data.mask labels = workspace.display_data.labels count = workspace.display_data.count color_image = np.zeros((mask.shape[0], mask.shape[1], 4)) # # We do the coloring using alpha values to let the different # things we draw meld together. # # The binary mask is white. # color_image[mask,:] = MASK_ALPHA if count > 0: mappable = matplotlib.cm.ScalarMappable( cmap = matplotlib.cm.get_cmap(cpprefs.get_default_colormap())) np.random.seed(0) colors = mappable.to_rgba(np.random.permutation(np.arange(count))) # # The labels # color_image[labels > 0,:] += colors[labels[labels > 0] - 1,:] * LABEL_ALPHA # # Do each diamond individually (because the angles are almost certainly # different for each # lcolors = colors * .5 + .5 # Wash the colors out a little for ii in range(count): diamond = self.get_diamond(angles[ii]) hshape = ((np.array(diamond.shape) -1) / 2).astype(int) iii = i[ii] jjj = j[ii] color_image[iii-hshape[0]:iii+hshape[0]+1, jjj-hshape[1]:jjj+hshape[1]+1,:][diamond,:] += \ lcolors[ii,:] * WORM_ALPHA # # Do our own alpha-normalization # color_image[:,:,-1][color_image[:,:,-1] == 0] = 1 color_image[:,:,:-1] = (color_image[:,:,:-1] / color_image[:,:,-1][:,:,np.newaxis]) plot00 = figure.subplot_imshow_bw(0,0, mask, self.image_name.value) figure.subplot_imshow_color(1, 0, color_image[:,:,:-1], title= self.object_name.value, normalize = False, sharexy = plot00)
def get_colors(self, count): '''Get colors used for two-measurement labels image''' import matplotlib.cm as cm cmap=cm.get_cmap(cpprefs.get_default_colormap()) # # Trick the colormap into divulging the values used. # sm = cm.ScalarMappable(cmap=cmap) colors = sm.to_rgba(np.arange(count)+1) return np.vstack((np.zeros(colors.shape[1]), colors))
def upgrade_settings(self, setting_values, variable_revision_number, module_name, from_matlab): if from_matlab and (variable_revision_number == 2): object_name, category, feature_nbr, image_name, size_scale, display_image, data_image, dpi_to_save, saved_image_contents = ( setting_values ) objects_or_image = OI_IMAGE if object_name == cpmeas.IMAGE else OI_OBJECTS measurement = "_".join((category, feature_nbr, image_name, size_scale)) setting_values = [ objects_or_image, object_name, measurement, display_image, "red", data_image, dpi_to_save, saved_image_contents, ] from_matlab = False variable_revision_number = 1 if variable_revision_number == 1: objects_or_image, objects_name, measurement, image_name, text_color, display_image, dpi, saved_image_contents = ( setting_values ) setting_values = [ objects_or_image, objects_name, measurement, image_name, text_color, display_image, 10, 2, saved_image_contents, ] variable_revision_number = 2 if variable_revision_number == 2: """Added annotation offset""" setting_values = setting_values + ["0"] variable_revision_number = 3 if variable_revision_number == 3: # Added color map mode setting_values = setting_values + [CT_TEXT, cpprefs.get_default_colormap()] variable_revision_number = 4 if variable_revision_number == 4: # added wants_image setting_values = setting_values + [cps.YES] variable_revision_number = 5 if variable_revision_number == 5: # added color_map_scale_choice and color_map_scale setting_values = setting_values + [CMS_USE_MEASUREMENT_RANGE, "0.0,1.0"] variable_revision_number = 6 return setting_values, variable_revision_number, from_matlab
def __init__(self, vw, color, can_delete): super(VWObjectsRow, self).__init__(vw, color, can_delete) self.update_chooser(first=True) name = self.chooser.GetStringSelection() self.data = bind_data_class(ObjectsData, self.color_ctrl, vw.redraw)( name, None, outline_color = self.color, colormap = cpprefs.get_default_colormap(), alpha = .5, mode = MODE_HIDE) vw.image.add(self.data) self.last_mode = MODE_LINES
def display(self, workspace): """Display the results of relabeling workspace - workspace containing saved display data """ from cellprofiler.gui.cpfigure import renumber_labels_for_display import matplotlib.cm as cm figure = workspace.create_or_find_figure( title="ReassignObjectNumbers, image cycle #%d" % (workspace.measurements.image_set_number), subplots=(1, 2) ) figure.subplot_imshow_labels(0, 0, workspace.display_data.orig_labels, title=self.objects_name.value) output_labels = renumber_labels_for_display(workspace.display_data.output_labels) if self.relabel_option == OPTION_UNIFY: if self.unify_option == UNIFY_DISTANCE and self.wants_image: # # Make a nice picture which superimposes the labels on the # guiding image # image = (stretch(workspace.display_data.image) * 255).astype(np.uint8) elif self.unify_option == UNIFY_PARENT: parent_objects = workspace.object_set.get_objects(self.parent_object.value) labels = parent_objects.segmented image = labels.astype(float) / (1.0 if np.max(labels) == 0 else np.max(labels)) image = (stretch(image) * 255).astype(np.uint8) image = np.dstack((image, image, image)) my_cm = cm.get_cmap(cpprefs.get_default_colormap()) my_cm.set_bad((0, 0, 0)) sm = cm.ScalarMappable(cmap=my_cm) m_output_labels = np.ma.array(output_labels, mask=output_labels == 0) output_image = sm.to_rgba(m_output_labels, bytes=True)[:, :, :3] image[output_labels > 0] = image[output_labels > 0] / 4 * 3 + output_image[output_labels > 0, :] / 4 figure.subplot_imshow( 0, 1, image, title=self.output_objects_name.value, sharex=figure.subplot(0, 0), sharey=figure.subplot(0, 0), ) else: figure.subplot_imshow_labels( 0, 1, workspace.display_data.output_labels, title=self.output_objects_name.value, sharex=figure.subplot(0, 0), sharey=figure.subplot(0, 0), )
def run(self, workspace): header = ("Image", "Objects", "Bin # (innermost=1)", "Bin count", "Fraction", "Intensity", "COV") stats = [] d = {} for image in self.images: for o in self.objects: for bin_count_settings in self.bin_counts: stats += \ self.do_measurements(workspace, image.image_name.value, o.object_name.value, o.center_object_name.value if o.center_choice != C_SELF else None, o.center_choice.value, bin_count_settings, d) if self.wants_zernikes: self.calculate_zernikes(workspace) if self.show_window: workspace.display_data.header = header workspace.display_data.stats = stats workspace.display_data.heatmaps = [] for heatmap in self.heatmaps: heatmap_img = d.get(id(heatmap)) if heatmap_img is not None: if self.show_window or heatmap.wants_to_save_display: labels = workspace.object_set.get_objects( heatmap.object_name.get_objects_name()).segmented if self.show_window: workspace.display_data.heatmaps.append( (heatmap_img, labels != 0)) if heatmap.wants_to_save_display: colormap = heatmap.colormap.value if colormap == matplotlib.cm.gray.name: output_pixels = heatmap_img else: if colormap == cps.DEFAULT: colormap = cpprefs.get_default_colormap() cm = matplotlib.cm.ScalarMappable( cmap=colormap) output_pixels = cm.to_rgba(heatmap_img)[:, :, :3] output_pixels[labels == 0, :] = 0 parent_image = workspace.image_set.get_image( heatmap.image_name.get_image_name()) output_img = cpi.Image( output_pixels, parent_image=parent_image) img_name = heatmap.display_name.value workspace.image_set.add(img_name, output_img)
def display_on_figure(self, workspace, axes, imshow_fn): import matplotlib import matplotlib.cm if self.use_color_map(): labels = workspace.display_data.labels if self.wants_image: pixel_data = workspace.display_data.pixel_data else: pixel_data = (labels != 0).astype(np.float32) if pixel_data.ndim == 3: pixel_data = np.sum(pixel_data, 2) / pixel_data.shape[2] colormap_name = self.colormap.value if colormap_name == cps.DEFAULT: colormap_name = cpprefs.get_default_colormap() colormap = matplotlib.cm.get_cmap(colormap_name) values = workspace.display_data.values vmask = workspace.display_data.mask colors = np.ones((len(vmask) + 1, 4)) colors[1:][~vmask, :3] = 1 sm = matplotlib.cm.ScalarMappable(cmap=colormap) if self.color_map_scale_choice == CMS_MANUAL: sm.set_clim(self.color_map_scale.min, self.color_map_scale.max) sm.set_array(values) colors[1:][vmask, :] = sm.to_rgba(values) img = colors[labels, :3] * pixel_data[:, :, np.newaxis] imshow_fn(img) assert isinstance(axes, matplotlib.axes.Axes) figure = axes.get_figure() assert isinstance(figure, matplotlib.figure.Figure) figure.colorbar(sm, ax=axes) else: imshow_fn(workspace.display_data.pixel_data) for x, y, value in zip(workspace.display_data.x, workspace.display_data.y, workspace.display_data.values): try: fvalue = float(value) svalue = "%.*f" % (self.decimals.value, value) except: svalue = str(value) text = matplotlib.text.Text( x=x, y=y, text=svalue, size=self.font_size.value, color=self.text_color.value, verticalalignment="center", horizontalalignment="center", ) axes.add_artist(text)
def display(self, workspace, figure): header = workspace.display_data.header stats = workspace.display_data.stats n_plots = len(workspace.display_data.heatmaps) + 1 n_vert = int(np.sqrt(n_plots)) n_horiz = int(np.ceil(float(n_plots) / n_vert)) figure.set_subplots((n_horiz, n_vert)) figure.subplot_table(0, 0, stats, col_labels=header) idx = 1 sharexy = None for heatmap, (heatmap_img, mask) in zip( self.heatmaps, workspace.display_data.heatmaps): heatmap_img = np.ma.array(heatmap_img, mask=~mask) if heatmap_img is not None: title = "%s %s %s" % ( heatmap.image_name.get_image_name(), heatmap.object_name.get_objects_name(), heatmap.measurement.value) x = idx % n_horiz y = int(idx / n_horiz) colormap = heatmap.colormap.value if colormap == cps.DEFAULT: colormap = cpprefs.get_default_colormap() if sharexy is None: sharexy = figure.subplot_imshow( x, y, heatmap_img, title=title, colormap=colormap, normalize=False, vmin=np.min(heatmap_img), vmax=np.max(heatmap_img), colorbar=True) else: figure.subplot_imshow( x, y, heatmap_img, title=title, colormap=colormap, colorbar=True, normalize=False, vmin=np.min(heatmap_img), vmax=np.max(heatmap_img), sharexy=sharexy) idx += 1
def display(self, workspace): '''Create an informative display for the module''' import matplotlib from cellprofiler.gui.cpfigure import renumber_labels_for_display original_labels = workspace.display_data.original_labels final_labels = workspace.display_data.final_labels mask = workspace.display_data.mask # # Create a composition of the final labels and mask # final_labels = renumber_labels_for_display(final_labels) outlines = outline(original_labels) > 0 cm = matplotlib.cm.get_cmap(cpprefs.get_default_colormap()) sm = matplotlib.cm.ScalarMappable(cmap = cm) # # Paint the labels in color # image = sm.to_rgba(final_labels)[:,:,:3] image[final_labels == 0,:] = 0 # # Make the mask a dark gray # image[(final_labels == 0) & mask,:] = .25 # # Make the outlines of the kept objects the primary color # and the outlines of removed objects red. # final_outlines = outline(final_labels) > 0 original_color = np.array(cpprefs.get_secondary_outline_color(), float) / 255 final_color = np.array(cpprefs.get_primary_outline_color(), float) / 255 image[outlines, :] = original_color[np.newaxis, :] image[final_outlines, :] = final_color[np.newaxis, :] figure = workspace.create_or_find_figure(title="MaskObjects, image cycle #%d"%( workspace.measurements.image_set_number),subplots=(2,1)) figure.subplot_imshow_labels(0, 0, original_labels, title = self.object_name.value) figure.subplot_imshow_color(1, 0, image, title = self.remaining_objects.value, sharex = figure.subplot(0,0), sharey = figure.subplot(0,0))
def display(self, workspace): '''Display the results of relabeling workspace - workspace containing saved display data ''' from cellprofiler.gui.cpfigure import renumber_labels_for_display import matplotlib.cm as cm figure = workspace.create_or_find_figure(title="ReassignObjectNumbers, image cycle #%d"%( workspace.measurements.image_set_number),subplots=(1,2)) figure.subplot_imshow_labels(0,0, workspace.display_data.orig_labels, title = self.objects_name.value) if self.wants_image: # # Make a nice picture which superimposes the labels on the # guiding image # output_labels = renumber_labels_for_display( workspace.display_data.output_labels) image = (stretch(workspace.display_data.image) * 255).astype(np.uint8) image = np.dstack((image,image,image)) my_cm = cm.get_cmap(cpprefs.get_default_colormap()) my_cm.set_bad((0,0,0)) sm = cm.ScalarMappable(cmap=my_cm) m_output_labels = np.ma.array(output_labels, mask = output_labels == 0) output_image = sm.to_rgba(m_output_labels, bytes=True)[:,:,:3] image[output_labels > 0 ] = ( image[output_labels > 0] / 4 * 3 + output_image[output_labels > 0,:] / 4) figure.subplot_imshow(0,1, image, title = self.output_objects_name.value, sharex = figure.subplot(0,0), sharey = figure.subplot(0,0)) else: figure.subplot_imshow_labels(0,1, workspace.display_data.output_labels, title = self.output_objects_name.value, sharex = figure.subplot(0,0), sharey = figure.subplot(0,0))
def __init__(self, vw, color, can_delete): super(VWImageRow, self).__init__(vw, color, can_delete) image_set = vw.workspace.image_set name = self.chooser.GetStringSelection() im = cpprefs.get_intensity_mode() if im == cpprefs.INTENSITY_MODE_LOG: normalization = NORMALIZE_LOG elif im == cpprefs.INTENSITY_MODE_NORMAL: normalization = NORMALIZE_LINEAR else: normalization = NORMALIZE_RAW alpha = 1.0 / (len(vw.image_rows) + 1.0) self.data = bind_data_class(ImageData, self.color_ctrl, vw.redraw)( name, None, mode = MODE_HIDE, color = self.color, colormap = cpprefs.get_default_colormap(), alpha = alpha, normalization = normalization) vw.image.add(self.data) self.last_mode = MODE_COLORIZE
def draw_outlines(self, pixel_data, labels): '''Draw a color image that shows the objects pixel_data - image, either b & w or color labels - labels for image returns - color image of same size as pixel_data ''' from cellprofiler.gui.cpfigure import renumber_labels_for_display import matplotlib labels = renumber_labels_for_display(labels) outlines = outline(labels) if pixel_data.ndim == 3: image = pixel_data.copy() else: image = np.dstack([pixel_data]*3) # # make labeled pixels a grayscale times the label color # cm = matplotlib.cm.get_cmap(cpprefs.get_default_colormap()) sm = matplotlib.cm.ScalarMappable(cmap = cm) labels_image = sm.to_rgba(labels)[:,:,:3] lmask = labels > 0 gray = (image[lmask,0] + image[lmask,1] + image[lmask,2]) / 3 for i in range(3): image[lmask,i] = gray * labels_image[lmask, i] # # Make the outline pixels a solid color # outlines_image = sm.to_rgba(outlines)[:,:,:3] image[outlines > 0,:] = outlines_image[outlines > 0,:] return image
def display(self, workspace): import matplotlib nsubplots = 0 if self.wants_population_density(): nsubplots += 1 if self.wants_distance_to_edge(): nsubplots += 1 figure = workspace.create_or_find_figure(subplots=(nsubplots, 1)) cmap = cpprefs.get_default_colormap() cm = matplotlib.cm.get_cmap(cmap) cm.set_bad(color='black') axes = None if self.wants_population_density(): image = np.ma.MaskedArray(workspace.display_data.count_display, workspace.display_data.count_display < 0) title = "# objects within %d px" % self.radius.value axes = figure.subplot_imshow(0, 0, image, title = title, colormap = cm, colorbar=True, normalize = False, vmin = 0, vmax = np.max(image)) if self.wants_distance_to_edge(): sm = matplotlib.cm.ScalarMappable(cmap = cm) image = np.ma.MaskedArray(workspace.display_data.distances, workspace.display_data.distances < 0) image = sm.to_rgba(image) # # We give the edge a little blur so that single pixels show up ok # edge = gaussian_filter(workspace.display_data.edge.astype(float), 3) edge = edge / np.max(edge) edge_color = sm.to_rgba(np.array([np.max(workspace.display_data.distances)]))[0] image = image * (1 - edge[:, :, np.newaxis]) + \ edge[:, :, np.newaxis] * edge_color[np.newaxis, np.newaxis, :] figure.subplot_imshow(nsubplots-1, 0, image, title = "Distance to edge")
def get_colormap(name): '''Get colormap, accounting for possible request for default''' if name == cps.DEFAULT: name = cpprefs.get_default_colormap() return matplotlib.cm.get_cmap(name)
def run(self, workspace): objects = workspace.object_set.get_objects(self.object_name.value) assert isinstance(objects, cpo.Objects) has_pixels = objects.areas > 0 labels = objects.small_removed_segmented kept_labels = objects.segmented neighbor_objects = workspace.object_set.get_objects(self.neighbors_name.value) assert isinstance(neighbor_objects, cpo.Objects) neighbor_labels = neighbor_objects.small_removed_segmented # # Need to add in labels touching border. # unedited_segmented = neighbor_objects.unedited_segmented touching_border = np.zeros(np.max(unedited_segmented) + 1, bool) touching_border[unedited_segmented[0, :]] = True touching_border[unedited_segmented[-1, :]] = True touching_border[unedited_segmented[:, 0]] = True touching_border[unedited_segmented[:, -1]] = True touching_border[0] = False touching_border_mask = touching_border[unedited_segmented] if np.any(touching_border) and \ np.all(~ touching_border_mask[neighbor_labels]): # Add the border labels if any were excluded touching_border_object_number = np.cumsum(touching_border) + \ np.max(neighbor_labels) touching_border_mask = touching_border_mask & neighbor_labels == 0 neighbor_labels[touching_border_mask] = touching_border_object_number[ unedited_segmented[touching_border_mask]] nobjects = np.max(labels) nneighbors = np.max(neighbor_labels) nkept_objects = objects.count _, object_numbers = objects.relate_labels(labels, kept_labels) if self.neighbors_are_objects: neighbor_numbers = object_numbers else: _, neighbor_numbers = neighbor_objects.relate_labels( neighbor_labels, neighbor_objects.segmented) neighbor_count = np.zeros((nobjects,)) pixel_count = np.zeros((nobjects,)) first_object_number = np.zeros((nobjects,),int) second_object_number = np.zeros((nobjects,),int) first_x_vector = np.zeros((nobjects,)) second_x_vector = np.zeros((nobjects,)) first_y_vector = np.zeros((nobjects,)) second_y_vector = np.zeros((nobjects,)) angle = np.zeros((nobjects,)) percent_touching = np.zeros((nobjects,)) expanded_labels = None if self.distance_method == D_EXPAND: # Find the i,j coordinates of the nearest foreground point # to every background point i,j = scind.distance_transform_edt(labels==0, return_distances=False, return_indices=True) # Assign each background pixel to the label of its nearest # foreground pixel. Assign label to label for foreground. labels = labels[i,j] expanded_labels = labels # for display distance = 1 # dilate once to make touching edges overlap scale = S_EXPANDED if self.neighbors_are_objects: neighbor_labels = labels.copy() elif self.distance_method == D_WITHIN: distance = self.distance.value scale = str(distance) elif self.distance_method == D_ADJACENT: distance = 1 scale = S_ADJACENT else: raise ValueError("Unknown distance method: %s" % self.distance_method.value) if nneighbors > (1 if self.neighbors_are_objects else 0): first_objects = [] second_objects = [] object_indexes = np.arange(nobjects, dtype=np.int32)+1 # # First, compute the first and second nearest neighbors, # and the angles between self and the first and second # nearest neighbors # ocenters = centers_of_labels( objects.small_removed_segmented).transpose() ncenters = centers_of_labels( neighbor_objects.small_removed_segmented).transpose() areas = fix(scind.sum(np.ones(labels.shape),labels, object_indexes)) perimeter_outlines = outline(labels) perimeters = fix(scind.sum( np.ones(labels.shape), perimeter_outlines, object_indexes)) i,j = np.mgrid[0:nobjects,0:nneighbors] distance_matrix = np.sqrt((ocenters[i,0] - ncenters[j,0])**2 + (ocenters[i,1] - ncenters[j,1])**2) # # order[:,0] should be arange(nobjects) # order[:,1] should be the nearest neighbor # order[:,2] should be the next nearest neighbor # if distance_matrix.shape[1] == 1: # a little buggy, lexsort assumes that a 2-d array of # second dimension = 1 is a 1-d array order = np.zeros(distance_matrix.shape, int) else: order = np.lexsort([distance_matrix]) first_neighbor = 1 if self.neighbors_are_objects else 0 first_object_index = order[:, first_neighbor] first_x_vector = ncenters[first_object_index,1] - ocenters[:,1] first_y_vector = ncenters[first_object_index,0] - ocenters[:,0] if nneighbors > first_neighbor+1: second_object_index = order[:, first_neighbor + 1] second_x_vector = ncenters[second_object_index,1] - ocenters[:,1] second_y_vector = ncenters[second_object_index,0] - ocenters[:,0] v1 = np.array((first_x_vector,first_y_vector)) v2 = np.array((second_x_vector,second_y_vector)) # # Project the unit vector v1 against the unit vector v2 # dot = (np.sum(v1*v2,0) / np.sqrt(np.sum(v1**2,0)*np.sum(v2**2,0))) angle = np.arccos(dot) * 180. / np.pi # Make the structuring element for dilation strel = strel_disk(distance) # # A little bigger one to enter into the border with a structure # that mimics the one used to create the outline # strel_touching = strel_disk(distance + .5) # # Get the extents for each object and calculate the patch # that excises the part of the image that is "distance" # away i,j = np.mgrid[0:labels.shape[0],0:labels.shape[1]] min_i, max_i, min_i_pos, max_i_pos =\ scind.extrema(i,labels,object_indexes) min_j, max_j, min_j_pos, max_j_pos =\ scind.extrema(j,labels,object_indexes) min_i = np.maximum(fix(min_i)-distance,0).astype(int) max_i = np.minimum(fix(max_i)+distance+1,labels.shape[0]).astype(int) min_j = np.maximum(fix(min_j)-distance,0).astype(int) max_j = np.minimum(fix(max_j)+distance+1,labels.shape[1]).astype(int) # # Loop over all objects # Calculate which ones overlap "index" # Calculate how much overlap there is of others to "index" # for object_number in object_numbers: if object_number == 0: # # No corresponding object in small-removed. This means # that the object has no pixels, e.g. not renumbered. # continue index = object_number - 1 patch = labels[min_i[index]:max_i[index], min_j[index]:max_j[index]] npatch = neighbor_labels[min_i[index]:max_i[index], min_j[index]:max_j[index]] # # Find the neighbors # patch_mask = patch==(index+1) extended = scind.binary_dilation(patch_mask,strel) neighbors = np.unique(npatch[extended]) neighbors = neighbors[neighbors != 0] if self.neighbors_are_objects: neighbors = neighbors[neighbors != object_number] nc = len(neighbors) neighbor_count[index] = nc if nc > 0: first_objects.append(np.ones(nc,int) * object_number) second_objects.append(neighbors) if self.neighbors_are_objects: # # Find the # of overlapping pixels. Dilate the neighbors # and see how many pixels overlap our image. Use a 3x3 # structuring element to expand the overlapping edge # into the perimeter. # outline_patch = perimeter_outlines[ min_i[index]:max_i[index], min_j[index]:max_j[index]] == object_number extended = scind.binary_dilation( (patch != 0) & (patch != object_number), strel_touching) overlap = np.sum(outline_patch & extended) pixel_count[index] = overlap if sum([len(x) for x in first_objects]) > 0: first_objects = np.hstack(first_objects) reverse_object_numbers = np.zeros( max(np.max(object_numbers), np.max(first_objects)) + 1, int) reverse_object_numbers[object_numbers] = np.arange(len(object_numbers)) + 1 first_objects = reverse_object_numbers[first_objects] second_objects = np.hstack(second_objects) reverse_neighbor_numbers = np.zeros( max(np.max(neighbor_numbers), np.max(second_objects)) + 1, int) reverse_neighbor_numbers[neighbor_numbers] = np.arange(len(neighbor_numbers)) + 1 second_objects= reverse_neighbor_numbers[second_objects] to_keep = (first_objects > 0) & (second_objects > 0) first_objects = first_objects[to_keep] second_objects = second_objects[to_keep] else: first_objects = np.zeros(0, int) second_objects = np.zeros(0, int) if self.neighbors_are_objects: percent_touching = pixel_count * 100 / perimeters else: percent_touching = pixel_count * 100.0 / areas object_indexes = object_numbers - 1 neighbor_indexes = neighbor_numbers - 1 # # Have to recompute nearest # first_object_number = np.zeros(nkept_objects, int) second_object_number = np.zeros(nkept_objects, int) if nkept_objects > (1 if self.neighbors_are_objects else 0): di = (ocenters[object_indexes[:, np.newaxis], 0] - ncenters[neighbor_indexes[np.newaxis, :], 0]) dj = (ocenters[object_indexes[:, np.newaxis], 1] - ncenters[neighbor_indexes[np.newaxis, :], 1]) distance_matrix = np.sqrt(di*di + dj*dj) distance_matrix[~ has_pixels, :] = np.inf distance_matrix[:, ~has_pixels] = np.inf # # order[:,0] should be arange(nobjects) # order[:,1] should be the nearest neighbor # order[:,2] should be the next nearest neighbor # order = np.lexsort([distance_matrix]).astype( first_object_number.dtype) if self.neighbors_are_objects: first_object_number[has_pixels] = order[has_pixels,1] + 1 if nkept_objects > 2: second_object_number[has_pixels] = order[has_pixels,2] + 1 else: first_object_number[has_pixels] = order[has_pixels,0] + 1 if nneighbors > 1: second_object_number[has_pixels] = order[has_pixels,1] + 1 else: object_indexes = object_numbers - 1 neighbor_indexes = neighbor_numbers - 1 first_objects = np.zeros(0, int) second_objects = np.zeros(0, int) # # Now convert all measurements from the small-removed to # the final number set. # neighbor_count = neighbor_count[object_indexes] neighbor_count[~ has_pixels] = 0 percent_touching = percent_touching[object_indexes] percent_touching[~ has_pixels] = 0 first_x_vector = first_x_vector[object_indexes] second_x_vector = second_x_vector[object_indexes] first_y_vector = first_y_vector[object_indexes] second_y_vector = second_y_vector[object_indexes] angle = angle[object_indexes] # # Record the measurements # assert(isinstance(workspace, cpw.Workspace)) m = workspace.measurements assert(isinstance(m, cpmeas.Measurements)) image_set = workspace.image_set features_and_data = [ (M_NUMBER_OF_NEIGHBORS, neighbor_count), (M_FIRST_CLOSEST_OBJECT_NUMBER, first_object_number), (M_FIRST_CLOSEST_DISTANCE, np.sqrt(first_x_vector**2+first_y_vector**2)), (M_SECOND_CLOSEST_OBJECT_NUMBER, second_object_number), (M_SECOND_CLOSEST_DISTANCE, np.sqrt(second_x_vector**2+second_y_vector**2)), (M_ANGLE_BETWEEN_NEIGHBORS, angle)] if self.neighbors_are_objects: features_and_data.append((M_PERCENT_TOUCHING, percent_touching)) for feature_name, data in features_and_data: m.add_measurement(self.object_name.value, self.get_measurement_name(feature_name), data) if len(first_objects) > 0: m.add_relate_measurement( self.module_num, cpmeas.NEIGHBORS, self.object_name.value, self.object_name.value if self.neighbors_are_objects else self.neighbors_name.value, m.image_set_number * np.ones(first_objects.shape, int), first_objects, m.image_set_number * np.ones(second_objects.shape, int), second_objects) labels = kept_labels neighbor_count_image = np.zeros(labels.shape,int) object_mask = objects.segmented != 0 object_indexes = objects.segmented[object_mask]-1 neighbor_count_image[object_mask] = neighbor_count[object_indexes] workspace.display_data.neighbor_count_image = neighbor_count_image if self.neighbors_are_objects: percent_touching_image = np.zeros(labels.shape) percent_touching_image[object_mask] = percent_touching[object_indexes] workspace.display_data.percent_touching_image = percent_touching_image image_set = workspace.image_set if self.wants_count_image.value: neighbor_cm_name = self.count_colormap.value neighbor_cm = get_colormap(neighbor_cm_name) sm = matplotlib.cm.ScalarMappable(cmap = neighbor_cm) img = sm.to_rgba(neighbor_count_image)[:,:,:3] img[:,:,0][~ object_mask] = 0 img[:,:,1][~ object_mask] = 0 img[:,:,2][~ object_mask] = 0 count_image = cpi.Image(img, masking_objects = objects) image_set.add(self.count_image_name.value, count_image) else: neighbor_cm_name = cpprefs.get_default_colormap() neighbor_cm = matplotlib.cm.get_cmap(neighbor_cm_name) if self.neighbors_are_objects and self.wants_percent_touching_image: percent_touching_cm_name = self.touching_colormap.value percent_touching_cm = get_colormap(percent_touching_cm_name) sm = matplotlib.cm.ScalarMappable(cmap = percent_touching_cm) img = sm.to_rgba(percent_touching_image)[:,:,:3] img[:,:,0][~ object_mask] = 0 img[:,:,1][~ object_mask] = 0 img[:,:,2][~ object_mask] = 0 touching_image = cpi.Image(img, masking_objects = objects) image_set.add(self.touching_image_name.value, touching_image) else: percent_touching_cm_name = cpprefs.get_default_colormap() percent_touching_cm = matplotlib.cm.get_cmap(percent_touching_cm_name) if self.show_window: workspace.display_data.neighbor_cm_name = neighbor_cm_name workspace.display_data.percent_touching_cm_name = percent_touching_cm_name workspace.display_data.orig_labels = objects.segmented workspace.display_data.expanded_labels = expanded_labels workspace.display_data.object_mask = object_mask
def run(self, workspace): objects = workspace.object_set.get_objects(self.object_name.value) labels = objects.segmented convert = True if not workspace.frame is None: figure = workspace.create_or_find_figure( title="ConvertObjectsToImage, image cycle #%d" % (workspace.measurements.image_set_number), subplots=(2, 1), ) figure.subplot_imshow_labels(0, 0, labels, "Original: %s" % self.object_name.value) if self.image_mode == IM_BINARY: pixel_data = labels != 0 if not workspace.frame is None: figure.subplot_imshow_bw( 1, 0, pixel_data, self.image_name.value, sharex=figure.subplot(0, 0), sharey=figure.subplot(0, 0) ) elif self.image_mode == IM_GRAYSCALE: pixel_data = labels.astype(float) / np.max(labels) if not workspace.frame is None: figure.subplot_imshow_grayscale( 1, 0, pixel_data, self.image_name.value, sharex=figure.subplot(0, 0), sharey=figure.subplot(0, 0) ) elif self.image_mode == IM_COLOR: import matplotlib.cm from cellprofiler.gui.cpfigure import renumber_labels_for_display if self.colormap.value == DEFAULT_COLORMAP: cm_name = cpprefs.get_default_colormap() elif self.colormap.value == COLORCUBE: # Colorcube missing from matplotlib cm_name = "gist_rainbow" elif self.colormap.value == LINES: # Lines missing from matplotlib and not much like it, # Pretty boring palette anyway, hence cm_name = "Pastel1" elif self.colormap.value == WHITE: # White missing from matplotlib, it's just a colormap # of all completely white... not even different kinds of # white. And, isn't white just a uniform sampling of # frequencies from the spectrum? cm_name = "Spectral" else: cm_name = self.colormap.value cm = matplotlib.cm.get_cmap(cm_name) mapper = matplotlib.cm.ScalarMappable(cmap=cm) pixel_data = mapper.to_rgba(renumber_labels_for_display(labels)) pixel_data = pixel_data[:, :, :3] pixel_data[labels == 0, :] = 0 if not workspace.frame is None: figure.subplot_imshow( 1, 0, pixel_data, self.image_name.value, sharex=figure.subplot(0, 0), sharey=figure.subplot(0, 0) ) elif self.image_mode == IM_UINT16: pixel_data = labels.copy() if not workspace.frame is None: figure.subplot_imshow_grayscale( 1, 0, pixel_data, self.image_name.value, sharex=figure.subplot(0, 0), sharey=figure.subplot(0, 0) ) convert = False image = cpi.Image(pixel_data, parent_image=objects.parent_image, convert=convert) workspace.image_set.add(self.image_name.value, image)
def redraw(self, event=None): if self.ignore_redraw: return min_height = min_width = np.iinfo(np.int32).max smallest = None size_mismatch = False images = [] for chooser, color, check, _ in self.image_rows: if not check.IsChecked(): continue assert isinstance(chooser, wx.Choice) selection = chooser.GetCurrentSelection() items = chooser.GetItems() if selection < 0 or selection >= len(items): continue image_name = items[selection] if not image_name in self.workspace.image_set.get_names(): continue image = self.workspace.image_set.get_image(image_name) red, green, blue = color.GetValue() images.append((image, red, green, blue)) height, width = image.pixel_data.shape[:2] if height < min_height or width < min_width: min_height, min_width = height, width smallest = image size_mismatch = True elif height > min_height or width > min_width: size_mismatch = True if len(images) == 0: self.frame.figure.canvas.Hide() return cplabels = [] for chooser, color, check, _ in self.object_rows: if not check.IsChecked(): continue idx = chooser.GetCurrentSelection() names = chooser.GetItems() if idx < 0 or idx >= len(names): continue objects_name = names[idx] if objects_name not in self.workspace.object_set.get_object_names(): continue objects = self.workspace.object_set.get_objects(objects_name) red, green, blue = color.GetValue() color = (red, green, blue) alpha_colormap = cpprefs.get_default_colormap() height, width = objects.shape[:2] if height < min_height or width < min_width: min_height, min_width = height, width smallest = objects size_mismatch = True elif height > min_height or width > min_width: size_mismatch = True cplabels.append( { CPLD_NAME: objects_name, CPLD_LABELS: [x[0] for x in objects.get_labels()], CPLD_OUTLINE_COLOR: color, CPLD_MODE: CPLDM_OUTLINES, CPLD_ALPHA_VALUE: .25, CPLD_ALPHA_COLORMAP: alpha_colormap, CPLD_LINE_WIDTH: 1, CPLD_SHOW: True}) if size_mismatch: for d in cplabels: d[CPLD_LABELS] = [ smallest.crop_image_similarly(l) for l in d[CPLD_LABELS]] if not self.frame.figure.canvas.IsShown(): self.frame.figure.canvas.Show() self.layout() width, height = min_width, min_height image = np.zeros((height, width, 3)) for src_image, red, green, blue in images: pixel_data = src_image.pixel_data.astype(np.float32) if size_mismatch: pixel_data = smallest.crop_image_similarly(pixel_data) if pixel_data.ndim == 3: src_depth = min(pixel_data.shape[2], 3) image[:, :, :src_depth] += \ pixel_data[:, :, :src_depth] else: image[:, :, 0] += pixel_data * red / 255 image[:, :, 1] += pixel_data * green / 255 image[:, :, 2] += pixel_data * blue / 255 if self.image is not None and \ tuple(self.image.image.shape) != tuple(image.shape): self.image = None self.axes.cla() if self.image == None: self.frame.subplot_imshow_color( 0, 0, image, clear = False, cplabels = cplabels) self.axes.set_xbound(-.5, width -.5) self.axes.set_ybound(-.5, height -.5) for artist in self.axes.artists: if isinstance(artist, CPImageArtist): self.image = artist else: self.image.image = image old_cplabels = self.image.kwargs["cplabels"] for cplabel in old_cplabels: cplabel[CPLD_SHOW] = False for cplabel in cplabels: name = cplabel[CPLD_NAME] matches = filter((lambda x: x[CPLD_NAME] == name), old_cplabels) if len(matches) == 0: old_cplabels.append(cplabel) else: matches[0][CPLD_LABELS] = cplabel[CPLD_LABELS] matches[0][CPLD_OUTLINE_COLOR] = cplabel[CPLD_OUTLINE_COLOR] matches[0][CPLD_SHOW] = True self.image.kwargs["cplabels"] = old_cplabels self.frame.subplot_params[(0, 0)]['cplabels'] = old_cplabels self.frame.update_line_labels(self.axes, self.image.kwargs) # # Remove all the old text labels # to_remove = [] for artist in list(self.axes.texts): artist.remove() m = self.workspace.measurements assert isinstance(m, cpmeas.Measurements) title_lines = [] object_values = {} for measurement_row in self.measurement_rows: assert isinstance(measurement_row, MeasurementRow) if not measurement_row.should_show(): continue object_name = measurement_row.get_object_name() if object_name is None or object_name not in m.get_object_names(): continue feature = measurement_row.get_measurement_name() if feature is None or not m.has_feature(object_name, feature): continue value = m[object_name, feature] if object_name in (cpmeas.IMAGE, cpmeas.EXPERIMENT): if isinstance(value, int): fmt = "%s: %d" elif isinstance(value, float): fmt = "%s: %.4f" else: fmt = "%s: %s" title_lines.append(fmt % (feature, value)) else: if object_name not in object_values: if any([not m.has_feature(object_name, lf) for lf in M_LOCATION_CENTER_X, M_LOCATION_CENTER_Y]): continue object_values[object_name] = []
def redraw(self, event=None): if self.ignore_redraw: return images = [] for chooser, color, check, _ in self.image_rows: if not check.IsChecked(): continue assert isinstance(chooser, wx.Choice) selection = chooser.GetCurrentSelection() items = chooser.GetItems() if selection < 0 or selection >= len(items): continue image_name = items[selection] if not image_name in self.workspace.image_set.get_names(): continue image = self.workspace.image_set.get_image(image_name) red, green, blue = color.GetValue() images.append((image, red, green, blue)) if len(images) == 0: self.frame.figure.canvas.Hide() return if not self.frame.figure.canvas.IsShown(): self.frame.figure.canvas.Show() self.layout() width = height = 0 for image, _, _, _ in images: width = max(width, image.pixel_data.shape[1]) height = max(height, image.pixel_data.shape[0]) image = np.zeros((height, width, 3)) for src_image, red, green, blue in images: pixel_data = src_image.pixel_data.astype(np.float32) src_height, src_width = pixel_data.shape[:2] if pixel_data.ndim == 3: src_depth = min(pixel_data.shape[2], 3) image[:src_height, :src_width, :src_depth] += \ pixel_data[:, :, :src_depth] else: image[:src_height, :src_width, 0] += pixel_data * red / 255 image[:src_height, :src_width, 1] += pixel_data * green / 255 image[:src_height, :src_width, 2] += pixel_data * blue / 255 cplabels = [] for chooser, color, check, _ in self.object_rows: if not check.IsChecked(): continue idx = chooser.GetCurrentSelection() names = chooser.GetItems() if idx < 0 or idx >= len(names): continue objects_name = names[idx] if objects_name not in self.workspace.object_set.get_object_names(): continue objects = self.workspace.object_set.get_objects(objects_name) red, green, blue = color.GetValue() color = (red, green, blue) alpha_colormap = cpprefs.get_default_colormap() cplabels.append( { CPLD_NAME: objects_name, CPLD_LABELS: [x[0] for x in objects.get_labels()], CPLD_OUTLINE_COLOR: color, CPLD_MODE: CPLDM_OUTLINES, CPLD_ALPHA_VALUE: .25, CPLD_ALPHA_COLORMAP: alpha_colormap, CPLD_LINE_WIDTH: 1}) if self.image is not None and \ tuple(self.image.image.shape) != tuple(image.shape): self.image = None self.axes.cla() if self.image == None: self.frame.subplot_imshow_color( 0, 0, image, clear = False, cplabels = cplabels) self.axes.set_xbound(-.5, width -.5) self.axes.set_ybound(-.5, height -.5) for artist in self.axes.artists: if isinstance(artist, CPImageArtist): self.image = artist else: self.image.image = image self.image.kwargs["cplabels"] = cplabels # # Remove all the old text labels # to_remove = [] for artist in list(self.axes.texts): artist.remove() m = self.workspace.measurements assert isinstance(m, cpmeas.Measurements) title_lines = [] object_values = {} for measurement_row in self.measurement_rows: assert isinstance(measurement_row, MeasurementRow) if not measurement_row.should_show(): continue object_name = measurement_row.get_object_name() if object_name is None or object_name not in m.get_object_names(): continue feature = measurement_row.get_measurement_name() if feature is None or not m.has_feature(object_name, feature): continue value = m[object_name, feature] if object_name in (cpmeas.IMAGE, cpmeas.EXPERIMENT): if isinstance(value, int): fmt = "%s: %d" elif isinstance(value, float): fmt = "%s: %.4f" else: fmt = "%s: %s" title_lines.append(fmt % (feature, value)) else: if object_name not in object_values: if any([not m.has_feature(object_name, lf) for lf in M_LOCATION_CENTER_X, M_LOCATION_CENTER_Y]): continue object_values[object_name] = []
def run(self, workspace): objects = workspace.object_set.get_objects(self.object_name.value) assert isinstance(objects, cpo.Objects) has_pixels = objects.areas > 0 labels = objects.small_removed_segmented kept_labels = objects.segmented neighbor_objects = workspace.object_set.get_objects(self.neighbors_name.value) assert isinstance(neighbor_objects, cpo.Objects) neighbor_labels = neighbor_objects.small_removed_segmented # # Need to add in labels touching border. # unedited_segmented = neighbor_objects.unedited_segmented touching_border = np.zeros(np.max(unedited_segmented) + 1, bool) touching_border[unedited_segmented[0, :]] = True touching_border[unedited_segmented[-1, :]] = True touching_border[unedited_segmented[:, 0]] = True touching_border[unedited_segmented[:, -1]] = True touching_border[0] = False touching_border_mask = touching_border[unedited_segmented] nobjects = np.max(labels) nneighbors = np.max(neighbor_labels) nkept_objects = objects.count if np.any(touching_border) and \ np.all(~ touching_border_mask[neighbor_labels!=0]): # Add the border labels if any were excluded touching_border_object_number = np.cumsum(touching_border) + \ np.max(neighbor_labels) touching_border_mask = touching_border_mask & neighbor_labels == 0 neighbor_labels = neighbor_labels.copy().astype(np.int32) neighbor_labels[touching_border_mask] = touching_border_object_number[ unedited_segmented[touching_border_mask]] _, object_numbers = objects.relate_labels(labels, kept_labels) if self.neighbors_are_objects: neighbor_numbers = object_numbers else: _, neighbor_numbers = neighbor_objects.relate_labels( neighbor_labels, neighbor_objects.segmented) neighbor_count = np.zeros((nobjects,)) pixel_count = np.zeros((nobjects,)) first_object_number = np.zeros((nobjects,),int) second_object_number = np.zeros((nobjects,),int) first_x_vector = np.zeros((nobjects,)) second_x_vector = np.zeros((nobjects,)) first_y_vector = np.zeros((nobjects,)) second_y_vector = np.zeros((nobjects,)) angle = np.zeros((nobjects,)) percent_touching = np.zeros((nobjects,)) expanded_labels = None if self.distance_method == D_EXPAND: # Find the i,j coordinates of the nearest foreground point # to every background point i,j = scind.distance_transform_edt(labels==0, return_distances=False, return_indices=True) # Assign each background pixel to the label of its nearest # foreground pixel. Assign label to label for foreground. labels = labels[i,j] expanded_labels = labels # for display distance = 1 # dilate once to make touching edges overlap scale = S_EXPANDED if self.neighbors_are_objects: neighbor_labels = labels.copy() elif self.distance_method == D_WITHIN: distance = self.distance.value scale = str(distance) elif self.distance_method == D_ADJACENT: distance = 1 scale = S_ADJACENT else: raise ValueError("Unknown distance method: %s" % self.distance_method.value) if nneighbors > (1 if self.neighbors_are_objects else 0): first_objects = [] second_objects = [] object_indexes = np.arange(nobjects, dtype=np.int32)+1 # # First, compute the first and second nearest neighbors, # and the angles between self and the first and second # nearest neighbors # ocenters = centers_of_labels( objects.small_removed_segmented).transpose() ncenters = centers_of_labels( neighbor_objects.small_removed_segmented).transpose() areas = fix(scind.sum(np.ones(labels.shape),labels, object_indexes)) perimeter_outlines = outline(labels) perimeters = fix(scind.sum( np.ones(labels.shape), perimeter_outlines, object_indexes)) i,j = np.mgrid[0:nobjects,0:nneighbors] distance_matrix = np.sqrt((ocenters[i,0] - ncenters[j,0])**2 + (ocenters[i,1] - ncenters[j,1])**2) # # order[:,0] should be arange(nobjects) # order[:,1] should be the nearest neighbor # order[:,2] should be the next nearest neighbor # if distance_matrix.shape[1] == 1: # a little buggy, lexsort assumes that a 2-d array of # second dimension = 1 is a 1-d array order = np.zeros(distance_matrix.shape, int) else: order = np.lexsort([distance_matrix]) first_neighbor = 1 if self.neighbors_are_objects else 0 first_object_index = order[:, first_neighbor] first_x_vector = ncenters[first_object_index,1] - ocenters[:,1] first_y_vector = ncenters[first_object_index,0] - ocenters[:,0] if nneighbors > first_neighbor+1: second_object_index = order[:, first_neighbor + 1] second_x_vector = ncenters[second_object_index,1] - ocenters[:,1] second_y_vector = ncenters[second_object_index,0] - ocenters[:,0] v1 = np.array((first_x_vector,first_y_vector)) v2 = np.array((second_x_vector,second_y_vector)) # # Project the unit vector v1 against the unit vector v2 # dot = (np.sum(v1*v2,0) / np.sqrt(np.sum(v1**2,0)*np.sum(v2**2,0))) angle = np.arccos(dot) * 180. / np.pi # Make the structuring element for dilation strel = strel_disk(distance) # # A little bigger one to enter into the border with a structure # that mimics the one used to create the outline # strel_touching = strel_disk(distance + .5) # # Get the extents for each object and calculate the patch # that excises the part of the image that is "distance" # away i,j = np.mgrid[0:labels.shape[0],0:labels.shape[1]] min_i, max_i, min_i_pos, max_i_pos =\ scind.extrema(i,labels,object_indexes) min_j, max_j, min_j_pos, max_j_pos =\ scind.extrema(j,labels,object_indexes) min_i = np.maximum(fix(min_i)-distance,0).astype(int) max_i = np.minimum(fix(max_i)+distance+1,labels.shape[0]).astype(int) min_j = np.maximum(fix(min_j)-distance,0).astype(int) max_j = np.minimum(fix(max_j)+distance+1,labels.shape[1]).astype(int) # # Loop over all objects # Calculate which ones overlap "index" # Calculate how much overlap there is of others to "index" # for object_number in object_numbers: if object_number == 0: # # No corresponding object in small-removed. This means # that the object has no pixels, e.g. not renumbered. # continue index = object_number - 1 patch = labels[min_i[index]:max_i[index], min_j[index]:max_j[index]] npatch = neighbor_labels[min_i[index]:max_i[index], min_j[index]:max_j[index]] # # Find the neighbors # patch_mask = patch==(index+1) extended = scind.binary_dilation(patch_mask,strel) neighbors = np.unique(npatch[extended]) neighbors = neighbors[neighbors != 0] if self.neighbors_are_objects: neighbors = neighbors[neighbors != object_number] nc = len(neighbors) neighbor_count[index] = nc if nc > 0: first_objects.append(np.ones(nc,int) * object_number) second_objects.append(neighbors) if self.neighbors_are_objects: # # Find the # of overlapping pixels. Dilate the neighbors # and see how many pixels overlap our image. Use a 3x3 # structuring element to expand the overlapping edge # into the perimeter. # outline_patch = perimeter_outlines[ min_i[index]:max_i[index], min_j[index]:max_j[index]] == object_number extended = scind.binary_dilation( (patch != 0) & (patch != object_number), strel_touching) overlap = np.sum(outline_patch & extended) pixel_count[index] = overlap if sum([len(x) for x in first_objects]) > 0: first_objects = np.hstack(first_objects) reverse_object_numbers = np.zeros( max(np.max(object_numbers), np.max(first_objects)) + 1, int) reverse_object_numbers[object_numbers] = np.arange(len(object_numbers)) + 1 first_objects = reverse_object_numbers[first_objects] second_objects = np.hstack(second_objects) reverse_neighbor_numbers = np.zeros( max(np.max(neighbor_numbers), np.max(second_objects)) + 1, int) reverse_neighbor_numbers[neighbor_numbers] = np.arange(len(neighbor_numbers)) + 1 second_objects= reverse_neighbor_numbers[second_objects] to_keep = (first_objects > 0) & (second_objects > 0) first_objects = first_objects[to_keep] second_objects = second_objects[to_keep] else: first_objects = np.zeros(0, int) second_objects = np.zeros(0, int) if self.neighbors_are_objects: percent_touching = pixel_count * 100 / perimeters else: percent_touching = pixel_count * 100.0 / areas object_indexes = object_numbers - 1 neighbor_indexes = neighbor_numbers - 1 # # Have to recompute nearest # first_object_number = np.zeros(nkept_objects, int) second_object_number = np.zeros(nkept_objects, int) if nkept_objects > (1 if self.neighbors_are_objects else 0): di = (ocenters[object_indexes[:, np.newaxis], 0] - ncenters[neighbor_indexes[np.newaxis, :], 0]) dj = (ocenters[object_indexes[:, np.newaxis], 1] - ncenters[neighbor_indexes[np.newaxis, :], 1]) distance_matrix = np.sqrt(di*di + dj*dj) distance_matrix[~ has_pixels, :] = np.inf distance_matrix[:, ~has_pixels] = np.inf # # order[:,0] should be arange(nobjects) # order[:,1] should be the nearest neighbor # order[:,2] should be the next nearest neighbor # order = np.lexsort([distance_matrix]).astype( first_object_number.dtype) if self.neighbors_are_objects: first_object_number[has_pixels] = order[has_pixels,1] + 1 if nkept_objects > 2: second_object_number[has_pixels] = order[has_pixels,2] + 1 else: first_object_number[has_pixels] = order[has_pixels,0] + 1 if nneighbors > 1: second_object_number[has_pixels] = order[has_pixels,1] + 1 else: object_indexes = object_numbers - 1 neighbor_indexes = neighbor_numbers - 1 first_objects = np.zeros(0, int) second_objects = np.zeros(0, int) # # Now convert all measurements from the small-removed to # the final number set. # neighbor_count = neighbor_count[object_indexes] neighbor_count[~ has_pixels] = 0 percent_touching = percent_touching[object_indexes] percent_touching[~ has_pixels] = 0 first_x_vector = first_x_vector[object_indexes] second_x_vector = second_x_vector[object_indexes] first_y_vector = first_y_vector[object_indexes] second_y_vector = second_y_vector[object_indexes] angle = angle[object_indexes] # # Record the measurements # assert(isinstance(workspace, cpw.Workspace)) m = workspace.measurements assert(isinstance(m, cpmeas.Measurements)) image_set = workspace.image_set features_and_data = [ (M_NUMBER_OF_NEIGHBORS, neighbor_count), (M_FIRST_CLOSEST_OBJECT_NUMBER, first_object_number), (M_FIRST_CLOSEST_DISTANCE, np.sqrt(first_x_vector**2+first_y_vector**2)), (M_SECOND_CLOSEST_OBJECT_NUMBER, second_object_number), (M_SECOND_CLOSEST_DISTANCE, np.sqrt(second_x_vector**2+second_y_vector**2)), (M_ANGLE_BETWEEN_NEIGHBORS, angle)] if self.neighbors_are_objects: features_and_data.append((M_PERCENT_TOUCHING, percent_touching)) for feature_name, data in features_and_data: m.add_measurement(self.object_name.value, self.get_measurement_name(feature_name), data) if len(first_objects) > 0: m.add_relate_measurement( self.module_num, cpmeas.NEIGHBORS, self.object_name.value, self.object_name.value if self.neighbors_are_objects else self.neighbors_name.value, m.image_set_number * np.ones(first_objects.shape, int), first_objects, m.image_set_number * np.ones(second_objects.shape, int), second_objects) labels = kept_labels neighbor_count_image = np.zeros(labels.shape,int) object_mask = objects.segmented != 0 object_indexes = objects.segmented[object_mask]-1 neighbor_count_image[object_mask] = neighbor_count[object_indexes] workspace.display_data.neighbor_count_image = neighbor_count_image if self.neighbors_are_objects: percent_touching_image = np.zeros(labels.shape) percent_touching_image[object_mask] = percent_touching[object_indexes] workspace.display_data.percent_touching_image = percent_touching_image image_set = workspace.image_set if self.wants_count_image.value: neighbor_cm_name = self.count_colormap.value neighbor_cm = get_colormap(neighbor_cm_name) sm = matplotlib.cm.ScalarMappable(cmap = neighbor_cm) img = sm.to_rgba(neighbor_count_image)[:,:,:3] img[:,:,0][~ object_mask] = 0 img[:,:,1][~ object_mask] = 0 img[:,:,2][~ object_mask] = 0 count_image = cpi.Image(img, masking_objects = objects) image_set.add(self.count_image_name.value, count_image) else: neighbor_cm_name = cpprefs.get_default_colormap() neighbor_cm = matplotlib.cm.get_cmap(neighbor_cm_name) if self.neighbors_are_objects and self.wants_percent_touching_image: percent_touching_cm_name = self.touching_colormap.value percent_touching_cm = get_colormap(percent_touching_cm_name) sm = matplotlib.cm.ScalarMappable(cmap = percent_touching_cm) img = sm.to_rgba(percent_touching_image)[:,:,:3] img[:,:,0][~ object_mask] = 0 img[:,:,1][~ object_mask] = 0 img[:,:,2][~ object_mask] = 0 touching_image = cpi.Image(img, masking_objects = objects) image_set.add(self.touching_image_name.value, touching_image) else: percent_touching_cm_name = cpprefs.get_default_colormap() percent_touching_cm = matplotlib.cm.get_cmap(percent_touching_cm_name) if self.show_window: workspace.display_data.neighbor_cm_name = neighbor_cm_name workspace.display_data.percent_touching_cm_name = percent_touching_cm_name workspace.display_data.orig_labels = objects.segmented workspace.display_data.expanded_labels = expanded_labels workspace.display_data.object_mask = object_mask
def display(self, workspace): '''Show an informative display''' import matplotlib import cellprofiler.gui.cpfigure figure = workspace.create_or_find_figure(subplots=(2, 1)) assert isinstance(figure, cellprofiler.gui.cpfigure.CPFigureFrame) i = workspace.display_data.i j = workspace.display_data.j angles = workspace.display_data.angle mask = workspace.display_data.mask labels = workspace.display_data.labels count = workspace.display_data.count color_image = np.zeros((mask.shape[0], mask.shape[1], 4)) # # We do the coloring using alpha values to let the different # things we draw meld together. # # The binary mask is white. # color_image[mask, :] = MASK_ALPHA if count > 0: mappable = matplotlib.cm.ScalarMappable( cmap=matplotlib.cm.get_cmap(cpprefs.get_default_colormap())) np.random.seed(0) colors = mappable.to_rgba(np.random.permutation(np.arange(count))) # # The labels # color_image[labels > 0, :] += colors[labels[labels > 0] - 1, :] * LABEL_ALPHA # # Do each diamond individually (because the angles are almost certainly # different for each # lcolors = colors * .5 + .5 # Wash the colors out a little for ii in range(count): diamond = self.get_diamond(angles[ii]) hshape = ((np.array(diamond.shape) - 1) / 2).astype(int) iii = i[ii] jjj = j[ii] color_image[iii-hshape[0]:iii+hshape[0]+1, jjj-hshape[1]:jjj+hshape[1]+1,:][diamond,:] += \ lcolors[ii,:] * WORM_ALPHA # # Do our own alpha-normalization # color_image[:, :, -1][color_image[:, :, -1] == 0] = 1 color_image[:, :, :-1] = (color_image[:, :, :-1] / color_image[:, :, -1][:, :, np.newaxis]) plot00 = figure.subplot_imshow_bw(0, 0, mask, self.image_name.value) figure.subplot_imshow_color(1, 0, color_image[:, :, :-1], title=self.object_name.value, normalize=False, sharex=plot00, sharey=plot00)
def run(self, workspace): objects = workspace.object_set.get_objects(self.object_name.value) alpha = np.zeros(objects.shape) if self.image_mode == IM_BINARY: pixel_data = np.zeros(objects.shape, bool) elif self.image_mode == IM_GRAYSCALE: pixel_data = np.zeros(objects.shape) elif self.image_mode == IM_UINT16: pixel_data = np.zeros(objects.shape, np.int32) else: pixel_data = np.zeros((objects.shape[0], objects.shape[1], 3)) convert = True for labels, indices in objects.get_labels(): mask = labels != 0 if np.all(~mask): continue if self.image_mode == IM_BINARY: pixel_data[mask] = True alpha[mask] = 1 elif self.image_mode == IM_GRAYSCALE: pixel_data[mask] = labels[mask].astype(float) / np.max(labels) alpha[mask] = 1 elif self.image_mode == IM_COLOR: import matplotlib.cm from cellprofiler.gui.cpfigure_tools import renumber_labels_for_display if self.colormap.value == DEFAULT_COLORMAP: cm_name = cpprefs.get_default_colormap() elif self.colormap.value == COLORCUBE: # Colorcube missing from matplotlib cm_name = "gist_rainbow" elif self.colormap.value == LINES: # Lines missing from matplotlib and not much like it, # Pretty boring palette anyway, hence cm_name = "Pastel1" elif self.colormap.value == WHITE: # White missing from matplotlib, it's just a colormap # of all completely white... not even different kinds of # white. And, isn't white just a uniform sampling of # frequencies from the spectrum? cm_name = "Spectral" else: cm_name = self.colormap.value cm = matplotlib.cm.get_cmap(cm_name) mapper = matplotlib.cm.ScalarMappable(cmap=cm) pixel_data[mask, :] += \ mapper.to_rgba(renumber_labels_for_display(labels))[mask, :3] alpha[mask] += 1 elif self.image_mode == IM_UINT16: pixel_data[mask] = labels[mask] alpha[mask] = 1 convert = False mask = alpha > 0 if self.image_mode == IM_BINARY: pass elif self.image_mode == IM_COLOR: pixel_data[mask, :] = pixel_data[mask, :] / alpha[mask][:, np.newaxis] else: pixel_data[mask] = pixel_data[mask] / alpha[mask] image = cpi.Image(pixel_data, parent_image=objects.parent_image, convert=convert) workspace.image_set.add(self.image_name.value, image) if self.show_window: workspace.display_data.ijv = objects.ijv workspace.display_data.pixel_data = pixel_data
def save_image(self, workspace): if self.show_window: workspace.display_data.wrote_image = False image = workspace.image_set.get_image(self.image_name.value) if self.save_image_or_figure == IF_IMAGE: pixels = image.pixel_data u16hack = (self.get_bit_depth() == BIT_DEPTH_16 and pixels.dtype.kind in ('u', 'i')) if self.file_format != FF_MAT: if self.rescale.value: pixels = pixels.copy() # Normalize intensities for each channel if pixels.ndim == 3: # RGB for i in range(3): img_min = np.min(pixels[:, :, i]) img_max = np.max(pixels[:, :, i]) if img_max > img_min: pixels[:, :, i] = (pixels[:, :, i] - img_min) / (img_max - img_min) else: # Grayscale img_min = np.min(pixels) img_max = np.max(pixels) if img_max > img_min: pixels = (pixels - img_min) / (img_max - img_min) elif not (u16hack or self.get_bit_depth() == BIT_DEPTH_FLOAT): # Clip at 0 and 1 if np.max(pixels) > 1 or np.min(pixels) < 0: sys.stderr.write( "Warning, clipping image %s before output. Some intensities are outside of range 0-1" % self.image_name.value) pixels = pixels.copy() pixels[pixels < 0] = 0 pixels[pixels > 1] = 1 if pixels.ndim == 2 and self.colormap != CM_GRAY and\ self.get_bit_depth() == BIT_DEPTH_8: # Convert grayscale image to rgb for writing if self.colormap == cps.DEFAULT: colormap = cpp.get_default_colormap() else: colormap = self.colormap.value cm = matplotlib.cm.get_cmap(colormap) mapper = matplotlib.cm.ScalarMappable(cmap=cm) pixels = mapper.to_rgba(pixels, bytes=True) pixel_type = ome.PT_UINT8 elif self.get_bit_depth() == BIT_DEPTH_8: pixels = (pixels * 255).astype(np.uint8) pixel_type = ome.PT_UINT8 elif self.get_bit_depth() == BIT_DEPTH_FLOAT: pixel_type = ome.PT_FLOAT else: if not u16hack: pixels = (pixels * 65535) pixel_type = ome.PT_UINT16 elif self.save_image_or_figure == IF_MASK: pixels = image.mask.astype(np.uint8) * 255 pixel_type = ome.PT_UINT8 elif self.save_image_or_figure == IF_CROPPING: pixels = image.crop_mask.astype(np.uint8) * 255 pixel_type = ome.PT_UINT8 filename = self.get_filename(workspace) if filename is None: # failed overwrite check return if self.get_file_format() == FF_MAT: scipy.io.matlab.mio.savemat(filename, {"Image": pixels}, format='5') elif self.get_file_format() == FF_BMP: save_bmp(filename, pixels) else: self.do_save_image(workspace, filename, pixels, pixel_type) if self.show_window: workspace.display_data.wrote_image = True if self.when_to_save != WS_LAST_CYCLE: self.save_filename_measurements(workspace)
def run(self, workspace): objects = workspace.object_set.get_objects(self.object_name.value) labels = objects.segmented convert = True if not workspace.frame is None: figure = workspace.create_or_find_figure( title="ConvertObjectsToImage, image cycle #%d" % (workspace.measurements.image_set_number), subplots=(2, 1)) figure.subplot_imshow_labels( 0, 0, labels, "Original: %s" % self.object_name.value) if self.image_mode == IM_BINARY: pixel_data = labels != 0 if not workspace.frame is None: figure.subplot_imshow_bw(1, 0, pixel_data, self.image_name.value, sharex=figure.subplot(0, 0), sharey=figure.subplot(0, 0)) elif self.image_mode == IM_GRAYSCALE: pixel_data = labels.astype(float) / (1.0 if np.max(labels) == 0 else np.max(labels)) if not workspace.frame is None: figure.subplot_imshow_grayscale(1, 0, pixel_data, self.image_name.value, sharex=figure.subplot(0, 0), sharey=figure.subplot(0, 0)) elif self.image_mode == IM_COLOR: import matplotlib.cm from cellprofiler.gui.cpfigure_tools import renumber_labels_for_display if self.colormap.value == DEFAULT_COLORMAP: cm_name = cpprefs.get_default_colormap() elif self.colormap.value == COLORCUBE: # Colorcube missing from matplotlib cm_name = "gist_rainbow" elif self.colormap.value == LINES: # Lines missing from matplotlib and not much like it, # Pretty boring palette anyway, hence cm_name = "Pastel1" elif self.colormap.value == WHITE: # White missing from matplotlib, it's just a colormap # of all completely white... not even different kinds of # white. And, isn't white just a uniform sampling of # frequencies from the spectrum? cm_name = "Spectral" else: cm_name = self.colormap.value cm = matplotlib.cm.get_cmap(cm_name) mapper = matplotlib.cm.ScalarMappable(cmap=cm) pixel_data = mapper.to_rgba(renumber_labels_for_display(labels)) pixel_data = pixel_data[:, :, :3] pixel_data[labels == 0, :] = 0 if not workspace.frame is None: figure.subplot_imshow(1, 0, pixel_data, self.image_name.value, sharex=figure.subplot(0, 0), sharey=figure.subplot(0, 0)) elif self.image_mode == IM_UINT16: pixel_data = labels.copy() if not workspace.frame is None: figure.subplot_imshow_grayscale(1, 0, pixel_data, self.image_name.value, sharex=figure.subplot(0, 0), sharey=figure.subplot(0, 0)) convert = False image = cpi.Image(pixel_data, parent_image=objects.parent_image, convert=convert) workspace.image_set.add(self.image_name.value, image)
def redraw(self, event=None): if self.ignore_redraw: return images = [] for chooser, color, check, _ in self.image_rows: if not check.IsChecked(): continue assert isinstance(chooser, wx.Choice) selection = chooser.GetCurrentSelection() items = chooser.GetItems() if selection < 0 or selection >= len(items): continue image_name = items[selection] if not image_name in self.workspace.image_set.get_names(): continue image = self.workspace.image_set.get_image(image_name) red, green, blue = color.GetValue() images.append((image, red, green, blue)) if len(images) == 0: self.frame.figure.canvas.Hide() return if not self.frame.figure.canvas.IsShown(): self.frame.figure.canvas.Show() self.layout() width = height = 0 for image, _, _, _ in images: width = max(width, image.pixel_data.shape[1]) height = max(height, image.pixel_data.shape[0]) image = np.zeros((height, width, 3)) for src_image, red, green, blue in images: pixel_data = src_image.pixel_data.astype(np.float32) src_height, src_width = pixel_data.shape[:2] if pixel_data.ndim == 3: src_depth = min(pixel_data.shape[2], 3) image[:src_height, :src_width, :src_depth] += \ pixel_data[:, :, :src_depth] else: image[:src_height, :src_width, 0] += pixel_data * red / 255 image[:src_height, :src_width, 1] += pixel_data * green / 255 image[:src_height, :src_width, 2] += pixel_data * blue / 255 cplabels = [] for chooser, color, check, _ in self.object_rows: if not check.IsChecked(): continue idx = chooser.GetCurrentSelection() names = chooser.GetItems() if idx < 0 or idx >= len(names): continue objects_name = names[idx] if objects_name not in self.workspace.object_set.get_object_names(): continue objects = self.workspace.object_set.get_objects(objects_name) red, green, blue = color.GetValue() color = (red, green, blue) alpha_colormap = cpprefs.get_default_colormap() cplabels.append( { CPLD_NAME: objects_name, CPLD_LABELS: [x[0] for x in objects.get_labels()], CPLD_OUTLINE_COLOR: color, CPLD_MODE: CPLDM_OUTLINES, CPLD_ALPHA_VALUE: .25, CPLD_ALPHA_COLORMAP: alpha_colormap, CPLD_LINE_WIDTH: 1}) if self.image is not None and \ tuple(self.image.image.shape) != tuple(image.shape): self.image = None self.axes.cla() if self.image == None: self.frame.subplot_imshow_color( 0, 0, image, clear = False, cplabels = cplabels) self.axes.set_xbound(-.5, width -.5) self.axes.set_ybound(-.5, height -.5) for artist in self.axes.artists: if isinstance(artist, CPImageArtist): self.image = artist else: self.image.image = image self.image.kwargs["cplabels"] = cplabels # # Remove all the old text labels # to_remove = [] for artist in list(self.axes.texts): artist.remove() m = self.workspace.measurements assert isinstance(m, cpmeas.Measurements) title_lines = [] object_values = {} for measurement_row in self.measurement_rows: assert isinstance(measurement_row, MeasurementRow) if not measurement_row.should_show(): continue object_name = measurement_row.get_object_name() if object_name is None or object_name not in m.get_object_names(): continue feature = measurement_row.get_measurement_name() if feature is None or not m.has_feature(object_name, feature): continue value = m[object_name, feature] if object_name in (cpmeas.IMAGE, cpmeas.EXPERIMENT): if isinstance(value, int): fmt = "%s: %d" elif isinstance(value, float): fmt = "%s: %.4f" else: fmt = "%s: %s" title_lines.append(fmt % (feature, value)) else: if object_name not in object_values: if any([not m.has_feature(object_name, lf) for lf in M_LOCATION_CENTER_X, M_LOCATION_CENTER_Y]): continue object_values[object_name] = [] object_values[object_name].append( (value, measurement_row))
def run(self, workspace): objects = workspace.object_set.get_objects(self.object_name.value) alpha = np.zeros(objects.shape) if self.image_mode == IM_BINARY: pixel_data = np.zeros(objects.shape, bool) elif self.image_mode == IM_GRAYSCALE: pixel_data = np.zeros(objects.shape) elif self.image_mode == IM_UINT16: pixel_data = np.zeros(objects.shape, np.int32) else: pixel_data = np.zeros((objects.shape[0], objects.shape[1], 3)) convert = True for labels, indices in objects.get_labels(): mask = labels != 0 if np.all(~ mask): continue if self.image_mode == IM_BINARY: pixel_data[mask] = True alpha[mask] = 1 elif self.image_mode == IM_GRAYSCALE: pixel_data[mask] = labels[mask].astype(float) / np.max(labels) alpha[mask] = 1 elif self.image_mode == IM_COLOR: import matplotlib.cm from cellprofiler.gui.cpfigure_tools import renumber_labels_for_display if self.colormap.value == DEFAULT_COLORMAP: cm_name = cpprefs.get_default_colormap() elif self.colormap.value == COLORCUBE: # Colorcube missing from matplotlib cm_name = "gist_rainbow" elif self.colormap.value == LINES: # Lines missing from matplotlib and not much like it, # Pretty boring palette anyway, hence cm_name = "Pastel1" elif self.colormap.value == WHITE: # White missing from matplotlib, it's just a colormap # of all completely white... not even different kinds of # white. And, isn't white just a uniform sampling of # frequencies from the spectrum? cm_name = "Spectral" else: cm_name = self.colormap.value cm = matplotlib.cm.get_cmap(cm_name) mapper = matplotlib.cm.ScalarMappable(cmap=cm) pixel_data[mask, :] += \ mapper.to_rgba(renumber_labels_for_display(labels))[mask, :3] alpha[mask] += 1 elif self.image_mode == IM_UINT16: pixel_data[mask] = labels[mask] alpha[mask] = 1 convert = False mask = alpha > 0 if self.image_mode == IM_BINARY: pass elif self.image_mode == IM_COLOR: pixel_data[mask, :] = pixel_data[mask, :] / alpha[mask][:, np.newaxis] else: pixel_data[mask] = pixel_data[mask] / alpha[mask] image = cpi.Image(pixel_data, parent_image = objects.parent_image, convert = convert) workspace.image_set.add(self.image_name.value, image) if self.show_window: workspace.display_data.ijv = objects.ijv workspace.display_data.pixel_data = pixel_data
def filter_objects(self, workspace, orig_labels): import wx import matplotlib from matplotlib.backends.backend_wxagg import FigureCanvasWxAgg from matplotlib.backends.backend_wxagg import NavigationToolbar2WxAgg from cellprofiler.gui.cpfigure import renumber_labels_for_display assert isinstance(workspace, cpw.Workspace) orig_objects_name = self.object_name.value # # Get the labels matrix and make a mask of objects to keep from it # # # Display a UI for choosing objects # style = wx.DEFAULT_DIALOG_STYLE | wx.RESIZE_BORDER dialog_box = wx.Dialog(workspace.frame, -1, "Choose objects to keep", style=style) sizer = wx.BoxSizer(wx.VERTICAL) dialog_box.SetSizer(sizer) figure = matplotlib.figure.Figure() panel = FigureCanvasWxAgg(dialog_box, -1, figure) sizer.Add(panel, 1, wx.EXPAND) toolbar = NavigationToolbar2WxAgg(panel) sizer.Add(toolbar, 0, wx.EXPAND) mask = orig_labels != 0 # # Make 3 axes # orig_axes = figure.add_subplot(2, 2, 1) orig_axes._adjustable = 'box-forced' keep_axes = figure.add_subplot(2, 2, 2, sharex=orig_axes, sharey=orig_axes) remove_axes = figure.add_subplot(2, 2, 4, sharex=orig_axes, sharey=orig_axes) for axes in (orig_axes, keep_axes, remove_axes): axes._adjustable = 'box-forced' info_axes = figure.add_subplot(2, 2, 3) assert isinstance(info_axes, matplotlib.axes.Axes) info_axes.set_axis_off() # # Add an explanation and possibly a checkbox to the info axis # ui_text = ("Keep or remove objects by clicking\n" "on them with the mouse.\n" 'Press the "Done" button when\nediting is complete.') info_axes.text(0, 0, ui_text, size="small") wants_image_display = [self.wants_image_display.value] sub_sizer = wx.BoxSizer(wx.HORIZONTAL) # # Need padding on top because tool bar is wonky about its height # sizer.Add(sub_sizer, 0, wx.EXPAND | wx.TOP, 10) resume_id = 100 cancel_id = 101 keep_all_id = 102 remove_all_id = 103 reverse_select = 104 ######################################### # # Buttons for keep / remove / toggle # ######################################### keep_button = wx.Button(dialog_box, keep_all_id, "Keep all") sub_sizer.Add(keep_button, 0, wx.ALIGN_CENTER) remove_button = wx.Button(dialog_box, remove_all_id, "Remove all") sub_sizer.Add(remove_button, 0, wx.ALIGN_CENTER) toggle_button = wx.Button(dialog_box, reverse_select, "Reverse selection") sub_sizer.Add(toggle_button, 0, wx.ALIGN_CENTER) ###################################### # # Buttons for resume and cancel # ###################################### button_sizer = wx.StdDialogButtonSizer() resume_button = wx.Button(dialog_box, resume_id, "Done") button_sizer.AddButton(resume_button) sub_sizer.Add(button_sizer, 0, wx.ALIGN_CENTER) def on_resume(event): dialog_box.EndModal(wx.OK) dialog_box.Bind(wx.EVT_BUTTON, on_resume, resume_button) button_sizer.SetAffirmativeButton(resume_button) cancel_button = wx.Button(dialog_box, cancel_id, "Cancel") button_sizer.AddButton(cancel_button) def on_cancel(event): dialog_box.EndModal(wx.CANCEL) dialog_box.Bind(wx.EVT_BUTTON, on_cancel, cancel_button) button_sizer.SetNegativeButton(cancel_button) button_sizer.Realize() ################### d i s p l a y ####### # # The following is a function that we can call to refresh # the figure's appearance based on the mask and the original labels # ########################################## cm = matplotlib.cm.get_cmap(cpprefs.get_default_colormap()) cm.set_bad((0, 0, 0)) def display(): if len(orig_axes.images) > 0: # Save zoom and scale if coming through here a second time x0, x1 = orig_axes.get_xlim() y0, y1 = orig_axes.get_ylim() set_lim = True else: set_lim = False for axes, labels, title in ((orig_axes, orig_labels, "Original: %s" % orig_objects_name), (keep_axes, orig_labels * mask, "Objects to keep"), (remove_axes, orig_labels * (~mask), "Objects to remove")): assert isinstance(axes, matplotlib.axes.Axes) labels = renumber_labels_for_display(labels) axes.clear() if np.all(labels == 0): use_cm = matplotlib.cm.gray is_blank = True else: use_cm = cm is_blank = False if wants_image_display[0]: outlines = outline(labels) image = workspace.image_set.get_image( self.image_name.value) image = image.pixel_data.astype(np.float) image, _ = cpo.size_similarly(labels, image) if image.ndim == 2: image = np.dstack((image, image, image)) if not is_blank: mappable = matplotlib.cm.ScalarMappable(cmap=use_cm) mappable.set_clim(1, labels.max()) limage = mappable.to_rgba(labels)[:, :, :3] image[outlines != 0, :] = limage[outlines != 0, :] axes.imshow(image) else: axes.imshow(labels, cmap=use_cm) axes.set_title(title, fontname=cpprefs.get_title_font_name(), fontsize=cpprefs.get_title_font_size()) if set_lim: orig_axes.set_xlim((x0, x1)) orig_axes.set_ylim((y0, y1)) figure.canvas.draw() panel.Refresh() if self.wants_image_display: display_image_checkbox = matplotlib.widgets.CheckButtons( info_axes, ["Display image"], [True]) display_image_checkbox.labels[0].set_size("small") r = display_image_checkbox.rectangles[0] rwidth = r.get_width() rheight = r.get_height() rx, ry = r.get_xy() new_rwidth = rwidth / 2 new_rheight = rheight / 2 new_rx = rx + rwidth / 2 new_ry = ry + rheight / 4 r.set_width(new_rwidth) r.set_height(new_rheight) r.set_xy((new_rx, new_ry)) l1, l2 = display_image_checkbox.lines[0] l1.set_data((np.array((new_rx, new_rx + new_rwidth)), np.array((new_ry, new_ry + new_rheight)))) l2.set_data((np.array((new_rx, new_rx + new_rwidth)), np.array((new_ry + new_rheight, new_ry)))) def on_display_image_clicked(_): wants_image_display[0] = not wants_image_display[0] display() display_image_checkbox.on_clicked(on_display_image_clicked) def on_click(event): if event.inaxes not in (orig_axes, keep_axes, remove_axes): return x = int(event.xdata) y = int(event.ydata) if (x < 0 or x >= orig_labels.shape[1] or y < 0 or y >= orig_labels.shape[0]): return lnum = orig_labels[y, x] if lnum == 0: return if event.inaxes == orig_axes: mask[orig_labels == lnum] = ~mask[orig_labels == lnum] elif event.inaxes == keep_axes: mask[orig_labels == lnum] = False else: mask[orig_labels == lnum] = True display() figure.canvas.mpl_connect('button_press_event', on_click) ################################ # # Functions for keep / remove/ toggle # ################################ def on_keep(event): mask[:, :] = (orig_labels != 0) display() dialog_box.Bind(wx.EVT_BUTTON, on_keep, keep_button) def on_remove(event): mask[:, :] = 0 display() dialog_box.Bind(wx.EVT_BUTTON, on_remove, remove_button) def on_toggle(event): mask[orig_labels != 0] = ~mask[orig_labels != 0] display() dialog_box.Bind(wx.EVT_BUTTON, on_toggle, toggle_button) display() dialog_box.Fit() result = dialog_box.ShowModal() dialog_box.Destroy() if result != wx.OK: raise RuntimeError("User cancelled EditObjectsManually") filtered_labels = orig_labels.copy() filtered_labels[~mask] = 0 return filtered_labels
def filter_objects(self, workspace, orig_labels): import wx import matplotlib from matplotlib.backends.backend_wxagg import FigureCanvasWxAgg from matplotlib.backends.backend_wxagg import NavigationToolbar2WxAgg from cellprofiler.gui.cpfigure import renumber_labels_for_display assert isinstance(workspace,cpw.Workspace) orig_objects_name = self.object_name.value # # Get the labels matrix and make a mask of objects to keep from it # # # Display a UI for choosing objects # style = wx.DEFAULT_DIALOG_STYLE | wx.RESIZE_BORDER dialog_box = wx.Dialog(workspace.frame, -1, "Choose objects to keep", style = style) sizer = wx.BoxSizer(wx.VERTICAL) dialog_box.SetSizer(sizer) figure = matplotlib.figure.Figure() panel = FigureCanvasWxAgg(dialog_box, -1, figure) sizer.Add(panel, 1, wx.EXPAND) toolbar = NavigationToolbar2WxAgg(panel) sizer.Add(toolbar, 0, wx.EXPAND) mask = orig_labels != 0 # # Make 3 axes # orig_axes = figure.add_subplot(2, 2, 1) orig_axes._adjustable = 'box-forced' keep_axes = figure.add_subplot(2, 2, 2, sharex = orig_axes, sharey = orig_axes) remove_axes = figure.add_subplot(2, 2, 4, sharex = orig_axes, sharey = orig_axes) for axes in (orig_axes, keep_axes, remove_axes): axes._adjustable = 'box-forced' info_axes = figure.add_subplot(2, 2, 3) assert isinstance(info_axes, matplotlib.axes.Axes) info_axes.set_axis_off() # # Add an explanation and possibly a checkbox to the info axis # ui_text = ("Keep or remove objects by clicking\n" "on them with the mouse.\n" 'Press the "Done" button when\nediting is complete.') info_axes.text(0,0, ui_text, size="small") wants_image_display = [self.wants_image_display.value] sub_sizer = wx.BoxSizer(wx.HORIZONTAL) # # Need padding on top because tool bar is wonky about its height # sizer.Add(sub_sizer, 0, wx.EXPAND | wx.TOP, 10) resume_id = 100 cancel_id = 101 keep_all_id = 102 remove_all_id = 103 reverse_select = 104 ######################################### # # Buttons for keep / remove / toggle # ######################################### keep_button = wx.Button(dialog_box, keep_all_id, "Keep all") sub_sizer.Add(keep_button, 0, wx.ALIGN_CENTER) remove_button = wx.Button(dialog_box, remove_all_id, "Remove all") sub_sizer.Add(remove_button,0, wx.ALIGN_CENTER) toggle_button = wx.Button(dialog_box, reverse_select, "Reverse selection") sub_sizer.Add(toggle_button,0, wx.ALIGN_CENTER) ###################################### # # Buttons for resume and cancel # ###################################### button_sizer = wx.StdDialogButtonSizer() resume_button = wx.Button(dialog_box, resume_id, "Done") button_sizer.AddButton(resume_button) sub_sizer.Add(button_sizer, 0, wx.ALIGN_CENTER) def on_resume(event): dialog_box.EndModal(wx.OK) dialog_box.Bind(wx.EVT_BUTTON, on_resume, resume_button) button_sizer.SetAffirmativeButton(resume_button) cancel_button = wx.Button(dialog_box, cancel_id, "Cancel") button_sizer.AddButton(cancel_button) def on_cancel(event): dialog_box.EndModal(wx.CANCEL) dialog_box.Bind(wx.EVT_BUTTON, on_cancel, cancel_button) button_sizer.SetNegativeButton(cancel_button) button_sizer.Realize() ################### d i s p l a y ####### # # The following is a function that we can call to refresh # the figure's appearance based on the mask and the original labels # ########################################## cm = matplotlib.cm.get_cmap(cpprefs.get_default_colormap()) cm.set_bad((0,0,0)) def display(): if len(orig_axes.images) > 0: # Save zoom and scale if coming through here a second time x0, x1 = orig_axes.get_xlim() y0, y1 = orig_axes.get_ylim() set_lim = True else: set_lim = False for axes, labels, title in ( (orig_axes, orig_labels, "Original: %s"%orig_objects_name), (keep_axes, orig_labels * mask,"Objects to keep"), (remove_axes, orig_labels * (~ mask), "Objects to remove")): assert isinstance(axes, matplotlib.axes.Axes) labels = renumber_labels_for_display(labels) axes.clear() if np.all(labels == 0): use_cm = matplotlib.cm.gray is_blank = True else: use_cm = cm is_blank = False if wants_image_display[0]: outlines = outline(labels) image = workspace.image_set.get_image(self.image_name.value) image = image.pixel_data.astype(np.float) image, _ = cpo.size_similarly(labels, image) if image.ndim == 2: image = np.dstack((image, image, image)) if not is_blank: mappable = matplotlib.cm.ScalarMappable(cmap=use_cm) mappable.set_clim(1,labels.max()) limage = mappable.to_rgba(labels)[:,:,:3] image[outlines != 0,:] = limage[outlines != 0, :] axes.imshow(image) else: axes.imshow(labels, cmap = use_cm) axes.set_title(title, fontname=cpprefs.get_title_font_name(), fontsize=cpprefs.get_title_font_size()) if set_lim: orig_axes.set_xlim((x0, x1)) orig_axes.set_ylim((y0, y1)) figure.canvas.draw() panel.Refresh() if self.wants_image_display: display_image_checkbox = matplotlib.widgets.CheckButtons( info_axes, ["Display image"], [True]) display_image_checkbox.labels[0].set_size("small") r = display_image_checkbox.rectangles[0] rwidth = r.get_width() rheight = r.get_height() rx, ry = r.get_xy() new_rwidth = rwidth / 2 new_rheight = rheight / 2 new_rx = rx + rwidth/2 new_ry = ry + rheight/4 r.set_width(new_rwidth) r.set_height(new_rheight) r.set_xy((new_rx, new_ry)) l1, l2 = display_image_checkbox.lines[0] l1.set_data((np.array((new_rx, new_rx+new_rwidth)), np.array((new_ry, new_ry+new_rheight)))) l2.set_data((np.array((new_rx, new_rx+new_rwidth)), np.array((new_ry + new_rheight, new_ry)))) def on_display_image_clicked(_): wants_image_display[0] = not wants_image_display[0] display() display_image_checkbox.on_clicked(on_display_image_clicked) def on_click(event): if event.inaxes not in (orig_axes, keep_axes, remove_axes): return x = int(event.xdata) y = int(event.ydata) if (x < 0 or x >= orig_labels.shape[1] or y < 0 or y >= orig_labels.shape[0]): return lnum = orig_labels[y,x] if lnum == 0: return if event.inaxes == orig_axes: mask[orig_labels == lnum] = ~mask[orig_labels == lnum] elif event.inaxes == keep_axes: mask[orig_labels == lnum] = False else: mask[orig_labels == lnum] = True display() figure.canvas.mpl_connect('button_press_event', on_click) ################################ # # Functions for keep / remove/ toggle # ################################ def on_keep(event): mask[:,:] = (orig_labels != 0) display() dialog_box.Bind(wx.EVT_BUTTON, on_keep, keep_button) def on_remove(event): mask[:,:] = 0 display() dialog_box.Bind(wx.EVT_BUTTON, on_remove, remove_button) def on_toggle(event): mask[orig_labels != 0] = ~mask[orig_labels != 0] display() dialog_box.Bind(wx.EVT_BUTTON, on_toggle, toggle_button) display() dialog_box.Fit() result = dialog_box.ShowModal() dialog_box.Destroy() if result != wx.OK: raise RuntimeError("User cancelled EditObjectsManually") filtered_labels = orig_labels.copy() filtered_labels[~mask] = 0 return filtered_labels