def test_invariance():
    for a, b, c in [(2.3, 1.2, 1.7), (1.5, 3.1, 3.1), (0.5, 1.0, 1.0),
                    (0.5, -0.5, 0.5)]:
        q = np.linspace(0.0, 2 * np.pi / a, 101)

        x = np.array([-a, a])
        h = np.array([b, c])
        _, C1 = NonuniformLineScan(x, h).power_spectrum_from_profile(
            wavevectors=q,
            algorithm='brute-force',
            short_cutoff=None,
            window='None')

        x = np.array([-a, 0, a])
        h = np.array([b, (b + c) / 2, c])
        _, C2 = NonuniformLineScan(x, h).power_spectrum_from_profile(
            wavevectors=q,
            algorithm='brute-force',
            short_cutoff=None,
            window='None')

        x = np.array([-a, 0, a / 2, a])
        h = np.array([b, (b + c) / 2, (3 * c + b) / 4, c])
        _, C3 = NonuniformLineScan(x, h).power_spectrum_from_profile(
            wavevectors=q,
            algorithm='brute-force',
            short_cutoff=None,
            window='None')

        assert_array_almost_equal(C1, C2)
        assert_array_almost_equal(C2, C3)
    def test_init_with_lists_calling_scale_and_detrend(self):
        # initialize with lists instead of arrays
        t = NonuniformLineScan(x=[1, 2, 3, 4], y=[2, 4, 6, 8])

        # the following commands should be possible without errors
        st = t.scale(1)
        st.detrend(detrend_mode='center')
 def test_squeeze(self):
     x = np.linspace(0, 4 * np.pi, 101) ** (1.3)
     h = np.sin(x)
     surface = NonuniformLineScan(x, h).scale(2.0)
     surface2 = surface.squeeze()
     self.assertTrue(isinstance(surface2, NonuniformLineScan))
     np.testing.assert_allclose(surface.positions(), surface2.positions())
     np.testing.assert_allclose(surface.heights(), surface2.heights())
    def test_positions_and_heights(self):
        x = np.array((0, 1, 1.5, 2, 3))
        h = 2 * x

        t = NonuniformLineScan(x, h)

        assert_array_equal(t.heights(), h)
        assert_array_equal(t.positions(), x)

        x2, h2 = t.positions_and_heights()
        assert_array_equal(x2, x)
        assert_array_equal(h2, h)
def test_nonuniform_triangle_autocorrelation():
    a = 0.7
    b = 3
    x = np.array([0, b])
    t = NonuniformLineScan(x, a * x)
    r, A = height_height_autocorrelation(t,
                                         distances=np.linspace(-4, 4, 101))

    assert_almost_equal(A[np.abs(r) < 1e-6][0], a ** 2 * b ** 3 / 3)

    r3, A3 = height_height_autocorrelation(t.detrend(detrend_mode='center'),
                                           distances=[0])
    s, = t.physical_sizes
    assert_almost_equal(A3[0], t.rms_height_from_profile() ** 2 * s)

    x = np.array([0, 1., 1.3, 1.7, 2.0, 2.5, 3.0])
    t = NonuniformLineScan(x, a * x)
    r2, A2 = height_height_autocorrelation(t, distances=np.linspace(-4, 4,
                                                                    101))

    assert_array_almost_equal(A, A2)

    r, A = height_height_autocorrelation(t.detrend(detrend_mode='center'),
                                         distances=[0])
    s, = t.physical_sizes
    assert_almost_equal(A[0], t.rms_height_from_profile() ** 2 * s)
    def test_nonuniform_curvatures(self):
        radius = 400.
        center = 50.

        # generate a nonregular monotically increasing sery of x
        xs = np.cumsum(np.random.lognormal(size=20))
        xs /= np.max(xs)
        xs *= 80.

        heights = 1 / (2 * radius) * (xs - center) ** 2

        surface = NonuniformLineScan(xs, heights)
        detrended = surface.detrend(detrend_mode="curvature")
        self.assertAlmostEqual(abs(detrended.curvatures[0]), 1 / radius)
