def test_project_vector3d(self): """Works for Vector3d objects with single and multiple vectors""" vector_one = Vector3d((0.578, 0.578, 0.578)) output_a = LambertProjection.project(vector_one) expected_a = np.array((0.81417, 0.81417)) assert (output_a[..., 0, 0]) == pytest.approx(expected_a[0], abs=1e-3) assert output_a[..., 0, 1] == pytest.approx(expected_a[1], abs=1e-3) vector_two = Vector3d( np.array( [[0.578, 0.578, 0.578], [0, 0.707, 0.707], [0.707, 0, 0.707]] ) ) output_b = LambertProjection.project(vector_two) expected_x = np.array((0.81417, 0, 0.678)) expected_y = np.array((0.81417, 0.678, 0)) assert output_b[..., 0, 0] == pytest.approx(expected_x[0], abs=1e-3) assert output_b[..., 0, 1] == pytest.approx(expected_y[0], abs=1e-3) assert output_b[..., 1, 0] == pytest.approx(expected_x[1], abs=1e-3) assert output_b[..., 1, 1] == pytest.approx(expected_y[1], abs=1e-3) assert output_b[..., 2, 0] == pytest.approx(expected_x[2], abs=1e-3) assert output_b[..., 2, 1] == pytest.approx(expected_y[2], abs=1e-3)
def test_project_ndarray(self): "Works for numpy ndarrays" ipt = np.array((0.578, 0.578, 0.578)) output = LambertProjection.project(ipt) expected = np.array((0.81417, 0.81417)) assert output[..., 0] == pytest.approx(expected[0], rel=1e-3) xyz = np.array(([0, 0, 1], [0, 1, 0], [2, 0, 0], [0, 0, -3])) xyz2 = np.array(([0, 0, -1], [0, -1, 0], [-2, 0, 0], [0, 0, 3])) xy = LambertProjection.project(xyz) xy2 = LambertProjection.project(xyz2) assert np.allclose( xy, ([0, 0], [0, np.sqrt(np.pi / 2)], [np.sqrt(np.pi / 2), 0], [0, 0]), ) assert np.allclose( xy2, ( [0, 0], [0, -np.sqrt(np.pi / 2)], [-np.sqrt(np.pi / 2), 0], [0, 0], ), )
def test_vector2xy_array(self): """Works for numpy arrays.""" output = LambertProjection.vector2xy(np.array([0.578, 0.578, 0.578])) assert np.allclose(output, 0.81480, atol=1e-5) xyz = np.array([ [0, 0, 1], [0, 1, 0], [2, 0, 0], [0, 0, -3], [0, 0, -1], [0, -1, 0], [-2, 0, 0], [0, 0, 3], ]) lambert_xy = [ [0, 0], [0, np.sqrt(np.pi / 2)], [np.sqrt(np.pi / 2), 0], [0, 0], [0, 0], [0, -np.sqrt(np.pi / 2)], [-np.sqrt(np.pi / 2), 0], [0, 0], ] assert np.allclose(LambertProjection.vector2xy(xyz), lambert_xy) assert np.allclose(_vector2xy.py_func(xyz), lambert_xy)
def test_shape_respect(self): """Check that LambertProjection.project() respects navigation axes""" sx = 60 a = np.arange(1, sx**2 + 1).reshape((sx, sx)) v = Vector3d(np.dstack([a, a, a])) assert v.shape == (sx, sx) assert v.data.shape == (sx, sx, 3) # Forward xy_lambert = LambertProjection.project(v) assert xy_lambert.shape == (sx, sx, 2) # and back xyz_frm_lambert = LambertProjection.iproject(xy_lambert) assert xyz_frm_lambert.shape == v.shape assert xyz_frm_lambert.data.shape == v.data.shape
def test_lambert_to_gnomonic(self): """Conversion from Lambert to Gnomonic works""" vec = np.array( (0.81417, 0.81417)) # Should give x,y,z = 1/sqrt(3) (1, 1, 1) output = LambertProjection.lambert_to_gnomonic(vec) expected = np.array((1, 1)) assert output[..., 0, 0] == pytest.approx(expected[0], abs=1e-2)
def test_iproject(self): """Conversion from Lambert to Cartesian coordinates works""" vec = np.array((0.81417, 0.81417)) expected = Vector3d((0.5770240896680434, 0.5770240896680434, 0.5780020760218183)) # Vector3d(1,) output = LambertProjection.iproject(vec) # Vector3d(1,1) assert output[0].x.data[0] == pytest.approx(expected.x.data[0], rel=1e-3) assert output[0].y.data[0] == pytest.approx(expected.y.data[0], rel=1e-3) assert output[0].z.data[0] == pytest.approx(expected.z.data[0], rel=1e-3)
def test_vector2xy_vector(self): """Works for Vector3d objects with single and multiple vectors""" vector_one = Vector3d((0.578, 0.578, 0.578)) output_a = LambertProjection.vector2xy(vector_one) expected_a = np.array((0.81417, 0.81417)) assert np.allclose(output_a[..., 0, 0], expected_a[0], atol=1e-3) assert np.allclose(output_a[..., 0, 1], expected_a[1], atol=1e-3) vector_two = Vector3d([[0.578, 0.578, 0.578], [0, 0.707, 0.707], [0.707, 0, 0.707]]) output_b = LambertProjection.vector2xy(vector_two) expected_x = np.array((0.81417, 0, 0.678)) expected_y = np.array((0.81417, 0.678, 0)) assert np.allclose(output_b[..., 0, 0], expected_x[0], atol=1e-3) assert np.allclose(output_b[..., 0, 1], expected_y[0], atol=1e-3) assert np.allclose(output_b[..., 1, 0], expected_x[1], atol=1e-3) assert np.allclose(output_b[..., 1, 1], expected_y[1], atol=1e-3) assert np.allclose(output_b[..., 2, 0], expected_x[2], atol=1e-3) assert np.allclose(output_b[..., 2, 1], expected_y[2], atol=1e-3)
def _get_lambert_interpolation_parameters( rotated_direction_cosines: Vector3d, npx: int, npy: int, scale: Union[int, float], ) -> tuple: """Get interpolation parameters in the square Lambert projection, as implemented in EMsoft. Parameters ---------- rotated_direction_cosines Rotated direction cosines vector. npx Number of pixels on the master pattern in the x direction. npy Number of pixels on the master pattern in the y direction. scale Factor to scale up from the square Lambert projection to the master pattern. Returns ------- nii : numpy.ndarray Row coordinate of a point. nij : numpy.ndarray Column coordinate of a point. niip : numpy.ndarray Row coordinate of neighboring point. nijp : numpy.ndarray Column coordinate of a neighboring point. di : numpy.ndarray Row interpolation weight factor. dj : numpy.ndarray Column interpolation weight factor. dim : numpy.ndarray Row interpolation weight factor. djm : numpy.ndarray Column interpolation weight factor. """ # Direction cosines to the square Lambert projection xy = ( scale * LambertProjection.project(rotated_direction_cosines) / (np.sqrt(np.pi / 2)) ) i = xy[..., 1] j = xy[..., 0] nii = (i + scale).astype(int) nij = (j + scale).astype(int) niip = nii + 1 nijp = nij + 1 niip = np.where(niip < npx, niip, nii).astype(int) nijp = np.where(nijp < npy, nijp, nij).astype(int) nii = np.where(nii < 0, niip, nii).astype(int) nij = np.where(nij < 0, nijp, nij).astype(int) di = i - nii + scale dj = j - nij + scale dim = 1.0 - di djm = 1.0 - dj return nii, nij, niip, nijp, di, dj, dim, djm
def test_gnomonic_to_lambert(self): """Conversion from Gnomonic to Lambert works""" vec = np.array((1, 1)) # Similar to the case above output = LambertProjection.gnomonic_to_lambert(vec) expected = np.array((0.81417, 0.81417)) assert output[..., 0, 0] == pytest.approx(expected[0], rel=1e-3)
def test_project_ndarray(self): "Works for numpy ndarrays" ipt = np.array((0.578, 0.578, 0.578)) output = LambertProjection.project(ipt) expected = np.array((0.81417, 0.81417)) assert output[..., 0] == pytest.approx(expected[0], rel=1e-3)
def test_xy2vector(self): """Conversion from Lambert to Cartesian coordinates works""" lambert_xy = np.array([0.81480, 0.81480]) v = LambertProjection.xy2vector(lambert_xy) assert np.allclose(v.data, 0.578, atol=1e-3)