8. 轨迹变换(“即时”变换)
在MDAnalysis中,一个 变换 是一个函数/类似函数的类,用于修改当前 Timestep
并返回 Timestep
。例如,一些分析和可视化通常需要进行坐标变换,如PBC校正和分子拟合。变换函数 (transformation_1
和 transformation_2
在下面的示例中)可以由用户针对任何给定的 Timestep
在弹道上,
u = MDAnalysis.Universe(topology, trajectory)
for ts in u.trajectory:
ts = transformation_2(transformation_1(ts))
在那里他们改变时间步长的坐标 ts
就位了。这些转换没有什么特别之处,只是它们必须以这样一种方式编写,即它们可以更改 Timestep
就位了。
如下所述 工作流程 ,可以将多个变换组合在一起并与轨迹相关联,从而使该轨迹 transformed on-the-fly 也就是说,从轨迹文件读取的数据将在例如 AtomGroup.positions
属性。
子模块 MDAnalysis.transformations
包含转换的集合(请参见 MDAnalysis中的转换 ),可以立即使用,但用户始终可以编写自定义转换(请参见 正在创建转换 )。
8.1. 工作流程
与手动应用转换相比,将整个 工作流程 具有轨迹的变换,并自动调用变换。
工作流是将按此顺序应用的转换函数的序列(元组或列表)。例如,
workflow = [transformation_1, transformation_2]
将有效地导致
ts = transformation_2(transformation_1(ts))
在轨道上的每一步。
用户可以使用添加的 Universe.trajectory.add_transformations
轨迹的方法(其中列表 workflow
取自上面的示例),
u.trajectory.add_transformations(*workflow)
或在 Universe
使用关键字参数创建 transformations :
u = MDAnalysis.Universe(topology, trajectory, transformations=workflow)
请注意,在这两种情况下,工作流在添加后不能更改。
8.2. 正在创建转换
一个简单的 变换 也可以是一个以 Timestep
作为输入,修改它,然后返回它。如果它不需要其他参数,只需要 Timestep
可以定义为以下示例:
def up_by_2(ts):
"""
Translate all coordinates by 2 angstroms up along the Z dimension.
"""
ts.positions = ts.positions + np.array([0, 0, 2], dtype=np.float32)
return ts
如果转换需要除 Timestep
,可以使用以下两种方法来创建此类转换:
8.2.1. 创建复杂的转换类
它是通过继承 MDAnalysis.transformations.base.TransformationBase
,它定义了 __call__()
对于转换类,可以直接应用于 Timestep
。 _transform()
必须进行定义,并包括对 MDAnalysis.coordinates.base.Timestep
。
因此,转换类可以大致定义如下:
from MDAnalysis.transformations import TransformationBase
class up_by_x_class(TransformationBase):
def __init__(self, distance):
self.distance = distance
def _transform(self, ts):
ts.positions = ts.positions + np.array([0, 0, self.distance], dtype=np.float32)
return ts
它是中的默认构造方法 MDAnalysis.transformations
从2.0.0版开始,因为它可以可靠地序列化。看见 MDAnalysis.transformations.translate
举个简单的例子。
8.2.2. 创建复杂的变换闭包函数
转换也可以是包装函数,该函数采用 Timestep
对象作为参数。因此,在这种情况下,变换函数(闭包)可以大致定义如下:
def up_by_x_func(distance):
"""
Creates a transformation that will translate all coordinates by a given amount along the Z dimension.
"""
def wrapped(ts):
ts.positions = ts.positions + np.array([0, 0, distance], dtype=np.float32)
return ts
return wrapped
使用包装函数的另一种方法是使用 functools
。上面的函数可以写成:
import functools
def up_by_x(ts, distance):
ts.positions = ts.positions + np.array([0, 0, distance], dtype=np.float32)
return ts
up_by_2 = functools.partial(up_by_x, distance=2)
尽管函数(闭包)用作转换,但从2.0.0版开始,在MDAnalysis中不使用它们,因为它们不能可靠地序列化,因此 Universe
这样的变换不能与常见的并行化方案(例如,基于 multiprocessing
)。有关如何编写闭包样式转换的详细描述,请参考MDAnalys1.x文档。
8.3. MDAnalysis中的转换
该模块 MDAnalysis.transformations
包含可立即在您自己的 workflows 。为了使用这些转换中的任何一种,必须首先导入模块:
import MDAnalysis.transformations
然后,可以如上所述将工作流添加到轨迹。值得注意的是,参数 max_threads 可以在创建转换实例时定义,以限制最大线程数。(请参阅 MDAnalysis.transformations.base.TransformationBase
有关更多详细信息)可以通过检查特定转换是否可以与并行分析一起使用 parallelizable
属性。
看见 当前实施的转换 中有关现有转换的更多信息 MDAnalysis.transformations
。
8.4. 如何实现转型
转换单个帧的坐标(尽管通常会将转换添加到 workflow ,如后续示例中所示):
u = MDAnalysis.Universe(topology, trajectory)
new_ts = MDAnalysis.transformations.translate([1,1,1])(u.trajectory.ts)
创建工作流并将其添加到轨迹:
u = MDAnalysis.Universe(topology, trajectory)
workflow = [MDAnalysis.transformations.translate([1,1,1]),
MDAnalysis.transformations.translate([1,2,3])]
u.trajectory.add_transformations(*workflow)
在定义领域时,将工作流作为关键字参数:
workflow = [MDAnalysis.transformations.translate([1,1,1]),
MDAnalysis.transformations.translate([1,2,3])]
u = MDAnalysis.Universe(topology, trajectory, transformations=workflow)
8.5. 转换类的构建块
转换通常利用NumPy的能力来获得更好的数组操作性能。然而,当涉及到并行性时,NumPy有时会通过超线程(当它使用OpenBlas后端时)或通过与其他并行引擎(例如DASK)一起工作来超额订阅线程。
在MDAnalysis中,我们使用 threadpoolctl 内部 TransformationBase
以控制转换的最大线程数。
还可以通过设置外部环境变量来应用全局线程限制,例如 OMP_NUM_THREADS=1 MKL_NUM_THREADS=1 OPENBLAS_NUM_THREADS=1 BLIS_NUM_THREADS=1 python script.py
。阅读有关并行性和资源管理的更多信息 scikit-learn documentations 。
建议用户对代码进行基准测试,因为在默认情况下,不同库之间的交互可能会导致性能不佳。
8.6. 当前实施的转换
- 8.6.1. 轨迹平移
MDAnalysis.transformations.translate
- 8.6.2. 弹道旋转
MDAnalysis.transformations.rotate
- 8.6.3. 轨迹坐标平均
MDAnalysis.transformations.positionaveraging
- 8.6.4. 拟合变换
MDAnalysis.transformations.fit
- 8.6.5. 展开/展开变换
MDAnalysis.transformations.wrap
- 8.6.6. 没有跳跃轨迹展开
MDAnalysis.transformations.nojump
- 8.6.7. 设置盒子尺寸
MDAnalysis.transformations.boxdimensions