diff --git a/docs/notebooks b/docs/notebooks index aa3caa64..6821d690 160000 --- a/docs/notebooks +++ b/docs/notebooks @@ -1 +1 @@ -Subproject commit aa3caa64339f850a3f925732c617e56c67e5aba9 +Subproject commit 6821d690b95d768649a3e41c50b12272fd95343b diff --git a/mkdocs.yml b/mkdocs.yml index f9ad6e09..bd13863c 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -18,7 +18,7 @@ nav: - Pathways: notebooks/paths.ipynb - Percolation: notebooks/percolation.ipynb - Multiple paths: notebooks/multiple_paths.ipynb - - Orientation tracking: notebooks/rotations.ipynb + - Orientation tracking: notebooks/orientations.ipynb - Python API: - gemdat: api/gemdat.md - gemdat.collective: api/gemdat_collective.md diff --git a/pyproject.toml b/pyproject.toml index 4abe16ab..6fa2d4e4 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -82,7 +82,7 @@ source = ["gemdat"] [tool.pytest.ini_options] testpaths = ["tests"] -[tool.ruff] +[tool.lint] # Enable Pyflakes `E` and `F` codes by default. select = [ "F", # Pyflakes @@ -93,7 +93,7 @@ select = [ line-length = 110 -[tool.ruff.isort] +[tool.lint.isort] known-first-party=["gemdat"] known-third-party = ["pymatgen"] required-imports = ["from __future__ import annotations"] diff --git a/src/gemdat/__init__.py b/src/gemdat/__init__.py index 2beb72b8..aed8be35 100644 --- a/src/gemdat/__init__.py +++ b/src/gemdat/__init__.py @@ -2,7 +2,7 @@ from .io import load_known_material, read_cif from .jumps import Jumps -from .rotations import Orientations +from .orientations import Orientations from .shape import ShapeAnalyzer from .simulation_metrics import SimulationMetrics from .trajectory import Trajectory diff --git a/src/gemdat/rotations.py b/src/gemdat/orientations.py similarity index 82% rename from src/gemdat/rotations.py rename to src/gemdat/orientations.py index 9d5fe0bd..5d1dbfbd 100644 --- a/src/gemdat/rotations.py +++ b/src/gemdat/orientations.py @@ -6,6 +6,7 @@ from pymatgen.symmetry.groups import PointGroup from gemdat.trajectory import Trajectory +from gemdat.utils import fft_autocorrelation, cartesian_to_spherical @dataclass @@ -22,15 +23,12 @@ class Orientations: Type of the central atoms satellite_type: str Type of the satellite atoms - nr_central_atoms: int - Number of central atoms, which corresponds to the number of cluster molecules vectors: np.ndarray - Vectors representing rotation direction + Vectors representing orientation direction """ trajectory: Trajectory center_type: str satellite_type: str - nr_central_atoms: int vectors: np.ndarray = field(init=False) in_vectors: InitVar[np.ndarray | None] = None @@ -66,11 +64,6 @@ def _trajectory_sat(self) -> Trajectory: """Return trajectory of satellite atoms.""" return self.trajectory.filter(self.satellite_type) - def _fractional_coordinates(self) -> tuple[np.ndarray, np.ndarray]: - """Return fractional coordinates of central atoms and satellite - atoms.""" - return self._trajectory_cent.positions, self._trajectory_sat.positions - @property def _distances(self) -> np.ndarray: """Calculate distances between every central atom and all satellite @@ -127,7 +120,11 @@ def _central_satellite_matrix(self, distance: np.ndarray, combinations: np.ndarray Matrix of combinations between central and satellite atoms """ - index_central_atoms = np.arange(self.nr_central_atoms) + nr_central_atoms = frac_coord_cent.shape[1] + + index_central_atoms = np.arange(nr_central_atoms) + + # index_central_atoms = np.arange(self.nr_central_atoms) matching_matrix = self._matching_matrix(distance, frac_coord_cent) combinations = np.array([(i, j) for i in index_central_atoms for j in matching_matrix[i, :]]) @@ -147,7 +144,9 @@ def _fractional_directions(self, distance: np.ndarray) -> np.ndarray: direction: np.ndarray Contains the direction between central atoms and their ligands. """ - frac_coord_cent, frac_coord_sat = self._fractional_coordinates() + frac_coord_cent = self._trajectory_cent.positions + frac_coord_sat = self._trajectory_sat.positions + combinations = self._central_satellite_matrix(distance, frac_coord_cent) @@ -241,6 +240,36 @@ def transform(self, matrix: np.ndarray) -> Orientations: return replace(self, in_vectors=vectors) + @property + def vectors_spherical(self) -> np.ndarray: + """Return vectors in spherical coordinates in degrees. + + Returns + ------- + np.array + azimuth, elevation, length + """ + return cartesian_to_spherical(self.vectors) + + def autocorrelation(self): + """Compute the autocorrelation of the orientation vectors using FFT.""" + return fft_autocorrelation(self.vectors) + + def plot_rectilinear(self, **kwargs): + """See [gemdat.plots.rectilinear][] for more info.""" + from gemdat import plots + return plots.rectilinear(orientations=self, **kwargs) + + def plot_bond_length_distribution(self, **kwargs): + """See [gemdat.plots.bond_length_distribution][] for more info.""" + from gemdat import plots + return plots.bond_length_distribution(orientations=self, **kwargs) + + def plot_autocorrelation(self, **kwargs): + """See [gemdat.plots.unit_vector_autocorrelation][] for more info.""" + from gemdat import plots + return plots.autocorrelation(orientations=self, **kwargs) + def calculate_spherical_areas(shape: tuple[int, int], radius: float = 1) -> np.ndarray: @@ -273,44 +302,3 @@ def calculate_spherical_areas(shape: tuple[int, int], #hacky way to get rid of singularity on poles areas[0, :] = areas[-1, 0] return areas - - -def mean_squared_angular_displacement(trajectory: np.ndarray) -> np.ndarray: - """Compute the mean squared angular displacement using FFT. - - Parameters - ---------- - trajectory : np.ndarray - The input signal in direct cartesian coordinates. It is expected - to have shape (n_times, n_particles, n_coordinates) - - Returns - ------- - msad: - The mean squared angular displacement - """ - n_times, n_particles, n_coordinates = trajectory.shape - - msad = np.zeros((n_particles, n_times)) - normalization = np.arange(n_times, 0, -1) - - for c in range(n_coordinates): - signal = trajectory[:, :, c] - - # Compute the FFT of the signal - fft_signal = np.fft.rfft(signal, n=2 * n_times - 1, axis=0) - # Compute the power spectral density in-place - np.square(np.abs(fft_signal), out=fft_signal) - # Compute the inverse FFT of the power spectral density - autocorr_c = np.fft.irfft(fft_signal, axis=0) - - # Only keep the positive times - autocorr_c = autocorr_c[:n_times, :] - - msad += autocorr_c.T / normalization - - # Normalize the msad such that it starts from 1 - # (this makes the normalization independent on the dimensions) - msad = msad / msad[:, 0, np.newaxis] - - return msad diff --git a/src/gemdat/plots/__init__.py b/src/gemdat/plots/__init__.py index 4a3bb72f..cb219c01 100644 --- a/src/gemdat/plots/__init__.py +++ b/src/gemdat/plots/__init__.py @@ -3,14 +3,14 @@ # Matplotlib plots from .matplotlib import ( + autocorrelation, bond_length_distribution, energy_along_path, jumps_3d_animation, path_on_grid, radial_distribution, - rectilinear_plot, + rectilinear, shape, - unit_vector_autocorrelation, ) # Plotly plots (matplotlib version might be available) @@ -45,10 +45,10 @@ 'plot_3d', 'msd_per_element', 'radial_distribution', - 'rectilinear_plot', + 'rectilinear', 'shape', 'vibrational_amplitudes', 'energy_along_path', 'path_on_grid', - 'unit_vector_autocorrelation', + 'autocorrelation', ] diff --git a/src/gemdat/plots/matplotlib/__init__.py b/src/gemdat/plots/matplotlib/__init__.py index 26384cd2..cc90af17 100644 --- a/src/gemdat/plots/matplotlib/__init__.py +++ b/src/gemdat/plots/matplotlib/__init__.py @@ -20,10 +20,10 @@ path_on_grid, ) from ._rdf import radial_distribution -from ._rotations import ( +from ._orientations import ( + autocorrelation, bond_length_distribution, - rectilinear_plot, - unit_vector_autocorrelation, + rectilinear, ) from ._shape import shape from ._vibration import ( @@ -46,8 +46,8 @@ 'msd_per_element', 'path_on_grid', 'radial_distribution', - 'rectilinear_plot', + 'rectilinear', 'shape', - 'unit_vector_autocorrelation', + 'autocorrelation', 'vibrational_amplitudes', ] diff --git a/src/gemdat/plots/matplotlib/_rotations.py b/src/gemdat/plots/matplotlib/_orientations.py similarity index 82% rename from src/gemdat/plots/matplotlib/_rotations.py rename to src/gemdat/plots/matplotlib/_orientations.py index bb4db243..e1647bea 100644 --- a/src/gemdat/plots/matplotlib/_rotations.py +++ b/src/gemdat/plots/matplotlib/_orientations.py @@ -5,18 +5,16 @@ from scipy.optimize import curve_fit from scipy.stats import skewnorm -from gemdat.rotations import ( +from gemdat.orientations import ( Orientations, calculate_spherical_areas, - mean_squared_angular_displacement, ) -from gemdat.utils import cartesian_to_spherical -def rectilinear_plot(*, - orientations: Orientations, - shape: tuple[int, int] = (90, 360), - normalize_histo: bool = True) -> plt.Figure: +def rectilinear(*, + orientations: Orientations, + shape: tuple[int, int] = (90, 360), + normalize_histo: bool = True) -> plt.Figure: """Plot a rectilinear projection of a spherical function. This function uses the transformed trajectory. @@ -34,11 +32,10 @@ def rectilinear_plot(*, fig : matplotlib.figure.Figure Output figure """ - # Convert the trajectory to spherical coordinates - trajectory = cartesian_to_spherical(orientations.vectors, degrees=True) - - az = trajectory[:, :, 0].flatten() - el = trajectory[:, :, 1].flatten() + # Convert the vectors to spherical coordinates + az, el, _ = orientations.vectors_spherical.T + az = az.flatten() + el = el.flatten() hist, xedges, yedges = np.histogram2d(el, az, shape) @@ -92,14 +89,11 @@ def bond_length_distribution(*, fig : matplotlib.figure.Figure Output figure """ - - # Convert the trajectory to spherical coordinates - trajectory = cartesian_to_spherical(orientations.vectors, degrees=True) + *_, bond_lengths = orientations.vectors_spherical.T + bond_lengths = bond_lengths.flatten() fig, ax = plt.subplots() - bond_lengths = trajectory[:, :, 2].flatten() - # Plot the normalized histogram hist, edges = np.histogram(bond_lengths, bins=bins, density=True) bin_centers = (edges[:-1] + edges[1:]) / 2 @@ -135,7 +129,7 @@ def _skewnorm_fit(x): return fig -def unit_vector_autocorrelation( +def autocorrelation( *, orientations: Orientations, ) -> plt.Figure: @@ -151,11 +145,7 @@ def unit_vector_autocorrelation( fig : matplotlib.figure.Figure Output figure """ - - # The trajectory is expected to have shape (n_times, n_particles, n_coordinates) - trajectory = orientations.vectors - - ac = mean_squared_angular_displacement(trajectory) + ac = orientations.autocorrelation() ac_std = ac.std(axis=0) ac_mean = ac.mean(axis=0) diff --git a/src/gemdat/utils.py b/src/gemdat/utils.py index c7f41556..cbd32b94 100644 --- a/src/gemdat/utils.py +++ b/src/gemdat/utils.py @@ -13,7 +13,7 @@ # shortcut to test data VASPRUN = Path(__file__).parents[ 2] / 'tests' / 'data' / 'short_simulation' / 'vasprun.xml' -VASPCACHE_ROTATIONS = Path(__file__).parents[ +VASPCACHE_ORIENTATIONS = Path(__file__).parents[ 2] / 'tests' / 'data' / 'short_simulation' / 'vasprun_rotations.cache' DATA = files('gemdat') / 'data' @@ -229,25 +229,26 @@ def _cart2sph(x: np.ndarray, y: np.ndarray, return az, el, r -def cartesian_to_spherical(direct_cart: np.ndarray, - degrees: bool) -> np.ndarray: +def cartesian_to_spherical(cart_coords: np.ndarray, + *, + degrees: bool = True) -> np.ndarray: """Trajectory from cartesian coordinates to spherical coordinates. Parameters ---------- - direct_cart : np.ndarray - Trajectory of the unit vectors in conventional coordinates + cart_coords : np.ndarray + Trajectory of the unit vectors in cartesian setting degrees : bool If true, return angles in degrees Returns ------- - direction_spherical : np.ndarray + spherical_coords : np.ndarray Trajectory of the unit vectors in spherical coordinates """ - x = direct_cart[:, :, 0] - y = direct_cart[:, :, 1] - z = direct_cart[:, :, 2] + x = cart_coords[:, :, 0] + y = cart_coords[:, :, 1] + z = cart_coords[:, :, 2] az, el, r = _cart2sph(x, y, z) @@ -255,6 +256,47 @@ def cartesian_to_spherical(direct_cart: np.ndarray, az = np.degrees(az) el = np.degrees(el) - direction_spherical = np.stack((az, el, r), axis=-1) + spherical_coords = np.stack((az, el, r), axis=-1) - return direction_spherical + return spherical_coords + + +def fft_autocorrelation(coords: np.ndarray) -> np.ndarray: + """Compute the autocorrelation of the given coordinates using FFT. + + Parameters + ---------- + coords : np.ndarray + The input signal in direct cartesian coordinates. It is expected + to have shape (n_times, n_particles, n_coordinates) + + Returns + ------- + autocorrelation: np.array + The autocorrelation of the input signal, with shape (n_particles, n_times) + """ + n_times, n_particles, n_coordinates = coords.shape + + autocorrelation = np.zeros((n_particles, n_times)) + normalization = np.arange(n_times, 0, -1) + + for c in range(n_coordinates): + signal = coords[:, :, c] + + # Compute the FFT of the signal + fft_signal = np.fft.rfft(signal, n=2 * n_times - 1, axis=0) + # Compute the power spectral density in-place + np.square(np.abs(fft_signal), out=fft_signal) + # Compute the inverse FFT of the power spectral density + autocorr_c = np.fft.irfft(fft_signal, axis=0) + + # Only keep the positive times + autocorr_c = autocorr_c[:n_times, :] + + autocorrelation += autocorr_c.T / normalization + + # Normalize the autocorrelation such that it starts from 1 + # and make it independent of n_coordinates + autocorrelation = autocorrelation / autocorrelation[:, 0, np.newaxis] + + return autocorrelation diff --git a/tests/conftest.py b/tests/conftest.py index c2fa76d9..70c1853a 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -4,7 +4,7 @@ import pytest from pymatgen.core import Species -from gemdat.rotations import Orientations +from gemdat.orientations import Orientations from gemdat.trajectory import Trajectory @@ -33,6 +33,4 @@ def trajectory(): def orientations(trajectory): center_type = 'B' satellite_type = 'Si' - nr_central_atoms = 1 - return Orientations(trajectory, center_type, satellite_type, - nr_central_atoms) + return Orientations(trajectory, center_type, satellite_type) diff --git a/tests/integration/conftest.py b/tests/integration/conftest.py index bc621138..c6e9efba 100644 --- a/tests/integration/conftest.py +++ b/tests/integration/conftest.py @@ -8,15 +8,14 @@ from gemdat.jumps import Jumps from gemdat.path import find_best_perc_path, free_energy_graph from gemdat.rdf import radial_distribution -from gemdat.rotations import Orientations +from gemdat.orientations import Orientations from gemdat.shape import ShapeAnalyzer from gemdat.trajectory import Trajectory -from gemdat.utils import cartesian_to_spherical from gemdat.volume import trajectory_to_volume DATA_DIR = Path(__file__).parents[1] / 'data' VASP_XML = DATA_DIR / 'short_simulation' / 'vasprun.xml' -VASP_ROTO_CACHE = DATA_DIR / 'short_simulation' / 'vasprun_rotations.cache' +VASP_ORI_CACHE = DATA_DIR / 'short_simulation' / 'vasprun_rotations.cache' def pytest_configure(): @@ -26,8 +25,8 @@ def pytest_configure(): ('Simulation data from vasprun.xml example is required for this test. ' 'Run `git submodule init`/`update`, and extract using `tar -C tests/data/short_simulation ' '-xjf tests/data/short_simulation/vasprun.xml.bz2`')) - pytest.vasprotocache_available = pytest.mark.skipif( - not VASP_ROTO_CACHE.exists(), + pytest.vasporicache_available = pytest.mark.skipif( + not VASP_ORI_CACHE.exists(), reason= ('Simulation data from vasprun_rotations.cache example is required for this test. ' 'Run `git submodule init`/`update`, and extract using `tar -C tests/data/short_simulation ' @@ -42,8 +41,8 @@ def vasp_traj(): @pytest.fixture(scope='module') -def vasp_traj_rotations(): - trajectory = Trajectory.from_cache(VASP_ROTO_CACHE) +def vasp_traj_orientations(): + trajectory = Trajectory.from_cache(VASP_ORI_CACHE) return trajectory @@ -136,12 +135,11 @@ def vasp_F_graph(vasp_path_vol): @pytest.fixture(scope='module') -def vasp_orientations(vasp_traj_rotations): +def vasp_orientations(vasp_traj_orientations): central_atoms = 'S' satellite_atoms = 'O' - n_expected_neigh = 8 - orientations = Orientations(vasp_traj_rotations, central_atoms, - satellite_atoms, n_expected_neigh) + orientations = Orientations(vasp_traj_orientations, central_atoms, + satellite_atoms) return orientations @@ -149,5 +147,5 @@ def vasp_orientations(vasp_traj_rotations): @pytest.fixture(scope='module') def vasp_orientations_spherical(vasp_orientations): cf = vasp_orientations.get_conventional_coordinates() - cf_spheric = cartesian_to_spherical(cf, degrees=True) + cf_spheric = cf.get_vectors_spherical() return cf_spheric diff --git a/tests/integration/plot_test.py b/tests/integration/plot_test.py index 272cad7d..91e3c442 100644 --- a/tests/integration/plot_test.py +++ b/tests/integration/plot_test.py @@ -95,14 +95,14 @@ def test_rectilinear(vasp_orientations): [1 / 2**0.5, 1 / 6**0.5, -1 / 3**0.5], [0, 2 / 6**0.5, 1 / 3**0.5]], ) orientations = vasp_orientations.normalize().transform(matrix=matrix) - plots.rectilinear_plot(orientations=orientations, normalize_histo=False) + orientations.plot_rectilinear(normalize_histo=False) @image_comparison2(baseline_images=['bond_length_distribution']) def test_bond_length_distribution(vasp_orientations): - plots.bond_length_distribution(orientations=vasp_orientations, bins=1000) + vasp_orientations.plot_bond_length_distribution(bins=1000) @image_comparison2(baseline_images=['unit_vector_autocorrelation']) def test_unit_vector_autocorrelation(vasp_orientations): - plots.unit_vector_autocorrelation(orientations=vasp_orientations) + vasp_orientations.plot_autocorrelation() diff --git a/tests/integration/rotations_test.py b/tests/integration/rotations_test.py index 6a64a537..8d1e3be3 100644 --- a/tests/integration/rotations_test.py +++ b/tests/integration/rotations_test.py @@ -5,14 +5,14 @@ import numpy as np import pytest -from gemdat.rotations import calculate_spherical_areas +from gemdat.orientations import calculate_spherical_areas matrix = np.array( [[1 / 2**0.5, -1 / 6**0.5, 1 / 3**0.5], [1 / 2**0.5, 1 / 6**0.5, -1 / 3**0.5], [0, 2 / 6**0.5, 1 / 3**0.5]], ) -@pytest.vasprotocache_available # type: ignore +@pytest.vasporicache_available # type: ignore def test_normalize(vasp_orientations): ret = vasp_orientations.normalize() assert isclose(ret.vectors.std(), 0.5773501929401034) @@ -21,7 +21,7 @@ def test_normalize(vasp_orientations): atol=1e-06) -@pytest.vasprotocache_available # type: ignore +@pytest.vasporicache_available # type: ignore def test_conventional(vasp_orientations): ret = vasp_orientations.transform(matrix=matrix) assert isclose(ret.vectors.std(), 0.8668510720176622) @@ -30,7 +30,7 @@ def test_conventional(vasp_orientations): atol=1e-06) -@pytest.vasprotocache_available # type: ignore +@pytest.vasporicache_available # type: ignore def test_symmetrize(vasp_orientations): ret = vasp_orientations.symmetrize(sym_group='m-3m') assert isclose(ret.vectors.std(), 0.8668511628167984) @@ -39,7 +39,7 @@ def test_symmetrize(vasp_orientations): atol=1e-06) -@pytest.vasprotocache_available # type: ignore +@pytest.vasporicache_available # type: ignore def test_normalize_symmetrize(vasp_orientations): ret = vasp_orientations.normalize().symmetrize(sym_group='m-3m') assert isclose(ret.vectors.std(), 0.577350269189626) @@ -48,7 +48,7 @@ def test_normalize_symmetrize(vasp_orientations): atol=1e-06) -@pytest.vasprotocache_available # type: ignore +@pytest.vasporicache_available # type: ignore def test_normalize_conventional_symmetrize(vasp_orientations): ret = vasp_orientations.normalize().transform(matrix=matrix).symmetrize( sym_group='m-3m') @@ -58,7 +58,7 @@ def test_normalize_conventional_symmetrize(vasp_orientations): atol=1e-06) -@pytest.vasprotocache_available # type: ignore +@pytest.vasporicache_available # type: ignore def test_conventional_normalize_symmetrize(vasp_orientations): ret = vasp_orientations.transform(matrix=matrix).normalize().symmetrize( sym_group='m-3m') @@ -68,7 +68,7 @@ def test_conventional_normalize_symmetrize(vasp_orientations): atol=1e-06) -@pytest.vasprotocache_available # type: ignore +@pytest.vasporicache_available # type: ignore def test_fractional_coordinates(vasp_orientations): direction = vasp_orientations._fractional_directions( vasp_orientations._distances) @@ -77,7 +77,7 @@ def test_fractional_coordinates(vasp_orientations): assert isclose(direction[3, 12, 2], -0.10902666) -@pytest.vasprotocache_available # type: ignore +@pytest.vasporicache_available # type: ignore def test_matching_matrix(vasp_orientations): distance = np.array([[1.0, 2.0, 1.5, 0.5, 3.0], [2.0, 1.0, 0.5, 1.5, 3.0]]) frac_coord_cent = np.array([[[0.3, 0.11, 0.78], [1.6, 1.0, 2.3]]]) diff --git a/tests/rotations_test.py b/tests/orientations_test.py similarity index 74% rename from tests/rotations_test.py rename to tests/orientations_test.py index 6de6de6c..659426b9 100644 --- a/tests/rotations_test.py +++ b/tests/orientations_test.py @@ -5,30 +5,28 @@ import numpy as np from pymatgen.core import Species -from gemdat.rotations import ( +from gemdat.orientations import ( Orientations, calculate_spherical_areas, - mean_squared_angular_displacement, ) +from gemdat.utils import fft_autocorrelation def test_orientations_init(trajectory): orientations = Orientations(trajectory=trajectory, center_type='B', - satellite_type='Si', - nr_central_atoms=1) + satellite_type='Si') assert isinstance(orientations, Orientations) assert orientations.center_type == 'B' assert orientations.satellite_type == 'Si' - assert orientations.nr_central_atoms == 1 + assert orientations.trajectory == trajectory def test_normalize(trajectory): orientations = Orientations(trajectory=trajectory, center_type='B', satellite_type='Si', - nr_central_atoms=1, in_vectors=np.array([[1, 2, 2], [2, 2, 1]], dtype=float)) ret = orientations.normalize() @@ -40,7 +38,6 @@ def test_conventional(trajectory): orientations = Orientations(trajectory=trajectory, center_type='B', satellite_type='Si', - nr_central_atoms=1, in_vectors=np.array( [[1, 0, 0], [0, 1, 0], [0, 0, 1]], dtype=float)) @@ -54,7 +51,6 @@ def test_symmetrize(trajectory): orientations = Orientations(trajectory=trajectory, center_type='B', satellite_type='Si', - nr_central_atoms=1, in_vectors=np.array([[[1, 0, 0]], [[0, 1, 0]]], dtype=float)) sym_ops = np.array([[0, -1, 0], [1, 0, 0], [0, 0, -1]]) @@ -71,12 +67,6 @@ def test_orientations(orientations): assert orientations._trajectory_sat.species == [Species('Si')] -def test_fractional_coordinates(orientations): - frac_coord_cent, frac_coord_sat = orientations._fractional_coordinates() - assert isinstance(frac_coord_cent, np.ndarray) - assert isinstance(frac_coord_sat, np.ndarray) - - def test_distances(orientations): distances = orientations._distances assert isinstance(distances, np.ndarray) @@ -90,9 +80,9 @@ def test_calculate_spherical_areas(): assert areas.shape == shape -def test_mean_squared_angular_displacement(trajectory): - msad = mean_squared_angular_displacement(trajectory.positions) - assert isinstance(msad, np.ndarray) - assert isclose(msad.mean(), 0.8142314269325723) - assert msad.shape == (trajectory.positions.shape[1], - trajectory.positions.shape[0]) +def test_fft_autocorrelation(trajectory): + autocorr = fft_autocorrelation(trajectory.positions) + assert isinstance(autocorr, np.ndarray) + assert isclose(autocorr.mean(), 0.8142314269325723) + assert autocorr.shape == (trajectory.positions.shape[1], + trajectory.positions.shape[0])