def run_on_objects(self, object_name, workspace):
        """Run, computing the area measurements for a single map of objects"""
        objects = workspace.get_objects(object_name)
        assert isinstance(objects, cpo.Objects)
        #
        # Do the ellipse-related measurements
        #
        i, j, l = objects.ijv.transpose()
        centers, eccentricity, major_axis_length, minor_axis_length, \
            theta, compactness =\
            ellipse_from_second_moments_ijv(i, j, 1, l, objects.indices, True)
        del i
        del j
        del l
        self.record_measurement(workspace, object_name,
                                F_ECCENTRICITY, eccentricity)
        self.record_measurement(workspace, object_name,
                                F_MAJOR_AXIS_LENGTH, major_axis_length)
        self.record_measurement(workspace, object_name, 
                                F_MINOR_AXIS_LENGTH, minor_axis_length)
        self.record_measurement(workspace, object_name, F_ORIENTATION, 
                                theta * 180 / np.pi)
        self.record_measurement(workspace, object_name, F_COMPACTNESS,
                                compactness)
        is_first = False
        if len(objects.indices) == 0:
            nobjects = 0
        else:
            nobjects = np.max(objects.indices)
        mcenter_x = np.zeros(nobjects)
        mcenter_y = np.zeros(nobjects)
        mextent = np.zeros(nobjects)
        mperimeters = np.zeros(nobjects)
        msolidity = np.zeros(nobjects)
        euler = np.zeros(nobjects)
        max_radius = np.zeros(nobjects)
        median_radius = np.zeros(nobjects)
        mean_radius = np.zeros(nobjects)
        min_feret_diameter = np.zeros(nobjects)
        max_feret_diameter = np.zeros(nobjects)
        zernike_numbers = self.get_zernike_numbers()
        zf = {}
        for n,m in zernike_numbers:
            zf[(n,m)] = np.zeros(nobjects)
        if nobjects > 0:
            chulls, chull_counts = convex_hull_ijv(objects.ijv, objects.indices)
            for labels, indices in objects.get_labels():
                to_indices = indices-1
                distances = distance_to_edge(labels)
                mcenter_y[to_indices], mcenter_x[to_indices] =\
                         maximum_position_of_labels(distances, labels, indices)
                max_radius[to_indices] = fix(scind.maximum(
                    distances, labels, indices))
                mean_radius[to_indices] = fix(scind.mean(
                    distances, labels, indices))
                median_radius[to_indices] = median_of_labels(
                    distances, labels, indices)
                #
                # The extent (area / bounding box area)
                #
                mextent[to_indices] = calculate_extents(labels, indices)
                #
                # The perimeter distance
                #
                mperimeters[to_indices] = calculate_perimeters(labels, indices)
                #
                # Solidity
                #
                msolidity[to_indices] = calculate_solidity(labels, indices)
                #
                # Euler number
                #
                euler[to_indices] = euler_number(labels, indices)
                #
                # Zernike features
                #
                zf_l = cpmz.zernike(zernike_numbers, labels, indices)
                for (n,m), z in zip(zernike_numbers, zf_l.transpose()):
                    zf[(n,m)][to_indices] = z
            #
            # Form factor
            #
            ff = 4.0 * np.pi * objects.areas / mperimeters**2
            #
            # Feret diameter
            #
            min_feret_diameter, max_feret_diameter = \
                feret_diameter(chulls, chull_counts, objects.indices)
            
        else:
            ff = np.zeros(0)

        for f, m in ([(F_AREA, objects.areas),
                      (F_CENTER_X, mcenter_x),
                      (F_CENTER_Y, mcenter_y),
                      (F_EXTENT, mextent),
                      (F_PERIMETER, mperimeters),
                      (F_SOLIDITY, msolidity),
                      (F_FORM_FACTOR, ff),
                      (F_EULER_NUMBER, euler),
                      (F_MAXIMUM_RADIUS, max_radius),
                      (F_MEAN_RADIUS, mean_radius),
                      (F_MEDIAN_RADIUS, median_radius),
                      (F_MIN_FERET_DIAMETER, min_feret_diameter),
                      (F_MAX_FERET_DIAMETER, max_feret_diameter)] +
                     [(self.get_zernike_name((n,m)), zf[(n,m)])
                       for n,m in zernike_numbers]):
            self.record_measurement(workspace, object_name, f, m) 
    def run_on_objects(self, object_name, workspace):
        """Run, computing the area measurements for a single map of objects"""
        objects = workspace.get_objects(object_name)

        if len(objects.shape) == 2:
            #
            # Do the ellipse-related measurements
            #
            i, j, l = objects.ijv.transpose()
            centers, eccentricity, major_axis_length, minor_axis_length, \
            theta, compactness = \
                ellipse_from_second_moments_ijv(i, j, 1, l, objects.indices, True)
            del i
            del j
            del l
            self.record_measurement(workspace, object_name,
                                    F_ECCENTRICITY, eccentricity)
            self.record_measurement(workspace, object_name,
                                    F_MAJOR_AXIS_LENGTH, major_axis_length)
            self.record_measurement(workspace, object_name,
                                    F_MINOR_AXIS_LENGTH, minor_axis_length)
            self.record_measurement(workspace, object_name, F_ORIENTATION,
                                    theta * 180 / np.pi)
            self.record_measurement(workspace, object_name, F_COMPACTNESS,
                                    compactness)
            is_first = False
            if len(objects.indices) == 0:
                nobjects = 0
            else:
                nobjects = np.max(objects.indices)
            mcenter_x = np.zeros(nobjects)
            mcenter_y = np.zeros(nobjects)
            mextent = np.zeros(nobjects)
            mperimeters = np.zeros(nobjects)
            msolidity = np.zeros(nobjects)
            euler = np.zeros(nobjects)
            max_radius = np.zeros(nobjects)
            median_radius = np.zeros(nobjects)
            mean_radius = np.zeros(nobjects)
            min_feret_diameter = np.zeros(nobjects)
            max_feret_diameter = np.zeros(nobjects)
            zernike_numbers = self.get_zernike_numbers()
            zf = {}
            for n, m in zernike_numbers:
                zf[(n, m)] = np.zeros(nobjects)
            if nobjects > 0:
                chulls, chull_counts = convex_hull_ijv(objects.ijv, objects.indices)
                for labels, indices in objects.get_labels():
                    to_indices = indices - 1
                    distances = distance_to_edge(labels)
                    mcenter_y[to_indices], mcenter_x[to_indices] = \
                        maximum_position_of_labels(distances, labels, indices)
                    max_radius[to_indices] = fix(scind.maximum(
                            distances, labels, indices))
                    mean_radius[to_indices] = fix(scind.mean(
                            distances, labels, indices))
                    median_radius[to_indices] = median_of_labels(
                            distances, labels, indices)
                    #
                    # The extent (area / bounding box area)
                    #
                    mextent[to_indices] = calculate_extents(labels, indices)
                    #
                    # The perimeter distance
                    #
                    mperimeters[to_indices] = calculate_perimeters(labels, indices)
                    #
                    # Solidity
                    #
                    msolidity[to_indices] = calculate_solidity(labels, indices)
                    #
                    # Euler number
                    #
                    euler[to_indices] = euler_number(labels, indices)
                    #
                    # Zernike features
                    #
                    if self.calculate_zernikes.value:
                        zf_l = cpmz.zernike(zernike_numbers, labels, indices)
                        for (n, m), z in zip(zernike_numbers, zf_l.transpose()):
                            zf[(n, m)][to_indices] = z
                #
                # Form factor
                #
                ff = 4.0 * np.pi * objects.areas / mperimeters ** 2
                #
                # Feret diameter
                #
                min_feret_diameter, max_feret_diameter = \
                    feret_diameter(chulls, chull_counts, objects.indices)

            else:
                ff = np.zeros(0)

            for f, m in ([(F_AREA, objects.areas),
                          (F_CENTER_X, mcenter_x),
                          (F_CENTER_Y, mcenter_y),
                          (F_CENTER_Z, np.ones_like(mcenter_x)),
                          (F_EXTENT, mextent),
                          (F_PERIMETER, mperimeters),
                          (F_SOLIDITY, msolidity),
                          (F_FORM_FACTOR, ff),
                          (F_EULER_NUMBER, euler),
                          (F_MAXIMUM_RADIUS, max_radius),
                          (F_MEAN_RADIUS, mean_radius),
                          (F_MEDIAN_RADIUS, median_radius),
                          (F_MIN_FERET_DIAMETER, min_feret_diameter),
                          (F_MAX_FERET_DIAMETER, max_feret_diameter)] +
                             [(self.get_zernike_name((n, m)), zf[(n, m)])
                              for n, m in zernike_numbers]):
                self.record_measurement(workspace, object_name, f, m)
        else:
            labels = objects.segmented

            props = skimage.measure.regionprops(labels)

            # Area
            areas = [prop.area for prop in props]

            self.record_measurement(workspace, object_name, F_AREA, areas)

            # Extent
            extents = [prop.extent for prop in props]

            self.record_measurement(workspace, object_name, F_EXTENT, extents)

            # Centers of mass
            centers = objects.center_of_mass()

            center_z, center_y, center_x = centers.transpose()

            self.record_measurement(workspace, object_name, F_CENTER_X, center_x)

            self.record_measurement(workspace, object_name, F_CENTER_Y, center_y)

            self.record_measurement(workspace, object_name, F_CENTER_Z, center_z)

            # Perimeters
            perimeters = []

            for label in np.unique(labels):
                if label == 0:
                    continue

                volume = np.zeros_like(labels, dtype='bool')

                volume[labels == label] = True

                verts, faces, _, _ = skimage.measure.marching_cubes(
                    volume,
                    spacing=objects.parent_image.spacing if objects.has_parent_image else (1.0,) * labels.ndim,
                    level=0
                )

                perimeters += [skimage.measure.mesh_surface_area(verts, faces)]

            if len(perimeters) == 0:
                self.record_measurement(workspace, object_name, F_PERIMETER, [0])
            else:
                self.record_measurement(workspace, object_name, F_PERIMETER, perimeters)

            for feature in self.get_feature_names():
                if feature in [F_AREA, F_EXTENT, F_CENTER_X, F_CENTER_Y, F_CENTER_Z, F_PERIMETER]:
                    continue

                self.record_measurement(workspace, object_name, feature, [np.nan])