-
Notifications
You must be signed in to change notification settings - Fork 723
Feature non linear time averaged msd #5066
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
Merged
orbeckst
merged 27 commits into
MDAnalysis:develop
from
gitsirsha:feature-Non-linear-time-averaged-msd
Aug 22, 2025
Merged
Changes from 15 commits
Commits
Show all changes
27 commits
Select commit
Hold shift + click to select a range
60973ba
Inditial addition of code to calculate time-averaged msd for non-line…
gitsirsha 0dc3db1
updated_documentation_v1_plots_removed
gitsirsha f6f55a1
Added_name_in_the_package/AUTHORS
gitsirsha e363635
addressed_review_comments_mainly_removed_linearity_check
gitsirsha 5aa09ca
added results delta t values
gitsirsha 871faa2
initial test added changed changelog and docs
gitsirsha 00fc309
added LAMMPSDUMP_non_linear to __all__
gitsirsha c90f52e
ran black 24.10.0
gitsirsha 7ad3e09
Revert "ran black 24.10.0"
gitsirsha b1ee485
added test for all msd types - added test with start stop step
gitsirsha 2bbdffb
ran black 24.4.2
gitsirsha ee764b7
ran black on datafiles.py
gitsirsha 0f50810
cleanup - removed docs and edited formatting
gitsirsha 7b16b9f
added results.msds_by_particle for non_linear method
gitsirsha 72b3dd3
minor chancge - versionadded to versionchanged
gitsirsha e367984
dtype removal and cleanup misplaced strings
gitsirsha 069bec5
Added entry to project.toml
gitsirsha ac4b4b2
Attribute definition edit for cases non_linear : bool
gitsirsha 3ceca5c
Indentation edit
gitsirsha 1a24e36
update warning in msd docs
orbeckst daad519
Testing doc formatting, WIP
gitsirsha 29df80e
Merge branch 'develop' into feature-Non-linear-time-averaged-msd
gitsirsha b578a67
Update self.results.delta_t_values #1
gitsirsha e26f53a
Update self.results.delta_t_values #2
gitsirsha 125e710
Update self.results.delta_t_values #3
gitsirsha 498a061
weird formatting edits
gitsirsha 788758d
removed dump_times
gitsirsha File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -103,8 +103,7 @@ | |
|
||
msd = MSD.results.timeseries | ||
|
||
Visual inspection of the MSD is important, so let's take a look at it with a | ||
simple plot. | ||
Visual inspection of the MSD is important, so let's take a look at it with a simple plot. | ||
|
||
.. code-block:: python | ||
|
||
|
@@ -173,7 +172,7 @@ | |
start_index = int(start_time/timestep) | ||
end_time = 60 | ||
linear_model = linregress(lagtimes[start_index:end_index], | ||
msd[start_index:end_index]) | ||
msd[start_index:end_index]) | ||
gitsirsha marked this conversation as resolved.
Show resolved
Hide resolved
|
||
slope = linear_model.slope | ||
error = linear_model.stderr | ||
# dim_fac is 3 as we computed a 3D msd with 'xyz' | ||
|
@@ -245,6 +244,7 @@ | |
from .base import AnalysisBase | ||
from ..core import groups | ||
from tqdm import tqdm | ||
import collections | ||
|
||
logger = logging.getLogger("MDAnalysis.analysis.msd") | ||
|
||
|
@@ -281,6 +281,13 @@ class EinsteinMSD(AnalysisBase): | |
the MSD. Otherwise, use the simple "windowed" algorithm. | ||
The tidynamics package is required for `fft=True`. | ||
Defaults to ``True``. | ||
non_linear : bool | ||
If ``True``, calculates MSD for trajectory where frames are | ||
non-linearly dumped. To use this set `fft=False`. | ||
Defaults to ``False``. | ||
orbeckst marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
.. versionadded:: 2.10.0 | ||
|
||
|
||
Attributes | ||
---------- | ||
|
@@ -290,6 +297,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. | ||
orbeckst marked this conversation as resolved.
Show resolved
Hide resolved
|
||
results.delta_t_values : :class:`numpy.ndarray` | ||
Array of unique Δt (time differences) at which time-averaged MSD values are | ||
orbeckst marked this conversation as resolved.
Show resolved
Hide resolved
|
||
computed. | ||
|
||
.. versionadded:: 2.10.0 | ||
|
||
ag : :class:`AtomGroup` | ||
The :class:`AtomGroup` resulting from your selection | ||
n_frames : int | ||
|
@@ -299,24 +312,20 @@ class EinsteinMSD(AnalysisBase): | |
|
||
|
||
.. versionadded:: 2.0.0 | ||
orbeckst marked this conversation as resolved.
Show resolved
Hide resolved
|
||
.. versionchanged:: 2.10.0 | ||
Added ability to calculate MSD from samples that are not linearly spaced with the | ||
new `non_linear` keyword argument. | ||
""" | ||
|
||
def __init__(self, u, select="all", msd_type="xyz", fft=True, **kwargs): | ||
r""" | ||
Parameters | ||
---------- | ||
u : Universe or AtomGroup | ||
An MDAnalysis :class:`Universe` or :class:`AtomGroup`. | ||
select : str | ||
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 | ||
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`. | ||
""" | ||
def __init__( | ||
self, | ||
u, | ||
select="all", | ||
msd_type="xyz", | ||
fft=True, | ||
non_linear=False, | ||
**kwargs, | ||
): | ||
if isinstance(u, groups.UpdatingAtomGroup): | ||
raise TypeError( | ||
"UpdatingAtomGroups are not valid for MSD " "computation" | ||
gitsirsha marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
@@ -329,6 +338,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.non_linear = non_linear | ||
|
||
# local | ||
self.ag = u.select_atoms(self.select) | ||
|
@@ -338,6 +348,7 @@ def __init__(self, u, select="all", msd_type="xyz", fft=True, **kwargs): | |
# result | ||
self.results.msds_by_particle = None | ||
self.results.timeseries = None | ||
self.results.delta_t_values = None | ||
orbeckst marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
def _prepare(self): | ||
# self.n_frames only available here | ||
|
@@ -383,10 +394,13 @@ def _single_frame(self): | |
] | ||
|
||
def _conclude(self): | ||
if self.fft: | ||
self._conclude_fft() | ||
if self.non_linear: | ||
self._conclude_non_linear() | ||
else: | ||
self._conclude_simple() | ||
if self.fft: | ||
self._conclude_fft() | ||
else: | ||
self._conclude_simple() | ||
|
||
def _conclude_simple(self): | ||
r"""Calculates the MSD via the simple "windowed" algorithm.""" | ||
|
@@ -421,3 +435,48 @@ def _conclude_fft(self): # with FFT, np.float64 bit prescision required. | |
positions[:, n, :] | ||
) | ||
self.results.timeseries = self.results.msds_by_particle.mean(axis=1) | ||
|
||
def _conclude_non_linear(self): | ||
|
||
dump_times = self.times | ||
gitsirsha marked this conversation as resolved.
Show resolved
Hide resolved
|
||
n_frames = self.n_frames | ||
n_atoms = self.n_particles | ||
positions = self._position_array.astype(np.float64) | ||
orbeckst marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
msd_dict = collections.defaultdict( | ||
list | ||
) # Dictionary to collect MSDs: {Δt: [msd1, msd2, ...]} | ||
gitsirsha marked this conversation as resolved.
Show resolved
Hide resolved
|
||
msds_by_particle_dict = collections.defaultdict(list) | ||
|
||
# TODO: optimize the code | ||
# Looping over all the frames as if the referenced gets shifted frame to frame | ||
orbeckst marked this conversation as resolved.
Show resolved
Hide resolved
|
||
for i in range(n_frames): | ||
for j in range(i + 1, n_frames): | ||
delta_t = dump_times[j] - dump_times[i] | ||
gitsirsha marked this conversation as resolved.
Show resolved
Hide resolved
|
||
# Compute displacement and squared displacement | ||
disp = positions[j] - positions[i] | ||
squared_disp = np.sum(disp**2, axis=1) | ||
msd = np.mean(squared_disp) | ||
# Store MSD under corresponding Δt | ||
msd_dict[delta_t].append(msd) | ||
msds_by_particle_dict[delta_t].append(squared_disp) | ||
|
||
msd_dict[0] = [0] | ||
msds_by_particle_dict[0.0] = [np.zeros(n_atoms)] | ||
|
||
# For each delta_t, stacked all squared_disp arrays and averaging over axis=0 (time origins) | ||
delta_t_values = sorted(msd_dict.keys()) | ||
avg_msds = [np.mean(msd_dict[dt]) for dt in delta_t_values] | ||
msds_by_particle_array = np.zeros((len(delta_t_values), n_atoms)) | ||
orbeckst marked this conversation as resolved.
Show resolved
Hide resolved
|
||
for idx, dt in enumerate(delta_t_values): | ||
# Stack list of arrays like -- (n_time_origins, n_atoms) | ||
arr = np.vstack(msds_by_particle_dict[dt]) | ||
msds_by_particle_array[idx, :] = np.mean(arr, axis=0) | ||
|
||
self.results.timeseries = np.array(avg_msds, dtype=np.float64) | ||
self.results.delta_t_values = np.array( | ||
delta_t_values, dtype=np.float64 | ||
) | ||
self.results.msds_by_particle = np.array( | ||
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. Why not just self.results.msds_by_particle = msds_by_particle_array I don't think you need to make it an array again. 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. Yes it is not required again. Thanks for pointing it out. |
||
msds_by_particle_array, dtype=np.float64 | ||
) |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.