Skip to content
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

Add in analysis function to calculate MSDs #2619

Merged
merged 136 commits into from
Jun 15, 2020
Merged
Show file tree
Hide file tree
Changes from 66 commits
Commits
Show all changes
136 commits
Select commit Hold shift + click to select a range
826b2ad
added msd class
Mar 2, 2020
6540de2
added in msd types and dimension factors
hmacdope Mar 2, 2020
f50622c
fill out framework to calculate msd
hmacdope Mar 2, 2020
aa29d3b
fill out framework to calculate msd
hmacdope Mar 2, 2020
6e72bd4
fix merge conflict
hmacdope Mar 2, 2020
671e537
skeleton algorithm for naieve MSD algorithm
hmacdope Mar 3, 2020
b0e296b
add in fft algorithm skeleton
hmacdope Mar 3, 2020
67fc0d0
naieve algorithm complete
hmacdope Mar 4, 2020
3018a62
added in fft compute and tests
hmacdope Mar 11, 2020
44407e4
cleaned up tests and started working on docs
hmacdope Mar 11, 2020
4711fb6
ready to open WIP opull request
hmacdope Mar 13, 2020
f9f7dd9
worked on documentation and examples
hmacdope Mar 13, 2020
2358a11
more work on docs
hmacdope Mar 13, 2020
a8d400a
doc and example improvements
hmacdope Mar 14, 2020
0a960e4
improved numerical performance of FFT based algorithm
hmacdope Mar 14, 2020
cc11cc6
added in tidynamics tests
hmacdope Mar 15, 2020
e9b17fe
clean up deps
hmacdope Mar 15, 2020
09b5458
added tidynamics to test deps
hmacdope Mar 15, 2020
a06294b
test tidynymaics in test block and updated docs
hmacdope Mar 15, 2020
4cf63fd
try and fix install
hmacdope Mar 15, 2020
e5e3629
fix single failed build
hmacdope Mar 15, 2020
2c469f0
change travis and appveyor settings
hmacdope Mar 15, 2020
546f7f2
fix .appveyor
hmacdope Mar 15, 2020
e02dd09
Merge branch 'develop' into add_msd
hmacdope Mar 15, 2020
033273b
relax to decimal=3 tol for FFT step_traj test due to failing numpy=1.…
hmacdope Mar 15, 2020
dd5b25d
Merge branch 'add_msd' of github.com:hmacdope/mdanalysis into add_msd
hmacdope Mar 15, 2020
83be862
switch .indices for .ix for proper indexing of coordinate array
hmacdope Mar 15, 2020
d318a91
implement reccomended changes and improve docs
hmacdope Mar 16, 2020
10e3fc2
add small test to ensure selection is working
hmacdope Mar 16, 2020
089a2bd
add capability to pull out MSDs per particle
hmacdope Mar 16, 2020
d108453
fix typo in per particle tests
hmacdope Mar 16, 2020
8ebc233
add in test to show numerical error in constan tvelocity trajectory.
hmacdope May 15, 2020
e2d383d
replaced own fft code with tidynamics
hmacdope May 17, 2020
73bc1f7
add duecredit citation
hmacdope May 17, 2020
c71f5e6
add FCA citation
hmacdope May 17, 2020
ddbc4e3
update requires and fix docs build
hmacdope May 17, 2020
523f81f
update citation
hmacdope May 17, 2020
6eb76e2
Merge branch 'develop' into add_msd
hmacdope May 18, 2020
86d59bb
fix appveyor and travis yml, removing duplication
hmacdope May 18, 2020
a934882
fix typo in travis.yml
hmacdope May 18, 2020
7759da7
fix failing numpy=1.13 nets and update CHANGELOG
hmacdope May 18, 2020
851daa3
Update package/CHANGELOG
hmacdope May 18, 2020
d23ee0e
Update package/MDAnalysis/analysis/msd.py
hmacdope May 18, 2020
49fbd86
Merge branch 'develop' into add_msd
hmacdope May 18, 2020
9af111a
clean up imports and typos
hmacdope May 19, 2020
19625f0
Merge branch 'add_msd' of github.com:hmacdope/mdanalysis into add_msd
hmacdope May 20, 2020
0f637dd
framework moved to subclass AnalysisBase
hmacdope May 20, 2020
4c5f487
AnalysisBase compatible and passing tests
hmacdope May 20, 2020
78f7d4f
fix msd_by_particle and corresponding tests
hmacdope May 20, 2020
b458ae8
removed some inline comments that were useless
hmacdope May 20, 2020
09416cb
changed parse_msd_type to a clearer selection syntax
hmacdope May 20, 2020
60f0cca
remove fstring causing failed builds
hmacdope May 20, 2020
38da36e
fix typo in fstring removal
hmacdope May 20, 2020
0e22adf
fix another typo in fstring removal
hmacdope May 20, 2020
504e19c
clean up half changes to select kwarg
hmacdope May 20, 2020
e805403
clean up references
hmacdope May 20, 2020
3ba54a0
Merge remote-tracking branch 'upstream/develop' into add_msd
hmacdope May 20, 2020
6f70f06
fix docstring references
hmacdope May 21, 2020
4894bbd
improve docs and add image
hmacdope May 22, 2020
3a48b61
spelling in docs
hmacdope May 22, 2020
0d34487
remove inner loop over n_particles in simple MSD algorithm
hmacdope May 23, 2020
4ca2bf7
add seeding for np.random.randint
hmacdope May 23, 2020
8249a65
add pytest.mark.parametrize and move global vars to pytest.fixtures
hmacdope May 25, 2020
63b8fff
refactor constant velocity test using pytest.mark.parametrize
hmacdope May 25, 2020
0fc07f7
add tidynamics versioning
hmacdope May 25, 2020
0d69b65
move tidynamics to out of CONDA_MIN_DEPENDENCIES
hmacdope May 25, 2020
98d4b48
Update package/MDAnalysis/analysis/msd.py
hmacdope Jun 1, 2020
7d530eb
change docs markup
hmacdope Jun 1, 2020
2c760eb
spelling
hmacdope Jun 1, 2020
a7136c0
spelling
hmacdope Jun 1, 2020
ef6b6f4
caps
hmacdope Jun 1, 2020
f4aeaea
spelling
hmacdope Jun 1, 2020
121ac17
spelling
hmacdope Jun 1, 2020
09bedac
phrasing
hmacdope Jun 1, 2020
e070fb8
spelling
hmacdope Jun 1, 2020
d8c81cd
spelling
hmacdope Jun 1, 2020
1ac4086
spelling
hmacdope Jun 1, 2020
7a58d73
spelling
hmacdope Jun 1, 2020
c3ae32b
markup
hmacdope Jun 1, 2020
7764f9e
spelling
hmacdope Jun 1, 2020
9005ad5
change dimensions of base array
hmacdope Jun 1, 2020
e898226
keep dim of _position_array consistent
hmacdope Jun 1, 2020
b370a27
Merge branch 'develop' into add_msd
hmacdope Jun 1, 2020
3f5f5f3
pep8 lint
hmacdope Jun 1, 2020
e4e46ba
fix PEP8 compliance for line length
hmacdope Jun 2, 2020
d09f79c
update docs for PEP8 compliance
hmacdope Jun 3, 2020
cff23b0
add more references and tidy docs
hmacdope Jun 3, 2020
ba6f37a
removed repetitive structure in self.msd
hmacdope Jun 3, 2020
42720d8
clean up and PEP8 tests
hmacdope Jun 3, 2020
0f5a009
fix typo
hmacdope Jun 3, 2020
cc53e1b
refactor to only use the right dimension
hmacdope Jun 3, 2020
79f93a4
change docs for array sizing
hmacdope Jun 3, 2020
e9f4cf4
authroship note
hmacdope Jun 3, 2020
b909aad
move tidynamics to try except import
hmacdope Jun 3, 2020
bac625b
typo
hmacdope Jun 3, 2020
1aef299
lag time to lag-time
hmacdope Jun 3, 2020
2648d05
add start stop step tests
hmacdope Jun 3, 2020
a5a9716
Merge branch 'develop' into add_msd
hmacdope Jun 10, 2020
eccc5ea
fix start stop step tests
hmacdope Jun 10, 2020
f27b0da
fix test offsets
hmacdope Jun 10, 2020
33a8907
change docs
hmacdope Jun 10, 2020
fb7f458
clean up extra variables
hmacdope Jun 10, 2020
ac3a525
Merge branch 'add_msd' of github.com:hmacdope/mdanalysis into add_msd
hmacdope Jun 10, 2020
5e8c17f
fix docs
hmacdope Jun 10, 2020
41dde3f
fix import Error
hmacdope Jun 10, 2020
269ea05
Update package/MDAnalysis/analysis/msd.py
hmacdope Jun 10, 2020
ae5b93b
Merge branch 'add_msd' of https://github.com/hmacdope/mdanalysis into…
orbeckst Jun 11, 2020
2feb81e
corrected indentation and updated CHANGELOG
orbeckst Jun 11, 2020
141dca8
EinsteinMSD: also document run() method
orbeckst Jun 11, 2020
d007ac9
reorganized analysis docs toc for structure
orbeckst Jun 11, 2020
e1dbbbe
Update package/MDAnalysis/analysis/msd.py
hmacdope Jun 11, 2020
923e161
Update package/MDAnalysis/analysis/msd.py
hmacdope Jun 11, 2020
607e228
Update package/MDAnalysis/analysis/msd.py
hmacdope Jun 11, 2020
e983f83
fix
hmacdope Jun 11, 2020
7d4e54f
typo
hmacdope Jun 11, 2020
8498f1a
change import
hmacdope Jun 11, 2020
e39433e
change import error
hmacdope Jun 11, 2020
50b9f11
Update package/MDAnalysis/analysis/msd.py
hmacdope Jun 11, 2020
af5cedf
newline
hmacdope Jun 11, 2020
e76f164
Revert "newline"
hmacdope Jun 11, 2020
1d62c0c
change docs
hmacdope Jun 11, 2020
a55ad30
change docs
hmacdope Jun 11, 2020
491da98
change docs
hmacdope Jun 11, 2020
09fb909
Merge branch 'add_msd' of github.com:hmacdope/mdanalysis into add_msd
hmacdope Jun 11, 2020
4d9c2d5
confusion over revert
hmacdope Jun 11, 2020
0cf1882
change author notes etc
hmacdope Jun 11, 2020
f1c7bd2
small edits
hmacdope Jun 11, 2020
7321bb6
rip out docstrings for internal functions
hmacdope Jun 12, 2020
18eb09c
fix docstrings and line conts
hmacdope Jun 12, 2020
353ae3e
remove extra dtypes
hmacdope Jun 12, 2020
78911b8
more dtypes removed
hmacdope Jun 12, 2020
e8478ba
Merge branch 'develop' into add_msd
hmacdope Jun 12, 2020
6513f8b
remove select from kwargs
hmacdope Jun 12, 2020
38eeb15
Merge branch 'add_msd' of github.com:hmacdope/mdanalysis into add_msd
hmacdope Jun 12, 2020
fe02375
Merge remote-tracking branch 'upstream/develop' into add_msd
hmacdope Jun 14, 2020
16dca64
fix docs build error
hmacdope Jun 14, 2020
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .appveyor.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ cache:
environment:
global:
CONDA_CHANNELS: conda-forge
CONDA_DEPENDENCIES: pip setuptools wheel cython mock six biopython networkx joblib matplotlib scipy vs2015_runtime pytest mmtf-python GridDataFormats hypothesis pytest-cov codecov chemfiles tqdm
CONDA_DEPENDENCIES: pip setuptools wheel cython mock six biopython networkx joblib matplotlib scipy vs2015_runtime pytest mmtf-python GridDataFormats hypothesis pytest-cov codecov chemfiles tqdm tidynamics>=1.0.0
PIP_DEPENDENCIES: gsd==1.9.3 duecredit parmed
DEBUG: "False"
MINGW_64: C:\mingw-w64\x86_64-6.3.0-posix-seh-rt_v5-rev1\mingw64\bin
Expand Down
2 changes: 1 addition & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ env:
- SETUP_CMD="${PYTEST_FLAGS}"
- BUILD_CMD="pip install -e package/ && (cd testsuite/ && python setup.py build)"
- CONDA_MIN_DEPENDENCIES="mmtf-python mock six biopython networkx cython matplotlib scipy griddataformats hypothesis gsd codecov"
- CONDA_DEPENDENCIES="${CONDA_MIN_DEPENDENCIES} seaborn>=0.7.0 clustalw=2.1 netcdf4 scikit-learn joblib>=0.12 chemfiles tqdm>=4.43.0"
- CONDA_DEPENDENCIES="${CONDA_MIN_DEPENDENCIES} seaborn>=0.7.0 clustalw=2.1 netcdf4 scikit-learn joblib>=0.12 chemfiles tqdm>=4.43.0 tidynamics>=1.0.0"
- CONDA_CHANNELS='biobuilds conda-forge'
- CONDA_CHANNEL_PRIORITY=True
- PIP_DEPENDENCIES="duecredit parmed"
Expand Down
1 change: 1 addition & 0 deletions package/CHANGELOG
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ Fixes
* Contact Analysis class respects PBC (Issue #2368)

Enhancements
* Added computation of Mean Squared Displacements (#2438, PR #2619)
hmacdope marked this conversation as resolved.
Show resolved Hide resolved
orbeckst marked this conversation as resolved.
Show resolved Hide resolved
hmacdope marked this conversation as resolved.
Show resolved Hide resolved
* Added methods to compute the root-mean-square-inner-product of subspaces
and the cumulative overlap of a vector in a subspace for PCA (PR #2613)
* Added .frames and .times arrays to AnalysisBase (Issue #2661)
Expand Down
331 changes: 331 additions & 0 deletions package/MDAnalysis/analysis/msd.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,331 @@
# -*- Mode: python; tab-width: 4; indent-tabs-mode:nil; coding:utf-8 -*-
# vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4
#
# MDAnalysis --- https://www.mdanalysis.org
# Copyright (c) 2006-2017 The MDAnalysis Development Team and contributors
# (see the file AUTHORS for the full list of names)
#
# Released under the GNU Public Licence, v2 or any higher version
#
# Please cite your use of MDAnalysis in published work:
#
# R. J. Gowers, M. Linke, J. Barnoud, T. J. E. Reddy, M. N. Melo, S. L. Seyler,
# D. L. Dotson, J. Domanski, S. Buchoux, I. M. Kenney, and O. Beckstein.
# MDAnalysis: A Python package for the rapid analysis of molecular dynamics
# simulations. In S. Benthall and S. Rostrup editors, Proceedings of the 15th
# Python in Science Conference, pages 102-109, Austin, TX, 2016. SciPy.
# doi: 10.25080/majora-629e541a-00e
#
# N. Michaud-Agrawal, E. J. Denning, T. B. Woolf, and O. Beckstein.
# MDAnalysis: A Toolkit for the Analysis of Molecular Dynamics Simulations.
# J. Comput. Chem. 32 (2011), 2319--2327, doi:10.1002/jcc.21787
#
# This module written by Hugo MacDermott-Opeskin 2020
hmacdope marked this conversation as resolved.
Show resolved Hide resolved

r"""
Mean Squared Displacement --- :mod:`MDAnalysis.analysis.msd`
==============================================================

:Authors: Hugo MacDermott-Opeskin
:Year: 2020
:Copyright: GNU Public License v2

This module implements the calculation of Mean Squared Displacmements (MSDs) by the Einstein relation.
hmacdope marked this conversation as resolved.
Show resolved Hide resolved
MSDs can be used to characterize the speed at which particles move and has its roots
in the study of Brownian motion. For a full explanation of the theory behind MSDs and the subsequent calculation of self-diffusivities the reader is directed to [Maginn2019]_.
hmacdope marked this conversation as resolved.
Show resolved Hide resolved
MSDs can be computed from the following expression, known as the "Einstein" formula:
hmacdope marked this conversation as resolved.
Show resolved Hide resolved

.. math::

MSD(r_{d}) = \bigg{\langle} \frac{1}{N} \sum_{i=1}^{N} |r_{d} - r_{d}(t_0)|^2 \bigg{\rangle}_{t_{0}}

Where :math:`N` is the number of equivalent particles the MSD is calculated over, :math:`r` are their coordinates and :math:`d` the desired
hmacdope marked this conversation as resolved.
Show resolved Hide resolved
dimensionality of the MSD. Note that while the definition of the MSD is universal, there are many practical considerations to computing the MSD
that vary between implementations. In this module, we compute a "windowed" MSD, where the MSD is averaged over all possible lag times :math:`\tau \le \tau_{max}`,
where :math:`\tau_{max}` is the length of the trajectory, thereby maximizing the number of samples.

The computation of the MSD in this way can be computationally intensive due to it's :math:`N^2` scaling with respect to :math:`\tau_{max}`.
hmacdope marked this conversation as resolved.
Show resolved Hide resolved
An algorithm to compute the MSD with :math:`N log(N)` scaling based on a Fast Fourier Transform is known and can be accessed by setting fft=True [Calandri2011]_ [Buyl2018]_.
hmacdope marked this conversation as resolved.
Show resolved Hide resolved

Please cite [Calandri2011]_ [Buyl2018]_ if you use this module in addition to the normal MDAnalysis citations.

Computing an MSD
----------------
This example computes a 3D MSD for the movement of 100 particles undergoing a random walk.
Files provided as part of the MDAnalysis test suite are used
(in the variables :data:`~MDAnalysis.tests.datafiles.RANDOM_WALK` and
:data:`~MDAnalysis.tests.datafiles.RANDOM_WALK_TOPO`)

First load all modules and test data

>>> import MDAnalysis as mda
>>> import MDAnalysis.analysis.msd as msd
>>> from MDAnalysis.tests.datafiles import RANDOM_WALK, RANDOM_WALK_TOPO
hmacdope marked this conversation as resolved.
Show resolved Hide resolved

Given a universe containing trajectory data we can extract the MSD
Analyis by using the class :class:`EinsteinMSD`
hmacdope marked this conversation as resolved.
Show resolved Hide resolved

>>> u = mda.Universe(RANDOM_WALK, RANDOM_WALK_TOPO)
>>> MSD = msd.EinsteinMSD(u, 'all', msd_type='xyz', fft=True)
>>> MSD.run()

The MSD can then be accessed as

>>> msd = MSD.timeseries

Visual inspection of the MSD is important, so lets take a look at it with a simple plot.
hmacdope marked this conversation as resolved.
Show resolved Hide resolved

>>> import matplotlib.pyplot as plt
>>> nframes = MSD.n_frames
>>> timestep = 1 # this needs to be the actual time between frames in your trajectory
>>> lagtimes = np.arange(nframes)*timestep # make the lag time axis
>>> fig = plt.figure()
>>> ax = plt.axes()
>>> ax.plot(lagtimes, msd, color="black", linestyle="-", label=r'3D random walk') # plot the actual MSD
hmacdope marked this conversation as resolved.
Show resolved Hide resolved
>>> exact = lagtimes*6
>>> ax.plot(lagtimes, exact, color="black", linestyle="--", label=r'$y=2 D\tau$') # plot the exact result
>>> plt.show()
hmacdope marked this conversation as resolved.
Show resolved Hide resolved

Which gives us the following plot of the MSD with respect to lag-time (:math:`\tau`).
hmacdope marked this conversation as resolved.
Show resolved Hide resolved
We can see that the MSD is approximately linear with respect to :math:`\tau`.
This is a numerical example of a known theoretical result that the MSD of a random walk is linear with respect to lagtime, with a slope of :math:`2d`.
In this expression :math:`d` is the dimensionality of the MSD which for our 3D MSD is equal to 3.
hmacdope marked this conversation as resolved.
Show resolved Hide resolved
For comparison we have plotted the line :math:`y=6\tau` to which an ensemble of 3D random walks should converge.

.. _figure-msd:

.. figure:: /images/msd_demo_plot.png
:scale: 100 %
:alt: MSD plot

Note that a segment of the MSD is required to be linear to accurately determine self-diffusivity.
This linear segment represents the so called "middle" of the MSD plot, where ballistic trajectories at short time-lags are excluded along with poorly averaged data at long time-lags.
We can select the "middle" of the MSD by indexing the MSD and the time-lags. Appropriately linear segments of the MSD can be confirmed with a log-log plot as is often reccomended [Maginn2019]_ where the "middle" segment can be identified as having a slope of 1.

>>> plt.loglog(lagtimes, msd)
>>> plt.show()

Now that we have identified what segment of our MSD to analyse, lets compute a self-diffusivity.
hmacdope marked this conversation as resolved.
Show resolved Hide resolved

Computing Self-Diffusivity
--------------------------------
Self-diffusivity is closely related to the MSD.

.. math::

D_d = \frac{1}{2d} \lim_{t \to \infty} \frac{d}{dt} MSD(r_{d})

From the MSD, self-diffusivities :math:`D` with the desired dimensionality :math:`d` can be computed by fitting the MSD with respect to the lag time to a linear model.
An example of this is shown below, using the MSD computed in the example above. The segment between :math:`\tau = 20` and :math:`\tau = 60` is used to demonstrate selection of an MSD segment.
hmacdope marked this conversation as resolved.
Show resolved Hide resolved

>>> from scipy.stats import linregress as lr
>>> start_time = 20
>>> start_index = int(start_time/timestep)
>>> end_time = 60
>>> end_index = int(end_time/timestep)
>>> linear_model = lr(lagtimes[start_index:end_index], msd[start_index:end_index])
>>> slope = linear_model.slope
>>> error = linear_model.rvalue
>>> D = slope * 1/(2*MSD.dim_fac) #dim_fac is 3 as we computed a 3D msd ('xyz')

We have now computed a self-diffusivity!


Notes
_____

There are several factors that must be taken into account when setting up and processing trajectories for computation of self-diffusivities.
These include specific instructions around simulation settings, using unwrapped trajectories and maintaining relatively small elapsed time between saved frames.
hmacdope marked this conversation as resolved.
Show resolved Hide resolved
Additionally corrections for finite size effects are sometimes employed along with varied means of estimating errors.
hmacdope marked this conversation as resolved.
Show resolved Hide resolved
The reader is directed to the following review, which describes many of the common pitfalls [Maginn2019]_. There are other ways to compute self-diffusivity including from a Green-Kubo integral. At this point in time these methods are beyond the scope of this module
hmacdope marked this conversation as resolved.
Show resolved Hide resolved
hmacdope marked this conversation as resolved.
Show resolved Hide resolved


References
----------

.. [Maginn2019] Maginn, E. J., Messerly, R. A., Carlson, D. J.; Roe, D. R., Elliott, J. R. Best Practices for Computing Transport Properties 1. Self-Diffusivity and Viscosity from Equilibrium Molecular Dynamics [Article v1.0]. Living J. Comput. Mol. Sci. 2019, 1 (1).



Classes and Functions
---------------------

.. autoclass:: EinsteinMSD
:members:

"""

from __future__ import division, absolute_import
hmacdope marked this conversation as resolved.
Show resolved Hide resolved

import numpy as np
import logging
import tidynamics
from ..due import due, Doi
from .base import AnalysisBase

due.cite(Doi("10.21105/joss.00877"),
description="Mean Squared Displacements with tidynamics",
path="MDAnalysis.analysis.msd",
cite_module=True)
due.cite(Doi("10.1051/sfn/201112010"),
description="FCA fast correlation algorithm",
path="MDAnalysis.analysis.msd",
cite_module=True)
del Doi

class EinsteinMSD(AnalysisBase):
r"""Class to calculate Mean Squared Displacement by the Einstein relation.

Attributes
----------
dim_fac : int
Dimensionality :math:`d` of the MSD.
timeseries : :class:`np.ndarray`
hmacdope marked this conversation as resolved.
Show resolved Hide resolved
The averaged MSD with respect to lag-time.
hmacdope marked this conversation as resolved.
Show resolved Hide resolved
msd_per_particle : :class:`np.ndarray`
The MSD of each individual particle with respect to lag-time.
n_frames : int
Number of frames in trajectory.
hmacdope marked this conversation as resolved.
Show resolved Hide resolved
n_particles : int
Number of particles MSD was calculated over.

hmacdope marked this conversation as resolved.
Show resolved Hide resolved
"""

def __init__(self, u, select=None, msd_type='xyz', fft=True, **kwargs):
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@orbeckst do we have a consensus on what the default selects should be? e.g. 'name CA' as a sensible default for memory-hungry analyses like this one?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I feel 'name CA' would be confusing as a default? Trying to find the diffusivity of a set of backbone atoms is from what I can tell rare.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree with @hmacdope that CA does not make sense here.

Can u also be a AtomGroup? If so, select=None should select everything so that one can easily use AtomGroups that already contain what's needed.

If u can only be a Universe then I am tempted to make select a required argument to force the user to say exactly what they want. Analyses classes are free to implement any call signature that they like (see the example for NewAnalysis). NewAnalysis(atomgroup, **kwargs) and NewAnalysis(universe, select=None, **kwargs) are common but NewAnalysis(universe, select, **kwargs) is allowed.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As it currently stands can only be a Universe. I will change select to be required as suggested?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

select no longer a kwarg

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

None of your code requires a Universe, you could just make it accept an AtomGroup by initialising with u.universe.trajectory. I think that's really it.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it typical to have select=None select all the atoms instead of directly setting select='all' as the default?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I honestly don't remember.... there's been something in the select vs selection discussion, hasn't it? In terms of "pythonic" behavior I always expect None for a kwarg to give me the default as opposed to the semantic "nothing". You're right, though, that in this case one could be clearer and set the default to "all". (u.select_atoms(None) gives an empty AtomGroup so I don't think that letting None pass through is the right approach.)

r"""
hmacdope marked this conversation as resolved.
Show resolved Hide resolved
Parameters
----------
u : Universe
An MDAnalysis :class:`Universe`.
selection : str
hmacdope marked this conversation as resolved.
Show resolved Hide resolved
An MDAnalysis selection string. Defaults to `None`.
hmacdope marked this conversation as resolved.
Show resolved Hide resolved
msd_type : {'xyz', 'xy', 'yz', 'xz', 'x', 'y', 'z'}
Desired dimensions to be included in the MSD. Defaults to 'xyz'.
fft : bool
Use a fast FFT based algorithm for computation of the MSD.
hmacdope marked this conversation as resolved.
Show resolved Hide resolved
Otherwise, use the simple "windowed" algorithm. Defaults to ``True``.

"""
self.u = u

super(EinsteinMSD, self).__init__(self.u.trajectory, **kwargs)

#args
self.select = select
self.msd_type = msd_type
self.fft = fft

#local
self._dim = None
self._position_array = None
self._atoms = None

#indexing
self._n_frames = 0
self._n_particles = 0

#result
self.dim_fac = 0
hmacdope marked this conversation as resolved.
Show resolved Hide resolved
self.timeseries = None
self.msds_by_particle = None

def _prepare(self):
self._parse_msd_type()
hmacdope marked this conversation as resolved.
Show resolved Hide resolved
self._atoms = self.u.select_atoms(self.select)
self._n_frames = len(self.u.trajectory)
orbeckst marked this conversation as resolved.
Show resolved Hide resolved
self._n_particles = len(self._atoms)
self._position_array = np.zeros((self._n_frames, self._n_particles, 3))
hmacdope marked this conversation as resolved.
Show resolved Hide resolved
self.msds_by_particle = np.zeros((self._n_frames, self._n_particles))
# self.timeseries not set here

def _parse_msd_type(self):
r""" Sets up the desired dimensionality of the MSD.

Parameters
----------
self.msd_type : {'xyz', 'xy', 'yz', 'xz', 'x', 'y', 'z'}
Dimensions to be included in the MSD.

Returns
-------
hmacdope marked this conversation as resolved.
Show resolved Hide resolved
self._dim : list
Array-like used to slice the positions to obtain desired dimensionality
self.dim_fac : int
Dimension factor :math:`d` of the MSD.

"""
keys = {'x':[0], 'y':[1], 'z':[2], 'xy':[0,1], 'xz':[0,2], 'yz':[1,2], 'xyz':[0,1,2]}
hmacdope marked this conversation as resolved.
Show resolved Hide resolved

self.msd_type = self.msd_type.lower()

try:
self._dim = keys[self.msd_type]
except KeyError:
raise ValueError('invalid msd_type: {} specified, please specify one of xyz, xy, xz, yz, x, y, z'.format(self.msd_type))

self.dim_fac = len(self._dim)

def _single_frame(self):
r""" Constructs array of positions for MSD calculation.

Parameters
----------
self.u : :class:`Universe`
MDAnalysis Universe

Returns
hmacdope marked this conversation as resolved.
Show resolved Hide resolved
-------
self._position_array : :class:`np.ndarray`
Array of particle positions with respect to time shape = (n_frames, n_particles, 3)
"""

self._position_array[self._frame_index,:,:] = self._atoms.positions
hmacdope marked this conversation as resolved.
Show resolved Hide resolved

def _conclude(self):
if self.fft == True:
hmacdope marked this conversation as resolved.
Show resolved Hide resolved
self.timeseries = self._conclude_fft()
else:
self.timeseries = self._conclude_simple()

def _conclude_simple(self):
r""" Calculates the MSD via the simple "windowed" algorithm.

Parameters
----------
self._position_array : :class:`np.ndarray`
Array of particle positions with respect to time shape (n_frames, n_particles, 3).

Returns
hmacdope marked this conversation as resolved.
Show resolved Hide resolved
-------
self.timeseries : :class:`np.ndarray`
hmacdope marked this conversation as resolved.
Show resolved Hide resolved
The MSD as a function of lag-time.

"""
lagtimes = np.arange(1,self.n_frames)
self.msds_by_particle[0,:] = np.zeros(self._n_particles) # preset the zero lagtime so we don't have to iterate through
hmacdope marked this conversation as resolved.
Show resolved Hide resolved
for lag in lagtimes:
disp = self._position_array[:-lag,:,self._dim] - self._position_array[lag:,:,self._dim]
sqdist = np.square(disp, dtype=np.float64).sum(axis=-1, dtype=np.float64) #accumulation in np.float64 required
self.msds_by_particle[lag,:] = np.mean(sqdist, axis=0, dtype=np.float64)
msd = self.msds_by_particle.mean(axis=1, dtype=np.float64)
return msd

def _conclude_fft(self): #with FFT, np.float64 bit prescision required.
r""" Calculates the MSD via the FCA fast correlation algorithm.

Parameters
----------
self._position_array : :class:`np.ndarray`
Array of particle positions with respect to time shape (n_frames, n_particles, 3).

Returns
hmacdope marked this conversation as resolved.
Show resolved Hide resolved
-------
self.timeseries : :class:`np.ndarray`
The MSD as a function of lagtime.

"""
reshape_positions = self._position_array[:,:,self._dim].astype(np.float64)
for n in range(self._n_particles):
self.msds_by_particle[:,n] = tidynamics.msd(reshape_positions[:,n,:])
msd = self.msds_by_particle.mean(axis=1, dtype=np.float64)
hmacdope marked this conversation as resolved.
Show resolved Hide resolved
return msd
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
.. automodule:: MDAnalysis.analysis.msd
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ Structure
analysis/helanal
analysis/rdf
analysis/dihedrals

analysis/msd

Volumetric analysis
===================
Expand Down
12 changes: 12 additions & 0 deletions package/doc/sphinx/source/documentation_pages/references.rst
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,19 @@ If you use :meth:`~MDAnalysis.analysis.pca.PCA.cumulative_overlap` or

.. _`10.1016/j.str.2007.12.011`: https://dx.doi.org/10.1016/j.str.2007.12.011

If you use the Mean Squared Displacement analysis code in
:mod:`MDAnalysis.analysis.msd` please cite [Calandri2011]_ and [Buyl2018]_.

.. [Calandri2011] Calandrini, V., Pellegrini, E., Calligari, P., Hinsen, K., Kneller, G. R.
NMoldyn-Interfacing Spectroscopic Experiments, Molecular Dynamics Simulations and Models for Time Correlation Functions.
*Collect. SFN*, **12**, 201–232 (2011). doi: `10.1051/sfn/201112010`_

.. _`10.1051/sfn/201112010`: https://doi.org/10.1051/sfn/201112010

.. [Buyl2018] Buyl, P. tidynamics: A tiny package to compute the dynamics of stochastic and molecular simulations. Journal of Open Source Software,
3(28), 877 (2018). doi: `10.21105/joss.00877`_

.. _`10.21105/joss.00877`: https://doi.org/10.21105/joss.00877

.. _citations-using-duecredit:

Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions package/setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -558,6 +558,7 @@ def dynamic_author_list():
'scipy>=1.0.0',
'matplotlib>=1.5.1',
'mock',
'tidynamics>=1.0.0',
hmacdope marked this conversation as resolved.
Show resolved Hide resolved
'tqdm>=4.43.0',
]
if not os.name == 'nt':
Expand Down
Loading