From 276c54aae976fa078f50326076cfed7fa886f436 Mon Sep 17 00:00:00 2001 From: arm61 Date: Tue, 3 Jan 2023 15:11:08 +0100 Subject: [PATCH 1/2] Try a different sampling approach --- kinisi/diffusion.py | 27 ++++++++++++++++++++++----- kinisi/parser.py | 6 ++++-- 2 files changed, 26 insertions(+), 7 deletions(-) diff --git a/kinisi/diffusion.py b/kinisi/diffusion.py index 7fa19967..5dc5f09b 100644 --- a/kinisi/diffusion.py +++ b/kinisi/diffusion.py @@ -422,6 +422,19 @@ def conductivity(self, temperature: float, volume: float, **kwargs): conversion = 1000 / (volume * const.N_A) * (const.N_A * const.e)**2 / (const.R * temperature) self._sigma = Distribution(D * conversion) + @staticmethod + def n_samples(disp_shape, max_obs: int) -> int: + """ + Calculate the maximum number of independent observations. + :param disp_shape:: The shape of the displacements array. + :param max_obs: The maximum number of observations for the trajectory. + :return: Maximum number of independent observations. + """ + n_obs = disp_shape[1] + n_atoms = disp_shape[0] + dt_int = max_obs - n_obs + 1 + return int(max_obs / dt_int * n_atoms) + @property def sigma(self) -> Union[Distribution, None]: """ @@ -458,24 +471,28 @@ def __init__(self, delta_t: np.ndarray, disp_3d: List[np.ndarray], sub_sample_dt: int = 1, - n_resamples: int = 1000, - max_resamples: int = 10000, + n_resamples: int = 500, + max_resamples: int = 5000, dimension: str = 'xyz', alpha: float = 1e-3, + time_step: float = 1.0, + step_skip: int = 1, random_state: np.random.mtrand.RandomState = None, progress: bool = True): super().__init__(delta_t, disp_3d, sub_sample_dt, dimension) self._iterator = self.iterator(progress, range(len(self._displacements))) + timesteps = (delta_t / (np.diff(delta_t)[0])).astype(int) for i in self._iterator: disp_slice = self._displacements[i][:, :, self._slice].reshape(self._displacements[i].shape[0], self._displacements[i].shape[1], self.dims) d_squared = np.sum(disp_slice**2, axis=-1) if d_squared.size <= 1: continue - self._n_o = np.append(self._n_o, d_squared.size) + # n_i = self.n_samples(d_squared.shape, self._max_obs) + self._n_o = np.append(self._n_o, d_squared[:, ::timesteps[i]].size) self._euclidian_displacements.append(Distribution(np.sqrt(d_squared.flatten()))) - distro = self.sample_until_normal(d_squared, d_squared.size, n_resamples, max_resamples, alpha, - random_state) + distro = self.sample_until_normal(d_squared, d_squared[:, ::timesteps[i]].size, n_resamples, max_resamples, alpha, + random_state) self._distributions.append(distro) self._n = np.append(self._n, d_squared.mean()) self._s = np.append(self._s, np.std(distro.samples, ddof=1)) diff --git a/kinisi/parser.py b/kinisi/parser.py index 0f1078aa..722f40f8 100644 --- a/kinisi/parser.py +++ b/kinisi/parser.py @@ -176,7 +176,8 @@ def get_disps(self, disp_mem = 0 itemsize = drift_corrected.itemsize for i, timestep in enumerate(iterator): - disp_mem += np.product(drift_corrected[self.indices, timestep::timestep].shape) * itemsize + # disp_mem += np.product(drift_corrected[self.indices, timestep::timestep].shape) * itemsize + disp_mem += np.product(drift_corrected[self.indices, timestep::].shape) * itemsize disp_mem += (len(self.indices) * drift_corrected.shape[-1]) * itemsize disp_mem *= 1e-9 if disp_mem > self.memory_limit: @@ -194,7 +195,8 @@ def get_disps(self, np.subtract(drift_corrected[self.indices, timestep:], drift_corrected[self.indices, :-timestep]) ], axis=1) - disp_3d.append(disp[:, ::timestep]) + # disp_3d.append(disp[:, ::timestep]) + disp_3d.append(disp) else: raise ValueError( f"The sampling option of {self.sampling} is unrecognized, " From 51f5fcdf7782c67ffa1ee6bcf7d301887fb64ea7 Mon Sep 17 00:00:00 2001 From: arm61 Date: Fri, 6 Jan 2023 09:53:13 +0100 Subject: [PATCH 2/2] Implementing everything for running the paper/ --- docs/source/arrhenius_t.ipynb | 6 +- docs/source/vasp_d.ipynb | 5 +- docs/source/vasp_dj.ipynb | 363 ++++++++++++++++++++++++++++++ docs/source/vasp_msd.ipynb | 2 +- kinisi/analyzer.py | 39 ++-- kinisi/conductivity_analyzer.py | 14 +- kinisi/diffusion.py | 72 +++--- kinisi/diffusion_analyzer.py | 14 +- kinisi/jump_diffusion_analyzer.py | 14 +- kinisi/parser.py | 12 +- kinisi/tests/test_analyze.py | 2 +- kinisi/tests/test_diffusion.py | 132 +++++++---- kinisi/tests/test_parser.py | 17 +- 13 files changed, 558 insertions(+), 134 deletions(-) create mode 100644 docs/source/vasp_dj.ipynb diff --git a/docs/source/arrhenius_t.ipynb b/docs/source/arrhenius_t.ipynb index 00b175e3..0275116a 100644 --- a/docs/source/arrhenius_t.ipynb +++ b/docs/source/arrhenius_t.ipynb @@ -112,7 +112,7 @@ "id": "c204d962-a8f8-4989-9d84-e9a6ae52730f", "metadata": {}, "source": [ - "The list of diffusion coefficient objects (which are `uravu.distribution.Distribution` type objects) and array of temperatures can then be passed to the `kinisi.arrhenius.StandardArrhenius` class. " + "The list of diffusion coefficient objects (which are `uravu.distribution.Distribution` type objects) and array of temperatures can then be passed to the `kinisi.arrhenius.StandardArrhenius` class, where we use the `bounds` keyword argument to give a minimum and maximum value for the activation energy and preexponential factor." ] }, { @@ -122,7 +122,7 @@ "metadata": {}, "outputs": [], "source": [ - "s = StandardArrhenius(temperatures, D)" + "s = StandardArrhenius(temperatures, D, bounds=((0.01, 0.2), (1e-5, 1e-1)))" ] }, { @@ -140,7 +140,7 @@ "metadata": {}, "outputs": [], "source": [ - "s.max_likelihood('diff_evo')" + "s.max_likelihood('mini')" ] }, { diff --git a/docs/source/vasp_d.ipynb b/docs/source/vasp_d.ipynb index f4101fab..b24cc3a3 100644 --- a/docs/source/vasp_d.ipynb +++ b/docs/source/vasp_d.ipynb @@ -125,7 +125,8 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "It appears that the non-Gaussian parameter does not accurately predict the start of the diffusive regime for this example, so we will set the start of the diffusive regime to be 4 ps using the keyword argument of `dt_skip=4`. \n", + "It appears that the non-Gaussian parameter does okay at predicting the of the diffusive regime for this example (it is slightly underestimated), therefore we will set the `use_ngp` keyword argument to `True`. \n", + "If the non-Gaussian parameter gave an incorrect value, the start of the diffusive regim could be set to, say, 4 ps using the keyword argument of `dt_skip=4`. \n", "The `d_params` dictionary defines parameters about the diffusion estimation, documented in the [diffusion module](https://kinisi.readthedocs.io/en/latest/diffusion.html#kinisi.diffusion.MSDBootstrap). " ] }, @@ -135,7 +136,7 @@ "metadata": {}, "outputs": [], "source": [ - "d_params = {'dt_skip': 4}" + "d_params = {'use_ngp': True}" ] }, { diff --git a/docs/source/vasp_dj.ipynb b/docs/source/vasp_dj.ipynb new file mode 100644 index 00000000..ae819dcd --- /dev/null +++ b/docs/source/vasp_dj.ipynb @@ -0,0 +1,363 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": { + "tags": [] + }, + "source": [ + "# Diffusion coefficient from a VASP file\n", + "\n", + "[Previously](./vasp_msd.html), we looked at obtaining accurate estimates for the mean-squared displacement with `kinisi`. \n", + "Here, we show using the same class to evaluate the diffusion coefficient, using the `kinisi` [methodology](./methodology.html)." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import numpy as np\n", + "from kinisi.analyze import JumpDiffusionAnalyzer\n", + "from pymatgen.io.vasp import Xdatcar\n", + "np.random.seed(42)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "There the `p_params` dictionary describes details about the simulation, and are documented in the [parser module](./parser.html)." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "p_params = {'specie': 'Li',\n", + " 'time_step': 2.0,\n", + " 'step_skip': 50}" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "While the `b_params` dictionary describes the details of the bootstrapping process, these are documented in the [diffusion module](./diffusion.html#kinisi.diffusion.MSDBootstrap). Here, we indicate that we only want to investigate diffusion in the *xy*-plane of the system." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "b_params = {'dimension': 'xyz'}" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from kinisi.parser import PymatgenParser" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "xd = Xdatcar('./example_XDATCAR.gz')\n", + "diff = JumpDiffusionAnalyzer.from_Xdatcar(xd, parser_params=p_params, bootstrap_params=b_params)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "In the above cells, we parse and determine the uncertainty on the mean-squared displacement as a function of the timestep. \n", + "We should visualise this, to check that we are observing diffusion in our material and to determine the timescale at which this diffusion begins. " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import matplotlib.pyplot as plt" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "plt.errorbar(diff.dt, diff.tmsd, diff.tmsd_std)\n", + "plt.axvline(diff.ngp_max, color='g')\n", + "plt.ylabel('MSD/Å$^2$')\n", + "plt.xlabel('$\\Delta t$/ps')\n", + "plt.show()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The vertical green line indicates the start of the diffusive regime, based on the maximum of the [non-Gaussian parameter](https://doi.org/10.1073/pnas.1900239116). \n", + "We can also visualise this on a log-log scale, which helps to reveal the diffusive regime. " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "plt.errorbar(diff.dt, diff.tmsd, diff.tmsd_std)\n", + "plt.axvline(diff.ngp_max, color='g')\n", + "plt.ylabel('MSD/Å$^2$')\n", + "plt.xlabel('$\\Delta t$/ps')\n", + "plt.yscale('log')\n", + "plt.xscale('log')\n", + "plt.show()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "It appears that the non-Gaussian parameter does not accurately predict the start of the diffusive regime for this example, so we will set the start of the diffusive regime to be 4 ps using the keyword argument of `dt_skip=4`. \n", + "The `d_params` dictionary defines parameters about the diffusion estimation, documented in the [diffusion module](https://kinisi.readthedocs.io/en/latest/diffusion.html#kinisi.diffusion.MSDBootstrap). " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "d_params = {'dt_skip': 5}" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We can then run the diffusion analysis as follows. " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "diff.jump_diffusion(d_params)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "This method estimates the correlation matrix between the timesteps and uses likelihood sampling to find the diffusion coefficient, $D$ and intercept (the units are cm\\ :sup:`2`\\ /s and Å\\ :sup:`2` respectively).\n", + "Now we can probe these objects.\n", + "\n", + "We can get the median and 95 % confidence interval using, " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "diff.D_J.n, diff.D_J.con_int()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "diff.intercept.n, diff.intercept.con_int()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Or we can get all of the sampled values from one of these objects. " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "diff.D_J.samples" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "tags": [] + }, + "source": [ + "Having completed the analysis, we can save the object for use later (such as downstream by a plotting script). " + ] + }, + { + "cell_type": "markdown", + "metadata": { + "nbsphinx": "hidden", + "tags": [] + }, + "source": [ + "These hidden cells exist to remove any existing `example.hdf` file on builiding." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "nbsphinx": "hidden", + "tags": [] + }, + "outputs": [], + "source": [ + "!rm example.hdf" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "diff.save('example.hdf')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The data is saved in a HDF5 file format which helps us efficiently store our data. \n", + "We can then load the data with the following class method. " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "loaded_diff = JumpDiffusionAnalyzer.load('example.hdf')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We can plot the data with the credible intervals from the $D$ and $D_{\\text{offset}}$ distribution." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "credible_intervals = [[16, 84], [2.5, 97.5], [0.15, 99.85]]\n", + "alpha = [0.6, 0.4, 0.2]\n", + "\n", + "plt.plot(loaded_diff.dt, loaded_diff.tmsd, 'k-')\n", + "for i, ci in enumerate(credible_intervals):\n", + " plt.fill_between(loaded_diff.dt,\n", + " *np.percentile(loaded_diff.distribution, ci, axis=1),\n", + " alpha=alpha[i],\n", + " color='#0173B2',\n", + " lw=0)\n", + "plt.ylabel('MSD/Å$^2$')\n", + "plt.xlabel('$\\Delta t$/ps')\n", + "plt.show()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Additionally, we can visualise the distribution of the diffusion coefficient that has been determined." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "plt.hist(loaded_diff.D_J.samples, density=True)\n", + "plt.axvline(loaded_diff.D_J.n, c='k')\n", + "plt.xlabel('$D$/cm$^2$s$^{-1}$')\n", + "plt.ylabel('$p(D$/cm$^2$s$^{-1})$')\n", + "plt.show()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Or the joint probability distribution for the diffusion coefficient and intercept." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from corner import corner" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "corner(loaded_diff.flatchain, labels=['$D$/cm$^2$s$^{-1}$', 'intercept/Å$^2$'])\n", + "plt.show()" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.9.7" + } + }, + "nbformat": 4, + "nbformat_minor": 4 +} diff --git a/docs/source/vasp_msd.ipynb b/docs/source/vasp_msd.ipynb index 293655f5..d273f51d 100644 --- a/docs/source/vasp_msd.ipynb +++ b/docs/source/vasp_msd.ipynb @@ -95,7 +95,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.9.13" + "version": "3.9.7" } }, "nbformat": 4, diff --git a/kinisi/analyzer.py b/kinisi/analyzer.py index 8c33636a..c590c2a0 100644 --- a/kinisi/analyzer.py +++ b/kinisi/analyzer.py @@ -24,9 +24,10 @@ class Analyzer: :param volume: The volume of the simulation cell. """ - def __init__(self, delta_t: np.ndarray, disp_3d: List[np.ndarray], volume: float): + def __init__(self, delta_t: np.ndarray, disp_3d: List[np.ndarray], n_o: np.ndarray, volume: float): self._delta_t = delta_t self._disp_3d = disp_3d + self._n_o = n_o self._volume = volume def save(self, filename: str): @@ -71,7 +72,7 @@ def to_dict(self) -> dict: """ :return: Dictionary description of Analyzer. """ - return {'delta_t': self._delta_t, 'disp_3d': self._disp_3d, 'volume': self._volume} + return {'delta_t': self._delta_t, 'disp_3d': self._disp_3d, 'n_o': self._n_o, 'volume': self._volume} @classmethod def from_dict(cls, my_dict: dict) -> 'Analyzer': @@ -108,14 +109,17 @@ def _from_pymatgen(cls, """ if dtype is None: u = PymatgenParser(trajectory, **parser_params) - return cls(u.delta_t, u.disp_3d, u.volume, **kwargs) + return cls(u.delta_t, u.disp_3d, u._n_o, u.volume, **kwargs) elif dtype == 'identical': u = [PymatgenParser(f, **parser_params) for f in trajectory] - return cls(u[0].delta_t, cls._stack_trajectories(u), u[0].volume, **kwargs) + n_o = np.zeros(u[0]._n_o.size) + for i in u: + n_o += i._n_o + return cls(u[0].delta_t, cls._stack_trajectories(u), n_o, u[0].volume, **kwargs) elif dtype == 'consecutive': structures = _flatten_list([x for x in trajectory]) u = PymatgenParser(structures, **parser_params) - return cls(u.delta_t, u.disp_3d, u.volume, **kwargs) + return cls(u.delta_t, u.disp_3d, u._n_o, u.volume, **kwargs) else: raise ValueError('The dtype specified was not recognised, please consult the kinisi documentation.') @@ -143,14 +147,17 @@ def _from_Xdatcar(cls, if dtype is None: structures = trajectory.structures u = PymatgenParser(structures, **parser_params) - return cls(u.delta_t, u.disp_3d, u.volume, **kwargs) + return cls(u.delta_t, u.disp_3d, u._n_o, u.volume, **kwargs) elif dtype == 'identical': u = [PymatgenParser(f.structures, **parser_params) for f in trajectory] - return cls(u[0].delta_t, cls._stack_trajectories(u), u[0].volume, **kwargs) + n_o = np.zeros(u[0]._n_o.size) + for i in u: + n_o += i._n_o + return cls(u[0].delta_t, cls._stack_trajectories(u), n_o, u[0].volume, **kwargs) elif dtype == 'consecutive': structures = _flatten_list([x.structures for x in trajectory]) u = PymatgenParser(structures, **parser_params) - return cls(u.delta_t, u.disp_3d, u.volume, **kwargs) + return cls(u.delta_t, u.disp_3d, u._n_o, u.volume, **kwargs) else: raise ValueError('The dtype specified was not recognised, please consult the kinisi documentation.') @@ -176,15 +183,18 @@ def _from_file(cls, trajectory: Union[str, List[str]], parser_params: dict, dtyp if dtype is None: structures = Xdatcar(trajectory).structures u = PymatgenParser(structures, **parser_params) - return cls(u.delta_t, u.disp_3d, u.volume, **kwargs) + return cls(u.delta_t, u.disp_3d, u._n_o, u.volume, **kwargs) elif dtype == 'identical': u = [PymatgenParser(Xdatcar(f).structures, **parser_params) for f in trajectory] - return cls(u[0].delta_t, cls._stack_trajectories(u), u[0].volume, **kwargs) + n_o = np.zeros(u[0]._n_o.size) + for i in u: + n_o += i._n_o + return cls(u[0].delta_t, cls._stack_trajectories(u), n_o, u[0].volume, **kwargs) elif dtype == 'consecutive': trajectory_list = (Xdatcar(f) for f in trajectory) structures = _flatten_list([x.structures for x in trajectory_list]) u = PymatgenParser(structures, **parser_params) - return cls(u.delta_t, u.disp_3d, u.volume, **kwargs) + return cls(u.delta_t, u.disp_3d, u._n_o, u.volume, **kwargs) else: raise ValueError('The dtype specified was not recognised, please consult the kinisi documentation.') @@ -215,10 +225,13 @@ def _from_universe(cls, "To use the MDAnalysis from file parsing, MDAnalysis must be installed.") # pragma: no cover if dtype is None: u = MDAnalysisParser(trajectory, **parser_params) - return cls(u.delta_t, u.disp_3d, u.volume, **kwargs) + return cls(u.delta_t, u.disp_3d, u._n_o, u.volume, **kwargs) elif dtype == 'identical': u = [MDAnalysisParser(t, **parser_params) for t in trajectory] - return cls(u[0].delta_t, cls._stack_trajectories(u), u[0].volume, **kwargs) + n_o = np.zeros(u[0]._n_o.size) + for i in u: + n_o += i._n_o + return cls(u[0].delta_t, cls._stack_trajectories(u), n_o, u[0].volume, **kwargs) else: raise ValueError('The dtype specified was not recognised, please consult the kinisi documentation.') diff --git a/kinisi/conductivity_analyzer.py b/kinisi/conductivity_analyzer.py index e47ba580..9d441cfa 100644 --- a/kinisi/conductivity_analyzer.py +++ b/kinisi/conductivity_analyzer.py @@ -33,8 +33,8 @@ class ConductivityAnalyzer(Analyzer): if all values are the same. Optional, default is :py:attr:`1`. """ - def __init__(self, delta_t: np.ndarray, disp_3d: List[np.ndarray], volume: float): - super().__init__(delta_t, disp_3d, volume) + def __init__(self, delta_t: np.ndarray, disp_3d: List[np.ndarray], n_o: np.ndarray,volume: float): + super().__init__(delta_t, disp_3d, n_o, volume) self._diff = None def to_dict(self) -> dict: @@ -54,7 +54,7 @@ def from_dict(cls, my_dict: dict) -> 'ConductivityAnalyzer': :return: New :py:class`ConductivityAnalyzer` object. """ - cond_anal = cls(my_dict['delta_t'], my_dict['disp_3d'], my_dict['volume']) + cond_anal = cls(my_dict['delta_t'], my_dict['disp_3d'], my_dict['n_o'], my_dict['volume']) cond_anal._diff = diffusion.Bootstrap.from_dict(my_dict['diff']) return cond_anal @@ -88,7 +88,7 @@ def from_pymatgen(cls, if bootstrap_params is None: bootstrap_params = {} cond_anal = super()._from_pymatgen(trajectory, parser_params, dtype=dtype) - cond_anal._diff = diffusion.MSCDBootstrap(cond_anal._delta_t, cond_anal._disp_3d, ionic_charge, + cond_anal._diff = diffusion.MSCDBootstrap(cond_anal._delta_t, cond_anal._disp_3d, ionic_charge, cond_anal._n_o, **bootstrap_params) return cond_anal @@ -121,7 +121,7 @@ def from_Xdatcar(cls, if bootstrap_params is None: bootstrap_params = {} cond_anal = super()._from_Xdatcar(trajectory, parser_params, dtype=dtype) - cond_anal._diff = diffusion.MSCDBootstrap(cond_anal._delta_t, cond_anal._disp_3d, ionic_charge, + cond_anal._diff = diffusion.MSCDBootstrap(cond_anal._delta_t, cond_anal._disp_3d, ionic_charge, cond_anal._n_o, **bootstrap_params) return cond_anal @@ -152,7 +152,7 @@ def from_file(cls, if bootstrap_params is None: bootstrap_params = {} cond_anal = super()._from_file(trajectory, parser_params, dtype=dtype) - cond_anal._diff = diffusion.MSCDBootstrap(cond_anal._delta_t, cond_anal._disp_3d, ionic_charge, + cond_anal._diff = diffusion.MSCDBootstrap(cond_anal._delta_t, cond_anal._disp_3d, ionic_charge, cond_anal._n_o, **bootstrap_params) return cond_anal @@ -184,7 +184,7 @@ def from_universe(cls, if bootstrap_params is None: bootstrap_params = {} cond_anal = super()._from_universe(trajectory, parser_params, dtype=dtype) - cond_anal._diff = diffusion.MSCDBootstrap(cond_anal._delta_t, cond_anal._disp_3d, ionic_charge, + cond_anal._diff = diffusion.MSCDBootstrap(cond_anal._delta_t, cond_anal._disp_3d, ionic_charge, cond_anal._n_o, **bootstrap_params) return cond_anal diff --git a/kinisi/diffusion.py b/kinisi/diffusion.py index 5dc5f09b..9b6be462 100644 --- a/kinisi/diffusion.py +++ b/kinisi/diffusion.py @@ -27,7 +27,14 @@ 'xy': np.s_[:2], 'xz': np.s_[::2], 'yz': np.s_[1:], - 'xyz': np.s_[:] + 'xyz': np.s_[:], + b'x': np.s_[0], + b'y': np.s_[1], + b'z': np.s_[2], + b'xy': np.s_[:2], + b'xz': np.s_[::2], + b'yz': np.s_[1:], + b'xyz': np.s_[:] } @@ -44,7 +51,7 @@ class Bootstrap: :param progress: Show tqdm progress for sampling. Optional, default is :py:attr:`True`. """ - def __init__(self, delta_t: np.ndarray, disp_3d: List[np.ndarray], sub_sample_dt: int = 1, dimension='xyz'): + def __init__(self, delta_t: np.ndarray, disp_3d: List[np.ndarray], n_o: np.ndarray, sub_sample_dt: int = 1, dimension: str='xyz'): self._displacements = disp_3d[::sub_sample_dt] self._delta_t = np.array(delta_t[::sub_sample_dt]) self._max_obs = self._displacements[0].shape[1] @@ -53,9 +60,10 @@ def __init__(self, delta_t: np.ndarray, disp_3d: List[np.ndarray], sub_sample_dt self._n = np.array([]) self._s = np.array([]) self._v = np.array([]) - self._n_i = np.array([], dtype=int) - self._n_o = np.array([], dtype=int) + self._n_o = n_o self._ngp = np.array([]) + self._sub_sample_dt = sub_sample_dt + self._dimension = dimension self._euclidian_displacements = [] self._diffusion_coefficient = None self._jump_diffusion_coefficient = None @@ -64,6 +72,7 @@ def __init__(self, delta_t: np.ndarray, disp_3d: List[np.ndarray], sub_sample_dt self.gradient = None self.flatchain = None self._covariance_matrix = None + print(dimension) self._slice = DIMENSIONALITY[dimension.lower()] self.dims = len(dimension.lower()) @@ -74,12 +83,14 @@ def to_dict(self) -> dict: my_dict = { 'displacements': self._displacements, 'delta_t': self._delta_t, + 'n_o': self._n_o, 'max_obs': self._max_obs, 'dt': self._dt, 'n': self._n, 's': self._s, 'v': self._v, - 'n_i': self._n_i, + 'sub_sample_dt': self._sub_sample_dt, + 'dimension': self._dimension, 'ngp': self._ngp, 'covariance_matrix': self._covariance_matrix, 'diffusion_coefficient': None, @@ -112,7 +123,7 @@ def from_dict(cls, my_dict: dict) -> 'Bootstrap': :return: New :py:class`Bootstrap` object. """ - boot = cls(my_dict['delta_t'], my_dict['displacements'], sub_sample_dt=1, dimension='xyz') + boot = cls(my_dict['delta_t'], my_dict['displacements'], my_dict['n_o'], sub_sample_dt=my_dict['sub_sample_dt'], dimension=my_dict['dimension']) boot._max_obs = my_dict['max_obs'] boot._distributions = [Distribution.from_dict(d) for d in my_dict['distributions']] boot._euclidian_displacements = [Distribution.from_dict(d) for d in my_dict['euclidian_displacements']] @@ -120,7 +131,7 @@ def from_dict(cls, my_dict: dict) -> 'Bootstrap': boot._n = my_dict['n'] boot._s = my_dict['s'] boot._v = my_dict['v'] - boot._n_i = my_dict['n_i'] + boot._n_o = my_dict['n_o'] boot._ngp = my_dict['ngp'] if my_dict['diffusion_coefficient'] is not None: boot._diffusion_coefficient = Distribution.from_dict(my_dict['diffusion_coefficient']) @@ -422,19 +433,6 @@ def conductivity(self, temperature: float, volume: float, **kwargs): conversion = 1000 / (volume * const.N_A) * (const.N_A * const.e)**2 / (const.R * temperature) self._sigma = Distribution(D * conversion) - @staticmethod - def n_samples(disp_shape, max_obs: int) -> int: - """ - Calculate the maximum number of independent observations. - :param disp_shape:: The shape of the displacements array. - :param max_obs: The maximum number of observations for the trajectory. - :return: Maximum number of independent observations. - """ - n_obs = disp_shape[1] - n_atoms = disp_shape[0] - dt_int = max_obs - n_obs + 1 - return int(max_obs / dt_int * n_atoms) - @property def sigma(self) -> Union[Distribution, None]: """ @@ -454,6 +452,7 @@ class MSDBootstrap(Bootstrap): :code:`[atom, displacement observation, dimension]`. There is one array in the list for each delta_t value. Note: it is necessary to use a list of arrays as the number of observations is not necessary the same at each data point. + :param n_o: Number of statistically independent observations of the MSD at each timestep. :param sub_sample_dt: The frequency in observations to be sampled. Default is :py:attr:`1` (every observation) :param n_resamples: The initial number of resamples to be performed. Default is :py:attr:`1000` :param max_resamples: The max number of resamples to be performed by the distribution is assumed to be normal. @@ -470,28 +469,24 @@ class MSDBootstrap(Bootstrap): def __init__(self, delta_t: np.ndarray, disp_3d: List[np.ndarray], + n_o: np.ndarray, sub_sample_dt: int = 1, - n_resamples: int = 500, - max_resamples: int = 5000, + n_resamples: int = 1000, + max_resamples: int = 10000, dimension: str = 'xyz', alpha: float = 1e-3, - time_step: float = 1.0, - step_skip: int = 1, random_state: np.random.mtrand.RandomState = None, progress: bool = True): - super().__init__(delta_t, disp_3d, sub_sample_dt, dimension) + super().__init__(delta_t, disp_3d, n_o, sub_sample_dt, dimension) self._iterator = self.iterator(progress, range(len(self._displacements))) - timesteps = (delta_t / (np.diff(delta_t)[0])).astype(int) for i in self._iterator: disp_slice = self._displacements[i][:, :, self._slice].reshape(self._displacements[i].shape[0], self._displacements[i].shape[1], self.dims) d_squared = np.sum(disp_slice**2, axis=-1) if d_squared.size <= 1: continue - # n_i = self.n_samples(d_squared.shape, self._max_obs) - self._n_o = np.append(self._n_o, d_squared[:, ::timesteps[i]].size) self._euclidian_displacements.append(Distribution(np.sqrt(d_squared.flatten()))) - distro = self.sample_until_normal(d_squared, d_squared[:, ::timesteps[i]].size, n_resamples, max_resamples, alpha, + distro = self.sample_until_normal(d_squared, int(n_o[i]), n_resamples, max_resamples, alpha, random_state) self._distributions.append(distro) self._n = np.append(self._n, d_squared.mean()) @@ -499,6 +494,7 @@ def __init__(self, self._v = np.append(self._v, np.var(distro.samples, ddof=1)) self._ngp = np.append(self._ngp, self.ngp_calculation(d_squared)) self._dt = np.append(self._dt, self._delta_t[i]) + self._n_o = self._n_o[:self._n.size] class TMSDBootstrap(Bootstrap): @@ -511,6 +507,7 @@ class TMSDBootstrap(Bootstrap): :code:`[atom, displacement observation, dimension]`. There is one array in the list for each delta_t value. Note: it is necessary to use a list of arrays as the number of observations is not necessary the same at each data point. + :param n_o: Number of statistically independent observations of the MSD at each timestep. :param sub_sample_dt: The frequency in observations to be sampled. Optional, default is :py:attr:`1` (every observation) :param n_resamples: The initial number of resamples to be performed. Optional, default @@ -530,6 +527,7 @@ class TMSDBootstrap(Bootstrap): def __init__(self, delta_t: np.ndarray, disp_3d: List[np.ndarray], + n_o: np.ndarray, sub_sample_dt: int = 1, n_resamples: int = 1000, max_resamples: int = 10000, @@ -537,7 +535,7 @@ def __init__(self, alpha: float = 1e-3, random_state: np.random.mtrand.RandomState = None, progress: bool = True): - super().__init__(delta_t, disp_3d, sub_sample_dt, dimension) + super().__init__(delta_t, disp_3d, n_o, sub_sample_dt, dimension) self._iterator = self.iterator(progress, range(int(len(self._displacements) / 2))) for i in self._iterator: disp_slice = self._displacements[i][:, :, self._slice].reshape(self._displacements[i].shape[0], @@ -546,9 +544,9 @@ def __init__(self, coll_motion = np.sum(np.sum(disp_slice, axis=0)**2, axis=-1) if coll_motion.size <= 1: continue - self._n_o = np.append(self._n_o, coll_motion.size) + self._n_o = np.append(self._n_o, n_o[i]) self._euclidian_displacements.append(Distribution(np.sqrt(d_squared.flatten()))) - distro = self.sample_until_normal(coll_motion, coll_motion.size, n_resamples, max_resamples, alpha, + distro = self.sample_until_normal(coll_motion, int(n_o[i] / d_squared.shape[0]), n_resamples, max_resamples, alpha, random_state) self._distributions.append(distro) self._n = np.append(self._n, distro.n) @@ -556,6 +554,7 @@ def __init__(self, self._v = np.append(self._v, np.var(distro.samples, ddof=1)) self._ngp = np.append(self._ngp, self.ngp_calculation(d_squared.flatten())) self._dt = np.append(self._dt, self._delta_t[i]) + self._n_o = self._n_o[:self._n.size] class MSCDBootstrap(Bootstrap): @@ -570,6 +569,7 @@ class MSCDBootstrap(Bootstrap): not necessary the same at each data point. :param ionic_charge: The charge on the mobile ions, either an array with a value for each ion or a scalar if all values are the same. + :param n_o: Number of statistically independent observations of the MSD at each timestep. :param sub_sample_dt: The frequency in observations to be sampled. Optional, default is :py:attr:`1` (every observation). :param n_resamples: The initial number of resamples to be performed. Optional, default is :py:attr:`1000`. @@ -589,6 +589,7 @@ def __init__(self, delta_t: np.ndarray, disp_3d: List[np.ndarray], ionic_charge: Union[np.ndarray, int], + n_o: np.ndarray, sub_sample_dt: int = 1, n_resamples: int = 1000, max_resamples: int = 10000, @@ -596,7 +597,7 @@ def __init__(self, alpha: float = 1e-3, random_state: np.random.mtrand.RandomState = None, progress: bool = True): - super().__init__(delta_t, disp_3d, sub_sample_dt, dimension) + super().__init__(delta_t, disp_3d, n_o, sub_sample_dt, dimension) self._iterator = self.iterator(progress, range(int(len(self._displacements) / 2))) try: _ = len(ionic_charge) @@ -609,9 +610,9 @@ def __init__(self, sq_chg_motion = np.sum(np.sum((ionic_charge * self._displacements[i].T).T, axis=0)**2, axis=-1) if sq_chg_motion.size <= 1: continue - self._n_o = np.append(self._n_o, sq_chg_motion.size) + self._n_o = np.append(self._n_o, n_o[i]) self._euclidian_displacements.append(Distribution(np.sqrt(d_squared.flatten()))) - distro = self.sample_until_normal(sq_chg_motion, sq_chg_motion.size, n_resamples, max_resamples, alpha, + distro = self.sample_until_normal(sq_chg_motion, int(n_o[i] / d_squared.shape[0]), n_resamples, max_resamples, alpha, random_state) self._distributions.append(distro) self._n = np.append(self._n, distro.n) @@ -619,6 +620,7 @@ def __init__(self, self._v = np.append(self._v, np.var(distro.samples, ddof=1)) self._ngp = np.append(self._ngp, self.ngp_calculation(d_squared.flatten())) self._dt = np.append(self._dt, self._delta_t[i]) + self._n_o = self._n_o[:self._n.size] def _bootstrap(array: np.ndarray, n_samples: int, n_resamples: int, random_state: np.random.mtrand.RandomState = None): diff --git a/kinisi/diffusion_analyzer.py b/kinisi/diffusion_analyzer.py index 81361295..91f0b8c9 100644 --- a/kinisi/diffusion_analyzer.py +++ b/kinisi/diffusion_analyzer.py @@ -31,8 +31,8 @@ class DiffusionAnalyzer(Analyzer): the appropriate documentation for more guidance on this. Optional, default is the default bootstrap parameters. """ - def __init__(self, delta_t: np.ndarray, disp_3d: List[np.ndarray], volume: float): - super().__init__(delta_t, disp_3d, volume) + def __init__(self, delta_t: np.ndarray, disp_3d: List[np.ndarray], n_o: np.ndarray, volume: float): + super().__init__(delta_t, disp_3d, n_o, volume) self._diff = None def to_dict(self) -> dict: @@ -52,7 +52,7 @@ def from_dict(cls, my_dict: dict) -> 'DiffusionAnalyzer': :return: New :py:class:`DiffusionAnalyzer` object. """ - diff_anal = cls(my_dict['delta_t'], my_dict['disp_3d'], my_dict['volume']) + diff_anal = cls(my_dict['delta_t'], my_dict['disp_3d'], my_dict['n_o'], my_dict['volume']) diff_anal._diff = diffusion.Bootstrap.from_dict(my_dict['diff']) return diff_anal @@ -84,7 +84,7 @@ def from_pymatgen(cls, if bootstrap_params is None: bootstrap_params = {} diff = super()._from_pymatgen(trajectory, parser_params, dtype=dtype) - diff._diff = diffusion.MSDBootstrap(diff._delta_t, diff._disp_3d, **bootstrap_params) + diff._diff = diffusion.MSDBootstrap(diff._delta_t, diff._disp_3d, diff._n_o, **bootstrap_params) return diff @classmethod @@ -113,7 +113,7 @@ def from_Xdatcar(cls, if bootstrap_params is None: bootstrap_params = {} diff = super()._from_Xdatcar(trajectory, parser_params, dtype=dtype) - diff._diff = diffusion.MSDBootstrap(diff._delta_t, diff._disp_3d, **bootstrap_params) + diff._diff = diffusion.MSDBootstrap(diff._delta_t, diff._disp_3d, diff._n_o, **bootstrap_params) return diff @classmethod @@ -140,7 +140,7 @@ def from_file(cls, if bootstrap_params is None: bootstrap_params = {} diff = super()._from_file(trajectory, parser_params, dtype=dtype) - diff._diff = diffusion.MSDBootstrap(diff._delta_t, diff._disp_3d, **bootstrap_params) + diff._diff = diffusion.MSDBootstrap(diff._delta_t, diff._disp_3d, diff._n_o, **bootstrap_params) return diff @classmethod @@ -168,7 +168,7 @@ def from_universe(cls, if bootstrap_params is None: bootstrap_params = {} diff = super()._from_universe(trajectory, parser_params, dtype=dtype) - diff._diff = diffusion.MSDBootstrap(diff._delta_t, diff._disp_3d, **bootstrap_params) + diff._diff = diffusion.MSDBootstrap(diff._delta_t, diff._disp_3d, diff._n_o, **bootstrap_params) return diff def diffusion(self, diffusion_params: Union[dict, None] = None): diff --git a/kinisi/jump_diffusion_analyzer.py b/kinisi/jump_diffusion_analyzer.py index 3ad5876e..324e4db2 100644 --- a/kinisi/jump_diffusion_analyzer.py +++ b/kinisi/jump_diffusion_analyzer.py @@ -31,8 +31,8 @@ class JumpDiffusionAnalyzer(Analyzer): the appropriate documentation for more guidance on this. Optional, default is the default bootstrap parameters. """ - def __init__(self, delta_t: np.ndarray, disp_3d: List[np.ndarray], volume: float): - super().__init__(delta_t, disp_3d, volume) + def __init__(self, delta_t: np.ndarray, disp_3d: List[np.ndarray], n_o: np.ndarray, volume: float): + super().__init__(delta_t, disp_3d, n_o, volume) self._diff = None def to_dict(self) -> dict: @@ -52,7 +52,7 @@ def from_dict(cls, my_dict) -> 'JumpDiffusionAnalyzer': :return: New :py:class:`DiffusionAnalyzer` object. """ - jdiff_anal = cls(my_dict['delta_t'], my_dict['disp_3d'], my_dict['volume']) + jdiff_anal = cls(my_dict['delta_t'], my_dict['disp_3d'], my_dict['n_o'], my_dict['volume']) jdiff_anal._diff = diffusion.Bootstrap.from_dict(my_dict['diff']) return jdiff_anal @@ -83,7 +83,7 @@ def from_pymatgen(cls, if bootstrap_params is None: bootstrap_params = {} jdiff_anal = super()._from_pymatgen(trajectory, parser_params, dtype=dtype) - jdiff_anal._diff = diffusion.TMSDBootstrap(jdiff_anal._delta_t, jdiff_anal._disp_3d, **bootstrap_params) + jdiff_anal._diff = diffusion.TMSDBootstrap(jdiff_anal._delta_t, jdiff_anal._disp_3d, jdiff_anal._n_o, **bootstrap_params) return jdiff_anal @classmethod @@ -112,7 +112,7 @@ def from_Xdatcar(cls, if bootstrap_params is None: bootstrap_params = {} jdiff_anal = super()._from_Xdatcar(trajectory, parser_params, dtype=dtype) - jdiff_anal._diff = diffusion.TMSDBootstrap(jdiff_anal._delta_t, jdiff_anal._disp_3d, **bootstrap_params) + jdiff_anal._diff = diffusion.TMSDBootstrap(jdiff_anal._delta_t, jdiff_anal._disp_3d, jdiff_anal._n_o, **bootstrap_params) return jdiff_anal @classmethod @@ -139,7 +139,7 @@ def from_file(cls, if bootstrap_params is None: bootstrap_params = {} jdiff_anal = super()._from_file(trajectory, parser_params, dtype=dtype) - jdiff_anal._diff = diffusion.TMSDBootstrap(jdiff_anal._delta_t, jdiff_anal._disp_3d, **bootstrap_params) + jdiff_anal._diff = diffusion.TMSDBootstrap(jdiff_anal._delta_t, jdiff_anal._disp_3d, jdiff_anal._n_o, **bootstrap_params) return jdiff_anal @classmethod @@ -167,7 +167,7 @@ def from_universe(cls, if bootstrap_params is None: bootstrap_params = {} jdiff_anal = super()._from_universe(trajectory, parser_params, dtype=dtype) - jdiff_anal._diff = diffusion.TMSDBootstrap(jdiff_anal._delta_t, jdiff_anal._disp_3d, **bootstrap_params) + jdiff_anal._diff = diffusion.TMSDBootstrap(jdiff_anal._delta_t, jdiff_anal._disp_3d, jdiff_anal._n_o, **bootstrap_params) return jdiff_anal def jump_diffusion(self, jump_diffusion_params: Union[dict, None] = None): diff --git a/kinisi/parser.py b/kinisi/parser.py index 722f40f8..5320eb85 100644 --- a/kinisi/parser.py +++ b/kinisi/parser.py @@ -86,7 +86,7 @@ def __init__(self, self.timesteps = self.get_timesteps(n_steps, spacing) - self.delta_t, self.disp_3d = self.get_disps(self.timesteps, drift_corrected, progress) + self.delta_t, self.disp_3d, self._n_o = self.get_disps(self.timesteps, drift_corrected, progress) @property def volume(self) -> float: @@ -169,6 +169,7 @@ def get_disps(self, """ delta_t = timesteps * self.time_step * self.step_skip disp_3d = [] + n_samples = np.array([]) if progress: iterator = tqdm(timesteps, desc='Getting Displacements') else: @@ -176,7 +177,6 @@ def get_disps(self, disp_mem = 0 itemsize = drift_corrected.itemsize for i, timestep in enumerate(iterator): - # disp_mem += np.product(drift_corrected[self.indices, timestep::timestep].shape) * itemsize disp_mem += np.product(drift_corrected[self.indices, timestep::].shape) * itemsize disp_mem += (len(self.indices) * drift_corrected.shape[-1]) * itemsize disp_mem *= 1e-9 @@ -188,6 +188,8 @@ def get_disps(self, for i, timestep in enumerate(iterator): if self.sampling == 'single-origin': disp = drift_corrected[self.indices, i:i + 1] + if np.multiply(*disp[:, ::timestep].shape[:2]) <= 1: + continue disp_3d.append(disp) elif self.sampling == 'non-overlapping': disp = np.concatenate([ @@ -195,14 +197,16 @@ def get_disps(self, np.subtract(drift_corrected[self.indices, timestep:], drift_corrected[self.indices, :-timestep]) ], axis=1) - # disp_3d.append(disp[:, ::timestep]) + if np.multiply(*disp[:, ::timestep].shape[:2]) <= 1: + continue disp_3d.append(disp) else: raise ValueError( f"The sampling option of {self.sampling} is unrecognized, " "please use 'non-overlapping' or 'single-origin'." ) - return delta_t, disp_3d + n_samples = np.append(n_samples, np.multiply(*disp[:, ::timestep].shape[:2])) + return delta_t, disp_3d, n_samples class PymatgenParser(Parser): diff --git a/kinisi/tests/test_analyze.py b/kinisi/tests/test_analyze.py index 3c198997..d926c4d2 100644 --- a/kinisi/tests/test_analyze.py +++ b/kinisi/tests/test_analyze.py @@ -56,7 +56,7 @@ def test_xdatcar_pmg(self): assert_almost_equal(a._delta_t.max(), 14.0) assert len(a._disp_3d) == 100 assert a._disp_3d[0].shape == (192, 140, 3) - assert a._disp_3d[1].shape == (192, 70, 3) + assert a._disp_3d[1].shape == (192, 139, 3) assert a._disp_3d[-1].shape == (192, 1, 3) def test_file_path_pmg(self): diff --git a/kinisi/tests/test_diffusion.py b/kinisi/tests/test_diffusion.py index 330fc54e..4d9d553c 100644 --- a/kinisi/tests/test_diffusion.py +++ b/kinisi/tests/test_diffusion.py @@ -28,8 +28,9 @@ class TestBootstrap(unittest.TestCase): def test_dictionary_roundtrip(self): disp_3d = [RNG.randn(100, i, 3) for i in range(20, 10, -1)] + n_o = np.ones(len(disp_3d)) * 100 dt = np.linspace(100, 1000, 10) - a = Bootstrap(dt, disp_3d) + a = Bootstrap(dt, disp_3d, n_o) b = Bootstrap.from_dict(a.to_dict()) for i, d in enumerate(disp_3d): assert_almost_equal(a._displacements[i], b._displacements[i]) @@ -43,8 +44,9 @@ def test_dictionary_roundtrip(self): def test_initialisation(self): disp_3d = [RNG.randn(100, i, 3) for i in range(20, 10, -1)] + n_o = np.ones(len(disp_3d)) * 100 dt = np.linspace(100, 1000, 10) - bs = Bootstrap(dt, disp_3d) + bs = Bootstrap(dt, disp_3d, n_o) for i, d in enumerate(disp_3d): assert_almost_equal(bs._displacements[i], d) assert_almost_equal(bs._delta_t, dt) @@ -57,8 +59,9 @@ def test_initialisation(self): def test_initialisation_sub_sample_dt(self): disp_3d = [RNG.randn(100, i, 3) for i in range(20, 10, -1)] + n_o = np.ones(len(disp_3d)) * 100 dt = np.linspace(100, 1000, 10) - bs = Bootstrap(dt, disp_3d, sub_sample_dt=2) + bs = Bootstrap(dt, disp_3d, n_o, sub_sample_dt=2) for i, d in enumerate(disp_3d[::2]): assert_almost_equal(bs._displacements[i], d) assert_almost_equal(bs._delta_t, dt[::2]) @@ -112,8 +115,9 @@ class TestMSDBootstrap(unittest.TestCase): def test_dictionary_roundtrip(self): with warnings.catch_warnings(record=True) as _: disp_3d = [RNG.randn(100, i, 3) for i in range(20, 10, -1)] + n_o = np.ones(len(disp_3d)) * 100 dt = np.linspace(100, 1000, 10) - a = MSDBootstrap(dt, disp_3d, random_state=np.random.RandomState(0)) + a = MSDBootstrap(dt, disp_3d, n_o, random_state=np.random.RandomState(0)) b = MSDBootstrap.from_dict(a.to_dict()) for i, d in enumerate(disp_3d): assert_almost_equal(a._displacements[i], b._displacements[i]) @@ -135,8 +139,9 @@ def test_dictionary_roundtrip(self): def test_initialisation(self): with warnings.catch_warnings(record=True) as _: disp_3d = [RNG.randn(100, i, 3) for i in range(20, 10, -1)] + n_o = np.ones(len(disp_3d)) * 100 dt = np.linspace(100, 1000, 10) - bs = MSDBootstrap(dt, disp_3d, random_state=np.random.RandomState(0)) + bs = MSDBootstrap(dt, disp_3d, n_o, random_state=np.random.RandomState(0)) assert bs.n.shape == (10, ) assert bs.s.shape == (10, ) assert_almost_equal(bs.v, np.square(bs.s)) @@ -150,8 +155,9 @@ def test_initialisation(self): def test_initialisation_n_resamples(self): with warnings.catch_warnings(record=True) as _: disp_3d = [RNG.randn(100, i, 3) for i in range(20, 10, -1)] + n_o = np.ones(len(disp_3d)) * 100 dt = np.linspace(100, 1000, 10) - bs = MSDBootstrap(dt, disp_3d, n_resamples=10, random_state=np.random.RandomState(0)) + bs = MSDBootstrap(dt, disp_3d, n_o, n_resamples=10, random_state=np.random.RandomState(0)) assert bs.n.shape == (10, ) assert bs.s.shape == (10, ) assert_almost_equal(bs.v, np.square(bs.s)) @@ -165,8 +171,9 @@ def test_initialisation_n_resamples(self): def test_initialisation_max_resamples(self): with warnings.catch_warnings(record=True) as _: disp_3d = [RNG.randn(100, i, 3) for i in range(20, 10, -1)] + n_o = np.ones(len(disp_3d)) * 100 dt = np.linspace(100, 1000, 10) - bs = MSDBootstrap(dt, disp_3d, n_resamples=10, max_resamples=100, random_state=np.random.RandomState(0)) + bs = MSDBootstrap(dt, disp_3d, n_o, n_resamples=10, max_resamples=100, random_state=np.random.RandomState(0)) assert bs.n.shape == (10, ) assert bs.s.shape == (10, ) assert_almost_equal(bs.v, np.square(bs.s)) @@ -180,8 +187,9 @@ def test_initialisation_max_resamples(self): def test_initialisation_random_state(self): with warnings.catch_warnings(record=True) as _: disp_3d = [RNG.randn(100, i, 3) for i in range(20, 10, -1)] + n_o = np.ones(len(disp_3d)) * 100 dt = np.linspace(100, 1000, 10) - bs1 = MSDBootstrap(dt, disp_3d, random_state=np.random.RandomState(0)) + bs1 = MSDBootstrap(dt, disp_3d, n_o, random_state=np.random.RandomState(0)) assert bs1.n.shape == (10, ) assert bs1.s.shape == (10, ) assert_almost_equal(bs1.v, np.square(bs1.s)) @@ -191,15 +199,16 @@ def test_initialisation_random_state(self): assert isinstance(i, Distribution) for i in bs1._distributions: assert i.samples.size >= 1000 - bs2 = MSDBootstrap(dt, disp_3d, random_state=np.random.RandomState(0)) + bs2 = MSDBootstrap(dt, disp_3d, n_o, random_state=np.random.RandomState(0)) assert bs1._distributions[-1].size == bs2._distributions[-1].size assert_almost_equal(bs1._distributions[-1].samples, bs2._distributions[-1].samples) def test_initialisation_progress(self): with warnings.catch_warnings(record=True) as _: disp_3d = [RNG.randn(100, i, 3) for i in range(20, 10, -1)] + n_o = np.ones(len(disp_3d)) * 100 dt = np.linspace(100, 1000, 10) - bs = MSDBootstrap(dt, disp_3d, progress=False, random_state=np.random.RandomState(0)) + bs = MSDBootstrap(dt, disp_3d, n_o, progress=False, random_state=np.random.RandomState(0)) assert bs.n.shape == (10, ) assert bs.s.shape == (10, ) assert_almost_equal(bs.v, np.square(bs.s)) @@ -214,8 +223,9 @@ def test_initialisation_progress(self): def test_initialisation_skip_where_low_samples(self): with warnings.catch_warnings(record=True) as _: disp_3d = [RNG.randn(1, i, 3) for i in range(10, 1, -1)] + n_o = np.ones(len(disp_3d)) * 100 dt = np.linspace(100, 1000, 10) - bs = MSDBootstrap(dt, disp_3d, progress=False, random_state=np.random.RandomState(0)) + bs = MSDBootstrap(dt, disp_3d, n_o, progress=False, random_state=np.random.RandomState(0)) assert bs.n.shape == (9, ) assert bs.s.shape == (9, ) assert_almost_equal(bs.v, np.square(bs.s)) @@ -230,8 +240,9 @@ def test_initialisation_skip_where_low_samples(self): def test_bootstrap_dictionary_roundtrip(self): with warnings.catch_warnings(record=True) as _: disp_3d = [RNG.randn(100, i, 3) for i in range(20, 10, -1)] + n_o = np.ones(len(disp_3d)) * 100 dt = np.linspace(100, 1000, 10) - a = MSDBootstrap(dt, disp_3d, random_state=np.random.RandomState(0)) + a = MSDBootstrap(dt, disp_3d, n_o, random_state=np.random.RandomState(0)) a.diffusion() b = MSDBootstrap.from_dict(a.to_dict()) for i, d in enumerate(disp_3d): @@ -254,8 +265,9 @@ def test_bootstrap_dictionary_roundtrip(self): def test_bootstrap(self): with warnings.catch_warnings(record=True) as _: disp_3d = [RNG.randn(100, i, 3) for i in range(20, 10, -1)] + n_o = np.ones(len(disp_3d)) * 100 dt = np.linspace(100, 1000, 10) - bs = MSDBootstrap(dt, disp_3d, random_state=RNG) + bs = MSDBootstrap(dt, disp_3d, n_o, random_state=RNG) bs.diffusion() assert bs.covariance_matrix.shape == (10, 10) assert isinstance(bs._diffusion_coefficient, Distribution) @@ -266,8 +278,9 @@ def test_bootstrap(self): def test_bootstrap_dt_skip(self): with warnings.catch_warnings(record=True) as _: disp_3d = [RNG.randn(100, i, 3) for i in range(20, 10, -1)] + n_o = np.ones(len(disp_3d)) * 100 dt = np.linspace(100, 1000, 10) - bs = MSDBootstrap(dt, disp_3d) + bs = MSDBootstrap(dt, disp_3d, n_o) bs.diffusion(dt_skip=150) assert bs.covariance_matrix.shape == (9, 9) assert isinstance(bs._diffusion_coefficient, Distribution) @@ -278,8 +291,9 @@ def test_bootstrap_dt_skip(self): def test_bootstrap_use_ngp(self): with warnings.catch_warnings(record=True) as _: disp_3d = [RNG.randn(100, i, 3) for i in range(200, 10, -1)] + n_o = np.ones(len(disp_3d)) * 100 dt = np.linspace(100, 1000, 190) - bs = MSDBootstrap(dt, disp_3d, random_state=RNG) + bs = MSDBootstrap(dt, disp_3d, n_o, random_state=RNG) bs.diffusion(use_ngp=True) assert bs.covariance_matrix.shape == (190 - np.argmax(bs.ngp), 190 - np.argmax(bs.ngp)) assert isinstance(bs._diffusion_coefficient, Distribution) @@ -290,8 +304,9 @@ def test_bootstrap_use_ngp(self): def test_bootstrap_fit_intercept(self): with warnings.catch_warnings(record=True) as _: disp_3d = [RNG.randn(100, i, 3) for i in range(20, 10, -1)] + n_o = np.ones(len(disp_3d)) * 100 dt = np.linspace(100, 1000, 10) - bs = MSDBootstrap(dt, disp_3d, random_state=RNG) + bs = MSDBootstrap(dt, disp_3d, n_o, random_state=RNG) bs.diffusion(n_samples=500, fit_intercept=False) assert bs.covariance_matrix.shape == (10, 10) assert isinstance(bs._diffusion_coefficient, Distribution) @@ -301,8 +316,9 @@ def test_bootstrap_fit_intercept(self): def test_bootstrap_n_samples(self): with warnings.catch_warnings(record=True) as _: disp_3d = [RNG.randn(100, i, 3) for i in range(20, 10, -1)] + n_o = np.ones(len(disp_3d)) * 100 dt = np.linspace(100, 1000, 10) - bs = MSDBootstrap(dt, disp_3d, random_state=RNG) + bs = MSDBootstrap(dt, disp_3d, n_o, random_state=RNG) bs.diffusion(n_samples=100) assert bs.covariance_matrix.shape == (10, 10) assert isinstance(bs._diffusion_coefficient, Distribution) @@ -313,8 +329,9 @@ def test_bootstrap_n_samples(self): def test_bootstrap_D(self): with warnings.catch_warnings(record=True) as _: disp_3d = [RNG.randn(100, i, 3) for i in range(20, 10, -1)] + n_o = np.ones(len(disp_3d)) * 100 dt = np.linspace(100, 1000, 10) - bs = MSDBootstrap(dt, disp_3d, random_state=RNG) + bs = MSDBootstrap(dt, disp_3d, n_o, random_state=RNG) bs.diffusion(n_samples=100) assert bs.covariance_matrix.shape == (10, 10) assert isinstance(bs._diffusion_coefficient, Distribution) @@ -325,8 +342,9 @@ def test_bootstrap_D(self): def test_bootstrap_thin(self): with warnings.catch_warnings(record=True) as _: disp_3d = [RNG.randn(100, i, 3) for i in range(20, 10, -1)] + n_o = np.ones(len(disp_3d)) * 100 dt = np.linspace(100, 1000, 10) - bs = MSDBootstrap(dt, disp_3d, random_state=RNG) + bs = MSDBootstrap(dt, disp_3d, n_o, random_state=RNG) bs.diffusion(use_ngp=True, thin=1) assert bs.covariance_matrix.shape == (10 - np.argmax(bs.ngp), 10 - np.argmax(bs.ngp)) assert isinstance(bs._diffusion_coefficient, Distribution) @@ -358,8 +376,9 @@ class TestTMSDBootstrap(unittest.TestCase): def test_initialisation(self): with warnings.catch_warnings(record=True) as _: disp_3d = [RNG.randn(100, i, 3) for i in range(20, 10, -1)] + n_o = np.ones(len(disp_3d)) * 100 dt = np.linspace(100, 1000, 10) - bs = TMSDBootstrap(dt, disp_3d, random_state=np.random.RandomState(0)) + bs = TMSDBootstrap(dt, disp_3d, n_o, random_state=np.random.RandomState(0)) assert bs.n.shape == (5, ) assert bs.s.shape == (5, ) assert_almost_equal(bs.v, np.square(bs.s)) @@ -373,8 +392,9 @@ def test_initialisation(self): def test_initialisation_n_resamples(self): with warnings.catch_warnings(record=True) as _: disp_3d = [RNG.randn(100, i, 3) for i in range(20, 10, -1)] + n_o = np.ones(len(disp_3d)) * 100 dt = np.linspace(100, 1000, 10) - bs = TMSDBootstrap(dt, disp_3d, n_resamples=10, random_state=np.random.RandomState(0)) + bs = TMSDBootstrap(dt, disp_3d, n_o, n_resamples=10, random_state=np.random.RandomState(0)) assert bs.n.shape == (5, ) assert bs.s.shape == (5, ) assert_almost_equal(bs.v, np.square(bs.s)) @@ -388,8 +408,9 @@ def test_initialisation_n_resamples(self): def test_initialisation_max_resamples(self): with warnings.catch_warnings(record=True) as _: disp_3d = [RNG.randn(100, i, 3) for i in range(20, 10, -1)] + n_o = np.ones(len(disp_3d)) * 100 dt = np.linspace(100, 1000, 10) - bs = TMSDBootstrap(dt, disp_3d, n_resamples=10, max_resamples=100, random_state=np.random.RandomState(0)) + bs = TMSDBootstrap(dt, disp_3d, n_o, n_resamples=10, max_resamples=100, random_state=np.random.RandomState(0)) assert bs.n.shape == (5, ) assert bs.s.shape == (5, ) assert_almost_equal(bs.v, np.square(bs.s)) @@ -403,8 +424,9 @@ def test_initialisation_max_resamples(self): def test_initialisation_random_state(self): with warnings.catch_warnings(record=True) as _: disp_3d = [RNG.randn(100, i, 3) for i in range(20, 10, -1)] + n_o = np.ones(len(disp_3d)) * 100 dt = np.linspace(100, 1000, 10) - bs1 = TMSDBootstrap(dt, disp_3d, random_state=np.random.RandomState(0)) + bs1 = TMSDBootstrap(dt, disp_3d, n_o, random_state=np.random.RandomState(0)) assert bs1.n.shape == (5, ) assert bs1.s.shape == (5, ) assert_almost_equal(bs1.v, np.square(bs1.s)) @@ -414,15 +436,16 @@ def test_initialisation_random_state(self): assert isinstance(i, Distribution) for i in bs1._distributions: assert i.samples.size >= 1000 - bs2 = TMSDBootstrap(dt, disp_3d, random_state=np.random.RandomState(0)) + bs2 = TMSDBootstrap(dt, disp_3d, n_o, random_state=np.random.RandomState(0)) assert bs1._distributions[-1].size == bs2._distributions[-1].size assert_almost_equal(bs1._distributions[-1].samples, bs2._distributions[-1].samples) def test_initialisation_progress(self): with warnings.catch_warnings(record=True) as _: disp_3d = [RNG.randn(100, i, 3) for i in range(20, 10, -1)] + n_o = np.ones(len(disp_3d)) * 100 dt = np.linspace(100, 1000, 10) - bs = TMSDBootstrap(dt, disp_3d, progress=False, random_state=np.random.RandomState(0)) + bs = TMSDBootstrap(dt, disp_3d, n_o, progress=False, random_state=np.random.RandomState(0)) assert bs.n.shape == (5, ) assert bs.s.shape == (5, ) assert_almost_equal(bs.v, np.square(bs.s)) @@ -437,8 +460,9 @@ def test_initialisation_progress(self): def test_initialisation_skip_where_low_samples(self): with warnings.catch_warnings(record=True) as _: disp_3d = [RNG.randn(1, i, 3) for i in range(10, 1, -1)] + n_o = np.ones(len(disp_3d)) * 100 dt = np.linspace(100, 1000, 10) - bs = TMSDBootstrap(dt, disp_3d, progress=False, random_state=np.random.RandomState(0)) + bs = TMSDBootstrap(dt, disp_3d, n_o, progress=False, random_state=np.random.RandomState(0)) assert bs.n.shape == (4, ) assert bs.s.shape == (4, ) assert_almost_equal(bs.v, np.square(bs.s)) @@ -453,8 +477,9 @@ def test_initialisation_skip_where_low_samples(self): def test_bootstrap(self): with warnings.catch_warnings(record=True) as _: disp_3d = [RNG.randn(100, i, 3) for i in range(20, 10, -1)] + n_o = np.ones(len(disp_3d)) * 100 dt = np.linspace(100, 1000, 10) - bs = TMSDBootstrap(dt, disp_3d, random_state=RNG) + bs = TMSDBootstrap(dt, disp_3d, n_o, random_state=RNG) bs.jump_diffusion() assert bs.covariance_matrix.shape == (5, 5) assert isinstance(bs._jump_diffusion_coefficient, Distribution) @@ -465,8 +490,9 @@ def test_bootstrap(self): def test_bootstrap_use_ngp(self): with warnings.catch_warnings(record=True) as _: disp_3d = [RNG.randn(100, i, 3) for i in range(20, 10, -1)] + n_o = np.ones(len(disp_3d)) * 100 dt = np.linspace(100, 1000, 10) - bs = TMSDBootstrap(dt, disp_3d, random_state=RNG) + bs = TMSDBootstrap(dt, disp_3d, n_o, random_state=RNG) bs.jump_diffusion(use_ngp=True) assert bs.covariance_matrix.shape == (5 - np.argmax(bs.ngp), 5 - np.argmax(bs.ngp)) assert isinstance(bs._jump_diffusion_coefficient, Distribution) @@ -477,8 +503,9 @@ def test_bootstrap_use_ngp(self): def test_bootstrap_fit_intercept(self): with warnings.catch_warnings(record=True) as _: disp_3d = [RNG.randn(100, i, 3) for i in range(20, 10, -1)] + n_o = np.ones(len(disp_3d)) * 100 dt = np.linspace(100, 1000, 10) - bs = TMSDBootstrap(dt, disp_3d, random_state=RNG) + bs = TMSDBootstrap(dt, disp_3d, n_o, random_state=RNG) bs.jump_diffusion(n_samples=500, fit_intercept=False) assert bs.covariance_matrix.shape == (5, 5) assert isinstance(bs._jump_diffusion_coefficient, Distribution) @@ -488,8 +515,9 @@ def test_bootstrap_fit_intercept(self): def test_bootstrap_n_samples(self): with warnings.catch_warnings(record=True) as _: disp_3d = [RNG.randn(100, i, 3) for i in range(20, 10, -1)] + n_o = np.ones(len(disp_3d)) * 100 dt = np.linspace(100, 1000, 10) - bs = TMSDBootstrap(dt, disp_3d, random_state=RNG) + bs = TMSDBootstrap(dt, disp_3d, n_o, random_state=RNG) bs.jump_diffusion(n_samples=100) assert bs.covariance_matrix.shape == (5, 5) assert isinstance(bs._jump_diffusion_coefficient, Distribution) @@ -500,8 +528,9 @@ def test_bootstrap_n_samples(self): def test_bootstrap_D(self): with warnings.catch_warnings(record=True) as _: disp_3d = [RNG.randn(100, i, 3) for i in range(20, 10, -1)] + n_o = np.ones(len(disp_3d)) * 100 dt = np.linspace(100, 1000, 10) - bs = TMSDBootstrap(dt, disp_3d, random_state=RNG) + bs = TMSDBootstrap(dt, disp_3d, n_o, random_state=RNG) bs.jump_diffusion(n_samples=100) assert bs.covariance_matrix.shape == (5, 5) assert isinstance(bs._jump_diffusion_coefficient, Distribution) @@ -512,8 +541,9 @@ def test_bootstrap_D(self): def test_bootstrap_thin(self): with warnings.catch_warnings(record=True) as _: disp_3d = [RNG.randn(100, i, 3) for i in range(200, 10, -1)] + n_o = np.ones(len(disp_3d)) * 100 dt = np.linspace(100, 1000, 190) - bs = TMSDBootstrap(dt, disp_3d, random_state=RNG) + bs = TMSDBootstrap(dt, disp_3d, n_o, random_state=RNG) bs.jump_diffusion(use_ngp=True, thin=1) assert bs.covariance_matrix.shape == (95 - np.argmax(bs.ngp), 95 - np.argmax(bs.ngp)) assert isinstance(bs._jump_diffusion_coefficient, Distribution) @@ -547,8 +577,9 @@ class TestMSCDBootstrap(unittest.TestCase): def test_initialisation(self): with warnings.catch_warnings(record=True) as _: disp_3d = [RNG.randn(100, i, 3) for i in range(20, 10, -1)] + n_o = np.ones(len(disp_3d)) * 100 dt = np.linspace(100, 1000, 10) - bs = MSCDBootstrap(dt, disp_3d, 1, random_state=np.random.RandomState(0)) + bs = MSCDBootstrap(dt, disp_3d, 1, n_o, random_state=np.random.RandomState(0)) assert bs.n.shape == (5, ) assert bs.s.shape == (5, ) assert_almost_equal(bs.v, np.square(bs.s)) @@ -562,8 +593,9 @@ def test_initialisation(self): def test_initialisation_n_resamples(self): with warnings.catch_warnings(record=True) as _: disp_3d = [RNG.randn(100, i, 3) for i in range(20, 10, -1)] + n_o = np.ones(len(disp_3d)) * 100 dt = np.linspace(100, 1000, 10) - bs = MSCDBootstrap(dt, disp_3d, np.ones(100), n_resamples=10, random_state=np.random.RandomState(0)) + bs = MSCDBootstrap(dt, disp_3d, np.ones(100), n_o, n_resamples=10, random_state=np.random.RandomState(0)) assert bs.n.shape == (5, ) assert bs.s.shape == (5, ) assert_almost_equal(bs.v, np.square(bs.s)) @@ -577,8 +609,9 @@ def test_initialisation_n_resamples(self): def test_initialisation_max_resamples(self): with warnings.catch_warnings(record=True) as _: disp_3d = [RNG.randn(100, i, 3) for i in range(20, 10, -1)] + n_o = np.ones(len(disp_3d)) * 100 dt = np.linspace(100, 1000, 10) - bs = MSCDBootstrap(dt, disp_3d, 1, n_resamples=10, max_resamples=100, random_state=np.random.RandomState(0)) + bs = MSCDBootstrap(dt, disp_3d, 1, n_o, n_resamples=10, max_resamples=100, random_state=np.random.RandomState(0)) assert bs.n.shape == (5, ) assert bs.s.shape == (5, ) assert_almost_equal(bs.v, np.square(bs.s)) @@ -592,8 +625,9 @@ def test_initialisation_max_resamples(self): def test_initialisation_random_state(self): with warnings.catch_warnings(record=True) as _: disp_3d = [RNG.randn(100, i, 3) for i in range(20, 10, -1)] + n_o = np.ones(len(disp_3d)) * 100 dt = np.linspace(100, 1000, 10) - bs1 = MSCDBootstrap(dt, disp_3d, 1, random_state=np.random.RandomState(0)) + bs1 = MSCDBootstrap(dt, disp_3d, 1, n_o, random_state=np.random.RandomState(0)) assert bs1.n.shape == (5, ) assert bs1.s.shape == (5, ) assert_almost_equal(bs1.v, np.square(bs1.s)) @@ -603,15 +637,16 @@ def test_initialisation_random_state(self): assert isinstance(i, Distribution) for i in bs1._distributions: assert i.samples.size >= 1000 - bs2 = MSCDBootstrap(dt, disp_3d, 1, random_state=np.random.RandomState(0)) + bs2 = MSCDBootstrap(dt, disp_3d, 1, n_o, random_state=np.random.RandomState(0)) assert bs1._distributions[-1].size == bs2._distributions[-1].size assert_almost_equal(bs1._distributions[-1].samples, bs2._distributions[-1].samples) def test_initialisation_progress(self): with warnings.catch_warnings(record=True) as _: disp_3d = [RNG.randn(100, i, 3) for i in range(20, 10, -1)] + n_o = np.ones(len(disp_3d)) * 100 dt = np.linspace(100, 1000, 10) - bs = MSCDBootstrap(dt, disp_3d, 1, progress=False, random_state=np.random.RandomState(0)) + bs = MSCDBootstrap(dt, disp_3d, 1, n_o, progress=False, random_state=np.random.RandomState(0)) assert bs.n.shape == (5, ) assert bs.s.shape == (5, ) assert_almost_equal(bs.v, np.square(bs.s)) @@ -626,8 +661,9 @@ def test_initialisation_progress(self): def test_initialisation_skip_where_low_samples(self): with warnings.catch_warnings(record=True) as _: disp_3d = [RNG.randn(1, i, 3) for i in range(10, 1, -1)] + n_o = np.ones(len(disp_3d)) * 100 dt = np.linspace(100, 1000, 10) - bs = MSCDBootstrap(dt, disp_3d, 1, progress=False, random_state=np.random.RandomState(0)) + bs = MSCDBootstrap(dt, disp_3d, 1, n_o, progress=False, random_state=np.random.RandomState(0)) assert bs.n.shape == (4, ) assert bs.s.shape == (4, ) assert_almost_equal(bs.v, np.square(bs.s)) @@ -642,8 +678,9 @@ def test_initialisation_skip_where_low_samples(self): def test_bootstrap(self): with warnings.catch_warnings(record=True) as _: disp_3d = [RNG.randn(100, i, 3) for i in range(20, 10, -1)] + n_o = np.ones(len(disp_3d)) * 100 dt = np.linspace(100, 1000, 10) - bs = MSCDBootstrap(dt, disp_3d, 1, random_state=RNG) + bs = MSCDBootstrap(dt, disp_3d, 1, n_o, random_state=RNG) bs.conductivity(1, 10) assert bs.covariance_matrix.shape == (5, 5) assert isinstance(bs.sigma, Distribution) @@ -654,8 +691,9 @@ def test_bootstrap(self): def test_bootstrap_use_ngp(self): with warnings.catch_warnings(record=True) as _: disp_3d = [RNG.randn(100, i, 3) for i in range(200, 10, -1)] + n_o = np.ones(len(disp_3d)) * 100 dt = np.linspace(100, 1000, 190) - bs = MSCDBootstrap(dt, disp_3d, 1, random_state=RNG) + bs = MSCDBootstrap(dt, disp_3d, 1, n_o, random_state=RNG) bs.conductivity(1, 10, use_ngp=True) assert bs.covariance_matrix.shape == (95 - np.argmax(bs.ngp), 95 - np.argmax(bs.ngp)) assert isinstance(bs.sigma, Distribution) @@ -666,8 +704,9 @@ def test_bootstrap_use_ngp(self): def test_bootstrap_fit_intercept(self): with warnings.catch_warnings(record=True) as _: disp_3d = [RNG.randn(100, i, 3) for i in range(20, 10, -1)] + n_o = np.ones(len(disp_3d)) * 100 dt = np.linspace(100, 1000, 10) - bs = MSCDBootstrap(dt, disp_3d, 1, random_state=RNG) + bs = MSCDBootstrap(dt, disp_3d, 1, n_o, random_state=RNG) bs.conductivity(1, 10, n_samples=500, fit_intercept=False) assert bs.covariance_matrix.shape == (5, 5) assert isinstance(bs.sigma, Distribution) @@ -677,8 +716,9 @@ def test_bootstrap_fit_intercept(self): def test_bootstrap_n_samples(self): with warnings.catch_warnings(record=True) as _: disp_3d = [RNG.randn(100, i, 3) for i in range(20, 10, -1)] + n_o = np.ones(len(disp_3d)) * 100 dt = np.linspace(100, 1000, 10) - bs = MSCDBootstrap(dt, disp_3d, 1, random_state=RNG) + bs = MSCDBootstrap(dt, disp_3d, 1, n_o, random_state=RNG) bs.conductivity(1, 10, n_samples=100) assert bs.covariance_matrix.shape == (5, 5) assert isinstance(bs.sigma, Distribution) @@ -689,8 +729,9 @@ def test_bootstrap_n_samples(self): def test_bootstrap_D(self): with warnings.catch_warnings(record=True) as _: disp_3d = [RNG.randn(100, i, 3) for i in range(20, 10, -1)] + n_o = np.ones(len(disp_3d)) * 100 dt = np.linspace(100, 1000, 10) - bs = MSCDBootstrap(dt, disp_3d, 1, random_state=RNG) + bs = MSCDBootstrap(dt, disp_3d, 1, n_o, random_state=RNG) bs.conductivity(1, 10, n_samples=100) assert bs.covariance_matrix.shape == (5, 5) assert isinstance(bs.sigma, Distribution) @@ -701,8 +742,9 @@ def test_bootstrap_D(self): def test_bootstrap_thin(self): with warnings.catch_warnings(record=True) as _: disp_3d = [RNG.randn(100, i, 3) for i in range(200, 10, -1)] + n_o = np.ones(len(disp_3d)) * 100 dt = np.linspace(100, 1000, 190) - bs = MSCDBootstrap(dt, disp_3d, 1, random_state=RNG) + bs = MSCDBootstrap(dt, disp_3d, 1, n_o, random_state=RNG) bs.conductivity(1, 10, use_ngp=True, thin=1) assert bs.covariance_matrix.shape == (95 - np.argmax(bs.ngp), 95 - np.argmax(bs.ngp)) assert isinstance(bs.sigma, Distribution) diff --git a/kinisi/tests/test_parser.py b/kinisi/tests/test_parser.py index 5b5934b6..7d35979f 100644 --- a/kinisi/tests/test_parser.py +++ b/kinisi/tests/test_parser.py @@ -51,10 +51,9 @@ def test_parser_disp_3d(self): p = parser.Parser(dc, indices, [], time_step, step_skip, min_dt=20) assert_equal(len(p.disp_3d), 81) dt = np.arange(20, 101, 1) - for i, d in enumerate(p.disp_3d): - assert_equal(d.shape[0], 100) - assert_equal(d.shape[1], int(100 / dt[i])) - assert_equal(d.shape[2], 3) + assert_equal(p.disp_3d[0].shape[0], 100) + assert_equal(p.disp_3d[0].shape[1], 81) + assert_equal(p.disp_3d[0].shape[2], 3) def test_get_timesteps(self): p = parser.Parser(dc, indices, [], time_step, step_skip, min_dt=20) @@ -82,13 +81,13 @@ def test_correct_drift_framework(self): def test_get_disps(self): p = parser.Parser(dc, indices, [], time_step, step_skip, min_dt=20) - dt, disp_3d = p.get_disps(np.arange(20, 101, 1), dc) + dt, disp_3d, n_samples = p.get_disps(np.arange(20, 101, 1), dc) assert_equal(dt, np.arange(20, 101, 1)) assert_equal(len(disp_3d), 81) - for i, d in enumerate(disp_3d): - assert_equal(d.shape[0], 100) - assert_equal(d.shape[1], int(100 / dt[i])) - assert_equal(d.shape[2], 3) + assert_equal(len(n_samples), 81) + assert_equal(disp_3d[0].shape[0], 100) + assert_equal(disp_3d[0].shape[1], 81) + assert_equal(disp_3d[0].shape[2], 3) def test_pymatgen_init(self): xd = Xdatcar(os.path.join(os.path.dirname(kinisi.__file__), 'tests/inputs/example_XDATCAR.gz'))