def test_anisotropy():
    x = np.arange(10)
    # perfectly anisotropic
    output = cluster_morphology.measure_3d(x, x, x)
    np.testing.assert_almost_equal(output['anisotropy'][0], 1.)

    # isotropic
    output = cluster_morphology.measure_3d(x_cube, y_cube, z_cube)
    np.testing.assert_almost_equal(output['anisotropy'][0], 0.)
    def execute(self, namespace):
        from PYME.Analysis.points import cluster_morphology as cmorph
        import numpy as np

        inp = namespace[self.inputName]

        # make sure labeling scheme is consistent with what pyme conventions
        if np.min(inp[self.labelKey]) < 0:
            raise UserWarning(
                'This module expects 0-label for unclustered points, and no negative labels'
            )

        labels = inp[self.labelKey].astype(np.int)
        I = np.argsort(labels)
        I = I[labels[I] > 0]

        x_vals, y_vals, z_vals = inp['x'][I], inp['y'][I], inp['z'][I]
        labels = labels[I]
        maxLabel = labels[-1]

        #find the unique labels, and their separation in the sorted list of points
        unique_labels, counts = np.unique(labels, return_counts=True)

        #allocate memory to store results in
        measurements = np.zeros(maxLabel, cmorph.measurement_dtype)

        # loop over labels, recalling that input is now sorted, and we know how many points are in each label.
        # Note that missing labels result in zeroed entries (i.e. the initial values are not changed).
        # Missing values can be filtered out later, if desired, by filtering on the 'counts' column, but having a dense
        # array where index == label number makes any postprocessing in which we might want to find the data
        # corresponding to a particular label MUCH easier and faster.
        indi = 0
        for label_num, ct in zip(unique_labels, counts):
            indf = indi + ct

            # create x,y,z arrays for this cluster, and calculate center of mass
            x, y, z = x_vals[indi:indf], y_vals[indi:indf], z_vals[indi:indf]

            cluster_index = label_num - 1  # we ignore the unclustered points, and start labeling at 1
            cmorph.measure_3d(x, y, z, output=measurements[cluster_index])

            indi = indf

        meas = tabular.RecArraySource(measurements)

        try:
            meas.mdh = namespace[self.inputName].mdh
        except AttributeError:
            pass

        namespace[self.outputName] = meas
def test_principle_axes():
    x = np.arange(10)
    nill = np.zeros_like(x)
    # perfectly anisotropic
    output = cluster_morphology.measure_3d(x, nill, nill)
    np.testing.assert_array_almost_equal(np.array([output['sigma0'][0], output['sigma1'][0], output['sigma2'][0]]),
                                         np.array([np.std(x, ddof=1), 0, 0]))

    np.testing.assert_array_almost_equal(np.array([output['sigma_x'][0], output['sigma_y'][0], output['sigma_z'][0]]),
                                         np.array([np.std(x, ddof=1), 0, 0]))

    np.testing.assert_almost_equal(np.array([1, 0, 0]), output['axis0'][0])