def test_slope_distribution_simple_line_scan():
    x = np.array((1, 2, 3, 4))
    y = -2 * x

    t = NonuniformLineScan(x, y).detrend(detrend_mode='center')

    topography = FakeTopographyModel(t)

    result = slope_distribution(topography, bins=3)

    assert sorted(result.keys()) == EXPECTED_KEYS_FOR_DIST_ANALYSIS

    assert result['name'] == 'Slope distribution'
    assert result['scalars'] == {
        'Mean Slope (x direction)': dict(value=-2., unit='1'),  # absolute value of slope
        'RMS Slope (x direction)': dict(value=2., unit='1'),  # absolute value of slope
    }

    assert result['xlabel'] == 'Slope'
    assert result['ylabel'] == 'Probability'
    assert result['xunit'] == '1'
    assert result['yunit'] == '1'

    assert len(result['series']) == 2

    exp_bins = np.array([-2-1/1500, -2, -2+1/1500])  # for slopes
    exp_slope_dist_values = [0, 1500, 0]  # integral with dx=1/3 results to 1
    series0 = result['series'][0]
    np.testing.assert_almost_equal(series0['x'], exp_bins)
    np.testing.assert_almost_equal(series0['y'], exp_slope_dist_values)
def test_height_distribution_simple_line_scan():
    x = np.array((1, 2, 3))
    y = 2 * x

    info = dict(unit='nm')

    t = NonuniformLineScan(x, y, info=info).detrend(detrend_mode='center')

    topography = FakeTopographyModel(t)

    result = height_distribution(topography)

    assert sorted(result.keys()) == EXPECTED_KEYS_FOR_DIST_ANALYSIS

    assert result['name'] == 'Height distribution'
    assert result['scalars'] == {
        'Mean Height': {'value': 0, 'unit': 'nm'},
        'RMS Height': {'value': math.sqrt(4. / 3), 'unit': 'nm'},
    }

    assert result['xlabel'] == 'Height'
    assert result['ylabel'] == 'Probability'
    assert result['xunit'] == 'nm'
    assert result['yunit'] == 'nm⁻¹'

    assert len(result['series']) == 2

    exp_bins = np.array([-1, 1])  # expected values for height bins
    exp_height_dist_values = [1. / 6, 2. / 6]  # expected values
    series0 = result['series'][0]
    np.testing.assert_almost_equal(series0['x'], exp_bins)
    np.testing.assert_almost_equal(series0['y'], exp_height_dist_values)
def test_power_spectrum_simple_nonuniform_linescan():
    unit = 'nm'
    x = np.arange(10)
    y = -2 * x ** 2  # constant curvature

    t = NonuniformLineScan(x, y, info=dict(unit=unit)).detrend(detrend_mode='center')
    topography = FakeTopographyModel(t)

    result = power_spectrum(topography)

    assert sorted(result.keys()) == EXPECTED_KEYS_FOR_PLOT_CARD_ANALYSIS

    assert result['name'] == 'Power-spectral density (PSD)'

    assert result['xlabel'] == 'Wavevector'
    assert result['ylabel'] == 'PSD'
    assert result['xunit'] == '{}⁻¹'.format(unit)
    assert result['yunit'] == '{}³'.format(unit)

    assert len(result['series']) == 2

    s0, s1 = result['series']

    assert s0['name'] == '1D PSD along x'
    assert s1['name'] == '1D PSD along x (incl. unreliable data)'
    def test_rms_height_nonuniform(self):
        numerical = NonuniformLineScan(self.X,
                                       self.sinsurf).rms_height_from_profile()
        analytical = np.sqrt(self.hm**2 / 2)
        # numerical = np.sqrt(np.trapz(self.sinsurf**2, self.X))

        self.assertAlmostEqual(numerical, analytical, self.precision)
    def test_attribute_error(self):
        t = NonuniformLineScan([1, 2, 4], [2, 4, 8])
        with self.assertRaises(AttributeError):
            t.scale_factor
        # a scaled line scan has a scale_factor
        self.assertEqual(t.scale(1).scale_factor, 1)

        #
        # This should also work after the topography has been pickled
        #
        pt = pickle.dumps(t)
        t2 = pickle.loads(pt)

        with self.assertRaises(AttributeError):
            t2.scale_factor
        # a scaled line scan has a scale_factor
        self.assertEqual(t2.scale(1).scale_factor, 1)
def test_contact_mechanics_incompatible_topography():
    x = np.arange(10)
    arr = 2 * x
    info = dict(unit='nm')
    t = NonuniformLineScan(x, arr, info=info).detrend("center")
    topography = FakeTopographyModel(t)

    with pytest.raises(IncompatibleTopographyException):
        contact_mechanics(topography)
    def test_nonuniform_quadratic(self):
        x = np.linspace(0, 10, 11) ** 1.3
        a = 1.2
        b = 1.8
        c = 0.3
        y = a + b * x + c * x * x / 2
        surf = NonuniformLineScan(x, y)
        self.assertAlmostEqual(surf.rms_curvature_from_profile(), c)

        surf = surf.detrend(detrend_mode='height')
        self.assertAlmostEqual(surf.mean(), 0.0)

        surf.detrend_mode = 'curvature'
        self.assertAlmostEqual(surf.mean(), 0.0)
        self.assertAlmostEqual(surf.rms_slope_from_profile(), 0.0)
        self.assertAlmostEqual(surf.rms_curvature_from_profile(), 0.0)
