def test_fourier_derivative_realness(nx, ny):
    # fourier_derivative internally asserts that the imaginary part is within
    # numerical tolerance. We check here this error isn't raised for any
    # configuration of odd and even grid points
    topography = Topography(np.random.random((nx, ny)),
                            physical_sizes=(2., 3.))
    topography.fourier_derivative(imtol=1e-12)
Ejemplo n.º 2
0
    def test_saving_loading_and_sphere(self):
        # domain physical_sizes (edge length of square)
        length = 8 + 4 * rand()
        R = 17 + 6 * rand()  # sphere radius
        res = 2  # nb_grid_pts
        x_c = length * rand()  # coordinates of center
        y_c = length * rand()
        x = np.arange(res, dtype=float) * length / res - x_c
        y = np.arange(res, dtype=float) * length / res - y_c
        r2 = np.zeros((res, res))
        for i in range(res):
            for j in range(res):
                r2[i, j] = x[i]**2 + y[j]**2
        h = np.sqrt(R**2 - r2) - R  # profile of sphere

        S1 = Topography(h, h.shape)
        with tmp_dir() as dir:
            fname = os.path.join(dir, "surface")
            S1.save(fname)
            # TODO: datafiles fixture may solve the problem
            # For some reason, this does not find the file...
            # S2 = read_asc(fname)
            S2 = S1

        S3 = make_sphere(R, (res, res), (length, length), (x_c, y_c))
        self.assertTrue(np.array_equal(S1.heights(), S2.heights()))
        self.assertTrue(np.array_equal(S1.heights(), S3.heights()))
def test_uniform_brute_force_autocorrelation_from_area():
    n = 10
    m = 11
    for surf in [Topography(np.ones([n, m]), (n, m), periodic=False),
                 Topography(np.random.random([n, m]), (n, m), periodic=False)]:
        r, A, A_xy = surf.autocorrelation_from_area(nbins=100, return_map=True)

        nx, ny = surf.nb_grid_pts
        dir_A_xy = np.zeros([n, m])
        dir_A = np.zeros_like(A)
        dir_n = np.zeros_like(A)
        for dx in range(n):
            for dy in range(m):
                for i in range(nx - dx):
                    for j in range(ny - dy):
                        dir_A_xy[dx, dy] += (surf.heights()[i, j] -
                                             surf.heights()[
                                                 i + dx, j + dy]) ** 2 / 2
                dir_A_xy[dx, dy] /= (nx - dx) * (ny - dy)
                d = np.sqrt(dx ** 2 + dy ** 2)
                i = np.argmin(np.abs(r - d))
                dir_A[i] += dir_A_xy[dx, dy]
                dir_n[i] += 1
        dir_n[dir_n == 0] = 1
        dir_A /= dir_n
        assert_array_almost_equal(A_xy, dir_A_xy)
        assert_array_almost_equal(A[:-2], dir_A[:-2])
Ejemplo n.º 4
0
def test_init_with_lists_calling_scale_and_detrend():
    t = Topography(np.array([[1, 1, 1, 1], [1, 1, 1, 1], [1, 1, 1, 1]]),
                   physical_sizes=(1, 1))

    # the following commands should be possible without errors
    st = t.scale(1)
    st.detrend(detrend_mode='center')
def test_squeeze():
    x = np.linspace(0, 4 * np.pi, 101)
    y = np.linspace(0, 8 * np.pi, 103)
    h = np.sin(x.reshape(-1, 1)) + np.cos(y.reshape(1, -1))
    surface = Topography(h, (1.2, 3.2)).scale(2.0)
    surface2 = surface.squeeze()
    assert isinstance(surface2, Topography)
    np.testing.assert_allclose(surface.heights(), surface2.heights())
def test_fourier_interpolate_transpose_symmetry(nx, ny, fine_nx, fine_ny):
    topography = Topography(np.random.random((nx, ny)),
                            physical_sizes=(1., 1.5))
    interp = topography.interpolate_fourier((fine_nx, fine_ny))
    interp_t = topography.transpose().interpolate_fourier(
        (fine_ny, fine_nx)).transpose()

    np.testing.assert_allclose(interp.heights(), interp_t.heights())
def test_power_spectrum_from_profile():
    X = np.arange(3).reshape(1, 3)
    Y = np.arange(4).reshape(4, 1)
    h = X + Y

    t = Topography(h, (8, 6))

    q1, C1 = t.power_spectrum_from_profile(window='hann')
