有几种方法可以回答这个问题。首先,
基本上我在想,对于我轨迹中的每一帧,MDAnalysis 会检查 ION 1 在第 1 帧中的位置。然后在第 2 帧中,它会再次检查相同的离子并将其与之前的位置进行比较。例如,如果它从 + 坐标变为 - 坐标,那么我会有一个添加 +1 的计数,这意味着它包裹了一次。如果它从 - 变为 +,我会让它减去 1。然后在所有帧结束时,我会有一个数字,可以帮助我确定如何执行我的分析。
您可以编写自己的分析类。下面是一种未经测试的方法原型——本教程更多地介绍了每种方法(_prepare、_conclude 等)的作用。
from MDAnalysis.analysis.base import AnalysisBase
import numpy as np
class CountWrappings(AnalysisBase):
def __init__(self, universe, select="name NA"):
super().__init__(universe.universe.trajectory)
# these are your selected ions
self.atomgroup = universe.select_atoms(select)
self.n_atoms = len(self.atomgroup)
def _prepare(self):
# self.results is a dictionary of results
self.results.wrapping_per_frame = np.zeros((self.n_frames, self.n_atoms), dtype=bool)
self._last_positions = self.atomgroup.positions
def _single_frame(self):
# does sign change for any element in 2D array?
compare_signs = np.sign(self.atomgroup.positions) == np.sign(self._last_positions)
sign_changes_any_axis = np.any(compare_signs, axis=1)
# _frame_index is the relative index of the frame being currently analyzed
self.results.wrapping_per_frame[self._frame_index] = sign_changes_any_axis
self._last_positions = self.atomgroup.positions
def _conclude(self):
self.results.n_wraps = self.results.wrapping_per_frame.sum(axis=0)
n_wraps = CountWrappings(my_universe, select="name NA CL MG")
n_wraps.run()
print(n_wraps.results.wrapping_per_frame)
print(n_wraps.results.n_wraps)
但是,我不确定这是否能解决您的实际目标:
我想通过实施一种方法来解开包装盒边缘的离子的包装坐标来纠正这个问题。
你在计算相对于任何东西的离子位置吗?潜在地,您可以在每个离子和中心之间添加键,以便您可以使用 AtomGroup.unwrap() 函数。或者,您的数据是否与 GROMACS 兼容?GROMACS 有一个名为“nojump”的解包实用程序,它可以解包跨越盒子边缘的原子,例如
gmx trjconv -f my_trajectory.xtc -s my_topology.gro -pbc nojump -o my_unwrapped_trajectory.xtc