def measure_objects(self, operand, workspace):
     '''Performs the measurements on the requested objects'''
     objects = workspace.get_objects(operand.operand_objects.value)
     if objects.has_parent_image:
         area_occupied = np.sum(objects.segmented[objects.parent_image.mask]>0)
         perimeter = np.sum(outline(np.logical_and(objects.segmented != 0,objects.parent_image.mask)))
         total_area = np.sum(objects.parent_image.mask)
     else:
         area_occupied = np.sum(objects.segmented > 0)
         perimeter = np.sum(outline(objects.segmented) > 0)
         total_area = np.product(objects.segmented.shape)
     m = workspace.measurements
     m.add_image_measurement(F_AREA_OCCUPIED%(operand.operand_objects.value),
                             np.array([area_occupied], dtype=float ))
     m.add_image_measurement(F_PERIMETER%(operand.operand_objects.value),
                             np.array([perimeter], dtype=float ))
     m.add_image_measurement(F_TOTAL_AREA%(operand.operand_objects.value),
                             np.array([total_area], dtype=float))
     if operand.should_save_image.value:
         binary_pixels = objects.segmented > 0
         output_image = cpi.Image(binary_pixels,
                                  parent_image = objects.parent_image)
         workspace.image_set.add(operand.image_name.value,
                                 output_image)
     return[[operand.operand_objects.value,
             str(area_occupied),str(perimeter),str(total_area)]]
Esempio n. 2
0
 def measure_objects(self, operand, workspace):
     '''Performs the measurements on the requested objects'''
     objects = workspace.get_objects(operand.operand_objects.value)
     if objects.has_parent_image:
         area_occupied = np.sum(
             objects.segmented[objects.parent_image.mask] > 0)
         perimeter = np.sum(
             outline(
                 np.logical_and(objects.segmented != 0,
                                objects.parent_image.mask)))
         total_area = np.sum(objects.parent_image.mask)
     else:
         area_occupied = np.sum(objects.segmented > 0)
         perimeter = np.sum(outline(objects.segmented) > 0)
         total_area = np.product(objects.segmented.shape)
     m = workspace.measurements
     m.add_image_measurement(
         F_AREA_OCCUPIED % (operand.operand_objects.value),
         np.array([area_occupied], dtype=float))
     m.add_image_measurement(F_PERIMETER % (operand.operand_objects.value),
                             np.array([perimeter], dtype=float))
     m.add_image_measurement(F_TOTAL_AREA % (operand.operand_objects.value),
                             np.array([total_area], dtype=float))
     if operand.should_save_image.value:
         binary_pixels = objects.segmented > 0
         output_image = cpi.Image(binary_pixels,
                                  parent_image=objects.parent_image)
         workspace.image_set.add(operand.image_name.value, output_image)
     return [[
         operand.operand_objects.value,
         str(area_occupied),
         str(perimeter),
         str(total_area)
     ]]
Esempio n. 3
0
 def test_02_04_edge(self):
     x = numpy.array([[0, 0, 1, 1, 1, 0, 0], [0, 0, 1, 1, 1, 0, 0],
                      [0, 0, 1, 1, 1, 0, 0], [0, 0, 0, 0, 0, 0, 0]])
     e = numpy.array([[0, 0, 1, 1, 1, 0, 0], [0, 0, 1, 0, 1, 0, 0],
                      [0, 0, 1, 1, 1, 0, 0], [0, 0, 0, 0, 0, 0, 0]])
     result = OL.outline(x)
     self.assertTrue(numpy.all(result == e))
 def test_04_02_masked_edge(self):
     # Regression test of issue #1115
     labels = np.zeros((20,50), int)
     labels[15:25, 15:25] = 1
     image = np.random.uniform(size=labels.shape).astype(np.float32)
     #
     # Mask the edge of the object
     #
     mask = ~ cpmo.outline(labels).astype(bool)
     m = cpmeas.Measurements()
     m.add(IMAGE_NAME, cpi.Image(image, mask=mask))
     object_set = cpo.ObjectSet()
     o = cpo.Objects()
     o.segmented = labels
     object_set.add_objects(o, OBJECT_NAME)
     pipeline = P.Pipeline()
     def callback(caller, event):
         self.assertFalse(isinstance(event, P.RunExceptionEvent))
     pipeline.add_listener(callback)
     module = MOI.MeasureObjectIntensity()
     module.module_num = 1
     module.images[0].name.value = IMAGE_NAME
     module.objects[0].name.value = OBJECT_NAME
     pipeline.add_module(module)
     workspace = cpw.Workspace(pipeline, module, m, object_set,
                               m, None)
     module.run(workspace)
Esempio n. 5
0
    def test_04_02_masked_edge(self):
        # Regression test of issue #1115
        labels = np.zeros((20, 50), int)
        labels[15:25, 15:25] = 1
        image = np.random.uniform(size=labels.shape).astype(np.float32)
        #
        # Mask the edge of the object
        #
        mask = ~cpmo.outline(labels).astype(bool)
        m = cpmeas.Measurements()
        m.add(IMAGE_NAME, cpi.Image(image, mask=mask))
        object_set = cpo.ObjectSet()
        o = cpo.Objects()
        o.segmented = labels
        object_set.add_objects(o, OBJECT_NAME)
        pipeline = P.Pipeline()

        def callback(caller, event):
            self.assertFalse(isinstance(event, P.RunExceptionEvent))

        pipeline.add_listener(callback)
        module = MOI.MeasureObjectIntensity()
        module.module_num = 1
        module.images[0].name.value = IMAGE_NAME
        module.objects[0].name.value = OBJECT_NAME
        pipeline.add_module(module)
        workspace = cpw.Workspace(pipeline, module, m, object_set, m, None)
        module.run(workspace)
Esempio n. 6
0
 def run(self, workspace):
     '''Find the outlines on the current image set
     
     workspace    - The workspace contains
         pipeline     - instance of cpp for this run
         image_set    - the images in the image set being processed
         object_set   - the objects (labeled masks) in this image set
         measurements - the measurements for this run
         frame        - the parent frame to whatever frame is created. None means don't draw.
     '''
     gridding = workspace.get_grid(self.grid_name.value)
     if self.shape_choice == SHAPE_RECTANGLE:
         labels = self.run_rectangle(workspace, gridding)
     elif self.shape_choice == SHAPE_CIRCLE_FORCED:
         labels = self.run_forced_circle(workspace, gridding)
     elif self.shape_choice == SHAPE_CIRCLE_NATURAL:
         labels = self.run_natural_circle(workspace, gridding)
     elif self.shape_choice == SHAPE_NATURAL:
         labels = self.run_natural(workspace, gridding)
     objects = cpo.Objects()
     objects.segmented = labels
     object_count = gridding.rows * gridding.columns
     workspace.object_set.add_objects(objects, 
                                      self.output_objects_name.value)
     add_object_location_measurements(workspace.measurements,
                                      self.output_objects_name.value,
                                      labels, object_count)
     add_object_count_measurements(workspace.measurements,
                                   self.output_objects_name.value,
                                   object_count)
     if self.wants_outlines:
         outlines = outline(labels!=0)
         outline_image = cpi.Image(outlines)
         workspace.image_set.add(self.outlines_name.value, outline_image)
Esempio n. 7
0
 def outlines(self):
     '''Get a mask of all the points on the border of objects'''
     if self._outlines is None:
         for i, labels in enumerate(self.labels):
             if i == 0:
                 self._outlines = outline(labels) != 0
             else:
                 self._outlines = self._outlines | (outline(labels) != 0)
         if self.line_width > 1:
             hw = float(self.line_width) / 2
             d = distance_transform_edt(~ self._outlines)
             dti, dtj = np.where((d < hw+.5) & ~self._outlines)
             self._outlines = self._outlines.astype(np.float32)
             self._outlines[dti, dtj] = np.minimum(1, hw + .5 - d[dti, dtj])
   
     return self._outlines.astype(np.float32)
 def run(self, workspace):
     input_objects = workspace.object_set.get_objects(self.object_name.value)
     output_objects = cpo.Objects()
     output_objects.segmented = self.do_labels(input_objects.segmented)
     if (input_objects.has_small_removed_segmented and 
         self.operation not in (O_EXPAND, O_EXPAND_INF, O_DIVIDE)):
         output_objects.small_removed_segmented = \
             self.do_labels(input_objects.small_removed_segmented)
     if (input_objects.has_unedited_segmented and
         self.operation not in (O_EXPAND, O_EXPAND_INF, O_DIVIDE)):
         output_objects.unedited_segmented = \
             self.do_labels(input_objects.unedited_segmented)
     workspace.object_set.add_objects(output_objects,
                                      self.output_object_name.value)
     add_object_count_measurements(workspace.measurements, 
                                   self.output_object_name.value,
                                   np.max(output_objects.segmented))
     add_object_location_measurements(workspace.measurements,
                                      self.output_object_name.value,
                                      output_objects.segmented)
     if self.wants_outlines.value:
         outline_image = cpi.Image(outline(output_objects.segmented) > 0,
                                   parent_image = input_objects.parent_image)
         workspace.image_set.add(self.outlines_name.value, outline_image)
     
     if workspace.frame is not None:
         figure = workspace.create_or_find_figure(title="ExpandOrShrinkObjects, image cycle #%d"%(
             workspace.measurements.image_set_number),subplots=(2,1))
         figure.subplot_imshow_labels(0,0,input_objects.segmented,
                                      self.object_name.value)
         figure.subplot_imshow_labels(1,0,output_objects.segmented,
                                      self.output_object_name.value,
                                      sharex = figure.subplot(0,0),
                                      sharey = figure.subplot(0,0))
Esempio n. 9
0
 def test_07_01_make_ijv_outlines(self):
     np.random.seed(70)
     x = cpo.Objects()
     ii,jj = np.mgrid[0:10,0:20]
     masks = [(ii-ic)**2 + (jj - jc) **2 < r **2 
              for ic, jc, r in ((4,5,5), (4,12,5), (6, 8, 5))]
     i = np.hstack([ii[mask] for mask in masks])
     j = np.hstack([jj[mask] for mask in masks])
     v = np.hstack([[k+1] * np.sum(mask) for k, mask in enumerate(masks)])
     
     x.ijv = np.column_stack((i,j,v))
     x.parent_image = cpi.Image(np.zeros((10,20)))
     colors = np.random.uniform(size=(3, 3)).astype(np.float32)
     image = x.make_ijv_outlines(colors)
     i1 = [i for i, color in enumerate(colors) if np.all(color == image[0,5,:])]
     self.assertEqual(len(i1), 1)
     i2 = [i for i, color in enumerate(colors) if np.all(color == image[0,12,:])]
     self.assertEqual(len(i2), 1)
     i3 = [i for i, color in enumerate(colors) if np.all(color == image[-1,8,:])]
     self.assertEqual(len(i3), 1)
     self.assertNotEqual(i1[0], i2[0])
     self.assertNotEqual(i2[0], i3[0])
     colors = colors[np.array([i1[0], i2[0], i3[0]])]
     outlines = np.zeros((10,20,3), np.float32)
     alpha = np.zeros((10,20))
     for i, (color, mask) in enumerate(zip(colors, masks)):
         my_outline = outline(mask)
         outlines[my_outline] += color
         alpha[my_outline] += 1
     alpha[alpha == 0] = 1
     outlines /= alpha[:,:,np.newaxis]
     np.testing.assert_almost_equal(outlines, image)
Esempio n. 10
0
 def test_07_01_make_ijv_outlines(self):
     np.random.seed(70)
     x = cpo.Objects()
     ii,jj = np.mgrid[0:10,0:20]
     masks = [(ii-ic)**2 + (jj - jc) **2 < r **2 
              for ic, jc, r in ((4,5,5), (4,12,5), (6, 8, 5))]
     i = np.hstack([ii[mask] for mask in masks])
     j = np.hstack([jj[mask] for mask in masks])
     v = np.hstack([[k+1] * np.sum(mask) for k, mask in enumerate(masks)])
     
     x.ijv = np.column_stack((i,j,v))
     x.parent_image = cpi.Image(np.zeros((10,20)))
     colors = np.random.uniform(size=(3, 3)).astype(np.float32)
     image = x.make_ijv_outlines(colors)
     i1 = [i for i, color in enumerate(colors) if np.all(color == image[0,5,:])]
     self.assertEqual(len(i1), 1)
     i2 = [i for i, color in enumerate(colors) if np.all(color == image[0,12,:])]
     self.assertEqual(len(i2), 1)
     i3 = [i for i, color in enumerate(colors) if np.all(color == image[-1,8,:])]
     self.assertEqual(len(i3), 1)
     self.assertNotEqual(i1[0], i2[0])
     self.assertNotEqual(i2[0], i3[0])
     colors = colors[np.array([i1[0], i2[0], i3[0]])]
     outlines = np.zeros((10,20,3), np.float32)
     alpha = np.zeros((10,20))
     for i, (color, mask) in enumerate(zip(colors, masks)):
         my_outline = outline(mask)
         outlines[my_outline] += color
         alpha[my_outline] += 1
     alpha[alpha == 0] = 1
     outlines /= alpha[:,:,np.newaxis]
     np.testing.assert_almost_equal(outlines, image)
    def run(self, workspace):
        input_objects = workspace.object_set.get_objects(self.object_name.value)
        output_objects = cpo.Objects()
        output_objects.segmented = self.do_labels(input_objects.segmented)
        if (input_objects.has_small_removed_segmented and 
            self.operation not in (O_EXPAND, O_EXPAND_INF, O_DIVIDE)):
            output_objects.small_removed_segmented = \
                self.do_labels(input_objects.small_removed_segmented)
        if (input_objects.has_unedited_segmented and
            self.operation not in (O_EXPAND, O_EXPAND_INF, O_DIVIDE)):
            output_objects.unedited_segmented = \
                self.do_labels(input_objects.unedited_segmented)
        workspace.object_set.add_objects(output_objects,
                                         self.output_object_name.value)
        add_object_count_measurements(workspace.measurements, 
                                      self.output_object_name.value,
                                      np.max(output_objects.segmented))
        add_object_location_measurements(workspace.measurements,
                                         self.output_object_name.value,
                                         output_objects.segmented)
        if self.wants_outlines.value:
            outline_image = cpi.Image(outline(output_objects.segmented) > 0,
                                      parent_image = input_objects.parent_image)
            workspace.image_set.add(self.outlines_name.value, outline_image)

        if self.show_window:
            workspace.display_data.input_objects_segmented = input_objects.segmented
            workspace.display_data.output_objects_segmented = output_objects.segmented
