Source code for drsip.tilt_angle_criterion

"""
==================================================================
Tilt Angle Criterion (:mod:`drsip.tilt_angle_criterion`)
==================================================================

Module contains functions implementing the tilt angle criterion.

Functions
---------

.. autofunction:: tilt_angle_criterion
.. autofunction:: get_cylindrical_axis
"""
import numpy as np


[docs]def tilt_angle_criterion(cylindrical_axis, membrane_norm, cutoff=0.541052): """Tilt angle criterion The tilt angle of a monomer is the acute angle between its cylindrical axis and the membrane normal. If the tilt angle is less than the cutoff, it passes the criterion otherwise it fails the criterion. Parameters ---------- cylindrical_axis, membrane_norm : np.array 3-dim vector of the monomer's cylindrical axis and the membrane normal. The membrane normal is the axis orthogonal to the membrane bilayer. cutoff : float, optional Tilt angle cutoff in radians. Default cutoff is 0.541052 rad (31 degrees). Returns ------- list Returns the tilt angle (float) and pass status (bool). The pass status is True if the monomer passes the filter, otherwise False. """ b, a = np.sort([np.linalg.norm(cylindrical_axis), np.linalg.norm(membrane_norm)]) c = np.linalg.norm(membrane_norm - cylindrical_axis) if b >= c: mu = c - (a-b) else: mu = b - (a-c) current_angle = 2 * \ np.arctan(np.sqrt(((a-b)+c) * mu / ((a+(b+c)) * ((a-c)+b)))) if current_angle > np.pi/2: current_angle = np.pi - current_angle pass_status = current_angle < cutoff return [current_angle, pass_status]
[docs]def get_cylindrical_axis(CA_sel, transmembrane_helix_sel_strs): """Get the cylindrical axis of a monomer The cylindrical axis of a monomer is the average of the longitudinal axis (unit vector) of the transmembrane helices. Parameters ---------- CA_sel : MDAnalysis.core.groups.AtomGroup MDAnalysis' atomgroup containing the monomer's C-alpha atoms. transmembrane_helix_sel_strs : list List of MDAnalysis style atom selection strings, selecting each transmembrane helix. Returns ------- np.array 3-dim vector (unit vector) containing the cylindrical axis of the monomer. """ prot_segments = np.unique(CA_sel.segids) combined_transmembrane_helix_sel_str = '(' + \ ' or '.join(transmembrane_helix_sel_strs) + ')' static_cylindrical_axis = np.zeros(3) first_static_helix_PA1 = None if len(prot_segments) == 1: transmembrane_helix_sel = CA_sel.select_atoms( combined_transmembrane_helix_sel_str) for transmembrane_helix_sel_str in transmembrane_helix_sel_strs: helix_sel = transmembrane_helix_sel.select_atoms( transmembrane_helix_sel_str) if helix_sel.n_atoms < 3: continue diff = helix_sel.positions - helix_sel.positions.mean(axis=0) # We do not scale the diff with 1/(N-1) because we're not using the # eigenvalues other than comparing their relative values (largest) static_helix_PA1 = np.linalg.eigh(diff.T.dot(diff))[1][:, 2] if first_static_helix_PA1 is None: first_static_helix_PA1 = static_helix_PA1 elif static_helix_PA1.dot(first_static_helix_PA1) < 0: static_helix_PA1 = -static_helix_PA1 static_cylindrical_axis += static_helix_PA1 if first_static_helix_PA1 is None: raise Exception('No transmembrane helices were found') return static_cylindrical_axis/np.linalg.norm(static_cylindrical_axis) else: raise Exception('Residues from multiple chains were selected')