Example #14
0
    def test_setting_info_dict(self):
        x = np.array((0, 1, 1.5, 2, 3))
        h = 2 * x

        t = NonuniformLineScan(x, h)

        assert t.info == {}

        t = NonuniformLineScan(x, h, info=dict(unit='A'))
        assert t.info['unit'] == 'A'

        #
        # This info should be inherited in the pipeline
        #
        st = t.scale(2)
        assert st.info['unit'] == 'A'

        #
        # It should be also possible to set the info
        #
        st = t.scale(2, info=dict(unit='B'))
        assert st.info['unit'] == 'B'

        #
        # Again the info should be passed
        #
        dt = st.detrend(detrend_mode='center')
        assert dt.info['unit'] == 'B'

        #
        # Alternatively, it can be changed
        #
        dt = st.detrend(detrend_mode='center', info=dict(unit='C'))
        assert dt.info['unit'] == 'C'
def test_nonuniform_impulse_autocorrelation():
    a = 3
    b = 2
    x = np.array([0, a])
    t = NonuniformLineScan(x, b * np.ones_like(x))
    r, A = height_height_autocorrelation(t,
                                         distances=np.linspace(-4, 4, 101))

    A_ref = b ** 2 * (a - np.abs(r))
    A_ref[A_ref < 0] = 0

    assert_array_almost_equal(A, A_ref)

    a = 3
    b = 2
    x = np.array([-a, 0, 1e-9, a - 1e-9, a, 2 * a])
    y = np.zeros_like(x)
    y[2] = b
    y[3] = b
    t = NonuniformLineScan(x, y)
    r, A = height_height_autocorrelation(t,
                                         distances=np.linspace(-4, 4, 101))

    A_ref = b ** 2 * (a - np.abs(r))
    A_ref[A_ref < 0] = 0

    assert_array_almost_equal(A, A_ref)

    t = t.detrend(detrend_mode='center')
    r, A = height_height_autocorrelation(t,
                                         distances=np.linspace(0, 10, 201))

    s, = t.physical_sizes
    assert_almost_equal(A[0], t.rms_height_from_profile() ** 2 * s)
def test_variable_bandwidth_simple_nonuniform_linescan():
    x = np.arange(5)
    h = 2 * x
    info = dict(unit='nm')

    t = NonuniformLineScan(x, h, info=info).detrend('center')
    topography = FakeTopographyModel(t)

    result = variable_bandwidth(topography)

    assert sorted(result.keys()) == EXPECTED_KEYS_FOR_PLOT_CARD_ANALYSIS

    assert result['name'] == 'Variable-bandwidth analysis'
def nonuniform_line_scan(request):
    """Returns a nonuniform line scan, with all combinations of scaled and detrended.

    Detrended is always executed after scaling, if requested.

    Returns
    -------
    A nonuniform line scan.
    """
    x = np.array((0, 0.1, 0.2, 0.4, 0.5))
    h = np.sin(x)
    nonuniform_line_scan = NonuniformLineScan(x, h)
    return apply_param(nonuniform_line_scan, request.param)
 def test_power_spectrum_from_profile(self):
     #
     # this test was added, because there were issues calling
     # power spectrum 1D with a window given
     #
     t = NonuniformLineScan(x=[1, 2, 3, 4], y=[2, 4, 6, 8])
     q1, C1 = t.power_spectrum_from_profile(window='hann')
     q1, C1 = t.detrend('center').power_spectrum_from_profile(window='hann')
     q1, C1 = t.detrend('center').power_spectrum_from_profile()
     q1, C1 = t.detrend('height').power_spectrum_from_profile(window='hann')
     q1, C1 = t.detrend('height').power_spectrum_from_profile()