Esempio n. 12
0
 def run(self, workspace):
     '''Find the outlines on the current image set
     
     workspace    - The workspace contains
         pipeline     - instance of cpp for this run
         image_set    - the images in the image set being processed
         object_set   - the objects (labeled masks) in this image set
         measurements - the measurements for this run
         frame        - the parent frame to whatever frame is created. None means don't draw.
     '''
     gridding = workspace.get_grid(self.grid_name.value)
     if self.shape_choice == SHAPE_RECTANGLE:
         labels = self.run_rectangle(workspace, gridding)
     elif self.shape_choice == SHAPE_CIRCLE_FORCED:
         labels = self.run_forced_circle(workspace, gridding)
     elif self.shape_choice == SHAPE_CIRCLE_NATURAL:
         labels = self.run_natural_circle(workspace, gridding)
     elif self.shape_choice == SHAPE_NATURAL:
         labels = self.run_natural(workspace, gridding)
     objects = cpo.Objects()
     objects.segmented = labels
     object_count = gridding.rows * gridding.columns
     workspace.object_set.add_objects(objects,
                                      self.output_objects_name.value)
     add_object_location_measurements(workspace.measurements,
                                      self.output_objects_name.value,
                                      labels, object_count)
     add_object_count_measurements(workspace.measurements,
                                   self.output_objects_name.value,
                                   object_count)
     if self.wants_outlines:
         outlines = outline(labels != 0)
         outline_image = cpi.Image(outlines)
         workspace.image_set.add(self.outlines_name.value, outline_image)
    def test_01_02_object_with_cropping(self):
        labels = np.zeros((10, 10), int)
        labels[0:7, 3:8] = 1
        mask = np.zeros((10, 10), bool)
        mask[1:9, 1:9] = True
        image = cpi.Image(np.zeros((10, 10)), mask=mask)
        area_occupied = np.sum(labels[mask])
        perimeter = np.sum(outline(np.logical_and(labels, mask)))
        total_area = np.sum(mask)
        workspace = self.make_workspace(labels, image)
        module = workspace.module
        module.operands[0].operand_choice.value = "Objects"
        module.run(workspace)
        m = workspace.measurements

        def mn(x):
            return "AreaOccupied_%s_%s" % (
                x, module.operands[0].operand_objects.value)

        self.assertEqual(
            m.get_current_measurement("Image", mn("AreaOccupied")),
            area_occupied)
        self.assertEqual(m.get_current_measurement("Image", mn("Perimeter")),
                         perimeter)
        self.assertEqual(m.get_current_measurement("Image", mn("TotalArea")),
                         total_area)
    def run(self, workspace):
        input_objects = workspace.object_set.get_objects(self.object_name.value)
        output_objects = cpo.Objects()
        output_objects.segmented = self.do_labels(input_objects.segmented)
        if (input_objects.has_small_removed_segmented and 
            self.operation not in (O_EXPAND, O_EXPAND_INF, O_DIVIDE)):
            output_objects.small_removed_segmented = \
                self.do_labels(input_objects.small_removed_segmented)
        if (input_objects.has_unedited_segmented and
            self.operation not in (O_EXPAND, O_EXPAND_INF, O_DIVIDE)):
            output_objects.unedited_segmented = \
                self.do_labels(input_objects.unedited_segmented)
        workspace.object_set.add_objects(output_objects,
                                         self.output_object_name.value)
        add_object_count_measurements(workspace.measurements, 
                                      self.output_object_name.value,
                                      np.max(output_objects.segmented))
        add_object_location_measurements(workspace.measurements,
                                         self.output_object_name.value,
                                         output_objects.segmented)
        if self.wants_outlines.value:
            outline_image = cpi.Image(outline(output_objects.segmented) > 0,
                                      parent_image = input_objects.parent_image)
            workspace.image_set.add(self.outlines_name.value, outline_image)

        if self.show_window:
            workspace.display_data.input_objects_segmented = input_objects.segmented
            workspace.display_data.output_objects_segmented = output_objects.segmented
Esempio n. 15
0
 def outlines(self):
     '''Get a mask of all the points on the border of objects'''
     if self._outlines == None:
         for i, labels in enumerate(self.labels):
             if i == 0:
                 self._outlines = outline(labels) != 0
             else:
                 self._outlines = self._outlines | (outline(labels) != 0)
         if self.line_width > 1:
             hw = float(self.line_width) / 2
             d = distance_transform_edt(~ self._outlines)
             dti, dtj = np.where((d < hw+.5) & ~self._outlines)
             self._outlines = self._outlines.astype(np.float32)
             self._outlines[dti, dtj] = np.minimum(1, hw + .5 - d[dti, dtj])
   
     return self._outlines.astype(np.float32)
