Wrap to PBC#

Wrapping atomic coordinates into the primary periodic boundary condition unit cell.

The function molsysmt.pbc.wrap_to_pbc() maps atomic coordinates back into the primary space-filling periodic unit cell.

Added in version 1.0.0.

Basic usage#

Let’s wrap a continuous trajectory into the primary periodic box:

import molsysmt as msm
import numpy as np
import matplotlib.pyplot as plt
molsys = msm.convert(msm.systems['two LJ particles']['traj_two_lj_particles.trjpk'], to_form='molsysmt.StructuresDict')

We inspect the continuous particle coordinate trajectory before wrapping:

fig, ax = plt.subplots(figsize=(7, 3.5))
time = molsys['time']
ax.plot(time, molsys['coordinates'][:, 0, 0], label='Particle 0 (X)', color='navy')
ax.plot(time, molsys['coordinates'][:, 1, 0], label='Particle 1 (X)', color='firebrick')
ax.set_title('Continuous Coordinates Before Wrapping')
ax.set_xlabel('Time (ps)')
ax.set_ylabel('Coordinate (nm)')
ax.legend()
ax.grid(True, linestyle='--', alpha=0.5)
plt.tight_layout()
plt.show()
../../../../_images/3b3c76ec03cd582ceb6466a89741116ebdd336a5fcec1053e30f0a281d3baa45.png

We fold all atomic coordinates into the primary periodic unit cell with molsysmt.pbc.wrap_to_pbc():

molsys_wrapped = msm.pbc.wrap_to_pbc(molsys)

Plotting the wrapped coordinates confirms that all coordinates now evolve strictly within the periodic cell boundaries:

fig, ax = plt.subplots(figsize=(7, 3.5))
ax.plot(time, molsys_wrapped['coordinates'][:, 0, 0], label='Particle 0 (X)', color='navy')
ax.plot(time, molsys_wrapped['coordinates'][:, 1, 0], label='Particle 1 (X)', color='firebrick')
ax.set_title('Wrapped Coordinates Inside Primary Periodic Cell')
ax.set_xlabel('Time (ps)')
ax.set_ylabel('Coordinate (nm)')
ax.legend()
ax.grid(True, linestyle='--', alpha=0.5)
plt.tight_layout()
plt.show()
../../../../_images/92c22ec51013f3049d171f8970fff091fd79ee7a97d16f66d7ff90ff9854d079.png

We verify that inter-particle distances evaluated under periodic boundary conditions remain invariant under wrapping:

dist_orig = msm.structure.get_distances(molsys, selection=0, selection_2=1, pbc=True)
dist_wrap = msm.structure.get_distances(molsys_wrapped, selection=0, selection_2=1, pbc=True)
print('Periodic distances invariant under wrapping:', np.allclose(dist_orig, dist_wrap))
Periodic distances invariant under wrapping: True

Preserving covalent bonds during macromolecular wrapping#

When wrapping macromolecular structures containing bonded atoms (such as solvated proteins or peptides), setting compact='component' ensures connected covalent blocks are reconstructed and translated together:

molsys_pep = msm.convert(msm.systems['Met-enkephalin']['met_enkephalin.h5msm'])
molsys_solv = msm.build.solvate(molsys_pep, box_shape='cubic', clearance='14.0 angstroms', engine='PDBFixer')
molsys_pep_wrapped = msm.pbc.wrap_to_pbc(molsys_solv, compact='component')

We visualize the wrapped solvated macromolecular system in 3D:

msm.view(molsys_pep_wrapped)