def test_power_spectrum_from_profile(self): # # this test was added, because there were issues calling # power spectrum 1D with a window given # t = UniformLineScan([2, 4, 6, 8], 4) t.power_spectrum_from_profile(window='hann')
def test_checkerboard_detrend_order2_1d(): arr = np.zeros([6]) arr[:3] = 1.0 outarr = UniformLineScan(arr, arr.shape).checkerboard_detrend_profile(2, order=2) np.testing.assert_allclose(outarr, np.zeros([6]), atol=1e-12) arr[0] = -1.0 outarr = UniformLineScan(arr, arr.shape).checkerboard_detrend_profile(2, order=2) np.testing.assert_allclose(outarr, np.zeros([6]), atol=1e-12) arr[1] = 1.5 outarr = UniformLineScan(arr, arr.shape).checkerboard_detrend_profile(2, order=2) np.testing.assert_allclose(outarr, np.zeros([6]), atol=1e-12) # Order 1 (linear) cannot detrend this topography to zeros arr[1] = 1.5 outarr = UniformLineScan(arr, arr.shape).checkerboard_detrend_profile(2, order=1) np.testing.assert_allclose(outarr, [-0.5, 1.0, -0.5, 0.0, 0.0, 0.0], atol=1e-12)
def test_uniform(): for periodic in [True, False]: for L in [1.3, 10.6]: for k in [2, 4]: for n in [16, 128]: x = np.arange(n) * L / n h = np.sin(2 * np.pi * k * x / L) t = UniformLineScan(h, physical_sizes=L, periodic=periodic) q, C = t.power_spectrum_from_profile() # The ms height of the sine is 1/2. The sum over the PSD # (from -q to +q) is the ms height. Our PSD only contains # *half* of the full PSD (on the +q branch, the -q branch # is identical), therefore the sum over it is 1/4. assert_almost_equal(C.sum() / L, 1 / 4) if periodic: # The value at the individual wavevector must also # equal 1/4. This is only exactly true for the # periodic case. In the nonperiodic, this is convolved # with the Fourier transform of the window function. C /= L r = np.zeros_like(C) r[k] = 1 / 4 assert_array_almost_equal(C, r)
def test_squeeze(self): x = np.linspace(0, 4 * np.pi, 101) h = np.sin(x) surface = UniformLineScan(h, 4 * np.pi).scale(2.0) surface2 = surface.squeeze() self.assertTrue(isinstance(surface2, UniformLineScan)) np.testing.assert_allclose(surface.heights(), surface2.heights())
def test_init_with_lists_calling_scale_and_detrend(self): t = UniformLineScan([2, 4, 6, 8], 4) # initialize with list instead of arrays # the following commands should be possible without errors st = t.scale(1) st.detrend(detrend_mode='center')
def test_numeric_vs_analytical(): nx = 1001 L = 7.3 qs = 2 * np.pi * 8 / L t1 = UniformLineScan(np.sin(np.arange(nx) * L * qs / nx), L, periodic=True) x, y = t1.scale_dependent_slope_from_profile() assert_array_almost_equal(y, np.sqrt(1 - np.cos(qs * x)) / x)
def test_different_dictionary_instance_UniformLineScan(): """ see issue #301 """ a = UniformLineScan(np.array([1, 2, 3, 4]), physical_sizes=2) b = UniformLineScan(np.array([1, 8, 2, 4]), physical_sizes=1) assert id(a.info) != id(b.info)
def test_checkerboard_detrend_1d(): arr = np.zeros([6]) arr[:2] = 1.0 outarr = UniformLineScan(arr, arr.shape).checkerboard_detrend_profile(3) np.testing.assert_allclose(outarr, np.zeros([6]), atol=1e-12) arr[0] = -1.0 outarr = UniformLineScan(arr, arr.shape).checkerboard_detrend_profile(3) np.testing.assert_allclose(outarr, np.zeros([6]), atol=1e-12)
def test_rms_curvature_paraboloid_uniform_1D(): n = 16 x = np.arange(n) curvature = 0.1 heights = 0.5 * curvature * x**2 surf = UniformLineScan(heights, physical_sizes=(n, ), periodic=False) # central finite differences are second order and so exact for the parabola assert abs( (surf.rms_curvature_from_profile() - curvature) / curvature) < 1e-14
def test_analytic(): nb_pts = 1488 s = 4 * np.pi x = np.arange(nb_pts) * s / nb_pts h = np.sin(x) t1 = UniformLineScan(h, (s, )) t2 = UniformLineScan(h, (s, ), periodic=True) t3 = t1.to_nonuniform() d1 = t1.derivative(1) d2 = t2.derivative(1) d3 = t3.derivative(1) np.testing.assert_allclose(d1, np.cos(x[:-1] + (x[1] - x[0]) / 2), atol=1e-5) np.testing.assert_allclose(d2, np.cos(x + (x[1] - x[0]) / 2), atol=1e-5) np.testing.assert_allclose(d3, np.cos(x[:-1] + (x[1] - x[0]) / 2), atol=1e-5) d1 = t1.derivative(2) d2 = t2.derivative(2) d3 = t3.derivative(2) np.testing.assert_allclose(d1, -np.sin(x[:-2] + (x[1] - x[0])), atol=1e-5) np.testing.assert_allclose(d2, -np.sin(x), atol=1e-5) np.testing.assert_allclose(d3, -np.sin(x[:-2] + (x[1] - x[0])), atol=1e-5)
def test_detrend_heights_call(self): """ tests if the call of heights make no mistake """ n = 10 dx = 0.5 h = np.random.normal(size=n) t = UniformLineScan(h, dx * n) for mode in ["height", "curvature", "slope"]: detrended = t.detrend(detrend_mode=mode) detrended.heights()
def test_detrend_curvature(self): n = 10 dx = 0.5 x = np.arange(n) * dx R = 4. h = x ** 2 / R t = UniformLineScan(h, dx * n) detrended = t.detrend(detrend_mode="curvature") assert abs(detrended.coeffs[-1] / detrended.physical_sizes[0] ** 2 - 1 / R) < 1e-12
def test_positions_and_heights(self): h = np.array((0, 1, 2, 3, 4)) t = UniformLineScan(h, 4) assert_array_equal(t.heights(), h) expected_x = np.array((0., 0.8, 1.6, 2.4, 3.2)) np.testing.assert_allclose(t.positions(), expected_x) x2, h2 = t.positions_and_heights() np.testing.assert_allclose(x2, expected_x) assert_array_equal(h2, h)
def test_detrend_same_positions(self): """asserts that the detrended topography has the same x """ n = 10 dx = 0.5 h = np.random.normal(size=n) t = UniformLineScan(h, dx * n) for mode in ["curvature", "slope", "height"]: detrended = t.detrend(detrend_mode=mode) np.testing.assert_allclose(detrended.positions(), t.positions()) np.testing.assert_allclose(detrended.positions_and_heights()[0], t.positions_and_heights()[0])
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)
def test_detrend_reduces(self): """ tests if detrending really reduces the heights (or slope) as claimed """ n = 10 dx = 0.5 h = [0.82355941, -1.32205074, 0.77084813, 0.49928252, 0.57872149, 2.80200331, 0.09551251, -1.11616977, 2.07630937, -0.65408072] t = UniformLineScan(h, dx * n) for mode in ['height', 'curvature', 'slope']: detrended = t.detrend(detrend_mode=mode) self.assertAlmostEqual(detrended.mean(), 0) if mode == 'slope': self.assertGreater(t.rms_slope_from_profile(), detrended.rms_slope_from_profile(), msg=mode) else: self.assertGreater(t.rms_height_from_profile(), detrended.rms_height_from_profile(), msg=mode)
def test_attribute_error(self): h = np.array((0, 1, 2, 3, 4)) t = UniformLineScan(h, 4) with self.assertRaises(AttributeError): t.height_scale_factor # a scaled line scan has a scale_factor self.assertEqual(t.scale(1).height_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.height_scale_factor # a scaled line scan has a scale_factor self.assertEqual(t2.scale(1).height_scale_factor, 1)
def test_window_line_scan(): nx = 27 sx = 1.3 h = np.ones((nx, )) t = UniformLineScan(h, physical_sizes=(sx, ), periodic=True).window() np.testing.assert_almost_equal(t.heights()[0], 1.0) np.testing.assert_almost_equal((t.heights()**2).sum() / nx, 1.0) t = UniformLineScan(h, physical_sizes=(sx, ), periodic=False).window() np.testing.assert_almost_equal(t.heights()[0], 0.0) np.testing.assert_almost_equal((t.heights()**2).sum() / nx, 1.0) with pytest.raises(ValueError): UniformLineScan(h, physical_sizes=(sx, ), periodic=False).window(direction='y').window_data with pytest.raises(ValueError): UniformLineScan(h, physical_sizes=(sx, ), periodic=False).window(direction='radial').window_data
def test_uniform_impulse_autocorrelation(): nx = 16 for x, w, h, p in [(nx // 2, 3, 1, True), (nx // 3, 2, 2, True), (nx // 2, 5, 1, False), (nx // 3, 6, 2.5, False)]: y = np.zeros(nx) y[x - w // 2:x + (w + 1) // 2] = h r, A = UniformLineScan(y, nx, periodic=True).autocorrelation_from_profile() A_ana = np.zeros_like(A) A_ana[:w] = h ** 2 * np.linspace(w / nx, 1 / nx, w) A_ana = A_ana[0] - A_ana assert_array_almost_equal(A, A_ana)
def test_setting_info_dict(self): h = np.array((0, 1, 2, 3, 4)) t = UniformLineScan(h, 4) assert t.info == {} t = UniformLineScan(h, 4, 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 uniform_line_scan(request): """Returns a uniform line scan, with all combinations of scaled and detrended. Detrended is always executed after scaling, if requested. Returns ------- A uniform line scan. """ x = np.linspace(0, 4 * np.pi, 11) h = np.sin(x) uniform_line_scan = UniformLineScan(h, 4 * np.pi) return apply_param(uniform_line_scan, request.param)
def test_setting_info_dict(self): h = np.array((0, 1, 2, 3, 4)) t = UniformLineScan(h, 4) assert t.info == {} with pytest.deprecated_call(): t = UniformLineScan(h, 4, info=dict(unit='A')) t = UniformLineScan(h, 4, 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, 2, 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_default_window_1D(): x = np.linspace(0, 1, 200) heights = np.cos(2 * np.pi * x * 8.3) topography = UniformLineScan(heights, physical_sizes=1, periodic=True) if True: import matplotlib.pyplot as plt fig, ax = plt.subplots() ax.plot(*topography.power_spectrum_1D(), label="periodic=True") ax.set_xscale("log") ax.set_yscale("log") topography = UniformLineScan(heights, physical_sizes=1, periodic=False) if True: import matplotlib.pyplot as plt ax.plot(*topography.power_spectrum_1D(), label="periodic=False") ax.set_xscale("log") ax.set_yscale("log") ax.set_ylim(bottom=1e-6) ax.legend() plt.show(block=True)
def test_rms_slope_uniform(self): numerical = UniformLineScan(self.sinsurf[:-1], self.L).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_scale_factor(): nx = 8 sx = 1 topography = fourier_synthesis((nx, ), (sx, ), 0.8, rms_height=1., periodic=True) topography1 = UniformLineScan(topography.heights()[::2], sx, periodic=True) topography2 = UniformLineScan(topography.heights()[1::2], sx, periodic=True) d1 = topography.derivative(1, scale_factor=1) d2 = topography.derivative(1, scale_factor=np.uint32(2)) d3 = topography1.derivative(1, scale_factor=1) d4 = topography2.derivative(1, scale_factor=1) assert len(d2) == len(d1) np.testing.assert_allclose(d3, d2[::2]) np.testing.assert_allclose(d4, d2[1::2]) topography = fourier_synthesis((nx, ), (sx, ), 0.8, rms_height=1., periodic=False) topography1 = UniformLineScan(topography.heights()[::2], sx, periodic=False) topography2 = UniformLineScan(topography.heights()[1::2], sx, periodic=False) d1, d2 = topography.derivative(1, scale_factor=[1, 2]) d3 = topography1.derivative(1, scale_factor=1) d4 = topography2.derivative(1, scale_factor=1) assert len(d2) == len(d1) - 1 np.testing.assert_allclose(d3, d2[::2]) np.testing.assert_allclose(d4, d2[1::2]) ny = 10 sy = 0.8 topography = fourier_synthesis((nx, ny), (sx, sy), 0.8, rms_height=1., periodic=False) dx, dy = topography.derivative(1, scale_factor=[1, 2, 4]) dx1, dx2, dx4 = dx dy1, dy2, dy4 = dy assert dx1.shape[0] == nx - 1 assert dx1.shape[1] == ny - 1 assert dy1.shape[0] == nx - 1 assert dy1.shape[1] == ny - 1 assert dx2.shape[0] == nx - 2 assert dx2.shape[1] == ny - 2 assert dy2.shape[0] == nx - 2 assert dy2.shape[1] == ny - 2 assert dx4.shape[0] == nx - 4 assert dx4.shape[1] == ny - 4 assert dy4.shape[0] == nx - 4 assert dy4.shape[1] == ny - 4 dx, dy = topography.derivative(1, scale_factor=[(1, 4), (2, 1), (4, 2)]) dxn1, dxn2, dxn4 = dx dyn4, dyn1, dyn2 = dy np.testing.assert_allclose(dxn1, dx1) np.testing.assert_allclose(dyn1, dy1) np.testing.assert_allclose(dxn2, dx2) np.testing.assert_allclose(dyn2, dy2) np.testing.assert_allclose(dxn4, dx4) np.testing.assert_allclose(dyn4, dy4)
def test_lbfgsb_1D(dx, n): # test the 1D periodic objective is working s = n * dx Es = 1. substrate = PeriodicFFTElasticHalfSpace((n,), young=Es, physical_sizes=(s,), fft='serial') surface = UniformLineScan(np.cos(2 * np.pi * np.arange(n) / n), (s,)) system = make_system(substrate, surface) offset = 0.005 lbounds = np.zeros(n) bnds = system._reshape_bounds(lbounds, ) init_gap = np.zeros(n, ) # .flatten() disp = init_gap + surface.heights() + offset res = optim.minimize(system.primal_objective(offset, gradient=True), disp, method='L-BFGS-B', jac=True, bounds=bnds, options=dict(gtol=1e-5 * Es * surface.rms_slope_from_profile() * surface.area_per_pt, ftol=0)) forces = res.jac gap = res.x converged = res.success assert converged if hasattr(res.message, "decode"): decoded_message = res.message.decode() else: decoded_message = res.message assert decoded_message == \ 'CONVERGENCE: NORM_OF_PROJECTED_GRADIENT_<=_PGTOL' x = np.arange(n) * s / n mean_pressure = np.mean(forces) / substrate.area_per_pt assert mean_pressure > 0 pth = mean_pressure * _pressure( x / s, mean_pressure=s * mean_pressure / Es) if False: import matplotlib.pyplot as plt plt.figure() # plt.plot(np.arange(n)*s/n, surface.heights()) plt.plot(x, gap + (surface.heights()[:] + offset), 'r-') plt.plot(x, (surface.heights()[:] + offset), 'k-') plt.figure() plt.plot(x, forces / substrate.area_per_pt, 'k-') plt.plot(x, pth, 'r-') plt.show() assert (np.allclose( forces / substrate.area_per_pt, pth, atol=1e-2))
def test_properties(self): x = np.array((0, 1, 2, 3, 4)) h = 2 * x t = UniformLineScan(h, 5) self.assertEqual(t.dim, 1)
def test_smooth_flat_1d(self): arr = self._flat_arr a = 1.2 d = .2 arr = np.arange(5) * a + d surf = UniformLineScan(arr, (1,)).detrend(detrend_mode='center') self.assertTrue(surf.is_uniform) self.assertAlmostEqual(surf.mean(), 0) surf = UniformLineScan(arr, (1.5,)).detrend(detrend_mode='slope') self.assertEqual(surf.dim, 1) self.assertTrue(surf.is_uniform) self.assertAlmostEqual(surf.mean(), 0) self.assertAlmostEqual(surf.rms_slope_from_profile(), 0) surf = UniformLineScan(arr, arr.shape).detrend(detrend_mode='height') self.assertEqual(surf.dim, 1) self.assertTrue(surf.is_uniform) self.assertAlmostEqual(surf.mean(), 0) self.assertAlmostEqual(surf.rms_slope_from_profile(), 0) self.assertTrue( surf.rms_height_from_profile() < UniformLineScan(arr, arr.shape).rms_height_from_profile()) surf2 = UniformLineScan(arr, (1,)).detrend(detrend_mode='height') self.assertEqual(surf.dim, 1) self.assertTrue(surf2.is_uniform) self.assertAlmostEqual(surf2.rms_slope_from_profile(), 0) self.assertTrue( surf2.rms_height_from_profile() < UniformLineScan(arr, arr.shape).rms_height_from_profile()) self.assertAlmostEqual(surf.rms_height_from_profile(), surf2.rms_height_from_profile()) x, z = surf2.positions_and_heights() self.assertAlmostEqual(np.mean(np.diff(x)), surf2.physical_sizes[0] / surf2.nb_grid_pts[0])
def test_checkerboard_detrend_1d(self): arr = np.zeros([4]) arr[:2] = 1.0 outarr = UniformLineScan(arr, arr.shape).checkerboard_detrend((2,)) np.testing.assert_allclose(outarr, np.zeros([4]))