Esempio n. 16
0
    def display(self, workspace, figure):
        '''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.set_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,
                                    sharexy=figure.subplot(0, 0))
Esempio n. 17
0
 def display(self, workspace):
     '''Display what was filtered'''
     src_name = self.object_name.value
     src_objects = workspace.get_objects(src_name)
     target_name = self.target_name.value
     target_objects = workspace.get_objects(target_name)
     image = None
     image_names = [image for image in 
                    [m.measurement.get_image_name(workspace.pipeline)
                     for m in self.measurements]
                    if image is not None 
                    and image in workspace.image_set.get_names()]
     if len(image_names) == 0:
         # Measurement isn't image-based
         if src_objects.has_parent_image:
             image = src_objects.parent_image
     else:
         image = workspace.image_set.get_image(image_names[0])
     if image is None:
         # Oh so sad - no image, just display the old and new labels
         figure = workspace.create_or_find_figure(title="FilterObjects, image cycle #%d"%(
             workspace.measurements.image_set_number),subplots=(1,2))
         figure.subplot_imshow_labels(0,0,src_objects.segmented,
                                      title="Original: %s"%src_name)
         figure.subplot_imshow_labels(0,1,target_objects.segmented,
                                      title="Filtered: %s"%
                                      target_name,
                                      sharex = figure.subplot(0,0),
                                      sharey = figure.subplot(0,0))
     else:
         figure = workspace.create_or_find_figure(title="FilterObjects, image cycle #%d"%(
             workspace.measurements.image_set_number),subplots=(2,2))
         figure.subplot_imshow_labels(0,0,src_objects.segmented,
                                      title="Original: %s"%src_name)
         figure.subplot_imshow_labels(0,1,target_objects.segmented,
                                      title="Filtered: %s"%
                                      target_name,
                                      sharex = figure.subplot(0,0),
                                      sharey = figure.subplot(0,0))
         outs = outline(target_objects.segmented) > 0
         pixel_data = image.pixel_data
         maxpix = np.max(pixel_data)
         if maxpix == 0:
             maxpix = 1.0
         if len(pixel_data.shape) == 3:
             picture = pixel_data.copy()
         else:
             picture = np.dstack((pixel_data,pixel_data,pixel_data))
         red_channel = picture[:,:,0]
         red_channel[outs] = maxpix
         figure.subplot_imshow(1, 0, picture, "Filtered Outlines",
                               sharex = figure.subplot(0,0),
                               sharey = figure.subplot(0,0))
         
         if workspace.frame != None:
             statistics = [  ["Number of objects pre-filtering",  np.max(src_objects.segmented)],
                             ["Number of objects post-filtering", np.max(target_objects.segmented)]]
             figure.subplot_table(1, 1, statistics, ratio=[.8,.2])
Esempio n. 18
0
    def display(self, workspace, figure):
        '''Display what was filtered'''
        src_name = self.object_name.value
        src_objects_segmented = workspace.display_data.src_objects_segmented
        image = workspace.display_data.image
        image_names = workspace.display_data.image_names
        target_objects_segmented = workspace.display_data.target_objects_segmented

        target_name = self.target_name.value

        if image is None:
            # Oh so sad - no image, just display the old and new labels
            figure.set_subplots((1, 2))
            figure.subplot_imshow_labels(0,
                                         0,
                                         src_objects_segmented,
                                         title="Original: %s" % src_name)
            figure.subplot_imshow_labels(0,
                                         1,
                                         target_objects_segmented,
                                         title="Filtered: %s" % target_name,
                                         sharexy=figure.subplot(0, 0))
        else:
            figure.set_subplots((2, 2))
            figure.subplot_imshow_labels(0,
                                         0,
                                         src_objects_segmented,
                                         title="Original: %s" % src_name)
            figure.subplot_imshow_labels(0,
                                         1,
                                         target_objects_segmented,
                                         title="Filtered: %s" % target_name,
                                         sharexy=figure.subplot(0, 0))
            outs = outline(target_objects_segmented) > 0
            maxpix = np.max(image)
            if maxpix == 0:
                maxpix = 1.0
            if len(image.shape) == 3:
                picture = image.copy()
            else:
                picture = np.dstack((image, image, image))
            red_channel = picture[:, :, 0]
            red_channel[outs] = maxpix
            figure.subplot_imshow(1,
                                  0,
                                  picture,
                                  "Filtered Outlines",
                                  sharexy=figure.subplot(0, 0))

            statistics = [[np.max(src_objects_segmented)],
                          [np.max(target_objects_segmented)]]
            figure.subplot_table(
                1,
                1,
                statistics,
                row_labels=("Number of objects pre-filtering",
                            "Number of objects post-filtering"))
Esempio n. 19
0
 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))
Esempio n. 20
0
 def test_01_03_touching(self):
     x = numpy.array([[0, 0, 0, 0, 0, 0, 0], [0, 0, 1, 1, 1, 0, 0],
                      [0, 0, 1, 1, 1, 0, 0], [0, 0, 1, 1, 1, 0, 0],
                      [0, 0, 2, 2, 2, 0, 0], [0, 0, 2, 2, 2, 0, 0],
                      [0, 0, 2, 2, 2, 0, 0], [0, 0, 0, 0, 0, 0, 0]])
     e = numpy.array([[0, 0, 0, 0, 0, 0, 0], [0, 0, 1, 1, 1, 0, 0],
                      [0, 0, 1, 0, 1, 0, 0], [0, 0, 1, 1, 1, 0, 0],
                      [0, 0, 2, 2, 2, 0, 0], [0, 0, 2, 0, 2, 0, 0],
                      [0, 0, 2, 2, 2, 0, 0], [0, 0, 0, 0, 0, 0, 0]])
     result = OL.outline(x)
     self.assertTrue(numpy.all(result == e))
Esempio n. 21
0
 def test_02_04_edge(self):
     x = numpy.array([[ 0,0,1,1,1,0,0],
                      [ 0,0,1,1,1,0,0],
                      [ 0,0,1,1,1,0,0],
                      [ 0,0,0,0,0,0,0]])
     e = numpy.array([[ 0,0,1,1,1,0,0],
                      [ 0,0,1,0,1,0,0],
                      [ 0,0,1,1,1,0,0],
                      [ 0,0,0,0,0,0,0]])
     result = OL.outline(x)
     self.assertTrue(numpy.all(result==e))
Esempio n. 22
0
 def test_01_02_two_disjoint(self):
     x = numpy.array([[0, 0, 0, 0, 0, 0, 0], [0, 0, 1, 1, 1, 0, 0],
                      [0, 0, 1, 1, 1, 0, 0], [0, 0, 1, 1, 1, 0, 0],
                      [0, 0, 0, 0, 0, 0, 0], [0, 0, 2, 2, 2, 0, 0],
                      [0, 0, 2, 2, 2, 0, 0], [0, 0, 2, 2, 2, 0, 0],
                      [0, 0, 0, 0, 0, 0, 0]])
     e = numpy.array([[0, 0, 0, 0, 0, 0, 0], [0, 0, 1, 1, 1, 0, 0],
                      [0, 0, 1, 0, 1, 0, 0], [0, 0, 1, 1, 1, 0, 0],
                      [0, 0, 0, 0, 0, 0, 0], [0, 0, 2, 2, 2, 0, 0],
                      [0, 0, 2, 0, 2, 0, 0], [0, 0, 2, 2, 2, 0, 0],
                      [0, 0, 0, 0, 0, 0, 0]])
     result = OL.outline(x)
     self.assertTrue(numpy.all(result == e))
 def test_07_01_outlines(self):
     """Create an outline of the resulting objects"""
     labels = np.zeros((10, 10), int)
     labels[4, 4] = 1
     i, j = np.mgrid[0:10, 0:10] - 4
     expected = (i ** 2 + j ** 2 <= 4).astype(int)
     expected_outlines = outline(expected)
     workspace, module = self.make_workspace(labels, E.O_EXPAND, 2, wants_outlines=True)
     module.run(workspace)
     objects = workspace.object_set.get_objects(OUTPUT_NAME)
     self.assertTrue(np.all(objects.segmented == expected))
     self.assertTrue(OUTLINES_NAME in workspace.image_set.get_names())
     outlines = workspace.image_set.get_image(OUTLINES_NAME).pixel_data
     self.assertTrue(np.all(outlines == expected_outlines))
 def measure_images(self,operand,workspace):
     '''Performs measurements on the requested images'''
     image = workspace.image_set.get_image(operand.binary_name.value, must_be_binary = True)
     area_occupied = np.sum(image.pixel_data > 0)
     perimeter = np.sum(outline(image.pixel_data) > 0)
     total_area = np.prod(np.shape(image.pixel_data))
     m = workspace.measurements
     m.add_image_measurement(F_AREA_OCCUPIED%(operand.binary_name.value),
                             np.array([area_occupied], dtype=float))
     m.add_image_measurement(F_PERIMETER%(operand.binary_name.value),
                             np.array([perimeter], dtype=float))
     m.add_image_measurement(F_TOTAL_AREA%(operand.binary_name.value),
                             np.array([total_area], dtype=float))
     return [[operand.binary_name.value, str(area_occupied), str(perimeter), str(total_area)]]
Esempio n. 25
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()
Esempio n. 26
0
 def test_07_01_outlines(self):
     '''Create an outline of the resulting objects'''
     labels = np.zeros((10,10), int)
     labels[4,4] = 1
     i,j = np.mgrid[0:10,0:10]-4
     expected = (i**2 + j**2 <=4).astype(int)
     expected_outlines = outline(expected)
     workspace, module = self.make_workspace(labels, E.O_EXPAND, 2,
                                             wants_outlines = True)
     module.run(workspace)
     objects = workspace.object_set.get_objects(OUTPUT_NAME)
     self.assertTrue(np.all(objects.segmented == expected))
     self.assertTrue(OUTLINES_NAME in workspace.image_set.get_names())
     outlines = workspace.image_set.get_image(OUTLINES_NAME).pixel_data
     self.assertTrue(np.all(outlines == expected_outlines))
Esempio n. 27
0
    def make_ijv_outlines(self, colors):
        '''Make ijv-style color outlines
        
        Make outlines, coloring each object differently to distinguish between
        objects that might overlap.
        
        colors: a N x 3 color map to be used to color the outlines
        '''
        #
        # Get planes of non-overlapping objects. The idea here is to use
        # the most similar colors in the color space for objects that
        # don't overlap.
        #
        all_labels = [(outline(label), indexes)
                      for label, indexes in self.get_labels()]
        image = np.zeros(list(all_labels[0][0].shape) + [3], np.float32)
        #
        # Find out how many unique labels in each
        #
        counts = [np.sum(np.unique(l) != 0) for l, _ in all_labels]
        if len(counts) == 1 and counts[0] == 0:
            return image

        if len(colors) < len(all_labels):
            # Have to color 2 planes using the same color!
            # There's some chance that overlapping objects will get
            # the same color. Give me more colors to work with please.
            colors = np.vstack([colors] * (1 + len(all_labels) / len(colors)))
        r = np.random.mtrand.RandomState()
        alpha = np.zeros(all_labels[0][0].shape, np.float32)
        order = np.lexsort([counts])
        label_colors = []
        for idx, i in enumerate(order):
            max_available = len(colors) / (len(all_labels) - idx)
            ncolors = min(counts[i], max_available)
            my_colors = colors[:ncolors]
            colors = colors[ncolors:]
            my_colors = my_colors[r.permutation(np.arange(ncolors))]
            my_labels, indexes = all_labels[i]
            color_idx = np.zeros(np.max(indexes) + 1, int)
            color_idx[indexes] = np.arange(len(indexes)) % ncolors
            image[my_labels != 0,:] += \
                 my_colors[color_idx[my_labels[my_labels != 0]],:]
            alpha[my_labels != 0] += 1
        image[alpha > 0, :] /= alpha[alpha > 0][:, np.newaxis]
        return image
Esempio n. 28
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()
Esempio n. 29
0
    def display(self, workspace, figure):
        '''Display what was filtered'''
        src_name = self.object_name.value
        src_objects_segmented = workspace.display_data.src_objects_segmented
        image = workspace.display_data.image
        image_names = workspace.display_data.image_names
        target_objects_segmented = workspace.display_data.target_objects_segmented

        target_name = self.target_name.value

        if image is None:
            # Oh so sad - no image, just display the old and new labels
            figure.set_subplots((1, 2))
            figure.subplot_imshow_labels(0,0,src_objects_segmented,
                                         title="Original: %s"%src_name)
            figure.subplot_imshow_labels(0,1,target_objects_segmented,
                                         title="Filtered: %s"%
                                         target_name,
                                         sharexy = figure.subplot(0,0))
        else:
            figure.set_subplots((2, 2))
            figure.subplot_imshow_labels(0,0,src_objects_segmented,
                                         title="Original: %s"%src_name)
            figure.subplot_imshow_labels(0,1,target_objects_segmented,
                                         title="Filtered: %s"%
                                         target_name,
                                         sharexy = figure.subplot(0,0))
            outs = outline(target_objects_segmented) > 0
            maxpix = np.max(image)
            if maxpix == 0:
                maxpix = 1.0
            if len(image.shape) == 3:
                picture = image.copy()
            else:
                picture = np.dstack((image,image,image))
            red_channel = picture[:,:,0]
            red_channel[outs] = maxpix
            figure.subplot_imshow(1, 0, picture, "Filtered Outlines",
                                  sharexy = figure.subplot(0,0))
            
            statistics = [  [np.max(src_objects_segmented)],
                            [np.max(target_objects_segmented)]]
            figure.subplot_table(
                1, 1, statistics, 
                row_labels = ("Number of objects pre-filtering",  
                              "Number of objects post-filtering"))
Esempio n. 30
0
 def make_ijv_outlines(self, colors):
     '''Make ijv-style color outlines
     
     Make outlines, coloring each object differently to distinguish between
     objects that might overlap.
     
     colors: a N x 3 color map to be used to color the outlines
     '''
     #
     # Get planes of non-overlapping objects. The idea here is to use
     # the most similar colors in the color space for objects that
     # don't overlap.
     #
     all_labels = [(outline(label), indexes) for label, indexes in self.get_labels()]
     image = np.zeros(list(all_labels[0][0].shape) + [3], np.float32)
     #
     # Find out how many unique labels in each
     #
     counts = [np.sum(np.unique(l) != 0) for l, _ in all_labels]
     if len(counts) == 1 and counts[0] == 0:
         return image
     
     if len(colors) < len(all_labels):
         # Have to color 2 planes using the same color!
         # There's some chance that overlapping objects will get
         # the same color. Give me more colors to work with please.
         colors = np.vstack([colors] * (1 + len(all_labels) / len(colors)))
     r = np.random.mtrand.RandomState()
     alpha = np.zeros(all_labels[0][0].shape, np.float32)
     order = np.lexsort([counts])
     label_colors = []
     for idx,i in enumerate(order):
         max_available = len(colors) / (len(all_labels) - idx)
         ncolors = min(counts[i], max_available)
         my_colors = colors[:ncolors]
         colors = colors[ncolors:]
         my_colors = my_colors[r.permutation(np.arange(ncolors))]
         my_labels, indexes = all_labels[i]
         color_idx = np.zeros(np.max(indexes) + 1, int)
         color_idx[indexes] = np.arange(len(indexes)) % ncolors
         image[my_labels != 0,:] += \
              my_colors[color_idx[my_labels[my_labels != 0]],:]
         alpha[my_labels != 0] += 1
     image[alpha > 0, :] /= alpha[alpha > 0][:, np.newaxis]
     return image
    def run(self, workspace):
        image_name    = self.image_name.value
        objects_name  = self.objects_name.value
        outlines_name = self.outlines_name.value
        image         = workspace.image_set.get_image(image_name)
        pixel_data    = image.pixel_data
        
        labels = np.zeros(pixel_data.shape[:2], int)
        self.do_ui(workspace, pixel_data, labels)
        objects = cpo.Objects()
        objects.segmented = labels
        workspace.object_set.add_objects(objects, objects_name)

        ##################
        #
        # Add measurements
        #
        m = workspace.measurements
        #
        # The object count
        #
        object_count = np.max(labels)
        I.add_object_count_measurements(m, objects_name, object_count)
        #
        # The object locations
        #
        I.add_object_location_measurements(m, objects_name, labels)
        #
        # Outlines if we want them
        #
        if self.wants_outlines:
            outlines_name = self.outlines_name.value
            outlines = outline(labels)
            outlines_image = cpi.Image(outlines.astype(bool))
            workspace.image_set.add(outlines_name, outlines_image)
        #
        # Do the drawing here
        #
        if workspace.frame is not None:
            figure = workspace.create_or_find_figure(title="IdentifyObjectsManually, image cycle #%d"%(
                workspace.measurements.image_set_number),subplots=(2,1))
            figure.subplot_imshow_labels(0, 0, labels, objects_name)
            figure.subplot_imshow(1, 0, self.draw_outlines(pixel_data, labels),
                                  sharex = figure.subplot(0,0),
                                  sharey = figure.subplot(0,0))
Esempio n. 32
0
    def run(self, workspace):
        image_name    = self.image_name.value
        objects_name  = self.objects_name.value
        outlines_name = self.outlines_name.value
        image         = workspace.image_set.get_image(image_name)
        pixel_data    = image.pixel_data
        
        labels = np.zeros(pixel_data.shape[:2], int)
        self.do_ui(workspace, pixel_data, labels)
        objects = cpo.Objects()
        objects.segmented = labels
        workspace.object_set.add_objects(objects, objects_name)

        ##################
        #
        # Add measurements
        #
        m = workspace.measurements
        #
        # The object count
        #
        object_count = np.max(labels)
        I.add_object_count_measurements(m, objects_name, object_count)
        #
        # The object locations
        #
        I.add_object_location_measurements(m, objects_name, labels)
        #
        # Outlines if we want them
        #
        if self.wants_outlines:
            outlines_name = self.outlines_name.value
            outlines = outline(labels)
            outlines_image = cpi.Image(outlines.astype(bool))
            workspace.image_set.add(outlines_name, outlines_image)
        #
        # Do the drawing here
        #
        if workspace.frame is not None:
            figure = workspace.create_or_find_figure(title="IdentifyObjectsManually, image cycle #%d"%(
                workspace.measurements.image_set_number),subplots=(2,1))
            figure.subplot_imshow_labels(0, 0, labels, objects_name)
            figure.subplot_imshow(1, 0, self.draw_outlines(pixel_data, labels),
                                  sharex = figure.subplot(0,0),
                                  sharey = figure.subplot(0,0))
Esempio n. 33
0
 def test_01_03_touching(self):
     x = numpy.array([[ 0,0,0,0,0,0,0],
                      [ 0,0,1,1,1,0,0],
                      [ 0,0,1,1,1,0,0],
                      [ 0,0,1,1,1,0,0],
                      [ 0,0,2,2,2,0,0],
                      [ 0,0,2,2,2,0,0],
                      [ 0,0,2,2,2,0,0],
                      [ 0,0,0,0,0,0,0]])
     e = numpy.array([[ 0,0,0,0,0,0,0],
                      [ 0,0,1,1,1,0,0],
                      [ 0,0,1,0,1,0,0],
                      [ 0,0,1,1,1,0,0],
                      [ 0,0,2,2,2,0,0],
                      [ 0,0,2,0,2,0,0],
                      [ 0,0,2,2,2,0,0],
                      [ 0,0,0,0,0,0,0]])
     result = OL.outline(x)
     self.assertTrue(numpy.all(result==e))
    def run(self, workspace):
        image_name = self.image_name.value
        objects_name = self.objects_name.value
        outlines_name = self.outlines_name.value
        image = workspace.image_set.get_image(image_name)
        pixel_data = image.pixel_data

        labels = workspace.interaction_request(
            self, pixel_data, workspace.measurements.image_set_number)
        if labels is None:
            # User cancelled. Soldier on as best we can.
            workspace.cancel_request()
            labels = np.zeros(pixel_data.shape[:2], int)
        objects = cpo.Objects()
        objects.segmented = labels
        workspace.object_set.add_objects(objects, objects_name)

        ##################
        #
        # Add measurements
        #
        m = workspace.measurements
        #
        # The object count
        #
        object_count = np.max(labels)
        I.add_object_count_measurements(m, objects_name, object_count)
        #
        # The object locations
        #
        I.add_object_location_measurements(m, objects_name, labels)
        #
        # Outlines if we want them
        #
        if self.wants_outlines:
            outlines_name = self.outlines_name.value
            outlines = outline(labels)
            outlines_image = cpi.Image(outlines.astype(bool))
            workspace.image_set.add(outlines_name, outlines_image)

        workspace.display_data.labels = labels
        workspace.display_data.pixel_data = pixel_data
    def run(self, workspace):
        image_name    = self.image_name.value
        objects_name  = self.objects_name.value
        outlines_name = self.outlines_name.value
        image         = workspace.image_set.get_image(image_name)
        pixel_data    = image.pixel_data
        
        labels = workspace.interaction_request(
            self, pixel_data, workspace.measurements.image_set_number)
        if labels is None:
            # User cancelled. Soldier on as best we can.
            workspace.cancel_request()
            labels = np.zeros(pixel_data.shape[:2], int)
        objects = cpo.Objects()
        objects.segmented = labels
        workspace.object_set.add_objects(objects, objects_name)

        ##################
        #
        # Add measurements
        #
        m = workspace.measurements
        #
        # The object count
        #
        object_count = np.max(labels)
        I.add_object_count_measurements(m, objects_name, object_count)
        #
        # The object locations
        #
        I.add_object_location_measurements(m, objects_name, labels)
        #
        # Outlines if we want them
        #
        if self.wants_outlines:
            outlines_name = self.outlines_name.value
            outlines = outline(labels)
            outlines_image = cpi.Image(outlines.astype(bool))
            workspace.image_set.add(outlines_name, outlines_image)

        workspace.display_data.labels = labels
        workspace.display_data.pixel_data = pixel_data
Esempio n. 36
0
 def measure_images(self, operand, workspace):
     '''Performs measurements on the requested images'''
     image = workspace.image_set.get_image(operand.binary_name.value,
                                           must_be_binary=True)
     area_occupied = np.sum(image.pixel_data > 0)
     perimeter = np.sum(outline(image.pixel_data) > 0)
     total_area = np.prod(np.shape(image.pixel_data))
     m = workspace.measurements
     m.add_image_measurement(F_AREA_OCCUPIED % (operand.binary_name.value),
                             np.array([area_occupied], dtype=float))
     m.add_image_measurement(F_PERIMETER % (operand.binary_name.value),
                             np.array([perimeter], dtype=float))
     m.add_image_measurement(F_TOTAL_AREA % (operand.binary_name.value),
                             np.array([total_area], dtype=float))
     return [[
         operand.binary_name.value,
         str(area_occupied),
         str(perimeter),
         str(total_area)
     ]]
 def test_01_02_object_with_cropping(self):
     labels = np.zeros((10,10),int)
     labels[0:7,3:8] = 1
     mask = np.zeros((10,10),bool)
     mask[1:9,1:9] = True
     image = cpi.Image(np.zeros((10,10)),mask=mask)
     area_occupied = np.sum(labels[mask])
     perimeter = np.sum(outline(np.logical_and(labels,mask)))
     total_area = np.sum(mask)
     workspace = self.make_workspace(labels, image)
     module = workspace.module
     module.operands[0].operand_choice.value = "Objects"
     module.run(workspace)
     m = workspace.measurements
     def mn(x):
         return "AreaOccupied_%s_%s"%(x, module.operands[0].operand_objects.value)
     
     self.assertEqual(m.get_current_measurement("Image",mn("AreaOccupied")), area_occupied)
     self.assertEqual(m.get_current_measurement("Image",mn("Perimeter")), perimeter)
     self.assertEqual(m.get_current_measurement("Image",mn("TotalArea")), total_area)
Esempio n. 38
0
 def test_01_02_two_disjoint(self):
     x = numpy.array([[ 0,0,0,0,0,0,0],
                      [ 0,0,1,1,1,0,0],
                      [ 0,0,1,1,1,0,0],
                      [ 0,0,1,1,1,0,0],
                      [ 0,0,0,0,0,0,0],
                      [ 0,0,2,2,2,0,0],
                      [ 0,0,2,2,2,0,0],
                      [ 0,0,2,2,2,0,0],
                      [ 0,0,0,0,0,0,0]])
     e = numpy.array([[ 0,0,0,0,0,0,0],
                      [ 0,0,1,1,1,0,0],
                      [ 0,0,1,0,1,0,0],
                      [ 0,0,1,1,1,0,0],
                      [ 0,0,0,0,0,0,0],
                      [ 0,0,2,2,2,0,0],
                      [ 0,0,2,0,2,0,0],
                      [ 0,0,2,2,2,0,0],
                      [ 0,0,0,0,0,0,0]])
     result = OL.outline(x)
     self.assertTrue(numpy.all(result==e))
Esempio n. 39
0
    def run(self, workspace):
        input_objects = workspace.object_set.get_objects(
            self.object_name.value)
        output_objects = cpo.Objects()
        output_objects.segmented = self.do_labels(input_objects.segmented)
        if (input_objects.has_small_removed_segmented
                and self.operation not in (O_EXPAND, O_EXPAND_INF, O_DIVIDE)):
            output_objects.small_removed_segmented = \
                self.do_labels(input_objects.small_removed_segmented)
        if (input_objects.has_unedited_segmented
                and self.operation not in (O_EXPAND, O_EXPAND_INF, O_DIVIDE)):
            output_objects.unedited_segmented = \
                self.do_labels(input_objects.unedited_segmented)
        workspace.object_set.add_objects(output_objects,
                                         self.output_object_name.value)
        add_object_count_measurements(workspace.measurements,
                                      self.output_object_name.value,
                                      np.max(output_objects.segmented))
        add_object_location_measurements(workspace.measurements,
                                         self.output_object_name.value,
                                         output_objects.segmented)
        if self.wants_outlines.value:
            outline_image = cpi.Image(outline(output_objects.segmented) > 0,
                                      parent_image=input_objects.parent_image)
            workspace.image_set.add(self.outlines_name.value, outline_image)

        if workspace.frame is not None:
            figure = workspace.create_or_find_figure(
                title="ExpandOrShrinkObjects, image cycle #%d" %
                (workspace.measurements.image_set_number),
                subplots=(2, 1))
            figure.subplot_imshow_labels(0, 0, input_objects.segmented,
                                         self.object_name.value)
            figure.subplot_imshow_labels(1,
                                         0,
                                         output_objects.segmented,
                                         self.output_object_name.value,
                                         sharex=figure.subplot(0, 0),
                                         sharey=figure.subplot(0, 0))
    def run(self, workspace):
        image_name = self.image_name.value
        objects_name = self.objects_name.value
        outlines_name = self.outlines_name.value
        image = workspace.image_set.get_image(image_name)
        pixel_data = image.pixel_data

        labels = workspace.interaction_request(self, pixel_data)
        objects = cpo.Objects()
        objects.segmented = labels
        workspace.object_set.add_objects(objects, objects_name)

        ##################
        #
        # Add measurements
        #
        m = workspace.measurements
        #
        # The object count
        #
        object_count = np.max(labels)
        I.add_object_count_measurements(m, objects_name, object_count)
        #
        # The object locations
        #
        I.add_object_location_measurements(m, objects_name, labels)
        #
        # Outlines if we want them
        #
        if self.wants_outlines:
            outlines_name = self.outlines_name.value
            outlines = outline(labels)
            outlines_image = cpi.Image(outlines.astype(bool))
            workspace.image_set.add(outlines_name, outlines_image)

        workspace.display_data.labels = labels
        workspace.display_data.pixel_data = pixel_data
 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 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
Esempio n. 43
0
 def calculate_minimum_distances(self, workspace, parent_name):
     '''Calculate the distance from child center to parent perimeter'''
     meas = workspace.measurements
     assert isinstance(meas, cpmeas.Measurements)
     sub_object_name = self.sub_object_name.value
     parents = workspace.object_set.get_objects(parent_name)
     children = workspace.object_set.get_objects(sub_object_name)
     parents_of = self.get_parents_of(workspace, parent_name)
     if len(parents_of) == 0:
         dist = np.zeros((0, ))
     elif np.all(parents_of == 0):
         dist = np.array([np.NaN] * len(parents_of))
     else:
         mask = parents_of > 0
         ccenters = centers_of_labels(children.segmented).transpose()
         ccenters = ccenters[mask, :]
         parents_of_masked = parents_of[mask] - 1
         pperim = outline(parents.segmented)
         #
         # Get a list of all points on the perimeter
         #
         perim_loc = np.argwhere(pperim != 0)
         #
         # Get the label # for each point
         #
         perim_idx = pperim[perim_loc[:, 0], perim_loc[:, 1]]
         #
         # Sort the points by label #
         #
         idx = np.lexsort((perim_loc[:, 1], perim_loc[:, 0], perim_idx))
         perim_loc = perim_loc[idx, :]
         perim_idx = perim_idx[idx]
         #
         # Get counts and indexes to each run of perimeter points
         #
         counts = fix(
             scind.sum(np.ones(len(perim_idx)), perim_idx,
                       np.arange(1, perim_idx[-1] + 1))).astype(np.int32)
         indexes = np.cumsum(counts) - counts
         #
         # For the children, get the index and count of the parent
         #
         ccounts = counts[parents_of_masked]
         cindexes = indexes[parents_of_masked]
         #
         # Now make an array that has an element for each of that child's
         # perimeter points
         #
         clabel = np.zeros(np.sum(ccounts), int)
         #
         # cfirst is the eventual first index of each child in the
         # clabel array
         #
         cfirst = np.cumsum(ccounts) - ccounts
         clabel[cfirst[1:]] += 1
         clabel = np.cumsum(clabel)
         #
         # Make an index that runs from 0 to ccounts for each
         # child label.
         #
         cp_index = np.arange(len(clabel)) - cfirst[clabel]
         #
         # then add cindexes to get an index to the perimeter point
         #
         cp_index += cindexes[clabel]
         #
         # Now, calculate the distance from the centroid of each label
         # to each perimeter point in the parent.
         #
         dist = np.sqrt(
             np.sum((perim_loc[cp_index, :] - ccenters[clabel, :])**2, 1))
         #
         # Finally, find the minimum distance per child
         #
         min_dist = fix(scind.minimum(dist, clabel,
                                      np.arange(len(ccounts))))
         #
         # Account for unparented children
         #
         dist = np.array([np.NaN] * len(mask))
         dist[mask] = min_dist
     meas.add_measurement(sub_object_name, FF_MINIMUM % parent_name, dist)
Esempio n. 44
0
 def run(self, workspace):
     '''Run the module on an image set'''
     
     object_name = self.object_name.value
     remaining_object_name = self.remaining_objects.value
     original_objects = workspace.object_set.get_objects(object_name)
     
     if self.mask_choice == MC_IMAGE:
         mask = workspace.image_set.get_image(self.masking_image.value,
                                              must_be_binary = True)
         mask = mask.pixel_data
     else:
         masking_objects = workspace.object_set.get_objects(
             self.masking_objects.value)
         mask = masking_objects.segmented > 0
     if self.wants_inverted_mask:
         mask = ~mask
     #
     # Load the labels
     #
     labels = original_objects.segmented.copy()
     nobjects = np.max(labels)
     #
     # Resize the mask to cover the objects
     #
     mask, m1 = cpo.size_similarly(labels, mask)
     mask[~m1] = False
     #
     # Apply the mask according to the overlap choice.
     #
     if nobjects == 0:
         pass
     elif self.overlap_choice == P_MASK:
         labels = labels * mask
     else:
         pixel_counts = fix(scind.sum(mask, labels, 
                                      np.arange(1, nobjects+1,dtype=np.int32)))
         if self.overlap_choice == P_KEEP:
             keep = pixel_counts > 0
         else:
             total_pixels = fix(scind.sum(np.ones(labels.shape), labels,
                                          np.arange(1, nobjects+1,dtype=np.int32)))
             if self.overlap_choice == P_REMOVE:
                 keep = pixel_counts == total_pixels
             elif self.overlap_choice == P_REMOVE_PERCENTAGE:
                 fraction = self.overlap_fraction.value
                 keep = pixel_counts / total_pixels >= fraction
             else:
                 raise NotImplementedError("Unknown overlap-handling choice: %s",
                                           self.overlap_choice.value)
         keep = np.hstack(([False], keep))
         labels[~ keep[labels]] = 0
     #
     # Renumber the labels matrix if requested
     #
     if self.retain_or_renumber == R_RENUMBER:
         unique_labels = np.unique(labels[labels!=0])
         indexer = np.zeros(nobjects+1, int)
         indexer[unique_labels] = np.arange(1, len(unique_labels)+1)
         labels = indexer[labels]
         parent_objects = unique_labels
     else:
         parent_objects = np.arange(1, nobjects+1)
     #
     # Add the objects
     #
     remaining_objects = cpo.Objects()
     remaining_objects.segmented = labels
     remaining_objects.unedited_segmented = original_objects.unedited_segmented
     workspace.object_set.add_objects(remaining_objects, 
                                      remaining_object_name)
     #
     # Add measurements
     #
     m = workspace.measurements
     m.add_measurement(remaining_object_name,
                       I.FF_PARENT % object_name,
                       parent_objects)
     if np.max(original_objects.segmented) == 0:
         child_count = np.array([],int)
     else:
         child_count = fix(scind.sum(labels, original_objects.segmented,
                                     np.arange(1, nobjects+1,dtype=np.int32)))
         child_count = (child_count > 0).astype(int)
     m.add_measurement(object_name,
                       I.FF_CHILDREN_COUNT % remaining_object_name,
                       child_count)
     if self.retain_or_renumber == R_RETAIN:
         remaining_object_count = nobjects
     else:
         remaining_object_count = len(unique_labels)
     I.add_object_count_measurements(m, remaining_object_name,
                                     remaining_object_count)
     I.add_object_location_measurements(m, remaining_object_name, labels)
     #
     # Add an outline if asked to do so
     #
     if self.wants_outlines.value:
         outline_image = cpi.Image(outline(labels) > 0,
                                   parent_image = original_objects.parent_image)
         workspace.image_set.add(self.outlines_name.value, outline_image)
     #
     # Save the input, mask and output images for display
     #
     if self.show_window:
         workspace.display_data.original_labels = original_objects.segmented
         workspace.display_data.final_labels = labels
         workspace.display_data.mask = mask
    def run(self, workspace):
        """Run the module on the current data set
        
        workspace - has the current image set, object set, measurements
                    and the parent frame for the application if the module
                    is allowed to display. If the module should not display,
                    workspace.frame is None.
        """
        #
        # The object set holds "objects". Each of these is a container
        # for holding up to three kinds of image labels.
        #
        object_set = workspace.object_set
        #
        # Get the primary objects (the centers to be removed).
        # Get the string value out of primary_object_name.
        #
        primary_objects = object_set.get_objects(
            self.primary_objects_name.value)
        #
        # Get the cleaned-up labels image
        #
        primary_labels = primary_objects.segmented
        #
        # Do the same with the secondary object
        secondary_objects = object_set.get_objects(
            self.secondary_objects_name.value)
        secondary_labels = secondary_objects.segmented
        #
        # If one of the two label images is smaller than the other, we
        # try to find the cropping mask and we apply that mask to the larger
        #
        try:
            if any([
                    p_size < s_size for p_size, s_size in zip(
                        primary_labels.shape, secondary_labels.shape)
            ]):
                #
                # Look for a cropping mask associated with the primary_labels
                # and apply that mask to resize the secondary labels
                #
                secondary_labels = primary_objects.crop_image_similarly(
                    secondary_labels)
                tertiary_image = primary_objects.parent_image
            elif any([
                    p_size > s_size for p_size, s_size in zip(
                        primary_labels.shape, secondary_labels.shape)
            ]):
                primary_labels = secondary_objects.crop_image_similarly(
                    primary_labels)
                tertiary_image = secondary_objects.parent_image
            elif secondary_objects.parent_image != None:
                tertiary_image = secondary_objects.parent_image
            else:
                tertiary_image = primary_objects.parent_image
        except ValueError:
            # No suitable cropping - resize all to fit the secondary
            # labels which are the most critical.
            #
            primary_labels, _ = cpo.size_similarly(secondary_labels,
                                                   primary_labels)
            if secondary_objects.parent_image != None:
                tertiary_image = secondary_objects.parent_image
            else:
                tertiary_image = primary_objects.parent_image
                if tertiary_image is not None:
                    tertiary_image, _ = cpo.size_similarly(
                        secondary_labels, tertiary_image)
        #
        # Find the outlines of the primary image and use this to shrink the
        # primary image by one. This guarantees that there is something left
        # of the secondary image after subtraction
        #
        primary_outline = outline(primary_labels)
        tertiary_labels = secondary_labels.copy()
        if self.shrink_primary:
            primary_mask = np.logical_or(primary_labels == 0, primary_outline)
        else:
            primary_mask = primary_labels == 0
        tertiary_labels[primary_mask == False] = 0
        #
        # Get the outlines of the tertiary image
        #
        tertiary_outlines = outline(tertiary_labels) != 0
        #
        # Make the tertiary objects container
        #
        tertiary_objects = cpo.Objects()
        tertiary_objects.segmented = tertiary_labels
        tertiary_objects.parent_image = tertiary_image
        #
        # Relate tertiary objects to their parents & record
        #
        child_count_of_secondary, secondary_parents = \
            secondary_objects.relate_children(tertiary_objects)
        if self.shrink_primary:
            child_count_of_primary, primary_parents = \
                primary_objects.relate_children(tertiary_objects)
        else:
            # Primary and tertiary don't overlap. If tertiary object
            # disappeared, have primary disavow knowledge of it.
            child_count_of_primary = np.zeros(primary_objects.count)
            child_count_of_primary[tertiary_objects.areas > 0] = 1
            primary_parents = np.arange(1, tertiary_objects.count + 1)

        #
        # Write out the objects
        #
        workspace.object_set.add_objects(tertiary_objects,
                                         self.subregion_objects_name.value)
        #
        # Write out the measurements
        #
        m = workspace.measurements
        #
        # The parent/child associations
        #
        for parent_objects_name, parents_of, child_count\
         in ((self.primary_objects_name, primary_parents,child_count_of_primary),
             (self.secondary_objects_name, secondary_parents, child_count_of_secondary)):
            m.add_measurement(self.subregion_objects_name.value,
                              cpmi.FF_PARENT % (parent_objects_name.value),
                              parents_of)
            m.add_measurement(
                parent_objects_name.value,
                cpmi.FF_CHILDREN_COUNT % (self.subregion_objects_name.value),
                child_count)
        object_count = tertiary_objects.count
        #
        # The object count
        #
        cpmi.add_object_count_measurements(workspace.measurements,
                                           self.subregion_objects_name.value,
                                           object_count)
        #
        # The object locations
        #
        cpmi.add_object_location_measurements(
            workspace.measurements, self.subregion_objects_name.value,
            tertiary_labels)
        #
        # The outlines
        #
        if self.use_outlines.value:
            out_img = cpi.Image(tertiary_outlines.astype(bool),
                                parent_image=tertiary_image)
            workspace.image_set.add(self.outlines_name.value, out_img)

        if self.show_window:
            workspace.display_data.primary_labels = primary_labels
            workspace.display_data.secondary_labels = secondary_labels
            workspace.display_data.tertiary_labels = tertiary_labels
            workspace.display_data.tertiary_outlines = tertiary_outlines
Esempio n. 46
0
 def test_00_00_zeros(self):
     x = numpy.zeros((10,10),int)
     result = OL.outline(x)
     self.assertTrue(numpy.all(x==result))
Esempio n. 47
0
    def run(self, workspace):
        assert isinstance(workspace, cpw.Workspace)
        image_name = self.image_name.value
        image = workspace.image_set.get_image(image_name,
                                              must_be_grayscale=True)
        workspace.display_data.statistics = []
        img = image.pixel_data
        mask = image.mask
        objects = workspace.object_set.get_objects(self.primary_objects.value)
        global_threshold = None
        if self.method == M_DISTANCE_N:
            has_threshold = False
        else:
            thresholded_image = self.threshold_image(image_name, workspace)
            has_threshold = True

        #
        # Get the following labels:
        # * all edited labels
        # * labels touching the edge, including small removed
        #
        labels_in = objects.unedited_segmented.copy()
        labels_touching_edge = np.hstack(
            (labels_in[0, :], labels_in[-1, :], labels_in[:,
                                                          0], labels_in[:,
                                                                        -1]))
        labels_touching_edge = np.unique(labels_touching_edge)
        is_touching = np.zeros(np.max(labels_in) + 1, bool)
        is_touching[labels_touching_edge] = True
        is_touching = is_touching[labels_in]

        labels_in[(~is_touching) & (objects.segmented == 0)] = 0
        #
        # Stretch the input labels to match the image size. If there's no
        # label matrix, then there's no label in that area.
        #
        if tuple(labels_in.shape) != tuple(img.shape):
            tmp = np.zeros(img.shape, labels_in.dtype)
            i_max = min(img.shape[0], labels_in.shape[0])
            j_max = min(img.shape[1], labels_in.shape[1])
            tmp[:i_max, :j_max] = labels_in[:i_max, :j_max]
            labels_in = tmp

        if self.method in (M_DISTANCE_B, M_DISTANCE_N):
            if self.method == M_DISTANCE_N:
                distances, (i, j) = scind.distance_transform_edt(
                    labels_in == 0, return_indices=True)
                labels_out = np.zeros(labels_in.shape, int)
                dilate_mask = distances <= self.distance_to_dilate.value
                labels_out[dilate_mask] =\
                    labels_in[i[dilate_mask],j[dilate_mask]]
            else:
                labels_out, distances = propagate(img, labels_in,
                                                  thresholded_image, 1.0)
                labels_out[distances > self.distance_to_dilate.value] = 0
                labels_out[labels_in > 0] = labels_in[labels_in > 0]
            if self.fill_holes:
                small_removed_segmented_out = fill_labeled_holes(labels_out)
            else:
                small_removed_segmented_out = labels_out
            #
            # Create the final output labels by removing labels in the
            # output matrix that are missing from the segmented image
            #
            segmented_labels = objects.segmented
            segmented_out = self.filter_labels(small_removed_segmented_out,
                                               objects, workspace)
        elif self.method == M_PROPAGATION:
            labels_out, distance = propagate(img, labels_in, thresholded_image,
                                             self.regularization_factor.value)
            if self.fill_holes:
                small_removed_segmented_out = fill_labeled_holes(labels_out)
            else:
                small_removed_segmented_out = labels_out.copy()
            segmented_out = self.filter_labels(small_removed_segmented_out,
                                               objects, workspace)
        elif self.method == M_WATERSHED_G:
            #
            # First, apply the sobel filter to the image (both horizontal
            # and vertical). The filter measures gradient.
            #
            sobel_image = np.abs(scind.sobel(img))
            #
            # Combine the image mask and threshold to mask the watershed
            #
            watershed_mask = np.logical_or(thresholded_image, labels_in > 0)
            watershed_mask = np.logical_and(watershed_mask, mask)
            #
            # Perform the first watershed
            #
            labels_out = watershed(sobel_image,
                                   labels_in,
                                   np.ones((3, 3), bool),
                                   mask=watershed_mask)
            if self.fill_holes:
                small_removed_segmented_out = fill_labeled_holes(labels_out)
            else:
                small_removed_segmented_out = labels_out.copy()
            segmented_out = self.filter_labels(small_removed_segmented_out,
                                               objects, workspace)
        elif self.method == M_WATERSHED_I:
            #
            # invert the image so that the maxima are filled first
            # and the cells compete over what's close to the threshold
            #
            inverted_img = 1 - img
            #
            # Same as above, but perform the watershed on the original image
            #
            watershed_mask = np.logical_or(thresholded_image, labels_in > 0)
            watershed_mask = np.logical_and(watershed_mask, mask)
            #
            # Perform the watershed
            #
            labels_out = watershed(inverted_img,
                                   labels_in,
                                   np.ones((3, 3), bool),
                                   mask=watershed_mask)
            if self.fill_holes:
                small_removed_segmented_out = fill_labeled_holes(labels_out)
            else:
                small_removed_segmented_out = labels_out
            segmented_out = self.filter_labels(small_removed_segmented_out,
                                               objects, workspace)

        if self.wants_discard_edge and self.wants_discard_primary:
            #
            # Make a new primary object
            #
            lookup = scind.maximum(segmented_out, objects.segmented,
                                   range(np.max(objects.segmented) + 1))
            lookup = fix(lookup)
            lookup[0] = 0
            lookup[lookup != 0] = np.arange(np.sum(lookup != 0)) + 1
            segmented_labels = lookup[objects.segmented]
            segmented_out = lookup[segmented_out]
            new_objects = cpo.Objects()
            new_objects.segmented = segmented_labels
            if objects.has_unedited_segmented:
                new_objects.unedited_segmented = objects.unedited_segmented
            if objects.has_small_removed_segmented:
                new_objects.small_removed_segmented = objects.small_removed_segmented
            new_objects.parent_image = objects.parent_image
            primary_outline = outline(segmented_labels)
            if self.wants_primary_outlines:
                out_img = cpi.Image(primary_outline.astype(bool),
                                    parent_image=image)
                workspace.image_set.add(self.new_primary_outlines_name.value,
                                        out_img)
        else:
            primary_outline = outline(objects.segmented)
        secondary_outline = outline(segmented_out)

        #
        # Add the objects to the object set
        #
        objects_out = cpo.Objects()
        objects_out.unedited_segmented = small_removed_segmented_out
        objects_out.small_removed_segmented = small_removed_segmented_out
        objects_out.segmented = segmented_out
        objects_out.parent_image = image
        objname = self.objects_name.value
        workspace.object_set.add_objects(objects_out, objname)
        if self.use_outlines.value:
            out_img = cpi.Image(secondary_outline.astype(bool),
                                parent_image=image)
            workspace.image_set.add(self.outlines_name.value, out_img)
        object_count = np.max(segmented_out)
        #
        # Add measurements
        #
        measurements = workspace.measurements
        cpmi.add_object_count_measurements(measurements, objname, object_count)
        cpmi.add_object_location_measurements(measurements, objname,
                                              segmented_out)
        #
        # Relate the secondary objects to the primary ones and record
        # the relationship.
        #
        children_per_parent, parents_of_children = \
            objects.relate_children(objects_out)
        measurements.add_measurement(self.primary_objects.value,
                                     cpmi.FF_CHILDREN_COUNT % objname,
                                     children_per_parent)
        measurements.add_measurement(
            objname, cpmi.FF_PARENT % self.primary_objects.value,
            parents_of_children)
        image_numbers = np.ones(len(parents_of_children), int) *\
            measurements.image_set_number
        mask = parents_of_children > 0
        measurements.add_relate_measurement(
            self.module_num, R_PARENT, self.primary_objects.value,
            self.objects_name.value, image_numbers[mask],
            parents_of_children[mask], image_numbers[mask],
            np.arange(1,
                      len(parents_of_children) + 1)[mask])
        #
        # If primary objects were created, add them
        #
        if self.wants_discard_edge and self.wants_discard_primary:
            workspace.object_set.add_objects(
                new_objects, self.new_primary_objects_name.value)
            cpmi.add_object_count_measurements(
                measurements, self.new_primary_objects_name.value,
                np.max(new_objects.segmented))
            cpmi.add_object_location_measurements(
                measurements, self.new_primary_objects_name.value,
                new_objects.segmented)
            for parent_objects, parent_name, child_objects, child_name in (
                (objects, self.primary_objects.value, new_objects,
                 self.new_primary_objects_name.value),
                (new_objects, self.new_primary_objects_name.value, objects_out,
                 objname)):
                children_per_parent, parents_of_children = \
                    parent_objects.relate_children(child_objects)
                measurements.add_measurement(
                    parent_name, cpmi.FF_CHILDREN_COUNT % child_name,
                    children_per_parent)
                measurements.add_measurement(child_name,
                                             cpmi.FF_PARENT % parent_name,
                                             parents_of_children)
        if self.show_window:
            object_area = np.sum(segmented_out > 0)
            workspace.display_data.object_pct = \
                100 * object_area / np.product(segmented_out.shape)
            workspace.display_data.img = img
            workspace.display_data.segmented_out = segmented_out
            workspace.display_data.primary_labels = objects.segmented
            workspace.display_data.global_threshold = global_threshold
            workspace.display_data.object_count = object_count
    def run(self, workspace):
        """Run the module
        
        workspace    - The workspace contains
            pipeline     - instance of cpp for this run
            image_set    - the images in the image set being processed
            object_set   - the objects (labeled masks) in this image set
            measurements - the measurements for this run
            frame        - the parent frame to whatever frame is created. None means don't draw.
        """
        orig_objects_name = self.object_name.value
        filtered_objects_name = self.filtered_objects.value
        
        orig_objects = workspace.object_set.get_objects(orig_objects_name)
        assert isinstance(orig_objects, cpo.Objects)
        orig_labels = [l for l, c in orig_objects.get_labels()]

        if self.wants_image_display:
            guide_image = workspace.image_set.get_image(self.image_name.value)
            guide_image = guide_image.pixel_data
            if np.any(guide_image != np.min(guide_image)):
                guide_image = (guide_image - np.min(guide_image)) / (np.max(guide_image) - np.min(guide_image))
        else:
            guide_image = None
        filtered_labels = workspace.interaction_request(
            self, orig_labels, guide_image, workspace.measurements.image_set_number)
        if filtered_labels is None:
            # Ask whoever is listening to stop doing stuff
            workspace.cancel_request()
            # Have to soldier on until the cancel takes effect...
            filtered_labels = orig_labels
        #
        # Renumber objects consecutively if asked to do so
        #
        unique_labels = np.unique(np.array(filtered_labels))
        unique_labels = unique_labels[unique_labels != 0]
        object_count = len(unique_labels)
        if self.renumber_choice == R_RENUMBER:
            mapping = np.zeros(1 if len(unique_labels) == 0 else np.max(unique_labels)+1, int)
            mapping[unique_labels] = np.arange(1,object_count + 1)
            filtered_labels = [mapping[l] for l in filtered_labels]
        #
        # Make the objects out of the labels
        #
        filtered_objects = cpo.Objects()
        i, j = np.mgrid[0:filtered_labels[0].shape[0],
                        0:filtered_labels[0].shape[1]]
        ijv = np.zeros((0, 3), filtered_labels[0].dtype)
        for l in filtered_labels:
            ijv = np.vstack((ijv,
                             np.column_stack((i[l != 0],
                                              j[l != 0],
                                              l[l != 0]))))
        filtered_objects.set_ijv(ijv, orig_labels[0].shape)
        if orig_objects.has_unedited_segmented():
            filtered_objects.unedited_segmented = orig_objects.unedited_segmented
        if orig_objects.parent_image is not None:
            filtered_objects.parent_image = orig_objects.parent_image
        workspace.object_set.add_objects(filtered_objects, 
                                         filtered_objects_name)
        #
        # Add parent/child & other measurements
        #
        m = workspace.measurements
        child_count, parents = orig_objects.relate_children(filtered_objects)
        m.add_measurement(filtered_objects_name,
                          I.FF_PARENT%(orig_objects_name),
                          parents)
        m.add_measurement(orig_objects_name,
                          I.FF_CHILDREN_COUNT%(filtered_objects_name),
                          child_count)
        #
        # The object count
        #
        I.add_object_count_measurements(m, filtered_objects_name,
                                        object_count)
        #
        # The object locations
        #
        I.add_object_location_measurements_ijv(m, filtered_objects_name, ijv)
        #
        # Outlines if we want them
        #
        if self.wants_outlines:
            outlines_name = self.outlines_name.value
            outlines = outline(filtered_labels[0]).astype(bool)
            outlines_image = cpi.Image(outlines)
            workspace.image_set.add(outlines_name, outlines_image)

        workspace.display_data.orig_ijv = orig_objects.ijv
        workspace.display_data.filtered_ijv = filtered_objects.ijv
        workspace.display_data.shape = orig_labels[0].shape
    def run(self, workspace):
        if self.show_window:
            workspace.display_data.col_labels = ("Image", "Object", "Feature",
                                                 "Mean", "Median", "STD")
            workspace.display_data.statistics = statistics = []
        for image_name in [img.name for img in self.images]:
            image = workspace.image_set.get_image(image_name.value,
                                                  must_be_grayscale=True)
            for object_name in [obj.name for obj in self.objects]:
                # Need to refresh image after each iteration...
                img = image.pixel_data
                if image.has_mask:
                    masked_image = img.copy()
                    masked_image[~image.mask] = 0
                else:
                    masked_image = img
                objects = workspace.object_set.get_objects(object_name.value)
                nobjects = objects.count
                integrated_intensity = np.zeros((nobjects, ))
                integrated_intensity_edge = np.zeros((nobjects, ))
                mean_intensity = np.zeros((nobjects, ))
                mean_intensity_edge = np.zeros((nobjects, ))
                std_intensity = np.zeros((nobjects, ))
                std_intensity_edge = np.zeros((nobjects, ))
                min_intensity = np.zeros((nobjects, ))
                min_intensity_edge = np.zeros((nobjects, ))
                max_intensity = np.zeros((nobjects, ))
                max_intensity_edge = np.zeros((nobjects, ))
                mass_displacement = np.zeros((nobjects, ))
                lower_quartile_intensity = np.zeros((nobjects, ))
                median_intensity = np.zeros((nobjects, ))
                mad_intensity = np.zeros((nobjects, ))
                upper_quartile_intensity = np.zeros((nobjects, ))
                cmi_x = np.zeros((nobjects, ))
                cmi_y = np.zeros((nobjects, ))
                max_x = np.zeros((nobjects, ))
                max_y = np.zeros((nobjects, ))
                for labels, lindexes in objects.get_labels():
                    lindexes = lindexes[lindexes != 0]
                    labels, img = cpo.crop_labels_and_image(labels, img)
                    _, masked_image = cpo.crop_labels_and_image(
                        labels, masked_image)
                    outlines = cpmo.outline(labels)

                    if image.has_mask:
                        _, mask = cpo.crop_labels_and_image(labels, image.mask)
                        masked_labels = labels.copy()
                        masked_labels[~mask] = 0
                        masked_outlines = outlines.copy()
                        masked_outlines[~mask] = 0
                    else:
                        masked_labels = labels
                        masked_outlines = outlines

                    lmask = masked_labels > 0 & np.isfinite(
                        img)  # Ignore NaNs, Infs
                    has_objects = np.any(lmask)
                    if has_objects:
                        emask = masked_outlines > 0
                        limg = img[lmask]
                        eimg = img[emask]
                        llabels = labels[lmask]
                        elabels = labels[emask]
                        mesh_y, mesh_x = np.mgrid[0:masked_image.shape[0],
                                                  0:masked_image.shape[1]]
                        mesh_x = mesh_x[lmask]
                        mesh_y = mesh_y[lmask]
                        lcount = fix(
                            nd.sum(np.ones(len(limg)), llabels, lindexes))
                        ecount = fix(
                            nd.sum(np.ones(len(eimg)), elabels, lindexes))
                        integrated_intensity[lindexes-1] = \
                            fix(nd.sum(limg, llabels, lindexes))
                        integrated_intensity_edge[lindexes-1] = \
                            fix(nd.sum(eimg, elabels, lindexes))
                        mean_intensity[lindexes-1] = \
                            integrated_intensity[lindexes-1] / lcount
                        mean_intensity_edge[lindexes-1] = \
                            integrated_intensity_edge[lindexes-1] / ecount
                        std_intensity[lindexes - 1] = np.sqrt(
                            fix(
                                nd.mean(
                                    (limg - mean_intensity[llabels - 1])**2,
                                    llabels, lindexes)))
                        std_intensity_edge[lindexes - 1] = np.sqrt(
                            fix(
                                nd.mean((eimg -
                                         mean_intensity_edge[elabels - 1])**2,
                                        elabels, lindexes)))
                        min_intensity[lindexes - 1] = fix(
                            nd.minimum(limg, llabels, lindexes))
                        min_intensity_edge[lindexes - 1] = fix(
                            nd.minimum(eimg, elabels, lindexes))
                        max_intensity[lindexes - 1] = fix(
                            nd.maximum(limg, llabels, lindexes))
                        max_intensity_edge[lindexes - 1] = fix(
                            nd.maximum(eimg, elabels, lindexes))
                        # Compute the position of the intensity maximum
                        max_position = np.array(fix(
                            nd.maximum_position(limg, llabels, lindexes)),
                                                dtype=int)
                        max_position = np.reshape(max_position,
                                                  (max_position.shape[0], ))
                        max_x[lindexes - 1] = mesh_x[max_position]
                        max_y[lindexes - 1] = mesh_y[max_position]
                        # The mass displacement is the distance between the center
                        # of mass of the binary image and of the intensity image. The
                        # center of mass is the average X or Y for the binary image
                        # and the sum of X or Y * intensity / integrated intensity
                        cm_x = fix(nd.mean(mesh_x, llabels, lindexes))
                        cm_y = fix(nd.mean(mesh_y, llabels, lindexes))

                        i_x = fix(nd.sum(mesh_x * limg, llabels, lindexes))
                        i_y = fix(nd.sum(mesh_y * limg, llabels, lindexes))
                        cmi_x[lindexes -
                              1] = i_x / integrated_intensity[lindexes - 1]
                        cmi_y[lindexes -
                              1] = i_y / integrated_intensity[lindexes - 1]
                        diff_x = cm_x - cmi_x[lindexes - 1]
                        diff_y = cm_y - cmi_y[lindexes - 1]
                        mass_displacement[lindexes-1] = \
                            np.sqrt(diff_x * diff_x+diff_y*diff_y)
                        #
                        # Sort the intensities by label, then intensity.
                        # For each label, find the index above and below
                        # the 25%, 50% and 75% mark and take the weighted
                        # average.
                        #
                        order = np.lexsort((limg, llabels))
                        areas = lcount.astype(int)
                        indices = np.cumsum(areas) - areas
                        for dest, fraction in ((lower_quartile_intensity,
                                                1.0 / 4.0), (median_intensity,
                                                             1.0 / 2.0),
                                               (upper_quartile_intensity,
                                                3.0 / 4.0)):
                            qindex = indices.astype(float) + areas * fraction
                            qfraction = qindex - np.floor(qindex)
                            qindex = qindex.astype(int)
                            qmask = qindex < indices + areas - 1
                            qi = qindex[qmask]
                            qf = qfraction[qmask]
                            dest[lindexes[qmask] -
                                 1] = (limg[order[qi]] * (1 - qf) +
                                       limg[order[qi + 1]] * qf)
                            #
                            # In some situations (e.g. only 3 points), there may
                            # not be an upper bound.
                            #
                            qmask = (~qmask) & (areas > 0)
                            dest[lindexes[qmask] -
                                 1] = limg[order[qindex[qmask]]]
                        #
                        # Once again, for the MAD
                        #
                        madimg = limg - median_intensity[llabels - 1]
                        order = np.lexsort((limg, llabels))
                        qindex = indices.astype(float) + areas / 2.0
                        qfraction = qindex - np.floor(qindex)
                        qindex = qindex.astype(int)
                        qmask = qindex < indices + areas - 1
                        qi = qindex[qmask]
                        qf = qfraction[qmask]
                        mad_intensity[lindexes[qmask] -
                                      1] = (madimg[order[qi]] * (1 - qf) +
                                            madimg[order[qi + 1]] * qf)
                        qmask = (~qmask) & (areas > 0)
                        mad_intensity[lindexes[qmask] -
                                      1] = madimg[order[qindex[qmask]]]

                m = workspace.measurements
                for category, feature_name, measurement in \
                    ((INTENSITY, INTEGRATED_INTENSITY, integrated_intensity),
                     (INTENSITY, MEAN_INTENSITY, mean_intensity),
                     (INTENSITY, STD_INTENSITY, std_intensity),
                     (INTENSITY, MIN_INTENSITY, min_intensity),
                     (INTENSITY, MAX_INTENSITY, max_intensity),
                     (INTENSITY, INTEGRATED_INTENSITY_EDGE, integrated_intensity_edge),
                     (INTENSITY, MEAN_INTENSITY_EDGE, mean_intensity_edge),
                     (INTENSITY, STD_INTENSITY_EDGE, std_intensity_edge),
                     (INTENSITY, MIN_INTENSITY_EDGE, min_intensity_edge),
                     (INTENSITY, MAX_INTENSITY_EDGE, max_intensity_edge),
                     (INTENSITY, MASS_DISPLACEMENT, mass_displacement),
                     (INTENSITY, LOWER_QUARTILE_INTENSITY, lower_quartile_intensity),
                     (INTENSITY, MEDIAN_INTENSITY, median_intensity),
                     (INTENSITY, MAD_INTENSITY, mad_intensity),
                     (INTENSITY, UPPER_QUARTILE_INTENSITY, upper_quartile_intensity),
                     (C_LOCATION, LOC_CMI_X, cmi_x),
                     (C_LOCATION, LOC_CMI_Y, cmi_y),
                     (C_LOCATION, LOC_MAX_X, max_x),
                     (C_LOCATION, LOC_MAX_Y, max_y)):
                    measurement_name = "%s_%s_%s" % (category, feature_name,
                                                     image_name.value)
                    m.add_measurement(object_name.value, measurement_name,
                                      measurement)
                    if self.show_window and len(measurement) > 0:
                        statistics.append(
                            (image_name.value, object_name.value, feature_name,
                             np.round(np.mean(measurement),
                                      3), np.round(np.median(measurement), 3),
                             np.round(np.std(measurement), 3)))
    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
Esempio n. 51
0
 def run(self, workspace):
     '''Run the module on an image set'''
     
     object_name = self.object_name.value
     remaining_object_name = self.remaining_objects.value
     original_objects = workspace.object_set.get_objects(object_name)
     
     if self.mask_choice == MC_IMAGE:
         mask = workspace.image_set.get_image(self.masking_image.value,
                                              must_be_binary = True)
         mask = mask.pixel_data
     else:
         masking_objects = workspace.object_set.get_objects(
             self.masking_objects.value)
         mask = masking_objects.segmented > 0
     if self.wants_inverted_mask:
         mask = ~mask
     #
     # Load the labels
     #
     labels = original_objects.segmented.copy()
     nobjects = np.max(labels)
     #
     # Resize the mask to cover the objects
     #
     mask, m1 = cpo.size_similarly(labels, mask)
     mask[~m1] = False
     #
     # Apply the mask according to the overlap choice.
     #
     if nobjects == 0:
         pass
     elif self.overlap_choice == P_MASK:
         labels = labels * mask
     else:
         pixel_counts = fix(scind.sum(mask, labels, 
                                      np.arange(1, nobjects+1,dtype=np.int32)))
         if self.overlap_choice == P_KEEP:
             keep = pixel_counts > 0
         else:
             total_pixels = fix(scind.sum(np.ones(labels.shape), labels,
                                          np.arange(1, nobjects+1,dtype=np.int32)))
             if self.overlap_choice == P_REMOVE:
                 keep = pixel_counts == total_pixels
             elif self.overlap_choice == P_REMOVE_PERCENTAGE:
                 fraction = self.overlap_fraction.value
                 keep = pixel_counts / total_pixels >= fraction
             else:
                 raise NotImplementedError("Unknown overlap-handling choice: %s",
                                           self.overlap_choice.value)
         keep = np.hstack(([False], keep))
         labels[~ keep[labels]] = 0
     #
     # Renumber the labels matrix if requested
     #
     if self.retain_or_renumber == R_RENUMBER:
         unique_labels = np.unique(labels[labels!=0])
         indexer = np.zeros(nobjects+1, int)
         indexer[unique_labels] = np.arange(1, len(unique_labels)+1)
         labels = indexer[labels]
         parent_objects = unique_labels
     else:
         parent_objects = np.arange(1, nobjects+1)
     #
     # Add the objects
     #
     remaining_objects = cpo.Objects()
     remaining_objects.segmented = labels
     remaining_objects.unedited_segmented = original_objects.unedited_segmented
     workspace.object_set.add_objects(remaining_objects, 
                                      remaining_object_name)
     #
     # Add measurements
     #
     m = workspace.measurements
     m.add_measurement(remaining_object_name,
                       I.FF_PARENT % object_name,
                       parent_objects)
     if np.max(original_objects.segmented) == 0:
         child_count = np.array([],int)
     else:
         child_count = fix(scind.sum(labels, original_objects.segmented,
                                     np.arange(1, nobjects+1,dtype=np.int32)))
         child_count = (child_count > 0).astype(int)
     m.add_measurement(object_name,
                       I.FF_CHILDREN_COUNT % remaining_object_name,
                       child_count)
     if self.retain_or_renumber == R_RETAIN:
         remaining_object_count = nobjects
     else:
         remaining_object_count = len(unique_labels)
     I.add_object_count_measurements(m, remaining_object_name,
                                     remaining_object_count)
     I.add_object_location_measurements(m, remaining_object_name, labels)
     #
     # Add an outline if asked to do so
     #
     if self.wants_outlines.value:
         outline_image = cpi.Image(outline(labels) > 0,
                                   parent_image = original_objects.parent_image)
         workspace.image_set.add(self.outlines_name.value, outline_image)
     #
     # Save the input, mask and output images for display
     #
     if self.show_window:
         workspace.display_data.original_labels = original_objects.segmented
         workspace.display_data.final_labels = labels
         workspace.display_data.mask = mask
 def run(self, workspace):
     if self.show_window:
         workspace.display_data.col_labels = (
             "Image","Object","Feature","Mean","Median","STD")
         workspace.display_data.statistics = statistics = []
     for image_name in [img.name for img in self.images]:
         image = workspace.image_set.get_image(image_name.value,
                                               must_be_grayscale=True)
         for object_name in [obj.name for obj in self.objects]:
             # Need to refresh image after each iteration...
             img = image.pixel_data
             if image.has_mask:
                 masked_image = img.copy()
                 masked_image[~image.mask] = 0
             else:
                 masked_image = img
             objects = workspace.object_set.get_objects(object_name.value)
             nobjects = objects.count
             integrated_intensity = np.zeros((nobjects,))
             integrated_intensity_edge = np.zeros((nobjects,))
             mean_intensity = np.zeros((nobjects,))
             mean_intensity_edge = np.zeros((nobjects,))
             std_intensity = np.zeros((nobjects,))
             std_intensity_edge = np.zeros((nobjects,))
             min_intensity = np.zeros((nobjects,))
             min_intensity_edge = np.zeros((nobjects,))
             max_intensity = np.zeros((nobjects,))
             max_intensity_edge = np.zeros((nobjects,))
             mass_displacement = np.zeros((nobjects,))
             lower_quartile_intensity = np.zeros((nobjects,))
             median_intensity = np.zeros((nobjects,))
             mad_intensity = np.zeros((nobjects,))
             upper_quartile_intensity = np.zeros((nobjects,))
             cmi_x = np.zeros((nobjects,))
             cmi_y = np.zeros((nobjects,))
             max_x = np.zeros((nobjects,))
             max_y = np.zeros((nobjects,))
             for labels, lindexes in objects.get_labels():
                 lindexes = lindexes[lindexes != 0]
                 labels, img = cpo.crop_labels_and_image(labels, img)
                 _, masked_image = cpo.crop_labels_and_image(labels, masked_image)
                 outlines = cpmo.outline(labels)
                 
                 if image.has_mask:
                     _, mask = cpo.crop_labels_and_image(labels, image.mask)
                     masked_labels = labels.copy()
                     masked_labels[~mask] = 0
                     masked_outlines = outlines.copy()
                     masked_outlines[~mask] = 0
                 else:
                     masked_labels = labels
                     masked_outlines = outlines
                 
                 lmask = masked_labels > 0 & np.isfinite(img) # Ignore NaNs, Infs
                 has_objects = np.any(lmask)
                 if has_objects:
                     limg = img[lmask]
                     llabels = labels[lmask]
                     mesh_y, mesh_x = np.mgrid[0:masked_image.shape[0],
                                               0:masked_image.shape[1]]
                     mesh_x = mesh_x[lmask]
                     mesh_y = mesh_y[lmask]
                     lcount = fix(nd.sum(np.ones(len(limg)), llabels, lindexes))
                     integrated_intensity[lindexes-1] = \
                         fix(nd.sum(limg, llabels, lindexes))
                     mean_intensity[lindexes-1] = \
                         integrated_intensity[lindexes-1] / lcount
                     std_intensity[lindexes-1] = np.sqrt(
                         fix(nd.mean((limg - mean_intensity[llabels-1])**2, 
                                     llabels, lindexes)))
                     min_intensity[lindexes-1] = fix(nd.minimum(limg, llabels, lindexes))
                     max_intensity[lindexes-1] = fix(
                         nd.maximum(limg, llabels, lindexes))
                      # Compute the position of the intensity maximum
                     max_position = np.array( fix(nd.maximum_position(limg, llabels, lindexes)), dtype=int )
                     max_position = np.reshape( max_position, ( max_position.shape[0], ) )
                     max_x[lindexes-1] = mesh_x[ max_position ]
                     max_y[lindexes-1] = mesh_y[ max_position ]
                    # The mass displacement is the distance between the center
                     # of mass of the binary image and of the intensity image. The
                     # center of mass is the average X or Y for the binary image
                     # and the sum of X or Y * intensity / integrated intensity
                     cm_x = fix(nd.mean(mesh_x, llabels, lindexes))
                     cm_y = fix(nd.mean(mesh_y, llabels, lindexes))
                     
                     i_x = fix(nd.sum(mesh_x * limg, llabels, lindexes))
                     i_y = fix(nd.sum(mesh_y * limg, llabels, lindexes))
                     cmi_x[lindexes-1] = i_x / integrated_intensity[lindexes-1]
                     cmi_y[lindexes-1] = i_y / integrated_intensity[lindexes-1]
                     diff_x = cm_x - cmi_x[lindexes-1]
                     diff_y = cm_y - cmi_y[lindexes-1]
                     mass_displacement[lindexes-1] = \
                         np.sqrt(diff_x * diff_x+diff_y*diff_y)
                     #
                     # Sort the intensities by label, then intensity.
                     # For each label, find the index above and below
                     # the 25%, 50% and 75% mark and take the weighted
                     # average.
                     #
                     order = np.lexsort((limg, llabels))
                     areas = lcount.astype(int)
                     indices = np.cumsum(areas) - areas
                     for dest, fraction in (
                         (lower_quartile_intensity, 1.0/4.0),
                         (median_intensity, 1.0/2.0),
                         (upper_quartile_intensity, 3.0/4.0)):
                         qindex = indices.astype(float) + areas * fraction
                         qfraction = qindex - np.floor(qindex)
                         qindex = qindex.astype(int)
                         qmask = qindex < indices + areas-1
                         qi = qindex[qmask]
                         qf = qfraction[qmask]
                         dest[lindexes[qmask]-1] = (
                             limg[order[qi]] * (1 - qf) +
                             limg[order[qi + 1]] * qf)
                         #
                         # In some situations (e.g. only 3 points), there may
                         # not be an upper bound.
                         #
                         qmask = (~qmask) & (areas > 0)
                         dest[lindexes[qmask]-1] = limg[order[qindex[qmask]]]
                     #
                     # Once again, for the MAD
                     #
                     madimg = np.abs(limg - median_intensity[llabels-1])
                     order =  np.lexsort((madimg, llabels))
                     qindex = indices.astype(float) + areas / 2.0
                     qfraction = qindex - np.floor(qindex)
                     qindex = qindex.astype(int)
                     qmask = qindex < indices + areas-1
                     qi = qindex[qmask]
                     qf = qfraction[qmask]
                     mad_intensity[lindexes[qmask]-1] = (
                         madimg[order[qi]] * (1 - qf) +
                         madimg[order[qi + 1]] * qf)
                     qmask = (~qmask) & (areas > 0)
                     mad_intensity[lindexes[qmask]-1] = madimg[order[qindex[qmask]]]
                     
                 emask = masked_outlines > 0
                 eimg = img[emask]
                 elabels = labels[emask]
                 has_edge = len(eimg) > 0
                 if has_edge:
                     ecount = fix(nd.sum(
                         np.ones(len(eimg)), elabels, lindexes))
                     integrated_intensity_edge[lindexes-1] = \
                         fix(nd.sum(eimg, elabels, lindexes))
                     mean_intensity_edge[lindexes-1] = \
                         integrated_intensity_edge[lindexes-1] / ecount
                     std_intensity_edge[lindexes-1] = \
                         np.sqrt(fix(nd.mean(
                             (eimg - mean_intensity_edge[elabels-1])**2, 
                             elabels, lindexes)))
                     min_intensity_edge[lindexes-1] = fix(
                         nd.minimum(eimg, elabels, lindexes))
                     max_intensity_edge[lindexes-1] = fix(
                         nd.maximum(eimg, elabels, lindexes))
             m = workspace.measurements
             for category, feature_name, measurement in \
                 ((INTENSITY, INTEGRATED_INTENSITY, integrated_intensity),
                  (INTENSITY, MEAN_INTENSITY, mean_intensity),
                  (INTENSITY, STD_INTENSITY, std_intensity),
                  (INTENSITY, MIN_INTENSITY, min_intensity),
                  (INTENSITY, MAX_INTENSITY, max_intensity),
                  (INTENSITY, INTEGRATED_INTENSITY_EDGE, integrated_intensity_edge),
                  (INTENSITY, MEAN_INTENSITY_EDGE, mean_intensity_edge),
                  (INTENSITY, STD_INTENSITY_EDGE, std_intensity_edge),
                  (INTENSITY, MIN_INTENSITY_EDGE, min_intensity_edge),
                  (INTENSITY, MAX_INTENSITY_EDGE, max_intensity_edge),
                  (INTENSITY, MASS_DISPLACEMENT, mass_displacement),
                  (INTENSITY, LOWER_QUARTILE_INTENSITY, lower_quartile_intensity),
                  (INTENSITY, MEDIAN_INTENSITY, median_intensity),
                  (INTENSITY, MAD_INTENSITY, mad_intensity),
                  (INTENSITY, UPPER_QUARTILE_INTENSITY, upper_quartile_intensity),
                  (C_LOCATION, LOC_CMI_X, cmi_x),
                  (C_LOCATION, LOC_CMI_Y, cmi_y),
                  (C_LOCATION, LOC_MAX_X, max_x),
                  (C_LOCATION, LOC_MAX_Y, max_y)):
                 measurement_name = "%s_%s_%s"%(category,feature_name,
                                                image_name.value)
                 m.add_measurement(object_name.value,measurement_name, 
                                   measurement)
                 if self.show_window and len(measurement) > 0:
                     statistics.append((image_name.value, object_name.value, 
                                        feature_name,
                                        np.round(np.mean(measurement),3),
                                        np.round(np.median(measurement),3),
                                        np.round(np.std(measurement),3)))
Esempio n. 53
0
    def run(self, workspace):
        '''Filter objects for this image set, display results'''
        src_objects = workspace.get_objects(self.object_name.value)
        if self.mode == MODE_RULES:
            indexes = self.keep_by_rules(workspace, src_objects)
        elif self.mode == MODE_MEASUREMENTS:
            if self.filter_choice in (FI_MINIMAL, FI_MAXIMAL):
                indexes = self.keep_one(workspace, src_objects)
            if self.filter_choice in (FI_MINIMAL_PER_OBJECT, 
                                      FI_MAXIMAL_PER_OBJECT):
                indexes = self.keep_per_object(workspace, src_objects)
            if self.filter_choice == FI_LIMITS:
                indexes = self.keep_within_limits(workspace, src_objects)
        elif self.mode == MODE_BORDER:
            indexes = self.discard_border_objects(workspace, src_objects)
        else:
            raise ValueError("Unknown filter choice: %s"%
                             self.filter_choice.value)
        
        #
        # Create an array that maps label indexes to their new values
        # All labels to be deleted have a value in this array of zero
        #
        new_object_count = len(indexes)
        max_label = np.max(src_objects.segmented)
        label_indexes = np.zeros((max_label+1,),int)
        label_indexes[indexes] = np.arange(1,new_object_count+1)
        #
        # Loop over both the primary and additional objects
        #
        object_list = ([(self.object_name.value, self.target_name.value,
                         self.wants_outlines.value, self.outlines_name.value)] + 
                       [(x.object_name.value, x.target_name.value, 
                         x.wants_outlines.value, x.outlines_name.value)
                         for x in self.additional_objects])
        m = workspace.measurements
        for src_name, target_name, wants_outlines, outlines_name in object_list:
            src_objects = workspace.get_objects(src_name)
            target_labels = src_objects.segmented.copy()
            #
            # Reindex the labels of the old source image
            #
            target_labels[target_labels > max_label] = 0
            target_labels = label_indexes[target_labels]
            #
            # Make a new set of objects - retain the old set's unedited
            # segmentation for the new and generally try to copy stuff
            # from the old to the new.
            #
            target_objects = cpo.Objects()
            target_objects.segmented = target_labels
            target_objects.unedited_segmented = src_objects.unedited_segmented
            if src_objects.has_parent_image:
                target_objects.parent_image = src_objects.parent_image
            workspace.object_set.add_objects(target_objects, target_name)
            #
            # Add measurements for the new objects
            add_object_count_measurements(m, target_name, new_object_count)
            add_object_location_measurements(m, target_name, target_labels)
            #
            # Relate the old numbering to the new numbering
            #
            m.add_measurement(target_name,
                              FF_PARENT%(src_name),
                              np.array(indexes))
            #
            # Count the children (0 / 1)
            #
            child_count = (label_indexes[1:] > 0).astype(int)
            m.add_measurement(src_name,
                              FF_CHILDREN_COUNT % target_name,
                              child_count)
            #
            # Add an outline if asked to do so
            #
            if wants_outlines:
                outline_image = cpi.Image(outline(target_labels) > 0,
                                          parent_image = target_objects.parent_image)
                workspace.image_set.add(outlines_name, outline_image)

        if self.show_window:
            src_objects = workspace.get_objects(src_name)
            image_names = \
                [image for image in
                 [m.measurement.get_image_name(workspace.pipeline)
                  for m in self.measurements]
                 if image is not None
                 and image in workspace.image_set.get_names()]
            if len(image_names) == 0:
                # Measurement isn't image-based
                if src_objects.has_parent_image:
                    image = src_objects.parent_image.pixel_data
                else:
                    image = None
            else:
                image = workspace.image_set.get_image(image_names[0]).pixel_data

            workspace.display_data.src_objects_segmented = \
                src_objects.segmented
            workspace.display_data.image_names = image_names
            workspace.display_data.image = image
            workspace.display_data.target_objects_segmented = target_objects.segmented
Esempio n. 54
0
 def calculate_minimum_distances(self, workspace, parent_name):
     '''Calculate the distance from child center to parent perimeter'''
     meas = workspace.measurements
     assert isinstance(meas,cpmeas.Measurements)
     sub_object_name = self.sub_object_name.value
     parents = workspace.object_set.get_objects(parent_name)
     children = workspace.object_set.get_objects(sub_object_name)
     parents_of = self.get_parents_of(workspace, parent_name)
     if len(parents_of) == 0:
         dist = np.zeros((0,))
     elif np.all(parents_of == 0):
         dist = np.array([np.NaN] * len(parents_of))
     else:
         mask = parents_of > 0
         ccenters = centers_of_labels(children.segmented).transpose()
         ccenters = ccenters[mask,:]
         parents_of_masked = parents_of[mask] - 1
         pperim = outline(parents.segmented)
         #
         # Get a list of all points on the perimeter
         #
         perim_loc = np.argwhere(pperim != 0)
         #
         # Get the label # for each point
         #
         perim_idx = pperim[perim_loc[:,0],perim_loc[:,1]]
         #
         # Sort the points by label #
         #
         idx = np.lexsort((perim_loc[:,1],perim_loc[:,0],perim_idx))
         perim_loc = perim_loc[idx,:]
         perim_idx = perim_idx[idx]
         #
         # Get counts and indexes to each run of perimeter points
         #
         counts = fix(scind.sum(np.ones(len(perim_idx)),perim_idx,
                                np.arange(1,perim_idx[-1]+1))).astype(np.int32)
         indexes = np.cumsum(counts) - counts
         #
         # For the children, get the index and count of the parent
         #
         ccounts = counts[parents_of_masked]
         cindexes = indexes[parents_of_masked]
         #
         # Now make an array that has an element for each of that child's
         # perimeter points
         #
         clabel = np.zeros(np.sum(ccounts), int)
         #
         # cfirst is the eventual first index of each child in the
         # clabel array
         #
         cfirst = np.cumsum(ccounts) - ccounts
         clabel[cfirst[1:]] += 1
         clabel = np.cumsum(clabel)
         #
         # Make an index that runs from 0 to ccounts for each
         # child label.
         #
         cp_index = np.arange(len(clabel)) - cfirst[clabel]
         #
         # then add cindexes to get an index to the perimeter point
         #
         cp_index += cindexes[clabel]
         #
         # Now, calculate the distance from the centroid of each label
         # to each perimeter point in the parent.
         #
         dist = np.sqrt(np.sum((perim_loc[cp_index,:] - 
                                ccenters[clabel,:])**2,1))
         #
         # Finally, find the minimum distance per child
         #
         min_dist = fix(scind.minimum(dist, clabel, np.arange(len(ccounts))))
         #
         # Account for unparented children
         #
         dist = np.array([np.NaN] * len(mask))
         dist[mask] = min_dist
     meas.add_measurement(sub_object_name, FF_MINIMUM % parent_name, dist)
 def test_02_01_forced_location(self):
     d = D.DefineGrid()
     d.ordering.value = D.NUM_BY_COLUMNS
     #
     # Grid with x spacing = 10, y spacing = 20
     #
     diameter = 6
     gridding =d.build_grid_info(15,25,1,1,25,45,2,2)
     expected = self.make_rectangular_grid(gridding)
     i,j = np.mgrid[0:expected.shape[0],0:expected.shape[1]]
     ispot, jspot = np.mgrid[0:gridding.rows, 0:gridding.columns]
     y_locations = np.zeros(np.max(gridding.spot_table)+1,int)
     y_locations[gridding.spot_table.flatten()] = \
                gridding.y_locations[ispot.flatten()]
     x_locations = np.zeros(np.max(gridding.spot_table)+1,int)
     x_locations[gridding.spot_table.flatten()] =\
                gridding.x_locations[jspot.flatten()]
     idist = (i - y_locations[expected])
     jdist = (j - x_locations[expected])
     expected[idist**2 + jdist**2 > (float(diameter + 1)/2)**2] = 0
     workspace, module = self.make_workspace(gridding)
     self.assertTrue(isinstance(module, I.IdentifyObjectsInGrid))
     module.diameter_choice.value = I.AM_MANUAL
     module.diameter.value = diameter
     module.shape_choice.value = I.SHAPE_CIRCLE_FORCED
     module.wants_outlines.value = True
     module.run(workspace)
     labels = workspace.object_set.get_objects(OUTPUT_OBJECTS_NAME).segmented
     self.assertTrue(np.all(labels == expected[0:labels.shape[0],0:labels.shape[1]]))
     #
     # Check measurements
     #
     m = workspace.measurements
     self.assertTrue(isinstance(m, cpmeas.Measurements))
     xm = m.get_current_measurement(OUTPUT_OBJECTS_NAME, 'Location_Center_X')
     self.assertTrue(np.all(xm == x_locations[1:]))
     ym = m.get_current_measurement(OUTPUT_OBJECTS_NAME, 'Location_Center_Y')
     self.assertTrue(np.all(ym == y_locations[1:]))
     count = m.get_current_image_measurement('Count_%s'%OUTPUT_OBJECTS_NAME)
     self.assertEqual(count, gridding.rows * gridding.columns)
     
     columns = module.get_measurement_columns(workspace.pipeline)
     self.assertEqual(len(columns), 4)
     count_feature = 'Count_%s'%OUTPUT_OBJECTS_NAME
     self.assertTrue(all([column[0] == ("Image" if column[1] == count_feature
                                        else OUTPUT_OBJECTS_NAME)
                          for column in columns]))
     self.assertTrue(all([column[1] in ('Location_Center_X','Location_Center_Y', count_feature,'Number_Object_Number')
                          for column in columns]))
     #
     # Check the outlines
     #
     outlines = workspace.image_set.get_image(OUTLINES_NAME)
     outlines = outlines.pixel_data
     expected_outlines = outline(expected)
     self.assertTrue(np.all(outlines == (expected_outlines[0:outlines.shape[0],0:outlines.shape[1]]>0)))
     #
     # Check the measurements
     #
     categories = list(module.get_categories(None, OUTPUT_OBJECTS_NAME))
     self.assertEqual(len(categories), 2)
     categories.sort()
     self.assertEqual(categories[0], "Location")
     self.assertEqual(categories[1], "Number")
     categories = module.get_categories(None, cpmeas.IMAGE)
     self.assertEqual(len(categories), 1)
     self.assertEqual(categories[0], "Count")
     measurements = module.get_measurements(None, cpmeas.IMAGE, "Count")
     self.assertEqual(len(measurements), 1)
     self.assertEqual(measurements[0], OUTPUT_OBJECTS_NAME)
     measurements = module.get_measurements(None, OUTPUT_OBJECTS_NAME, "Location")
     self.assertEqual(len(measurements), 2)
     self.assertTrue(all(m in ('Center_X','Center_Y') for m in measurements))
     self.assertTrue('Center_X' in measurements)
     self.assertTrue('Center_Y' in measurements)
     measurements = module.get_measurements(None, OUTPUT_OBJECTS_NAME, "Number")
     self.assertEqual(len(measurements),1)
     self.assertEqual(measurements[0], "Object_Number")
    def run(self, workspace):
        """Run the module on the current data set
        
        workspace - has the current image set, object set, measurements
                    and the parent frame for the application if the module
                    is allowed to display. If the module should not display,
                    workspace.frame is None.
        """
        #
        # The object set holds "objects". Each of these is a container
        # for holding up to three kinds of image labels.
        #
        object_set = workspace.object_set
        #
        # Get the primary objects (the centers to be removed).
        # Get the string value out of primary_object_name.
        #
        primary_objects = object_set.get_objects(self.primary_objects_name.value)
        #
        # Get the cleaned-up labels image
        #
        primary_labels = primary_objects.segmented
        #
        # Do the same with the secondary object
        secondary_objects = object_set.get_objects(self.secondary_objects_name.value)
        secondary_labels = secondary_objects.segmented
        #
        # If one of the two label images is smaller than the other, we
        # try to find the cropping mask and we apply that mask to the larger
        #
        try:
            if any([p_size < s_size 
                    for p_size,s_size
                    in zip(primary_labels.shape, secondary_labels.shape)]):
                #
                # Look for a cropping mask associated with the primary_labels
                # and apply that mask to resize the secondary labels
                #
                secondary_labels = primary_objects.crop_image_similarly(secondary_labels)
                tertiary_image = primary_objects.parent_image
            elif any([p_size > s_size 
                    for p_size,s_size
                    in zip(primary_labels.shape, secondary_labels.shape)]):
                primary_labels = secondary_objects.crop_image_similarly(primary_labels)
                tertiary_image = secondary_objects.parent_image
            elif secondary_objects.parent_image is not None:
                tertiary_image = secondary_objects.parent_image
            else:
                tertiary_image = primary_objects.parent_image
        except ValueError:
            # No suitable cropping - resize all to fit the secondary
            # labels which are the most critical.
            #
            primary_labels, _ = cpo.size_similarly(secondary_labels, primary_labels)
            if secondary_objects.parent_image is not None:
                tertiary_image = secondary_objects.parent_image
            else:
                tertiary_image = primary_objects.parent_image
                if tertiary_image is not None:
                    tertiary_image, _ = cpo.size_similarly(secondary_labels, tertiary_image)
        #
        # Find the outlines of the primary image and use this to shrink the
        # primary image by one. This guarantees that there is something left
        # of the secondary image after subtraction
        #
        primary_outline = outline(primary_labels)
        tertiary_labels = secondary_labels.copy()
        if self.shrink_primary:
            primary_mask = np.logical_or(primary_labels == 0,
                                         primary_outline)
        else:
            primary_mask = primary_labels == 0
        tertiary_labels[primary_mask == False] = 0
        #
        # Get the outlines of the tertiary image
        #
        tertiary_outlines = outline(tertiary_labels)!=0
        #
        # Make the tertiary objects container
        #
        tertiary_objects = cpo.Objects()
        tertiary_objects.segmented = tertiary_labels
        tertiary_objects.parent_image = tertiary_image
        #
        # Relate tertiary objects to their parents & record
        #
        child_count_of_secondary, secondary_parents = \
            secondary_objects.relate_children(tertiary_objects)
        if self.shrink_primary:
            child_count_of_primary, primary_parents = \
                primary_objects.relate_children(tertiary_objects)
        else:
            # Primary and tertiary don't overlap.
            # Establish overlap between primary and secondary and commute
            _, secondary_of_primary = \
                secondary_objects.relate_children(primary_objects)
            mask = secondary_of_primary != 0
            child_count_of_primary = np.zeros(mask.shape, int)
            child_count_of_primary[mask] = child_count_of_secondary[
                secondary_of_primary[mask] - 1]
            primary_parents = np.zeros(secondary_parents.shape, 
                                       secondary_parents.dtype)
            primary_of_secondary = np.zeros(secondary_objects.count+1, int)
            primary_of_secondary[secondary_of_primary] = \
                np.arange(1, len(secondary_of_primary)+1)
            primary_of_secondary[0] = 0
            primary_parents = primary_of_secondary[secondary_parents]
        #
        # Write out the objects
        #
        workspace.object_set.add_objects(tertiary_objects,
                                         self.subregion_objects_name.value)
        #
        # Write out the measurements
        #
        m = workspace.measurements
        #
        # The parent/child associations
        #
        for parent_objects_name, parents_of, child_count, relationship in (
            (self.primary_objects_name, primary_parents, 
             child_count_of_primary, R_REMOVED),
            (self.secondary_objects_name, secondary_parents, 
             child_count_of_secondary, R_PARENT)):
            m.add_measurement(self.subregion_objects_name.value,
                              cpmi.FF_PARENT%(parent_objects_name.value),
                              parents_of)
            m.add_measurement(parent_objects_name.value,
                              cpmi.FF_CHILDREN_COUNT%(self.subregion_objects_name.value),
                              child_count)
            mask = parents_of != 0
            image_number = np.ones(np.sum(mask), int) * m.image_set_number
            child_object_number = np.argwhere(mask).flatten() + 1
            parent_object_number = parents_of[mask]
            m.add_relate_measurement(
                self.module_num, relationship,
                parent_objects_name.value, self.subregion_objects_name.value,
                image_number, parent_object_number,
                image_number, child_object_number)
            
        object_count = tertiary_objects.count
        #
        # The object count
        #
        cpmi.add_object_count_measurements(workspace.measurements,
                                           self.subregion_objects_name.value,
                                           object_count)
        #
        # The object locations
        #
        cpmi.add_object_location_measurements(workspace.measurements,
                                              self.subregion_objects_name.value,
                                              tertiary_labels)
        #
        # The outlines
        #
        if self.use_outlines.value:
            out_img = cpi.Image(tertiary_outlines.astype(bool),
                                parent_image = tertiary_image)
            workspace.image_set.add(self.outlines_name.value, out_img)

        if self.show_window:
            workspace.display_data.primary_labels = primary_labels
            workspace.display_data.secondary_labels = secondary_labels
            workspace.display_data.tertiary_labels = tertiary_labels
            workspace.display_data.tertiary_outlines = tertiary_outlines
    def run(self, workspace):
        """Run the module
        
        workspace    - The workspace contains
            pipeline     - instance of cpp for this run
            image_set    - the images in the image set being processed
            object_set   - the objects (labeled masks) in this image set
            measurements - the measurements for this run
            frame        - the parent frame to whatever frame is created. None means don't draw.
        """
        orig_objects_name = self.object_name.value
        filtered_objects_name = self.filtered_objects.value
        
        orig_objects = workspace.object_set.get_objects(orig_objects_name)
        assert isinstance(orig_objects, cpo.Objects)
        orig_labels = [l for l, c in orig_objects.get_labels()]

        if self.wants_image_display:
            guide_image = workspace.image_set.get_image(self.image_name.value)
            guide_image = guide_image.pixel_data
            if np.any(guide_image != np.min(guide_image)):
                guide_image = (guide_image - np.min(guide_image)) / (np.max(guide_image) - np.min(guide_image))
        else:
            guide_image = None
        filtered_labels = workspace.interaction_request(
            self, orig_labels, guide_image, workspace.measurements.image_set_number)
        if filtered_labels is None:
            # Ask whoever is listening to stop doing stuff
            workspace.cancel_request()
            # Have to soldier on until the cancel takes effect...
            filtered_labels = orig_labels
        #
        # Renumber objects consecutively if asked to do so
        #
        unique_labels = np.unique(np.array(filtered_labels))
        unique_labels = unique_labels[unique_labels != 0]
        object_count = len(unique_labels)
        if self.renumber_choice == R_RENUMBER:
            mapping = np.zeros(1 if len(unique_labels) == 0 else np.max(unique_labels)+1, int)
            mapping[unique_labels] = np.arange(1,object_count + 1)
            filtered_labels = [mapping[l] for l in filtered_labels]
        #
        # Make the objects out of the labels
        #
        filtered_objects = cpo.Objects()
        i, j = np.mgrid[0:filtered_labels[0].shape[0],
                        0:filtered_labels[0].shape[1]]
        ijv = np.zeros((0, 3), filtered_labels[0].dtype)
        for l in filtered_labels:
            ijv = np.vstack((ijv,
                             np.column_stack((i[l != 0],
                                              j[l != 0],
                                              l[l != 0]))))
        filtered_objects.set_ijv(ijv, orig_labels[0].shape)
        if orig_objects.has_unedited_segmented():
            filtered_objects.unedited_segmented = orig_objects.unedited_segmented
        if orig_objects.parent_image is not None:
            filtered_objects.parent_image = orig_objects.parent_image
        workspace.object_set.add_objects(filtered_objects, 
                                         filtered_objects_name)
        #
        # Add parent/child & other measurements
        #
        m = workspace.measurements
        child_count, parents = orig_objects.relate_children(filtered_objects)
        m.add_measurement(filtered_objects_name,
                          I.FF_PARENT%(orig_objects_name),
                          parents)
        m.add_measurement(orig_objects_name,
                          I.FF_CHILDREN_COUNT%(filtered_objects_name),
                          child_count)
        #
        # The object count
        #
        I.add_object_count_measurements(m, filtered_objects_name,
                                        object_count)
        #
        # The object locations
        #
        I.add_object_location_measurements_ijv(m, filtered_objects_name, ijv)
        #
        # Outlines if we want them
        #
        if self.wants_outlines:
            outlines_name = self.outlines_name.value
            outlines = outline(filtered_labels[0]).astype(bool)
            outlines_image = cpi.Image(outlines)
            workspace.image_set.add(outlines_name, outlines_image)

        workspace.display_data.orig_ijv = orig_objects.ijv
        workspace.display_data.filtered_ijv = filtered_objects.ijv
        workspace.display_data.shape = orig_labels[0].shape
    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