def test_autocorrelation_simple_nonuniform_topography():
    x = np.arange(5)
    h = 2 * x

    info = dict(unit='nm')

    t = NonuniformLineScan(x, h, info=info).detrend('center')
    topography = FakeTopographyModel(t)

    result = autocorrelation(topography)

    assert sorted(result.keys()) == EXPECTED_KEYS_FOR_PLOT_CARD_ANALYSIS

    assert result['name'] == 'Height-difference autocorrelation function (ACF)'
    def test_setting_info_dict(self):
        x = np.array((0, 1, 1.5, 2, 3))
        h = 2 * x

        t = NonuniformLineScan(x, h)

        assert t.info == {}

        with pytest.deprecated_call():
            t = NonuniformLineScan(x, h, info=dict(unit='A'))
        t = NonuniformLineScan(x, h, unit='A')
        with pytest.deprecated_call():
            assert t.info['unit'] == 'A'

        #
        # This info should be inherited in the pipeline
        #
        st = t.scale(2)
        with pytest.deprecated_call():
            assert st.info['unit'] == 'A'

        #
        # It should be also possible to set the info
        #
        with pytest.deprecated_call():
            st = t.scale(2, info=dict(unit='B'))
        st = t.scale(2, 1, unit='B')
        with pytest.deprecated_call():
            assert st.info['unit'] == 'B'

        #
        # Again the info should be passed
        #
        dt = st.detrend(detrend_mode='center')
        with pytest.deprecated_call():
            assert dt.info['unit'] == 'B'

        #
        # It can no longer be changed in detrend (you need to use scale)
        #
        with pytest.deprecated_call():
            dt = st.detrend(detrend_mode='center', info=dict(unit='C'))
def test_rectangle():
    for a, b in [(2.3, 1.45), (10.2, 0.1)]:
        x = np.array([-a, a])
        h = np.array([b, b])

        q = np.linspace(0.01, 8 * np.pi / a, 101)

        q, C = NonuniformLineScan(x,
                                  h).power_spectrum_1D(wavevectors=q,
                                                       algorithm='brute-force',
                                                       window='None')

        C_ana = (2 * b * np.sin(a * q) / q)**2
        C_ana /= 2 * a

        assert_array_almost_equal(C, C_ana)
def test_triangle():
    for a, b in [(0.5, -0.5), (1, 1), (2.3, 1.45), (10.2, 0.1)]:
        x = np.array([-a, a])
        h = np.array([-b, b])

        q = np.linspace(0.01, 8 * np.pi / a, 101)

        _, C = NonuniformLineScan(x, h).power_spectrum_from_profile(
            wavevectors=q,
            algorithm='brute-force',
            short_cutoff=None,
            window='None')

        C_ana = (2 * b * (a * q * np.cos(a * q) - np.sin(a * q)) /
                 (a * q**2))**2
        C_ana /= 2 * a

        assert_array_almost_equal(C, C_ana)
def test_rectangle_and_triangle():
    for a, b, c, d in [(0.123, 1.45, 10.1, 9.3), (-0.1, 5.4, -0.1, 3.43),
                       (-1, 1, 1, 1)]:
        x = np.array([a, b])
        h = np.array([c, d])

        q = np.linspace(0.01, 8 * np.pi / (b - a), 101)

        q, C = NonuniformLineScan(x, h).power_spectrum_from_profile(
            wavevectors=q, algorithm='brute-force', window='None')

        C_ana = np.exp(-1j *
                       (a + b) * q) * (np.exp(1j * a * q) *
                                       (c - d + 1j *
                                        (a - b) * d * q) + np.exp(1j * b * q) *
                                       (d - c - 1j *
                                        (a - b) * c * q)) / ((a - b) * q**2)
        C_ana = np.abs(C_ana)**2 / (b - a)

        assert_array_almost_equal(C, C_ana)
    def test_nonuniform2(self):
        x = np.array((1, 2, 3))
        y = 2 * x

        surf = NonuniformLineScan(x, y)
        self.assertFalse(surf.is_uniform)
        self.assertEqual(surf.dim, 1)
        der = surf.derivative(n=1)
        assert_array_equal(der, [2, 2])
        der = surf.derivative(n=2)
        assert_array_equal(der, [0])

        surf = surf.detrend(detrend_mode='height')
        self.assertFalse(surf.is_uniform)
        self.assertEqual(surf.dim, 1)

        der = surf.derivative(n=1)
        assert_array_equal(der, [0, 0])

        assert_array_equal(surf.heights(), np.zeros(y.shape))
        p = surf.positions_and_heights()
        assert_array_equal(p[0], x)
        assert_array_equal(p[1], np.zeros(y.shape))
