-
Notifications
You must be signed in to change notification settings - Fork 666
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Nongaussian parameter #3896
base: develop
Are you sure you want to change the base?
Nongaussian parameter #3896
Changes from all commits
c701aaa
2f5abd0
243a52b
b6dba74
49c42ca
31ec212
1b05f0f
27ee727
6dd7cba
10fd87d
2dc04a8
278924f
9d33765
e83a509
d81733d
c6c3368
ed0c704
6d91004
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -20,7 +20,6 @@ | |
# MDAnalysis: A Toolkit for the Analysis of Molecular Dynamics Simulations. | ||
# J. Comput. Chem. 32 (2011), 2319--2327, doi:10.1002/jcc.21787 | ||
# | ||
|
||
r""" | ||
Mean Squared Displacement --- :mod:`MDAnalysis.analysis.msd` | ||
============================================================== | ||
|
@@ -227,7 +226,18 @@ | |
References | ||
---------- | ||
|
||
<<<<<<< HEAD | ||
.. bibliography:: | ||
:filter: False | ||
:style: MDA | ||
|
||
Maginn2019 | ||
Yeh2004 | ||
Bulow2020 | ||
Fuchs1998 | ||
======= | ||
.. footbibliography:: | ||
>>>>>>> develop | ||
|
||
|
||
Classes | ||
|
@@ -262,21 +272,34 @@ | |
class EinsteinMSD(AnalysisBase): | ||
r"""Class to calculate Mean Squared Displacement by the Einstein relation. | ||
|
||
If `fft=False` so that the "windowed" algorithm is used, the second order | ||
nongaussian parameter can also computed with ``nongaussian==True`` to | ||
jaclark5 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
capture heterogeneity as different time scales. See :cite:p:`Fuchs1998` | ||
for more information. | ||
|
||
.. math:: | ||
|
||
\alpha_{2}(r_{d}) = \frac{3}{5} \frac{ \bigg{\langle} \frac{1}{N} \sum_{i=1}^{N} |r_{d} | ||
- r_{d}(t_0)|^4 \bigg{\rangle} } { \bigg{\langle} \frac{1}{N} \sum_{i=1}^{N} |r_{d} | ||
- r_{d}(t_0)|^2 \bigg{\rangle}^2 } - 1 | ||
|
||
Parameters | ||
---------- | ||
u : Universe or AtomGroup | ||
An MDAnalysis :class:`Universe` or :class:`AtomGroup`. | ||
Note that :class:`UpdatingAtomGroup` instances are not accepted. | ||
select : str | ||
select : str (optional) | ||
A selection string. Defaults to "all" in which case | ||
all atoms are selected. | ||
msd_type : {'xyz', 'xy', 'yz', 'xz', 'x', 'y', 'z'} | ||
msd_type : {'xyz', 'xy', 'yz', 'xz', 'x', 'y', 'z'} (optional) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Nitpick, idk what other people would say but personally I wouldn't say optional because has a default and will raise exception otherwise. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I actually changed the doc string to include the dtype instead of the allowed options. As for the use of optional, let me know what you want, but I thought the fact that it's a keyword argument with a default is what makes this an optional input. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. JK I realized that listing the options is a convention in MDAnalysis |
||
Desired dimensions to be included in the MSD. Defaults to 'xyz'. | ||
fft : bool | ||
fft : bool (optional) | ||
jaclark5 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
If ``True``, uses a fast FFT based algorithm for computation of | ||
the MSD. Otherwise, use the simple "windowed" algorithm. | ||
The tidynamics package is required for `fft=True`. | ||
Defaults to ``True``. | ||
nongaussian : bool (optional) | ||
jaclark5 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
If ``True`` the second order nongaussian parameter is calculated. | ||
|
||
Attributes | ||
---------- | ||
|
@@ -286,6 +309,12 @@ class EinsteinMSD(AnalysisBase): | |
The averaged MSD over all the particles with respect to lag-time. | ||
results.msds_by_particle : :class:`numpy.ndarray` | ||
The MSD of each individual particle with respect to lag-time. | ||
results.nongaussian_parameter : :class:`numpy.ndarray` | ||
Can only be ``True`` when `fft==False`. The averaged nongaussian | ||
parameter over all the particles with respect to lag-time. | ||
results.nongaussian_by_particle : :class:`numpy.ndarray` | ||
Only available when `fft==False`. The nongaussian parameter | ||
of each individual particle with respect to lag-time. | ||
ag : :class:`AtomGroup` | ||
The :class:`AtomGroup` resulting from your selection | ||
n_frames : int | ||
|
@@ -294,24 +323,36 @@ class EinsteinMSD(AnalysisBase): | |
Number of particles MSD was calculated over. | ||
|
||
|
||
.. versionchanged:: 2.4.0 | ||
jaclark5 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
Added optional second order non-gaussian parameter to output for | ||
"simple" algorithm. | ||
.. versionadded:: 2.0.0 | ||
""" | ||
|
||
def __init__(self, u, select='all', msd_type='xyz', fft=True, **kwargs): | ||
def __init__(self, | ||
u, | ||
select='all', | ||
msd_type='xyz', | ||
fft=True, | ||
nongaussian=False, | ||
**kwargs): | ||
r""" | ||
Parameters | ||
---------- | ||
u : Universe or AtomGroup | ||
An MDAnalysis :class:`Universe` or :class:`AtomGroup`. | ||
select : str | ||
select : str (optional) | ||
A selection string. Defaults to "all" in which case | ||
all atoms are selected. | ||
msd_type : {'xyz', 'xy', 'yz', 'xz', 'x', 'y', 'z'} | ||
Desired dimensions to be included in the MSD. | ||
fft : bool | ||
msd_type : {'xyz', 'xy', 'yz', 'xz', 'x', 'y', 'z'} (optional) | ||
Desired dimensions to be included in the MSD. Defaults to 'xyz'. | ||
fft : bool (optional) | ||
If ``True``, uses a fast FFT based algorithm for computation of | ||
the MSD. Otherwise, use the simple "windowed" algorithm. | ||
The tidynamics package is required for `fft=True`. | ||
nongaussian : bool (optional) | ||
If ``True`` the nongaussian parameter is calculated. | ||
Can only be ``True`` when `fft==False`. The averaged nongaussian | ||
""" | ||
if isinstance(u, groups.UpdatingAtomGroup): | ||
raise TypeError("UpdatingAtomGroups are not valid for MSD " | ||
|
@@ -324,6 +365,7 @@ def __init__(self, u, select='all', msd_type='xyz', fft=True, **kwargs): | |
self.msd_type = msd_type | ||
self._parse_msd_type() | ||
self.fft = fft | ||
self.nongaussian = nongaussian | ||
|
||
# local | ||
self.ag = u.select_atoms(self.select) | ||
|
@@ -333,12 +375,21 @@ def __init__(self, u, select='all', msd_type='xyz', fft=True, **kwargs): | |
# result | ||
self.results.msds_by_particle = None | ||
self.results.timeseries = None | ||
if fft and nongaussian: | ||
raise ValueError("The nongaussian parameter can only be computed" | ||
" when `fft=False`") | ||
elif nongaussian: | ||
self.results.nongaussian_by_particle = None | ||
self.results.nongaussian_parameter = None | ||
|
||
def _prepare(self): | ||
# self.n_frames only available here | ||
# these need to be zeroed prior to each run() call | ||
self.results.msds_by_particle = np.zeros((self.n_frames, | ||
self.n_particles)) | ||
self.results.msds_by_particle = np.zeros( | ||
(self.n_frames, self.n_particles)) | ||
if self.nongaussian: | ||
self.results.nongaussian_by_particle = np.zeros( | ||
(self.n_frames, self.n_particles)) | ||
self._position_array = np.zeros( | ||
(self.n_frames, self.n_particles, self.dim_fac)) | ||
# self.results.timeseries not set here | ||
|
@@ -347,8 +398,15 @@ def _parse_msd_type(self): | |
r""" Sets up the desired dimensionality of the MSD. | ||
|
||
""" | ||
keys = {'x': [0], 'y': [1], 'z': [2], 'xy': [0, 1], | ||
'xz': [0, 2], 'yz': [1, 2], 'xyz': [0, 1, 2]} | ||
keys = { | ||
'x': [0], | ||
'y': [1], | ||
'z': [2], | ||
'xy': [0, 1], | ||
'xz': [0, 2], | ||
'yz': [1, 2], | ||
'xyz': [0, 1, 2] | ||
} | ||
|
||
self.msd_type = self.msd_type.lower() | ||
|
||
|
@@ -377,7 +435,8 @@ def _conclude(self): | |
self._conclude_simple() | ||
|
||
def _conclude_simple(self): | ||
r""" Calculates the MSD via the simple "windowed" algorithm. | ||
r""" Calculates the MSD via the simple "windowed" algorithm | ||
with nongaussian parameter. | ||
|
||
""" | ||
lagtimes = np.arange(1, self.n_frames) | ||
|
@@ -386,7 +445,18 @@ def _conclude_simple(self): | |
disp = positions[:-lag, :, :] - positions[lag:, :, :] | ||
sqdist = np.square(disp).sum(axis=-1) | ||
self.results.msds_by_particle[lag, :] = np.mean(sqdist, axis=0) | ||
if self.nongaussian: | ||
self.results.nongaussian_by_particle[ | ||
lag, :] = 3.0 / 5.0 * np.mean( | ||
np.square(sqdist), axis=0) / np.square( | ||
self.results.msds_by_particle[lag, :]) - 1.0 | ||
|
||
self.results.timeseries = self.results.msds_by_particle.mean(axis=1) | ||
if self.nongaussian: | ||
self.results.nongaussian_parameter = (3.0 / 5.0 * np.mean( | ||
(self.results.nongaussian_by_particle + 1.0) * 5.0 / 3.0 * | ||
np.square(self.results.msds_by_particle), | ||
axis=1) / np.square(self.results.timeseries) - 1.0) | ||
|
||
def _conclude_fft(self): # with FFT, np.float64 bit prescision required. | ||
r""" Calculates the MSD via the FCA fast correlation algorithm. | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we need to make the parameter an optional addition to the
fft=False
run. MSDs are already expensive (esp without an FFT) and tacking on more compulsory computation is not ideal. Much better to have it as an optional kwarg.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fair enough, that also begs the question on whether this package will move toward cython modules?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
for the MSD package? There is likely some benefit there. We are generally encouraging of Cython contributions and have a bunch of extensions already written in Cython.
If you go down the cython side and need a hand feel free to ping. See setup.py for the minimal setup for a cython extension.