{ "cells": [ { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "# Contact analysis: number of contacts within a cutoff\n", "\n", "We calculate the number of salt bridges in an enzyme as it transitions from a closed to an open conformation.\n", "\n", "**Last updated:** December 2022 with MDAnalysis 2.4.0-dev0\n", "\n", "**Minimum version of MDAnalysis:** 0.17.0\n", "\n", "**Packages required:**\n", " \n", "* MDAnalysis (Michaud-Agrawal *et al.*, 2011, Gowers *et al.*, 2016)\n", "* MDAnalysisTests\n", "* [matplotlib](https://matplotlib.org)\n", "* [pandas](https://pandas.pydata.org)\n", "\n", "**See also**\n", "\n", "* [Write your own contacts analysis method](contacts_custom.ipynb)\n", "* [Q1 vs Q2 contact analysis](contacts_q1q2.ipynb)\n", "* [Fraction of native contacts over a trajectory](contacts_native_fraction.ipynb)" ] }, { "cell_type": "code", "execution_count": 1, "metadata": { "ExecuteTime": { "end_time": "2020-07-29T05:08:24.953983Z", "start_time": "2020-07-29T05:08:21.329652Z" }, "execution": { "iopub.execute_input": "2021-05-19T05:57:13.080694Z", "iopub.status.busy": "2021-05-19T05:57:13.080158Z", "iopub.status.idle": "2021-05-19T05:57:14.169643Z", "shell.execute_reply": "2021-05-19T05:57:14.170078Z" } }, "outputs": [], "source": [ "import MDAnalysis as mda\n", "from MDAnalysis.tests.datafiles import PSF, DCD\n", "from MDAnalysis.analysis import contacts\n", "\n", "import numpy as np\n", "import pandas as pd\n", "import matplotlib.pyplot as plt\n", "%matplotlib inline" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Background\n", "\n", "Quantifying the number of contacts over a trajectory can give insight into the formation and rearrangements of secondary and tertiary structure. This is closely related to native contacts analysis; where the fraction of native contacts refers to the fraction of contacts retained by a protein from the contacts in a reference frame, the number of contacts simply counts how many residues are within a certain cutoff for each frame. No reference is necessary. Please see the [Fraction of native contacts](contacts_native_fraction.ipynb#Background) for an introduction to native contacts analysis." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Loading files\n", "\n", "The test files we will be working with here feature adenylate kinase (AdK), a phosophotransferase enzyme. (Beckstein *et al.*, 2009) The trajectory ``DCD`` samples a transition from a closed to an open conformation." ] }, { "cell_type": "code", "execution_count": 2, "metadata": { "execution": { "iopub.execute_input": "2021-05-19T05:57:14.173557Z", "iopub.status.busy": "2021-05-19T05:57:14.172951Z", "iopub.status.idle": "2021-05-19T05:57:14.397389Z", "shell.execute_reply": "2021-05-19T05:57:14.396971Z" } }, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "/home/pbarletta/mambaforge/envs/mda-user-guide/lib/python3.9/site-packages/MDAnalysis/coordinates/DCD.py:165: DeprecationWarning: DCDReader currently makes independent timesteps by copying self.ts while other readers update self.ts inplace. This behaviour will be changed in 3.0 to be the same as other readers\n", " warnings.warn(\"DCDReader currently makes independent timesteps\"\n" ] } ], "source": [ "u = mda.Universe(PSF, DCD)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Defining the groups for contact analysis" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We define salt bridges as contacts between NH/NZ in ARG/LYS and OE\\*/OD\\* in ASP/GLU. It is not recommend to use this overly simplistic definition for real work that you want to publish." ] }, { "cell_type": "code", "execution_count": 3, "metadata": { "execution": { "iopub.execute_input": "2021-05-19T05:57:14.402746Z", "iopub.status.busy": "2021-05-19T05:57:14.401962Z", "iopub.status.idle": "2021-05-19T05:57:14.405378Z", "shell.execute_reply": "2021-05-19T05:57:14.405760Z" } }, "outputs": [], "source": [ "sel_basic = \"(resname ARG LYS) and (name NH* NZ)\"\n", "sel_acidic = \"(resname ASP GLU) and (name OE* OD*)\"\n", "acidic = u.select_atoms(sel_acidic)\n", "basic = u.select_atoms(sel_basic)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Calculating number of contacts within a cutoff" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Below, we define a function that calculates the number of contacts between `group_a` and `group_b` within the `radius` cutoff, for each frame in a trajectory." ] }, { "cell_type": "code", "execution_count": 4, "metadata": { "execution": { "iopub.execute_input": "2021-05-19T05:57:14.410261Z", "iopub.status.busy": "2021-05-19T05:57:14.409582Z", "iopub.status.idle": "2021-05-19T05:57:14.411114Z", "shell.execute_reply": "2021-05-19T05:57:14.411621Z" } }, "outputs": [], "source": [ "def contacts_within_cutoff(u, group_a, group_b, radius=4.5):\n", " timeseries = []\n", " for ts in u.trajectory:\n", " # calculate distances between group_a and group_b\n", " dist = contacts.distance_array(group_a.positions, group_b.positions)\n", " # determine which distances <= radius\n", " n_contacts = contacts.contact_matrix(dist, radius).sum()\n", " timeseries.append([ts.frame, n_contacts])\n", " return np.array(timeseries)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The results are returned as a numpy array. The first column is the frame, and the second is the number of contacts present in that frame." ] }, { "cell_type": "code", "execution_count": 5, "metadata": { "execution": { "iopub.execute_input": "2021-05-19T05:57:14.414883Z", "iopub.status.busy": "2021-05-19T05:57:14.414313Z", "iopub.status.idle": "2021-05-19T05:57:14.430769Z", "shell.execute_reply": "2021-05-19T05:57:14.431195Z" } }, "outputs": [ { "data": { "text/plain": [ "(98, 2)" ] }, "execution_count": 5, "metadata": {}, "output_type": "execute_result" } ], "source": [ "ca = contacts_within_cutoff(u, acidic, basic, radius=4.5)\n", "ca.shape" ] }, { "cell_type": "code", "execution_count": 6, "metadata": { "execution": { "iopub.execute_input": "2021-05-19T05:57:14.435679Z", "iopub.status.busy": "2021-05-19T05:57:14.435146Z", "iopub.status.idle": "2021-05-19T05:57:14.441001Z", "shell.execute_reply": "2021-05-19T05:57:14.441446Z" } }, "outputs": [ { "data": { "text/html": [ "
\n", " | Frame | \n", "# Contacts | \n", "
---|---|---|
0 | \n", "0 | \n", "69 | \n", "
1 | \n", "1 | \n", "73 | \n", "
2 | \n", "2 | \n", "77 | \n", "
3 | \n", "3 | \n", "77 | \n", "
4 | \n", "4 | \n", "85 | \n", "