.. DO NOT EDIT. .. THIS FILE WAS AUTOMATICALLY GENERATED BY SPHINX-GALLERY. .. TO MAKE CHANGES, EDIT THE SOURCE PYTHON FILE: .. "examples/gallery/structure/normal_modes.py" .. LINE NUMBERS ARE GIVEN BELOW. .. only:: html .. note:: :class: sphx-glr-download-link-note :ref:`Go to the end ` to download the full example code .. rst-class:: sphx-glr-example-title .. _sphx_glr_examples_gallery_structure_normal_modes.py: Visualization of normal modes from an elastic network model =========================================================== The *elastic network model* (ENM) is a fast method to estimate movements in a protein structure, without the need to run time-consuming MD simulations. A protein is modelled as *mass-and-spring* model, with the masses being the :math:`C_\alpha` atoms and the springs being the non-covalent bonds between adjacent residues. Via *normal mode analysis* distinct movements/oscillations can be extracted from the model. An *anisotropic network model* (ANM), is an ENM that includes directional information. Hence, the normal mode analysis yields eigenvectors, where each atom is represented by three vector components (*x*, *y*, *z*). Thus these vectors can be used for 3D representation. In the case of this example a normal mode analysis on an ANM was already conducted. This script merely takes the structure and obtained eigenvectors to add a smooth oscillation of the chosen normal mode to the structure. The newly created structure has multiple models, where each model depicts a different time in the oscillation period. Then the multi-model structure can be used to create a video of the oscillation using a molecular visualization program. The file containing the eigenvectors can be downloaded via this :download:`link `. .. GENERATED FROM PYTHON SOURCE LINES 32-114 .. image-sg:: /examples/gallery/structure/images/sphx_glr_normal_modes_001.gif :alt: normal modes :srcset: /examples/gallery/structure/images/sphx_glr_normal_modes_001.gif :class: sphx-glr-single-img .. code-block:: Python # Code source: Patrick Kunzmann # License: BSD 3 clause from tempfile import NamedTemporaryFile import numpy as np from numpy import newaxis import biotite.structure as struc import biotite.structure.io as strucio import biotite.structure.io.pdbx as pdbx import biotite.database.rcsb as rcsb # A CSV file containing the eigenvectors for the CA atoms VECTOR_FILE = "../../download/glycosylase_anm_vectors.csv" # The corresponding structure PDB_ID = "1MUG" # The normal mode to be visualized # '-1' is the last (and most significant) one MODE = -1 # The amount of frames (models) per oscillation FRAMES = 60 # The maximum oscillation amplitude for an atom # (The length of the ANM's eigenvectors make only sense when compared # relative to each other, the absolute values have no significance) MAX_AMPLITUDE = 5 # Load structure pdbx_file = pdbx.BinaryCIFFile.read(rcsb.fetch(PDB_ID, "bcif")) structure = pdbx.get_structure(pdbx_file, model=1) # Filter first peptide chain protein_chain = structure[ struc.filter_amino_acids(structure) & (structure.chain_id == structure.chain_id[0]) ] # Filter CA atoms ca = protein_chain[protein_chain.atom_name == "CA"] # Load eigenvectors for CA atoms # The first axis indicates the mode, # the second axis indicates the vector component vectors = np.loadtxt(VECTOR_FILE, delimiter=",").transpose() # Discard the last 6 modes, as these are movements of the entire system: # A system with N atoms has only 3N - 6 degrees of freedom # ^^^ vectors = vectors[:-6] # Extract vectors for given mode and reshape to (n,3) array mode_vectors = vectors[MODE].reshape((-1, 3)) # Rescale, so that the largest vector has the length 'MAX_AMPLITUDE' vector_lenghts = np.sqrt(np.sum(mode_vectors**2, axis=-1)) scale = MAX_AMPLITUDE / np.max(vector_lenghts) mode_vectors *= scale # Stepwise application of eigenvectors as smooth sine oscillation time = np.linspace(0, 2*np.pi, FRAMES, endpoint=False) deviation = np.sin(time)[:, newaxis, newaxis] * mode_vectors # Apply oscillation of CA atom to all atoms in the corresponding residue oscillation = np.zeros((FRAMES, len(protein_chain), 3)) residue_starts = struc.get_residue_starts( protein_chain, # The last array element will be the length of the atom array, # i.e. no valid index add_exclusive_stop=True ) for i in range(len(residue_starts) -1): res_start = residue_starts[i] res_stop = residue_starts[i+1] oscillation[:, res_start:res_stop, :] \ = protein_chain.coord[res_start:res_stop, :] + deviation[:, i:i+1, :] # An atom array stack containing all frames oscillating_structure = struc.from_template(protein_chain, oscillation) # Save as PDB for rendering a video with PyMOL temp = NamedTemporaryFile(suffix=".pdb") strucio.save_structure(temp.name, oscillating_structure) temp.close() .. _sphx_glr_download_examples_gallery_structure_normal_modes.py: .. only:: html .. container:: sphx-glr-footer sphx-glr-footer-example .. container:: sphx-glr-download sphx-glr-download-jupyter :download:`Download Jupyter notebook: normal_modes.ipynb ` .. container:: sphx-glr-download sphx-glr-download-python :download:`Download Python source code: normal_modes.py ` .. only:: html .. rst-class:: sphx-glr-signature `Gallery generated by Sphinx-Gallery `_