def test_constrained_conjugate_gradients():
    # punch radius:
    r_s = 20.0
    # equivalent Young's modulus
    E_s = 3.56
    for nx, ny in [(256, 256), (256, 255), (255, 256)]:
        for disp0, normal_force in [(None, 15), (0.1, None)]:
            sx = sy = 2.5 * r_s
            substrate = FreeFFTElasticHalfSpace((nx, ny), E_s, (sx, sy))
            x_range = np.arange(nx).reshape(-1, 1)
            y_range = np.arange(ny).reshape(1, -1)
            r_sq = (sx / nx * (x_range - nx // 2)) ** 2 + \
                   (sy / ny * (y_range - ny // 2)) ** 2
            surface = Topography(
                np.ma.masked_where(r_sq > r_s ** 2, np.zeros([nx, ny])),
                (sx, sy)
            )
            system = make_system(substrate, surface)
            try:
                result = system.minimize_proxy(offset=disp0,
                                               external_force=normal_force,
                                               pentol=1e-4)
            except substrate.FreeBoundaryError as err:
                if False:
                    import matplotlib.pyplot as plt
                    fig, ax = plt.subplots()

                    # ax.pcolormesh(substrate.force /
                    # surface.area_per_pt,rasterized=True)
                    plt.colorbar(ax.pcolormesh(surface.heights(),
                                               rasterized=True))
                    ax.set_xlabel("")
                    ax.set_ylabel("")

                    ax.legend()

                    fig.tight_layout()
                    plt.show(block=True)

                raise err
            offset = result.offset
            forces = -result.jac
            converged = result.success

            # Check that calculation has converged
            assert converged

            # Check that target values have been reached
            if disp0 is not None:
                np.testing.assert_almost_equal(offset, disp0)
            if normal_force is not None:
                np.testing.assert_almost_equal(-forces.sum(), normal_force)

            # Check contact stiffness
            np.testing.assert_almost_equal(
                -forces.sum() / offset / (2 * r_s * E_s),
                1.0, decimal=2)
def test_attribute_error():
    X = np.arange(3).reshape(1, 3)
    Y = np.arange(4).reshape(4, 1)
    h = X + Y
    t = Topography(h, (8, 6))

    # nonsense attributes return attribute error
    with pytest.raises(AttributeError):
        t.ababababababababa

    #
    # only scaled topographies have coeff
    #
    with pytest.raises(AttributeError):
        t.coeff

    st = t.scale(1)

    assert st.height_scale_factor == 1

    #
    # only detrended topographies have detrend_mode
    #
    with pytest.raises(AttributeError):
        st.detrend_mode

    dm = st.detrend(detrend_mode='height').detrend_mode
    assert dm == 'height'

    #
    # this all should also work after pickling
    #
    t2 = pickle.loads(pickle.dumps(t))

    with pytest.raises(AttributeError):
        t2.height_scale_factor

    st2 = t2.scale(1)

    assert st2.height_scale_factor == 1

    with pytest.raises(AttributeError):
        st2.detrend_mode

    dm2 = st2.detrend(detrend_mode='height').detrend_mode
    assert dm2 == 'height'

    #
    # this all should also work after scaled+pickled
    #
    t3 = pickle.loads(pickle.dumps(st))

    with pytest.raises(AttributeError):
        t3.detrend_mode

    dm3 = t3.detrend(detrend_mode='height').detrend_mode
    assert dm3 == 'height'
Ejemplo n.º 10
0
 def test_checkerboard_detrend_with_no_subdivisions(self):
     r = 32
     x, y = np.mgrid[:r, :r]
     h = 1.3 * x - 0.3 * y + 0.02 * x * x + 0.03 * y * y - 0.013 * x * y
     t = Topography(h, (1, 1), periodic=False)
     # This should be the same as a detrend with detrend_mode='height'
     ut1 = t.checkerboard_detrend((1, 1))
     ut2 = t.detrend().heights()
     np.testing.assert_allclose(ut1, ut2)
Ejemplo n.º 11
0
def test_mirror_stitch():
    t = Topography(np.array(((0, 1), (0, 0))), (2., 3.))
    tp = t.mirror_stitch()

    assert tp.is_periodic

    np.testing.assert_allclose(tp.physical_sizes, (4., 6.))

    np.testing.assert_allclose(
        tp.heights(), [[0, 1, 1, 0], [0, 0, 0, 0], [0, 0, 0, 0], [0, 1, 1, 0]])
def test_rms_curvature_paraboloid_uniform_2D():
    n = 16
    X, Y = np.mgrid[slice(0, n), slice(0, n)]
    curvature = 0.1
    heights = 0.5 * curvature * (X**2 + Y**2)
    surf = Topography(heights, physical_sizes=(n, n), periodic=False)
    # central finite differences are second order and so exact for the
    # paraboloid
    assert abs(
        (surf.rms_curvature_from_area() - curvature) / curvature) < 1e-15
 def test_randomly_rough(self):
     surface = fourier_synthesis((511, 511), (1., 1.), 0.8, rms_height=1)
     self.assertTrue(surface.is_uniform)
     cut = Topography(surface[:64, :64], physical_sizes=(64., 64.))
     self.assertTrue(cut.is_uniform)
     untilt1 = cut.detrend(detrend_mode='height')
     untilt2 = cut.detrend(detrend_mode='slope')
     self.assertTrue(untilt1.is_uniform)
     self.assertTrue(untilt2.is_uniform)
     self.assertTrue(untilt1.rms_height_from_area() < untilt2.rms_height_from_area())
     self.assertTrue(untilt1.rms_gradient() > untilt2.rms_gradient())
Ejemplo n.º 14
0
    def test_checkerboard_detrend_2d(self):
        arr = np.zeros([4, 4])
        arr[:2, :2] = 1.0
        outarr = Topography(arr, arr.shape).checkerboard_detrend((2, 2))
        np.testing.assert_allclose(outarr, np.zeros([4, 4]))

        arr = np.zeros([4, 4])
        arr[:2, :2] = 1.0
        arr[:2, 1] = 2.0
        outarr = Topography(arr, arr.shape).checkerboard_detrend((2, 2))
        np.testing.assert_allclose(outarr, np.zeros([4, 4]))
Ejemplo n.º 15
0
def test_positions_and_heights():
    X = np.arange(3).reshape(1, 3)
    Y = np.arange(4).reshape(4, 1)
    h = X + Y

    t = Topography(h, (8, 6))

    assert t.nb_grid_pts == (4, 3)

    assert_array_equal(t.heights(), h)
    X2, Y2, h2 = t.positions_and_heights()
    assert_array_equal(X2, [
        (0, 0, 0),
        (2, 2, 2),
        (4, 4, 4),
        (6, 6, 6),
    ])
    assert_array_equal(Y2, [
        (0, 2, 4),
        (0, 2, 4),
        (0, 2, 4),
        (0, 2, 4),
    ])
    assert_array_equal(h2, [(0, 1, 2), (1, 2, 3), (2, 3, 4), (3, 4, 5)])

    #
    # After detrending, the position and heights should have again
    # just 3 arrays and the third array should be the same as .heights()
    #
    dt = t.detrend(detrend_mode='slope')

    np.testing.assert_allclose(dt.heights(), [(0, 0, 0), (0, 0, 0), (0, 0, 0),
                                              (0, 0, 0)],
                               atol=1e-15)

    X2, Y2, h2 = dt.positions_and_heights()

    assert h2.shape == (4, 3)
    assert_array_equal(X2, [
        (0, 0, 0),
        (2, 2, 2),
        (4, 4, 4),
        (6, 6, 6),
    ])
    assert_array_equal(Y2, [
        (0, 2, 4),
        (0, 2, 4),
        (0, 2, 4),
        (0, 2, 4),
    ])
    np.testing.assert_allclose(h2, [(0, 0, 0), (0, 0, 0), (0, 0, 0),
                                    (0, 0, 0)],
                               atol=1e-15)
Ejemplo n.º 16
0
    def topography(self, channel_index=None, physical_sizes=None,
                   height_scale_factor=None, info={}, periodic=False,
                   subdomain_locations=None, nb_subdomain_grid_pts=None):
        if channel_index is None:
            channel_index = self._default_channel_index

        if subdomain_locations is not None or \
                nb_subdomain_grid_pts is not None:
            raise RuntimeError(
                'This reader does not support MPI parallelization.')
        close_file = False
        if not hasattr(self._fobj, 'read'):
            fobj = open(self._fobj, 'rb')
            close_file = True
        else:
            fobj = self._fobj

        channel = self._channels[channel_index]
        sx, sy = self._check_physical_sizes(physical_sizes,
                                            channel.physical_sizes)

        nx, ny = channel.nb_grid_pts

        offset = self._offsets[channel_index]
        dtype = np.dtype('<i2')

        ###################################

        fobj.seek(offset)
        rawdata = fobj.read(nx * ny * dtype.itemsize)
        unscaleddata = np.frombuffer(rawdata, count=nx * ny,
                                     dtype=dtype).reshape(nx, ny)

        # internal information from file
        _info = dict(unit=channel.info["unit"], data_source=channel.name)
        _info.update(info)
        if 'acquisition_time' in channel.info:
            _info['acquisition_time'] = channel.info['acquisition_time']

        # the orientation of the heights is modified in order to match
        # the image of gwyddion when plotted with imshow(t.heights().T)
        # or pcolormesh(t.heights().T) for origin in lower left and
        # with inverted y axis (cartesian coordinate system)
        surface = Topography(np.fliplr(unscaleddata.T), (sx, sy), info=_info,
                             periodic=periodic)
        if height_scale_factor is None:
            height_scale_factor = channel.info["height_scale_factor"]
        surface = surface.scale(height_scale_factor)

        if close_file:
            fobj.close()

        return surface
def test_default_window_2D():
    x = np.linspace(0, 1, 200).reshape(-1, 1)

    heights = np.cos(2 * np.pi * x * 8.3) * np.ones((1, 200))
    topography = Topography(heights, physical_sizes=(1, 1), periodic=True)

    if True:
        import matplotlib.pyplot as plt
        fig, ax = plt.subplots()
        ax.plot(*topography.power_spectrum_from_profile(),
                label="periodic=True")
        ax.plot(*topography.power_spectrum_from_area(nbins=20),
                label="2D, periodic=True")
        ax.set_xscale("log")
        ax.set_yscale("log")

    topography = Topography(heights, physical_sizes=(1, 1), periodic=False)

    if True:
        import matplotlib.pyplot as plt
        ax.plot(*topography.power_spectrum_from_profile(),
                label="periodic=False")
        ax.plot(*topography.power_spectrum_from_area(nbins=20),
                label="2D, periodic=False")
        ax.set_xscale("log")
        ax.set_yscale("log")
        # ax.set_ylim(bottom=1e-6)
        ax.legend()
        plt.show(block=True)
Ejemplo n.º 18
0
def test_checkerboard_detrend_profile_2d():
    arr = np.zeros([4, 4])
    arr[:2, :2] = 1.0
    outarr = Topography(arr, arr.shape).checkerboard_detrend_profile(2)
    np.testing.assert_allclose(outarr, np.zeros([4, 4]), atol=1e-12)

    arr = np.zeros([4, 4])
    arr[:2, :2] = 1.0
    arr[:2, 1] = 2.0
    arr[:,
        1] += 1  # offsets do not matter since all profile are independently tilt corrected
    arr[:, 2] += 1.5
    arr[:, 3] += 0.7
    outarr = Topography(arr, arr.shape).checkerboard_detrend_profile(2)
    np.testing.assert_allclose(outarr, np.zeros([4, 4]), atol=1e-12)
def test_hardwall_plastic_nonperiodic_disp_control(comm_self):
    # test just that it works without bug, not accuracy

    nx, ny = 128, 128

    sx = 0.005  # mm
    sy = 0.005  # mm

    x = np.arange(0, nx).reshape(-1, 1) * sx / nx - sx / 2
    y = np.arange(0, ny).reshape(1, -1) * sy / ny - sy / 2

    topography = Topography(-np.sqrt(x**2 + y**2) * 0.05,
                            physical_sizes=(sx, sy))

    Es = 230000  # MPa
    hardness = 6000  # MPa
    system = make_plastic_system(substrate="free",
                                 surface=PlasticTopography(
                                     topography=topography, hardness=hardness),
                                 young=Es,
                                 communicator=comm_self)

    offsets = [1e-4]

    disp0 = None
    for offset in offsets:
        sol = system.minimize_proxy(offset=offset,
                                    initial_displacements=disp0,
                                    pentol=1e-10)
        assert sol.success
Ejemplo n.º 20
0
def simple_linear_2d_topography():
    """Simple 2D topography, which is linear in y"""
    unit = 'nm'
    info = dict(unit=unit)
    y = np.arange(10).reshape((1, -1))
    x = np.arange(5).reshape((-1, 1))
    arr = -2 * y + 0 * x  # only slope in y direction
    t = Topography(arr, (5, 10), info=info).detrend('center')
    return t
def test_rms_curvature_sinewave_2D(periodic):
    precision = 5

    n = 256
    X, Y = np.mgrid[slice(0, n), slice(0, n)]
    hm = 0.3
    L = float(n)
    size = (L, L)

    surf = Topography(np.sin(2 * np.pi / L * X) * hm,
                      physical_sizes=size,
                      periodic=periodic)
    numerical_lapl = surf.rms_laplacian()
    analytical_lapl = np.sqrt((2 * np.pi / L)**4 * hm**2 / 2)
    # print(numerical-analytical)
    np.testing.assert_almost_equal(numerical_lapl, analytical_lapl, precision)

    np.testing.assert_almost_equal(surf.rms_curvature_from_area(),
                                   analytical_lapl / 2, precision)
def test_hard_wall_bearing_area(comm):
    # Test that at very low hardness we converge to (almost) the bearing
    # area geometry
    pnp = Reduction(comm)
    fullsurface = open_topography(os.path.join(FIXTURE_DIR, 'surface1.out'))
    fullsurface = fullsurface.topography(
        physical_sizes=fullsurface.channels[0].nb_grid_pts)
    nb_domain_grid_pts = fullsurface.nb_grid_pts
    substrate = PeriodicFFTElasticHalfSpace(nb_domain_grid_pts,
                                            1.0,
                                            fft='mpi',
                                            communicator=comm)
    surface = Topography(
        fullsurface.heights(),
        physical_sizes=nb_domain_grid_pts,
        decomposition='domain',
        subdomain_locations=substrate.topography_subdomain_locations,
        nb_subdomain_grid_pts=substrate.topography_nb_subdomain_grid_pts,
        communicator=substrate.communicator)

    plastic_surface = PlasticTopography(surface, 1e-12)
    system = PlasticNonSmoothContactSystem(substrate, plastic_surface)
    offset = -0.002
    if comm.rank == 0:

        def cb(it, p_r, d):
            print("{0}: area = {1}".format(it, d["area"]))
    else:

        def cb(it, p_r, d):
            pass

    result = system.minimize_proxy(offset=offset, callback=cb)
    assert result.success
    c = result.jac > 0.0
    ncontact = pnp.sum(c)
    assert plastic_surface.plastic_area == ncontact * surface.area_per_pt
    bearing_area = bisect(
        lambda x: pnp.sum((surface.heights() > x)) - ncontact, -0.03, 0.03)
    cba = surface.heights() > bearing_area
    # print(comm.Get_rank())
    assert pnp.sum(np.logical_not(c == cba)) < 25
def test_fourier_interpolate_nyquist(plot=False):
    # asserts that the interpolation follows the "minimal-osciallation"
    # assumption for the nyquist frequency

    topography = Topography(np.array([[1], [-1]]), physical_sizes=(1., 1.))
    interpolated_topography = topography.interpolate_fourier((64, 1))

    if plot:
        import matplotlib.pyplot as plt
        fig, ax = plt.subplots()

        x, y = topography.positions()
        ax.plot(x.flat, topography.heights().flat, "+")

        x, y = interpolated_topography.positions()
        ax.plot(x.flat, interpolated_topography.heights().flat, "-")
        fig.show()

    x, y = interpolated_topography.positions()
    np.testing.assert_allclose(interpolated_topography.heights(),
                               np.cos(2 * np.pi * x), atol=1e-14)
Ejemplo n.º 24
0
def test_heuristic_pentol():
    # just checks works without bug

    nx, ny = (10, 5)

    topo = Topography(np.resize(np.cos(2 * np.pi * np.arange(nx) / nx),
                                (nx, ny)),
                      physical_sizes=(nx, ny),
                      periodic=True)

    system = make_system(surface=topo, substrate="periodic", young=1)
    system.minimize_proxy(offset=-0.5)
Ejemplo n.º 25
0
def test_checkerboard_detrend_order2_2d():
    arr = np.zeros([6, 6])
    arr[:3, :3] = 1.0
    outarr = Topography(arr, arr.shape).checkerboard_detrend_area((2, 2),
                                                                  order=2)
    np.testing.assert_allclose(outarr, np.zeros([6, 6]), atol=1e-12)

    arr = np.zeros([6, 6])
    arr[:3, :3] = 1.0
    arr[:3, 1] = 2.0
    outarr = Topography(arr, arr.shape).checkerboard_detrend_area((2, 2),
                                                                  order=2)
    np.testing.assert_allclose(outarr, np.zeros([6, 6]), atol=1e-12)

    arr = np.zeros([6, 6])
    arr[:3, :3] = 1.0
    arr[:3, 1] = 2.0
    arr[:3, 2] = -0.5
    outarr = Topography(arr, arr.shape).checkerboard_detrend_area((2, 2),
                                                                  order=2)
    np.testing.assert_allclose(outarr, np.zeros([6, 6]), atol=1e-12)
    def test_saving_loading_and_sphere(self):
        # domain physical_sizes (edge length of square)
        length = 8 + 4 * rand()
        R = 17 + 6 * rand()  # sphere radius
        res = 2  # nb_grid_pts
        x_c = length * rand()  # coordinates of center
        y_c = length * rand()
        x = np.arange(res, dtype=float) * length / res - x_c
        y = np.arange(res, dtype=float) * length / res - y_c
        r2 = np.zeros((res, res))
        for i in range(res):
            for j in range(res):
                r2[i, j] = x[i] ** 2 + y[j] ** 2
        h = np.sqrt(R ** 2 - r2) - R  # profile of sphere

        S1 = Topography(h, h.shape)
        with tmp_dir() as dir:
            fname = os.path.join(dir, "surface")
            S1.to_matrix(fname)
            S2 = read_matrix(fname)
            self.assertTrue(np.allclose(S2.heights(), S1.heights()))

        S3 = make_sphere(R, (res, res), (length, length), (x_c, y_c))
        self.assertTrue(np.array_equal(S1.heights(), S2.heights()))
        self.assertTrue(np.array_equal(S1.heights(), S3.heights()))
def test_positions(comm):
    nx, ny = (12 * comm.Get_size(), 10 * comm.Get_size() + 1)
    sx = 33.
    sy = 54.
    fftengine = FFT((nx, ny), fft='mpi', communicator=comm)

    surf = Topography(np.zeros(fftengine.nb_subdomain_grid_pts),
                      physical_sizes=(sx, sy),
                      decomposition='subdomain',
                      nb_grid_pts=(nx, ny),
                      subdomain_locations=fftengine.subdomain_locations,
                      communicator=comm)

    x, y = surf.positions()
    assert x.shape == fftengine.nb_subdomain_grid_pts
    assert y.shape == fftengine.nb_subdomain_grid_pts

    assert Reduction(comm).min(x) == 0
    assert abs(Reduction(comm).max(x) - sx * (1 - 1. / nx)) \
           < 1e-8 * sx / nx, "{}".format(x)
    assert Reduction(comm).min(y) == 0
    assert abs(Reduction(comm).max(y) - sy * (1 - 1. / ny)) < 1e-8
def uniform_2d_topography(request):
    """Returns a uniform 2D topography, with all combinations of scaled and detrended.

    Detrended is always executed after scaling, if requested.

    Returns
    -------
    A uniform 2D topography.
    """
    y = np.arange(10).reshape((1, -1))
    x = np.arange(5).reshape((-1, 1))
    arr = -2 * y + 0 * x  # only slope in y direction
    topography = Topography(arr, (5, 10)).detrend('center')
    return apply_param(topography, request.param)
 def test_smooth_without_size(self):
     arr = self._flat_arr
     surf = Topography(arr, (1, 1)).detrend(detrend_mode='height')
     self.assertEqual(surf.dim, 2)
     self.assertTrue(surf.is_uniform)
     self.assertAlmostEqual(surf.mean(), 0)
     self.assertAlmostEqual(surf.rms_gradient(), 0)
     self.assertTrue(
         surf.rms_height_from_area() < Topography(arr, (1, 1)).rms_height_from_area())
def test_uniform_brute_force_autocorrelation_from_profile():
    n = 10
    for surf in [UniformLineScan(np.ones(n), n, periodic=False),
                 UniformLineScan(np.arange(n), n, periodic=False),
                 Topography(np.random.random(n).reshape(n, 1), (n, 1),
                            periodic=False)]:
        r, A = surf.autocorrelation_from_profile()

        n = len(A)
        dir_A = np.zeros(n)
        for d in range(n):
            for i in range(n - d):
                dir_A[d] += (surf.heights()[i] - surf.heights()[
                    i + d]) ** 2 / 2
            dir_A[d] /= (n - d)
        assert_array_almost_equal(A, dir_A)