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)]]
 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)
     ]]
Exemple #3
0
    def display(self, workspace, figure):
        """Create an informative display for the module"""
        import matplotlib

        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
        #
        outlines = outline(original_labels) > 0

        cm = figure.return_cmap()
        sm = matplotlib.cm.ScalarMappable(cmap=cm)
        #
        # Paint the labels in color
        #
        image = sm.to_rgba(final_labels, norm=False)[:, :, :3]
        image[final_labels == 0, :] = 0
        #
        # Make the mask a dark gray
        #
        image[(final_labels == 0) & mask, :] = 0.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()[0:3], float) / 255)
        final_color = np.array(cpprefs.get_primary_outline_color()[0:3],
                               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,
            colormap=sm,
        )
        figure.subplot_imshow_color(
            1,
            0,
            image,
            title=self.remaining_objects.value,
            sharexy=figure.subplot(0, 0),
            colormap=sm,
        )
Exemple #4
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.set_ijv(np.column_stack((i, j, v)), ii.shape)
        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 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 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)
Exemple #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 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)
 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))
Exemple #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.set_ijv(np.column_stack((i, j, v)), ii.shape)
        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)
Exemple #11
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)
Exemple #12
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 self.show_window:
            workspace.display_data.input_objects_segmented = input_objects.segmented
            workspace.display_data.output_objects_segmented = output_objects.segmented
Exemple #13
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))
Exemple #14
0
    def display(self, workspace, figure):
        '''Create an informative display for the module'''
        import matplotlib
        from cellprofiler.gui.tools 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))
 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))
Exemple #16
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))
Exemple #17
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))
Exemple #18
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_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.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)]]
Exemple #21
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))
Exemple #22
0
 def test_01_01_single(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],
     ])
     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],
     ])
     result = OL.outline(x)
     self.assertTrue(numpy.all(result == e))
Exemple #23
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
Exemple #24
0
 def test_02_05_diagonal(self):
     x = numpy.array([
         [0, 0, 0, 0, 0, 0, 0],
         [0, 0, 1, 1, 1, 0, 0],
         [0, 1, 1, 1, 1, 0, 0],
         [0, 1, 1, 1, 1, 0, 0],
         [0, 0, 1, 1, 0, 0, 0],
     ])
     e = numpy.array([
         [0, 0, 0, 0, 0, 0, 0],
         [0, 0, 1, 1, 1, 0, 0],
         [0, 1, 1, 0, 1, 0, 0],
         [0, 1, 1, 1, 1, 0, 0],
         [0, 0, 1, 1, 0, 0, 0],
     ])
     result = OL.outline(x)
     self.assertTrue(numpy.all(result == e))
Exemple #25
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 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
    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 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 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)
        if self.show_window:
            workspace.display_data.gridding = gridding
            workspace.display_data.labels = labels
    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)
        if self.show_window:
            workspace.display_data.gridding = gridding
            workspace.display_data.labels = labels
    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.tools 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
Exemple #35
0
 def test_00_00_zeros(self):
     x = numpy.zeros((10, 10), int)
     result = OL.outline(x)
     self.assertTrue(numpy.all(x == result))
Exemple #36
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),
                            )
                        )
 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")
Exemple #39
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 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 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)
Exemple #42
0
    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
        
        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)
        nkept_objects = objects.count
        nneighbors = np.max(neighbor_labels)
        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
            neighbor_has_pixels = has_pixels
        else:
            _, neighbor_numbers = neighbor_objects.relate_labels(
                neighbor_labels, neighbor_objects.segmented)
            neighbor_has_pixels = np.bincount(neighbor_labels.ravel())[1:] > 0
        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[:, ~neighbor_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 order.shape[1] > 1:
                        second_object_number[has_pixels] = order[has_pixels,
                                                                 1] + 1
        else:
            object_indexes = object_numbers - 1
            neighbor_indexes = neighbor_numbers - 1
            first_objects = np.zeros(0, int)
            second_objects = np.zeros(0, int)
        #
        # Now convert all measurements from the small-removed to
        # the final number set.
        #
        neighbor_count = neighbor_count[object_indexes]
        neighbor_count[~has_pixels] = 0
        percent_touching = percent_touching[object_indexes]
        percent_touching[~has_pixels] = 0
        first_x_vector = first_x_vector[object_indexes]
        second_x_vector = second_x_vector[object_indexes]
        first_y_vector = first_y_vector[object_indexes]
        second_y_vector = second_y_vector[object_indexes]
        angle = angle[object_indexes]
        #
        # Record the measurements
        #
        assert (isinstance(workspace, cpw.Workspace))
        m = workspace.measurements
        assert (isinstance(m, cpmeas.Measurements))
        image_set = workspace.image_set
        features_and_data = [
            (M_NUMBER_OF_NEIGHBORS, neighbor_count),
            (M_FIRST_CLOSEST_OBJECT_NUMBER, first_object_number),
            (M_FIRST_CLOSEST_DISTANCE,
             np.sqrt(first_x_vector**2 + first_y_vector**2)),
            (M_SECOND_CLOSEST_OBJECT_NUMBER, second_object_number),
            (M_SECOND_CLOSEST_DISTANCE,
             np.sqrt(second_x_vector**2 + second_y_vector**2)),
            (M_ANGLE_BETWEEN_NEIGHBORS, angle)
        ]
        if self.neighbors_are_objects:
            features_and_data.append((M_PERCENT_TOUCHING, percent_touching))
        for feature_name, data in features_and_data:
            m.add_measurement(self.object_name.value,
                              self.get_measurement_name(feature_name), data)
        if len(first_objects) > 0:
            m.add_relate_measurement(
                self.module_num, cpmeas.NEIGHBORS, self.object_name.value,
                self.object_name.value
                if self.neighbors_are_objects else self.neighbors_name.value,
                m.image_set_number * np.ones(first_objects.shape, int),
                first_objects,
                m.image_set_number * np.ones(second_objects.shape, int),
                second_objects)

        labels = kept_labels

        neighbor_count_image = np.zeros(labels.shape, int)
        object_mask = objects.segmented != 0
        object_indexes = objects.segmented[object_mask] - 1
        neighbor_count_image[object_mask] = neighbor_count[object_indexes]
        workspace.display_data.neighbor_count_image = neighbor_count_image

        if self.neighbors_are_objects:
            percent_touching_image = np.zeros(labels.shape)
            percent_touching_image[object_mask] = percent_touching[
                object_indexes]
            workspace.display_data.percent_touching_image = percent_touching_image

        image_set = workspace.image_set
        if self.wants_count_image.value:
            neighbor_cm_name = self.count_colormap.value
            neighbor_cm = get_colormap(neighbor_cm_name)
            sm = matplotlib.cm.ScalarMappable(cmap=neighbor_cm)
            img = sm.to_rgba(neighbor_count_image)[:, :, :3]
            img[:, :, 0][~object_mask] = 0
            img[:, :, 1][~object_mask] = 0
            img[:, :, 2][~object_mask] = 0
            count_image = cpi.Image(img, masking_objects=objects)
            image_set.add(self.count_image_name.value, count_image)
        else:
            neighbor_cm_name = cpprefs.get_default_colormap()
            neighbor_cm = matplotlib.cm.get_cmap(neighbor_cm_name)
        if self.neighbors_are_objects and self.wants_percent_touching_image:
            percent_touching_cm_name = self.touching_colormap.value
            percent_touching_cm = get_colormap(percent_touching_cm_name)
            sm = matplotlib.cm.ScalarMappable(cmap=percent_touching_cm)
            img = sm.to_rgba(percent_touching_image)[:, :, :3]
            img[:, :, 0][~object_mask] = 0
            img[:, :, 1][~object_mask] = 0
            img[:, :, 2][~object_mask] = 0
            touching_image = cpi.Image(img, masking_objects=objects)
            image_set.add(self.touching_image_name.value, touching_image)
        else:
            percent_touching_cm_name = cpprefs.get_default_colormap()
            percent_touching_cm = matplotlib.cm.get_cmap(
                percent_touching_cm_name)

        if self.show_window:
            workspace.display_data.neighbor_cm_name = neighbor_cm_name
            workspace.display_data.percent_touching_cm_name = percent_touching_cm_name
            workspace.display_data.orig_labels = objects.segmented
            workspace.display_data.expanded_labels = expanded_labels
            workspace.display_data.object_mask = object_mask
    def run(self, workspace):
        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):
        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)
        nkept_objects = objects.count
        nneighbors = np.max(neighbor_labels)
        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]]
        
        neighbor_has_pixels = np.bincount(neighbor_labels.ravel())[1:] > 0
        
        _, 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[:, ~neighbor_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 order.shape[1] > 1:
                        second_object_number[has_pixels] = order[has_pixels,1] + 1
        else:
            object_indexes = object_numbers - 1
            neighbor_indexes = neighbor_numbers - 1
            first_objects = np.zeros(0, int)
            second_objects = np.zeros(0, int)
        #
        # Now convert all measurements from the small-removed to
        # the final number set.
        #
        neighbor_count = neighbor_count[object_indexes]
        neighbor_count[~ has_pixels] = 0
        percent_touching = percent_touching[object_indexes]
        percent_touching[~ has_pixels] = 0
        first_x_vector = first_x_vector[object_indexes]
        second_x_vector = second_x_vector[object_indexes]
        first_y_vector = first_y_vector[object_indexes]
        second_y_vector = second_y_vector[object_indexes]
        angle = angle[object_indexes]
        #
        # Record the measurements
        #
        assert(isinstance(workspace, cpw.Workspace))
        m = workspace.measurements
        assert(isinstance(m, cpmeas.Measurements))
        image_set = workspace.image_set
        features_and_data = [
            (M_NUMBER_OF_NEIGHBORS, neighbor_count),
            (M_FIRST_CLOSEST_OBJECT_NUMBER, first_object_number),
            (M_FIRST_CLOSEST_DISTANCE, np.sqrt(first_x_vector**2+first_y_vector**2)),
            (M_SECOND_CLOSEST_OBJECT_NUMBER, second_object_number),
            (M_SECOND_CLOSEST_DISTANCE, np.sqrt(second_x_vector**2+second_y_vector**2)),
            (M_ANGLE_BETWEEN_NEIGHBORS, angle)]
        if self.neighbors_are_objects:
            features_and_data.append((M_PERCENT_TOUCHING, percent_touching))
        for feature_name, data in features_and_data:
            m.add_measurement(self.object_name.value,
                              self.get_measurement_name(feature_name),
                              data)
        if len(first_objects) > 0:
            m.add_relate_measurement(
                self.module_num, 
                cpmeas.NEIGHBORS,
                self.object_name.value,
                self.object_name.value if self.neighbors_are_objects 
                else self.neighbors_name.value,
                m.image_set_number * np.ones(first_objects.shape, int),
                first_objects,
                m.image_set_number * np.ones(second_objects.shape, int),
                second_objects)
                                 
        labels = kept_labels
        
        neighbor_count_image = np.zeros(labels.shape,int)
        object_mask = objects.segmented != 0
        object_indexes = objects.segmented[object_mask]-1
        neighbor_count_image[object_mask] = neighbor_count[object_indexes]
        workspace.display_data.neighbor_count_image = neighbor_count_image
        
        if self.neighbors_are_objects:
            percent_touching_image = np.zeros(labels.shape)
            percent_touching_image[object_mask] = percent_touching[object_indexes]
            workspace.display_data.percent_touching_image = percent_touching_image
        
        image_set = workspace.image_set
        if self.wants_count_image.value:
            neighbor_cm_name = self.count_colormap.value
            neighbor_cm = get_colormap(neighbor_cm_name)
            sm = matplotlib.cm.ScalarMappable(cmap = neighbor_cm)
            img = sm.to_rgba(neighbor_count_image)[:,:,:3]
            img[:,:,0][~ object_mask] = 0
            img[:,:,1][~ object_mask] = 0
            img[:,:,2][~ object_mask] = 0
            count_image = cpi.Image(img, masking_objects = objects)
            image_set.add(self.count_image_name.value, count_image)
        else:
            neighbor_cm_name = cpprefs.get_default_colormap()
            neighbor_cm = matplotlib.cm.get_cmap(neighbor_cm_name)
        if self.neighbors_are_objects and self.wants_percent_touching_image:
            percent_touching_cm_name = self.touching_colormap.value
            percent_touching_cm = get_colormap(percent_touching_cm_name)
            sm = matplotlib.cm.ScalarMappable(cmap = percent_touching_cm)
            img = sm.to_rgba(percent_touching_image)[:,:,:3]
            img[:,:,0][~ object_mask] = 0
            img[:,:,1][~ object_mask] = 0
            img[:,:,2][~ object_mask] = 0
            touching_image = cpi.Image(img, masking_objects = objects)
            image_set.add(self.touching_image_name.value,
                          touching_image)
        else:
            percent_touching_cm_name = cpprefs.get_default_colormap()
            percent_touching_cm = matplotlib.cm.get_cmap(percent_touching_cm_name)

        if self.show_window:
            workspace.display_data.neighbor_cm_name = neighbor_cm_name
            workspace.display_data.percent_touching_cm_name = percent_touching_cm_name
            workspace.display_data.orig_labels = objects.segmented
            workspace.display_data.expanded_labels = expanded_labels
            workspace.display_data.object_mask = object_mask
    def run(self, workspace):
        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
Exemple #48
0
    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", "channel", "Object",
                                                 "Feature", "Mean", "Median",
                                                 "STD")
            workspace.display_data.statistics = statistics = []
        for im in self.images:
            image_name = im.name
            image = workspace.image_set.get_image(image_name.value,
                                                  must_be_grayscale=False)
            nchan = im.nchannels.value
            for channel in range(nchan):
                for object_name in [obj.name for obj in self.objects]:
                    # Need to refresh image after each iteration...
                    if nchan == 1:
                        img = image.pixel_data.copy()
                    else:
                        img = image.pixel_data[:, :, channel].squeeze().copy()
                    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_c%s" % (
                            category, feature_name, image_name.value,
                            str(channel + 1))
                        m.add_measurement(object_name.value, measurement_name,
                                          measurement)
                        if self.show_window and len(measurement) > 0:
                            statistics.append(
                                (image_name.value, 'c' + str(channel + 1),
                                 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):
        """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,
                cellprofiler.measurement.FF_PARENT % parent_objects_name.value,
                parents_of)
            m.add_measurement(
                parent_objects_name.value,
                cellprofiler.measurement.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)

        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 test_00_00_zeros(self):
     x = numpy.zeros((10,10),int)
     result = OL.outline(x)
     self.assertTrue(numpy.all(x==result))
Exemple #52
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
Exemple #53
0
    def run(self, workspace):
        objects = workspace.object_set.get_objects(self.object_name.value)
        dimensions = len(objects.shape)
        assert isinstance(objects, 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)
        neighbor_labels = neighbor_objects.small_removed_segmented
        neighbor_kept_labels = neighbor_objects.segmented
        assert isinstance(neighbor_objects, Objects)
        if not self.wants_excluded_objects.value:
            # Remove labels not present in kept segmentation while preserving object IDs.
            mask = neighbor_kept_labels > 0
            neighbor_labels[~mask] = 0
        nobjects = numpy.max(labels)
        nkept_objects = len(objects.indices)
        nneighbors = numpy.max(neighbor_labels)

        _, object_numbers = objects.relate_labels(labels, kept_labels)
        if self.neighbors_are_objects:
            neighbor_numbers = object_numbers
            neighbor_has_pixels = has_pixels
        else:
            _, neighbor_numbers = neighbor_objects.relate_labels(
                neighbor_labels, neighbor_objects.small_removed_segmented)
            neighbor_has_pixels = numpy.bincount(
                neighbor_labels.ravel())[1:] > 0
        neighbor_count = numpy.zeros((nobjects, ))
        pixel_count = numpy.zeros((nobjects, ))
        first_object_number = numpy.zeros((nobjects, ), int)
        second_object_number = numpy.zeros((nobjects, ), int)
        first_x_vector = numpy.zeros((nobjects, ))
        second_x_vector = numpy.zeros((nobjects, ))
        first_y_vector = numpy.zeros((nobjects, ))
        second_y_vector = numpy.zeros((nobjects, ))
        angle = numpy.zeros((nobjects, ))
        percent_touching = numpy.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
            if dimensions == 2:
                i, j = scipy.ndimage.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]
            else:
                k, i, j = scipy.ndimage.distance_transform_edt(
                    labels == 0, return_distances=False, return_indices=True)
                labels = labels[k, 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 = numpy.arange(nobjects, dtype=numpy.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(
                scipy.ndimage.sum(numpy.ones(labels.shape), labels,
                                  object_indexes))
            perimeter_outlines = outline(labels)
            perimeters = fix(
                scipy.ndimage.sum(numpy.ones(labels.shape), perimeter_outlines,
                                  object_indexes))

            #
            # order[:,0] should be arange(nobjects)
            # order[:,1] should be the nearest neighbor
            # order[:,2] should be the next nearest neighbor
            #
            order = numpy.zeros((nobjects, min(nneighbors, 3)),
                                dtype=numpy.uint32)
            j = numpy.arange(nneighbors)
            # (0, 1, 2) unless there are less than 3 neighbors
            partition_keys = tuple(range(min(nneighbors, 3)))
            for i in range(nobjects):
                dr = numpy.sqrt((ocenters[i, 0] - ncenters[j, 0])**2 +
                                (ocenters[i, 1] - ncenters[j, 1])**2)
                order[i, :] = numpy.argpartition(dr, partition_keys)[:3]

            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 = numpy.array((first_x_vector, first_y_vector))
                v2 = numpy.array((second_x_vector, second_y_vector))
                #
                # Project the unit vector v1 against the unit vector v2
                #
                dot = numpy.sum(v1 * v2, 0) / numpy.sqrt(
                    numpy.sum(v1**2, 0) * numpy.sum(v2**2, 0))
                angle = numpy.arccos(dot) * 180.0 / numpy.pi

            # Make the structuring element for dilation
            if dimensions == 2:
                strel = strel_disk(distance)
            else:
                strel = skimage.morphology.ball(distance)
            #
            # A little bigger one to enter into the border with a structure
            # that mimics the one used to create the outline
            #
            if dimensions == 2:
                strel_touching = strel_disk(distance + 0.5)
            else:
                strel_touching = skimage.morphology.ball(distance + 0.5)
            #
            # Get the extents for each object and calculate the patch
            # that excises the part of the image that is "distance"
            # away
            if dimensions == 2:
                i, j = numpy.mgrid[0:labels.shape[0], 0:labels.shape[1]]

                minimums_i, maximums_i, _, _ = scipy.ndimage.extrema(
                    i, labels, object_indexes)
                minimums_j, maximums_j, _, _ = scipy.ndimage.extrema(
                    j, labels, object_indexes)

                minimums_i = numpy.maximum(fix(minimums_i) - distance,
                                           0).astype(int)
                maximums_i = numpy.minimum(
                    fix(maximums_i) + distance + 1,
                    labels.shape[0]).astype(int)
                minimums_j = numpy.maximum(fix(minimums_j) - distance,
                                           0).astype(int)
                maximums_j = numpy.minimum(
                    fix(maximums_j) + distance + 1,
                    labels.shape[1]).astype(int)
            else:
                k, i, j = numpy.mgrid[0:labels.shape[0], 0:labels.shape[1],
                                      0:labels.shape[2]]

                minimums_k, maximums_k, _, _ = scipy.ndimage.extrema(
                    k, labels, object_indexes)
                minimums_i, maximums_i, _, _ = scipy.ndimage.extrema(
                    i, labels, object_indexes)
                minimums_j, maximums_j, _, _ = scipy.ndimage.extrema(
                    j, labels, object_indexes)

                minimums_k = numpy.maximum(fix(minimums_k) - distance,
                                           0).astype(int)
                maximums_k = numpy.minimum(
                    fix(maximums_k) + distance + 1,
                    labels.shape[0]).astype(int)
                minimums_i = numpy.maximum(fix(minimums_i) - distance,
                                           0).astype(int)
                maximums_i = numpy.minimum(
                    fix(maximums_i) + distance + 1,
                    labels.shape[1]).astype(int)
                minimums_j = numpy.maximum(fix(minimums_j) - distance,
                                           0).astype(int)
                maximums_j = numpy.minimum(
                    fix(maximums_j) + distance + 1,
                    labels.shape[2]).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
                if dimensions == 2:
                    patch = labels[minimums_i[index]:maximums_i[index],
                                   minimums_j[index]:maximums_j[index], ]
                    npatch = neighbor_labels[
                        minimums_i[index]:maximums_i[index],
                        minimums_j[index]:maximums_j[index], ]
                else:
                    patch = labels[minimums_k[index]:maximums_k[index],
                                   minimums_i[index]:maximums_i[index],
                                   minimums_j[index]:maximums_j[index], ]
                    npatch = neighbor_labels[
                        minimums_k[index]:maximums_k[index],
                        minimums_i[index]:maximums_i[index],
                        minimums_j[index]:maximums_j[index], ]

                #
                # Find the neighbors
                #
                patch_mask = patch == (index + 1)
                if distance <= 5:
                    extended = scipy.ndimage.binary_dilation(patch_mask, strel)
                else:
                    extended = (scipy.signal.fftconvolve(
                        patch_mask, strel, mode="same") > 0.5)
                neighbors = numpy.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(numpy.ones(nc, int) * object_number)
                    second_objects.append(neighbors)
                #
                # 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.
                #
                if dimensions == 2:
                    outline_patch = (perimeter_outlines[
                        minimums_i[index]:maximums_i[index],
                        minimums_j[index]:maximums_j[index], ] == object_number
                                     )
                else:
                    outline_patch = (perimeter_outlines[
                        minimums_k[index]:maximums_k[index],
                        minimums_i[index]:maximums_i[index],
                        minimums_j[index]:maximums_j[index], ] == object_number
                                     )
                if self.neighbors_are_objects:
                    extendme = (patch != 0) & (patch != object_number)
                    if distance <= 5:
                        extended = scipy.ndimage.binary_dilation(
                            extendme, strel_touching)
                    else:
                        extended = (scipy.signal.fftconvolve(
                            extendme, strel_touching, mode="same") > 0.5)
                else:
                    if distance <= 5:
                        extended = scipy.ndimage.binary_dilation(
                            (npatch != 0), strel_touching)
                    else:
                        extended = (scipy.signal.fftconvolve(
                            (npatch != 0), strel_touching, mode="same") > 0.5)
                overlap = numpy.sum(outline_patch & extended)
                pixel_count[index] = overlap
            if sum([len(x) for x in first_objects]) > 0:
                first_objects = numpy.hstack(first_objects)
                reverse_object_numbers = numpy.zeros(
                    max(numpy.max(object_numbers), numpy.max(first_objects)) +
                    1, int)
                reverse_object_numbers[object_numbers] = (
                    numpy.arange(len(object_numbers)) + 1)
                first_objects = reverse_object_numbers[first_objects]

                second_objects = numpy.hstack(second_objects)
                reverse_neighbor_numbers = numpy.zeros(
                    max(numpy.max(neighbor_numbers), numpy.max(second_objects))
                    + 1, int)
                reverse_neighbor_numbers[neighbor_numbers] = (
                    numpy.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 = numpy.zeros(0, int)
                second_objects = numpy.zeros(0, int)
            percent_touching = pixel_count * 100 / perimeters
            object_indexes = object_numbers - 1
            neighbor_indexes = neighbor_numbers - 1
            #
            # Have to recompute nearest
            #
            first_object_number = numpy.zeros(nkept_objects, int)
            second_object_number = numpy.zeros(nkept_objects, int)
            if nkept_objects > (1 if self.neighbors_are_objects else 0):
                di = (ocenters[object_indexes[:, numpy.newaxis], 0] -
                      ncenters[neighbor_indexes[numpy.newaxis, :], 0])
                dj = (ocenters[object_indexes[:, numpy.newaxis], 1] -
                      ncenters[neighbor_indexes[numpy.newaxis, :], 1])
                distance_matrix = numpy.sqrt(di * di + dj * dj)
                distance_matrix[~has_pixels, :] = numpy.inf
                distance_matrix[:, ~neighbor_has_pixels] = numpy.inf
                #
                # order[:,0] should be arange(nobjects)
                # order[:,1] should be the nearest neighbor
                # order[:,2] should be the next nearest neighbor
                #
                order = numpy.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 order.shape[1] > 1:
                        second_object_number[has_pixels] = order[has_pixels,
                                                                 1] + 1
        else:
            object_indexes = object_numbers - 1
            neighbor_indexes = neighbor_numbers - 1
            first_objects = numpy.zeros(0, int)
            second_objects = numpy.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, Workspace)
        m = workspace.measurements
        assert isinstance(m, 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,
                numpy.sqrt(first_x_vector**2 + first_y_vector**2),
            ),
            (M_SECOND_CLOSEST_OBJECT_NUMBER, second_object_number),
            (
                M_SECOND_CLOSEST_DISTANCE,
                numpy.sqrt(second_x_vector**2 + second_y_vector**2),
            ),
            (M_ANGLE_BETWEEN_NEIGHBORS, angle),
            (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,
                NEIGHBORS,
                self.object_name.value,
                self.object_name.value
                if self.neighbors_are_objects else self.neighbors_name.value,
                m.image_set_number * numpy.ones(first_objects.shape, int),
                first_objects,
                m.image_set_number * numpy.ones(second_objects.shape, int),
                second_objects,
            )

        labels = kept_labels

        neighbor_count_image = numpy.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

        percent_touching_image = numpy.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 = Image(img, masking_objects=objects)
            image_set.add(self.count_image_name.value, count_image)
        else:
            neighbor_cm_name = "Blues"
            neighbor_cm = matplotlib.cm.get_cmap(neighbor_cm_name)
        if 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 = Image(img, masking_objects=objects)
            image_set.add(self.touching_image_name.value, touching_image)
        else:
            percent_touching_cm_name = "Oranges"
            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.neighbor_labels = neighbor_labels
            workspace.display_data.expanded_labels = expanded_labels
            workspace.display_data.object_mask = object_mask
            workspace.display_data.dimensions = dimensions