def simple_surface():
    class WrapTopography:
        def __init__(self, t):
            self._t = t
        def topography(self):
            return self._t

    class WrapRequest:
        def __init__(self, c):
            self._c = c
        def all(self):
            return self._c

    class WrapSurface:
        def __init__(self, c):
            self._c = c
        @property
        def topography_set(self):
            return WrapRequest(self._c)

    nx, ny = 113, 123
    sx, sy = 1, 1
    lx = 0.3
    topographies = [
        Topography(np.resize(np.sin(np.arange(nx) * sx * 2 * np.pi / (nx * lx)), (nx, ny)), (sx, sy), periodic=False,
                   unit='um')
    ]

    nx = 278
    sx = 100
    lx = 2
    x = np.arange(nx) * sx / nx
    topographies += [
        NonuniformLineScan(x, np.cos(x * np.pi / lx), unit='nm')
    ]

    return WrapSurface([WrapTopography(t) for t in topographies])
def test_curvature_distribution_simple_line_scan():
    unit = 'nm'
    x = np.arange(10)
    y = -2 * x ** 2  # constant curvature

    t = NonuniformLineScan(x, y, info=dict(unit=unit)).detrend(detrend_mode='center')
    topography = FakeTopographyModel(t)

    bins = np.array((-4.75, -4.25, -3.75, -3.25))  # special for this test in order to know results
    result = curvature_distribution(topography, bins=bins)

    assert sorted(result.keys()) == EXPECTED_KEYS_FOR_DIST_ANALYSIS

    assert result['name'] == 'Curvature distribution'

    assert pytest.approx(result['scalars']['Mean Curvature']['value']) == -4
    assert pytest.approx(result['scalars']['RMS Curvature']['value']) == 4
    assert result['scalars']['Mean Curvature']['unit'] == '{}⁻¹'.format(unit)
    assert result['scalars']['RMS Curvature']['unit'] == '{}⁻¹'.format(unit)

    assert result['xlabel'] == 'Curvature'
    assert result['ylabel'] == 'Probability'
    assert result['xunit'] == '{}⁻¹'.format(unit)
    assert result['yunit'] == unit

    assert len(result['series']) == 2

    exp_bins = (bins[1:] + bins[:-1]) / 2
    exp_curv_dist_values = [0, 2, 0]

    # integral over dx= should be 1
    assert np.trapz(exp_curv_dist_values, exp_bins) == pytest.approx(1)

    series0 = result['series'][0]
    np.testing.assert_almost_equal(series0['x'], exp_bins)
    np.testing.assert_almost_equal(series0['y'], exp_curv_dist_values)
Example #27
0
    def test_nonuniform3(self):
        x = np.array((1, 2, 3, 4))
        y = -2 * x

        surf = NonuniformLineScan(x, y)
        self.assertFalse(surf.is_uniform)
        self.assertEqual(surf.dim, 1)

        der = surf.derivative(n=1)
        assert_array_equal(der, [-2, -2, -2])
        der = surf.derivative(n=2)
        assert_array_equal(der, [0, 0])

        #
        # Similar with detrend which substracts mean value
        #
        surf2 = surf.detrend(detrend_mode='center')
        self.assertFalse(surf2.is_uniform)
        self.assertEqual(surf.dim, 1)

        der = surf2.derivative(n=1)
        assert_array_equal(der, [-2, -2, -2])

        #
        # Similar with detrend which eliminates slope
        #
        surf3 = surf.detrend(detrend_mode='height')
        self.assertFalse(surf3.is_uniform)
        self.assertEqual(surf.dim, 1)

        der = surf3.derivative(n=1)
        np.testing.assert_allclose(der, [0, 0, 0], atol=1e-14)
        np.testing.assert_allclose(surf3.heights(),
                                   np.zeros(y.shape),
                                   atol=1e-14)
        p = surf3.positions_and_heights()
        assert_array_equal(p[0], x)
        np.testing.assert_allclose(p[1], np.zeros(y.shape), atol=1e-14)
 def test_nonuniform_linear(self):
     x = np.linspace(0, 10, 11) ** 2
     y = 1.8 * x + 1.2
     surf = NonuniformLineScan(x, y).detrend(detrend_mode='height')
     self.assertAlmostEqual(surf.mean(), 0.0)
     self.assertAlmostEqual(surf.rms_slope_from_profile(), 0.0)
 def test_rms_slope_nonuniform(self):
     numerical = NonuniformLineScan(self.X,
                                    self.sinsurf).rms_slope_from_profile()
     analytical = np.sqrt(2 * np.pi**2 * self.hm**2 / self.L**2)
     # print(numerical-analytical)
     self.assertAlmostEqual(numerical, analytical, self.precision)
 def test_properties(self):
     x = np.array((0, 1, 1.5, 2, 3))
     h = 2 * x
     t = NonuniformLineScan(x, h)
     self.assertEqual(t.dim, 1)