In this notebook, I plot an interactive 2D map from a molecular dynamics trajectory in the IPython notebook in just a few lines of code. For this purpose, we will take advantage of the powerful package MMTK.
from __future__ import print_function, division
from MMTK import *
from MMTK.Trajectory import Trajectory, TrajectoryOutput, SnapshotGenerator
from MMTK.Proteins import Protein, PeptideChain
import numpy as np
%install_ext https://raw.githubusercontent.com/rasbt/watermark/master/watermark.py
%load_ext watermark
%watermark -v -m -p numpy,MMTK
NetCDF file format - MMTK trajectory (The trajectory can be easily translated from outcomes of popular Molecular dynamics software like Gromacs.)
filename = 'traj_prot_nojump.nc'
Reading the trajectory
trajectory = Trajectory(None, filename)
universe = trajectory.universe
proteins = universe.objectList(Protein)
chain = proteins[0][0]
# modified fonction, so it can be called with multiprocessing
def calpha_2dmap(trajectory = trajectory, dt = 10000, t = range(0, len(trajectory))):
"""
Calculate the distance between carbon alpha in the first protein of trajectory.
Parameters
----------
trajectory: MMTK.Trajectory
dt : int
dt in ns. The distances will be calculated every dt ns.
t : int
range of steps to take into account
"""
dist = []
universe = trajectory.universe
proteins = universe.objectList(Protein)
chain = proteins[0][0]
traj = trajectory[t]
for n, step in enumerate(traj):
if int(step['time']) % dt == 0:
universe.setConfiguration(step['configuration'])
for i in np.arange(len(chain)-1):
for j in np.arange(len(chain)-1):
dist.append(universe.distance(chain[i].peptide.C_alpha,
chain[j].peptide.C_alpha))
return(dist)
dist = calpha_2dmap()
dist = np.array(dist)
Reshaping the array¶
We reshape the dist array, so the first dimension corresponds to the time.
dist = dist.reshape(int(len(dist) / ((len(chain)-1) * (len(chain)-1))), len(chain)-1, len(chain)-1)
dist.shape # time, n_calpha, n_calpha
So the first dimension corresponds to the time and the 2 other dimensions correspond to the distances between the Carbon-$\alpha$ atoms of the 339 residues of the protein.
dist_mean = dist[-10:].mean(axis=0) # mean over the last 10 steps
dist_mean.shape
Static 2D map¶
We can naturally plot a static 2D map ...
fig = plt.figure()
plt.imshow(dist_mean, plt.get_cmap('YlOrRd'))
plt.colorbar()
Interactive 2D map¶
... but why wouldn't we plot an interactive one?
import IPython.html.widgets as widgets
from IPython.html.widgets import interact, interactive, fixed
len(dist[0])
@interact(
t=(0,len(dist)-1),
calpha_x_min = (0, len(dist[0])),
calpha_x_max = (0, len(dist[0])),
calpha_y_min = (0, len(dist[0])),
calpha_y_max = (0, len(dist[0]))
)
def interactive_map(t=0, calpha_x_min = 0, calpha_x_max = len(dist[0]), calpha_y_min = 0, calpha_y_max = len(dist[0])):
fig = plt.figure(figsize=(7,7))
ax = fig.add_subplot(1, 1, 1)
ax.set_xlim([calpha_x_min, calpha_x_max])
ax.set_ylim([calpha_y_min, calpha_y_max])
plt.imshow(dist[t], plt.get_cmap('YlOrRd'))
cbar = plt.colorbar()
cbar.ax.tick_params(labelsize=14)
plt.clim(0.0,7.0)
plt.title('2D map')
NOTE: the corresponding plot is encapsulated in the first video at the end of this page.
So now we can have our interactive 2D map. You can observe the 2D map in function of time or zoom to a specific region. If you are insterested in some specific distances, you can directly narrow a specific zone like that:
@interact(
t=(0,len(dist)-1),
calpha_x_min = (211, 227),
calpha_x_max = (211, 227),
calpha_y_min = (110, 143),
calpha_y_max = (110, 143))
def interactive_map(t=len(dist)-1, calpha_x_min = 0, calpha_x_max = len(dist[0]), calpha_y_min = 0, calpha_y_max = len(dist[0])):
fig = plt.figure(figsize=(7,7))
ax = fig.add_subplot(1, 1, 1)
ax.set_xlim([calpha_x_min, calpha_x_max])
ax.set_ylim([calpha_y_min, calpha_y_max])
ax.tick_params(labelsize=14)
plt.imshow(dist[t], plt.get_cmap('YlOrRd'), aspect = 'auto')
cbar = plt.colorbar()
cbar.ax.tick_params(labelsize=14)
plt.clim(0.0,6.0)
plt.title('2D map')
plt.tight_layout()
plt.savefig('2d.jpg', dpi=1000)
NOTE: the corresponding plot is encapsulated in the second video.
NOTE - if you cannot watch the videos on this page, you will find them at these URLs: