Source code for fast.analysis.contacts

# Author: Maxwell I. Zimmerman <mizimmer@wustl.edu>
# Contributors:
# Copywright (C) 2017, Washington University in St. Louis
# All rights reserved.
# Unauthorized copying of this file, via any medium, is strictly prohibited
# Proprietary and confidential


#######################################################################
# imports
#######################################################################


import glob
import itertools
import mdtraj as md
import numpy as np
import os
from .base_analysis import base_analysis
from .. import tools


#######################################################################
# code
#######################################################################


[docs]def best_hummer_q(traj, native, verbose=False, native_cutoff=0.45): """Compute the fraction of native contacts according the definition from Best, Hummer and Eaton [1]. Adapted from: 'http://mdtraj.org/latest/examples/native-contact.html' Parameters ---------- traj : md.Trajectory The trajectory to do the computation for native : md.Trajectory The 'native state'. This can be an entire trajecory, or just a single frame. Only the first conformation is used Returns ------- q : np.array, shape=(len(traj),) The fraction of native contacts in each frame of `traj` References ---------- ..[1] Best, Hummer, and Eaton, "Native contacts determine protein folding mechanisms in atomistic simulations" PNAS (2013) """ BETA_CONST = 50 # 1/nm LAMBDA_CONST = 1.8 NATIVE_CUTOFF = native_cutoff # nanometers # get the indices of all of the heavy atoms heavy = native.topology.select_atom_indices('heavy') # get the pairs of heavy atoms which are farther than 3 # residues apart heavy_pairs = np.array( [(i,j) for (i,j) in itertools.combinations(heavy, 2) if abs(native.topology.atom(i).residue.index - \ native.topology.atom(j).residue.index) > 3]) # compute the distances between these pairs in the native state heavy_pairs_distances = md.compute_distances(native[0], heavy_pairs)[0] # and get the pairs s.t. the distance is less than NATIVE_CUTOFF native_contacts = heavy_pairs[heavy_pairs_distances < NATIVE_CUTOFF] if verbose: print("Number of native contacts", len(native_contacts)) # now compute these distances for the whole trajectory r = md.compute_distances(traj, native_contacts) # and recompute them for just the native state r0 = md.compute_distances(native[0], native_contacts) q = np.mean( 1.0 / (1 + np.exp(BETA_CONST * (r - LAMBDA_CONST * r0))), axis=1) return q
[docs]class ContactsWrap(base_analysis): """Analyses the fraction of native contacts. Parameters ---------- base_struct : str or md.Trajectory, The base structure to compare for native contacts. This topology must match the structures to analyse. Can be provided as a pdb location or an md.Trajectory object. atom_indices : str or array, The atom indices to use for computing native contacts. Can be provided as a data file to load or an array. Attributes ---------- output_name : str, The file containing rankings. """ def __init__( self, base_struct, atom_indices=None): # determine base_struct self.base_struct = base_struct if type(base_struct) is md.Trajectory: self.base_struct_md = self.base_struct else: self.base_struct_md = md.load(base_struct) # determine atom indices self.atom_indices = atom_indices if type(atom_indices) is str: self.atom_indices_vals = np.loadtxt(atom_indices, dtype=int) else: self.atom_indices_vals = self.atom_indices @property def class_name(self): return "ContactsWrap" @property def config(self): return { 'base_struct': self.base_struct, 'atom_indices': self.atom_indices, } @property def analysis_folder(self): return None @property def base_output_name(self): return "contacts_per_state"
[docs] def run(self): # determine if file already exists if os.path.exists(self.output_name): pass else: # load centers centers = md.load( "./data/full_centers.xtc", top=self.base_struct_md, atom_indices=self.atom_indices_vals) # get subset if necessary if self.atom_indices_vals is None: struct_sub = self.base_struct_md else: struct_sub = self.base_struct_md.atom_slice(self.atom_indices_vals) # calculate and save contacts contacts = best_hummer_q(centers, struct_sub) np.save(self.output_name, contacts)