//  [python]
def trace_segments(self, segments_binary):
        """Find distance of every point in a segment from a segment endpoint

        segments_binary - a binary mask of the segments in an image.

        returns a tuple of the following:
        i - the i coordinate of a point in the mask
        j - the j coordinate of a point in the mask
        label - the segment's label
        order - the ordering (from 0 to N-1 where N is the # of points in
                the segment.)
        distance - the propagation distance of the point from the endpoint
        num_segments - the # of labelled segments
        """
        #
        # Break long skeletons into pieces whose maximum length
        # is max_skel_length.
        #
        segments_labeled, num_segments = scipy.ndimage.label(
            segments_binary, structure=centrosome.cpmorphology.eight_connect
        )
        if num_segments == 0:
            return (
                numpy.array([], int),
                numpy.array([], int),
                numpy.array([], int),
                numpy.array([], int),
                numpy.array([]),
                0,
            )
        #
        # Get one endpoint per segment
        #
        endpoints = centrosome.cpmorphology.endpoints(segments_binary)
        #
        # Use a consistent order: pick with lowest i, then j.
        # If a segment loops upon itself, we pick an arbitrary point.
        #
        order = numpy.arange(numpy.prod(segments_binary.shape))
        order.shape = segments_binary.shape
        order[~endpoints] += numpy.prod(segments_binary.shape)
        labelrange = numpy.arange(num_segments + 1).astype(int)
        endpoint_loc = scipy.ndimage.minimum_position(
            order, segments_labeled, labelrange
        )
        endpoint_loc = numpy.array(endpoint_loc, int)
        endpoint_labels = numpy.zeros(segments_labeled.shape, numpy.int16)
        endpoint_labels[endpoint_loc[:, 0], endpoint_loc[:, 1]] = segments_labeled[
            endpoint_loc[:, 0], endpoint_loc[:, 1]
        ]
        #
        # A corner case - propagate will trace a loop around both ways. So
        # we have to find that last point and remove it so
        # it won't trace in that direction
        #
        loops = ~endpoints[endpoint_loc[1:, 0], endpoint_loc[1:, 1]]
        if numpy.any(loops):
            # Consider all points around the endpoint, finding the one
            # which is numbered last
            dilated_ep_labels = centrosome.cpmorphology.grey_dilation(
                endpoint_labels, footprint=numpy.ones((3, 3), bool)
            )
            dilated_ep_labels[dilated_ep_labels != segments_labeled] = 0
            loop_endpoints = scipy.ndimage.maximum_position(
                order, dilated_ep_labels.astype(int), labelrange[1:][loops]
            )
            loop_endpoints = numpy.array(loop_endpoints, int)
            segments_binary_temp = segments_binary.copy()
            segments_binary_temp[loop_endpoints[:, 0], loop_endpoints[:, 1]] = False
        else:
            segments_binary_temp = segments_binary
        #
        # Now propagate from the endpoints to get distances
        #
        _, distances = propagate(
            numpy.zeros(segments_binary.shape), endpoint_labels, segments_binary_temp, 1
        )
        if numpy.any(loops):
            # set the end-of-loop distances to be very large
            distances[loop_endpoints[:, 0], loop_endpoints[:, 1]] = numpy.inf
        #
        # Order points by label # and distance
        #
        i, j = numpy.mgrid[0 : segments_binary.shape[0], 0 : segments_binary.shape[1]]
        i = i[segments_binary]
        j = j[segments_binary]
        labels = segments_labeled[segments_binary]
        distances = distances[segments_binary]
        order = numpy.lexsort((distances, labels))
        i = i[order]
        j = j[order]
        labels = labels[order]
        distances = distances[order]
        #
        # Number each point in a segment consecutively. We determine
        # where each label starts. Then we subtract the start index
        # of each point's label from each point to get the order relative
        # to the first index of the label.
        #
        segment_order = numpy.arange(len(i))
        areas = numpy.bincount(labels.flatten())
        indexes = numpy.cumsum(areas) - areas
        segment_order -= indexes[labels]
        return i, j, labels, segment_order, distances, num_segments