From af3730f2ad55c13adf0f1f55e639e7ec726e8f4a Mon Sep 17 00:00:00 2001 From: Marti Municoy Date: Thu, 28 May 2020 16:00:53 +0200 Subject: [PATCH 01/67] Example of a parameter extraction for PELE --- .../extract_parameters_from_SMIRNOFF.ipynb | 911 ++++++++++++++++++ 1 file changed, 911 insertions(+) create mode 100644 offPELE/examples/extract_parameters_from_SMIRNOFF.ipynb diff --git a/offPELE/examples/extract_parameters_from_SMIRNOFF.ipynb b/offPELE/examples/extract_parameters_from_SMIRNOFF.ipynb new file mode 100644 index 00000000..07bbd120 --- /dev/null +++ b/offPELE/examples/extract_parameters_from_SMIRNOFF.ipynb @@ -0,0 +1,911 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 41, + "metadata": {}, + "outputs": [], + "source": [ + "from rdkit import Chem\n", + "from rdkit.Chem.Draw import IPythonConsole\n", + "from rdkit.Chem.Draw.MolDrawing import MolDrawing, DrawingOptions\n", + "\n", + "DrawingOptions.bondLineWidth=1.8\n", + "\n", + "from openforcefield.topology import Molecule\n", + "from offPELE.utils import get_data_file_path" + ] + }, + { + "cell_type": "code", + "execution_count": 46, + "metadata": {}, + "outputs": [], + "source": [ + "file_path = get_data_file_path('ligands/BNZ.pdb')\n", + "ligand_rdkit_molecule = Chem.rdmolfiles.MolFromPDBFile(file_path, removeHs=False)\n", + "ligand_molecule = Molecule.from_rdkit(ligand_rdkit_molecule)" + ] + }, + { + "cell_type": "code", + "execution_count": 47, + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAAASwAAAEsCAIAAAD2HxkiAAAF5ElEQVR4nO3dUW7bVhRF0brojJVhhGNWPwikRdo6tSC+fUmu9ZcgQUhLW4cy7fjj+Xz+BnR+rw8A7k6EEBMhxEQIMRFCTIQQEyHERAgxEUJMhBATIcRECDERQkyEEBMhxEQIMRFCTIQQEyHERAgxEUJMhBATIcRECDERQkyEEBMhxEQIMRFCTIQQEyHERAgxEUJMhBATIcRECDERQkyEEBMhxEQIMRFCTIQQEyHERAgxEUJMhBATIcRECDERQkyEEBMhxEQIMRFCTIQQEyHERAgxEUJMhBATIcRECDERQkyEEBMhxEQIMRFCTIQQEyHERAgxEUJMhBATIcRECDERQkyEEBMhxEQIMRFCTIQQEyHERAgxEb7Btm2//J2zu8M5VkQIMRFCTIQQ+6M+gIu4wxukO5xjQoTv8Xg8/v7LSz5f73COCZejEBMhxEQIsY/n81kfA9yaJYSYCCEmwmNd4PP4FziF4UR4rMfjceon8bZtP90e5O1ECDERHu68Y2gG1xAhxES4whnH0AwuI0KIiXCRc42hGVxJhOucpUMFLiZCiIlwqfljaAbXEyHERLja5DE0gwnfT9j4+Bj3kR94SDdhCSEmwsbz+fz4+KiP4i9mMCRCiIkwM2cMzWBLhBATYWnCGJrBnAghJsJYO4ZmcAIRQswL4QjVGHr0J/Cj0XrhNaHL0QlcjkJMhLF2iybcI0GEEBNhacJbMmOYEyHERJiZMIM7Y9hyi2Kco3sYUj4/THkxvps5M/jDwEO6CZejgZlPdxelFRFCTISrzZzBnTFMiBBiIlxq8gzujOF6IoSYCNeZP4M7Y7iYCCEmwkXOMoM7Y7iSCFc4V4E7HS4jQoiJ8HBnnMGdMVxDhBAT4bHOO4M7Y7iACCEmwgOdfQZ3xvBoIjzKNQrc6fBQIoSYCA9xpRncGcPjiBBiIny/683gzhgeRIQQu2CE27b98neOc9UZ3C0ew/ahXOaCEc50ugu50x3wed3uf+B+4aX027dv//8P/9cM7htylpH85FC/Oobfv3//6r/+eDy++ldO7XYRvvAAf+mvnKi011z+BNe7ZoQz3zmcZQxHHeTMh/K9rhnhT9u18oE8S2mvWX9q4UO5jE/MLDX/VtuFX0HGEuH7zS/tNfo8iAhXm5yozBI+6Ef55Ak99rl+xmO+AEt4lE8Wb+YYKrAiwsa0DmUWEuGBppX2Gn0eTYSZOYnKrCXCY80p7TX6XECEpQmJyiwnwsNNKO01+lxDhCuMvV3htsQEIoSYCBcZOIZmcAgRjrC+Q5nNIcJ1zvIZGn0uJsKlhlyUuhAdRYQQE+Fq+RiawWlECDERBsIxNIMDiRBiImwkY2gGZ/KhLw156g85jNuyhBATYWnC19CYwZwIISbC2NjvJ2QZEULMC+EI1Rh69Ce45o9GO5fwmtDl6AQuRyEmwli7RRPukSBCiImwNOEtmTHMiRBiIsxMmMGdMWyJEGIibMyZwZ0xDIkQYiIMbNs2agZ3z+dz27b6KO5IhKtt2/Z4POqj+HePx0OH64kQYiJcavIM7ozheiKEmAjXmT+DO2O4mAgXOUuBOx2uJEKIiXCFc83gzhguI0KIifBwZ5zBnTFcQ4QQE+GxzjuDO2O4wKxvqIEbsoQQEyHERAgxEUJMhBATIcRE+Ab/vJN2vXtrdzjHigghJkKIiRBiflLve9zhDdIdzjEhwvf46au0L/l8vcM5JlyOQkyEEBMhxHw/IcQsIcRECDERQkyEEBMhxEQIMRFCTIQQEyHERAgxEUJMhBATIcRECDERQkyEEBMhxEQIMRFCTIQQEyHERAgxEUJMhBATIcRECDERQkyEEBMhxEQIMRFCTIQQEyHERAgxEUJMhBATIcRECDERQkyEEBMhxEQIMRFCTIQQEyHERAgxEUJMhBATIcRECDERQkyEEBMhxEQIMRFCTIQQEyHERAgxEUJMhBATIcRECDERQkyEEBMhxEQIMRFCTIQQEyHERAgxEUJMhBATIcRECDERQkyEEPsT+gxFZQGbML0AAAAASUVORK5CYII=\n", + "text/plain": [ + "" + ] + }, + "execution_count": 47, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "ligand_rdkit_molecule.Compute2DCoords()\n", + "Chem.Draw.MolToImage(ligand_rdkit_molecule)" + ] + }, + { + "cell_type": "code", + "execution_count": 48, + "metadata": {}, + "outputs": [], + "source": [ + "from openforcefield.typing.engines.smirnoff import ForceField\n", + "#from openforcefields import get_forcefield_dirs_paths\n", + "forcefield = ForceField('openff-1.1.1.offxml')" + ] + }, + { + "cell_type": "code", + "execution_count": 49, + "metadata": {}, + "outputs": [], + "source": [ + "system = forcefield.create_openmm_system(ligand_molecule.to_topology())" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": {}, + "outputs": [], + "source": [ + "forces = system.getForces()" + ] + }, + { + "cell_type": "code", + "execution_count": 19, + "metadata": {}, + "outputs": [], + "source": [ + "force = forces[1]" + ] + }, + { + "cell_type": "code", + "execution_count": 21, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "[1,\n", + " 3,\n", + " 6,\n", + " 0,\n", + " 2,\n", + " Quantity(value=3.141592653589793, unit=radian),\n", + " Quantity(value=1.5341333333333336, unit=kilojoule/mole)]" + ] + }, + "execution_count": 21, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "force.getTorsionParameters(1)" + ] + }, + { + "cell_type": "code", + "execution_count": 23, + "metadata": {}, + "outputs": [], + "source": [ + "from simtk.openmm import XmlSerializer\n", + "with open('complex.xml', 'w') as f:\n", + " f.write(XmlSerializer.serialize(system))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Get atomic mass" + ] + }, + { + "cell_type": "code", + "execution_count": 50, + "metadata": { + "scrolled": true + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "TopologyAtom 0 with reference atom and parent TopologyMolecule \n", + "TopologyAtom 1 with reference atom and parent TopologyMolecule \n", + "TopologyAtom 2 with reference atom and parent TopologyMolecule \n", + "TopologyAtom 3 with reference atom and parent TopologyMolecule \n", + "TopologyAtom 4 with reference atom and parent TopologyMolecule \n", + "TopologyAtom 5 with reference atom and parent TopologyMolecule \n", + "TopologyAtom 6 with reference atom and parent TopologyMolecule \n", + "TopologyAtom 7 with reference atom and parent TopologyMolecule \n", + "TopologyAtom 8 with reference atom and parent TopologyMolecule \n", + "TopologyAtom 9 with reference atom and parent TopologyMolecule \n", + "TopologyAtom 10 with reference atom and parent TopologyMolecule \n", + "TopologyAtom 11 with reference atom and parent TopologyMolecule \n" + ] + } + ], + "source": [ + "for atom in ligand_molecule.to_topology().topology_particles:\n", + " print(atom)\n", + " " + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Forcefield parameter handlers" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Parameter handler dependencies" + ] + }, + { + "cell_type": "code", + "execution_count": 58, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Constraints:\n", + "Bonds:\n", + " - Constraints\n", + "Angles:\n", + " - Constraints\n", + "ProperTorsions:\n", + "ImproperTorsions:\n", + "vdW:\n", + "Electrostatics:\n", + " - vdW\n", + "LibraryCharges:\n", + " - vdW\n", + " - Electrostatics\n", + "ToolkitAM1BCC:\n", + " - vdW\n", + " - Electrostatics\n", + " - LibraryCharges\n" + ] + } + ], + "source": [ + "for tagname, handler in forcefield._parameter_handlers.items():\n", + " print('{}:'.format(tagname))\n", + " if handler._DEPENDENCIES is not None:\n", + " for dep in handler._DEPENDENCIES:\n", + " print(' -', dep._TAGNAME)" + ] + }, + { + "cell_type": "code", + "execution_count": 59, + "metadata": {}, + "outputs": [], + "source": [ + "ordered_parameter_handlers = forcefield._resolve_parameter_handler_order()" + ] + }, + { + "cell_type": "code", + "execution_count": 63, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "vdW\n", + "Electrostatics\n", + "LibraryCharges\n", + "ToolkitAM1BCC\n", + "ImproperTorsions\n", + "ProperTorsions\n", + "Constraints\n", + "Angles\n", + "Bonds\n" + ] + } + ], + "source": [ + "for handler in ordered_parameter_handlers:\n", + " print(handler._TAGNAME)" + ] + }, + { + "cell_type": "code", + "execution_count": 154, + "metadata": {}, + "outputs": [], + "source": [ + "ligand_topology = ligand_molecule.to_topology()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Extract vdW parameters" + ] + }, + { + "cell_type": "code", + "execution_count": 155, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "vdW\n" + ] + } + ], + "source": [ + "from openforcefield.typing.engines.smirnoff.parameters import vdWHandler\n", + "\n", + "for handler in ordered_parameter_handlers:\n", + " if isinstance(handler, vdWHandler):\n", + " break\n", + "\n", + "vdW_handler = handler\n", + "print(vdW_handler._TAGNAME)" + ] + }, + { + "cell_type": "code", + "execution_count": 156, + "metadata": {}, + "outputs": [], + "source": [ + "vdW_matches = vdW_handler.find_matches(ligand_topology)" + ] + }, + { + "cell_type": "code", + "execution_count": 157, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "(0,) 0.086 kcal/mol None 1.908 A\n", + "(1,) 0.086 kcal/mol None 1.908 A\n", + "(2,) 0.086 kcal/mol None 1.908 A\n", + "(3,) 0.086 kcal/mol None 1.908 A\n", + "(4,) 0.086 kcal/mol None 1.908 A\n", + "(5,) 0.086 kcal/mol None 1.908 A\n", + "(6,) 0.015 kcal/mol None 1.459 A\n", + "(7,) 0.015 kcal/mol None 1.459 A\n", + "(8,) 0.015 kcal/mol None 1.459 A\n", + "(9,) 0.015 kcal/mol None 1.459 A\n", + "(10,) 0.015 kcal/mol None 1.459 A\n", + "(11,) 0.015 kcal/mol None 1.459 A\n" + ] + } + ], + "source": [ + "for topology_atom_indices, vdW_match in vdW_matches.items():\n", + " print(topology_atom_indices, vdW_match.parameter_type.epsilon, vdW_match.parameter_type.sigma,\n", + " vdW_match.parameter_type.rmin_half)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Extract electrostatic parameters" + ] + }, + { + "cell_type": "code", + "execution_count": 183, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Electrostatics\n" + ] + } + ], + "source": [ + "from openforcefield.typing.engines.smirnoff.parameters import ElectrostaticsHandler\n", + "\n", + "for handler in ordered_parameter_handlers:\n", + " if isinstance(handler, ElectrostaticsHandler):\n", + " break\n", + "\n", + "electrostatics_handler = handler\n", + "print(electrostatics_handler._TAGNAME)" + ] + }, + { + "cell_type": "code", + "execution_count": 184, + "metadata": {}, + "outputs": [], + "source": [ + "electrostatics_matches = electrostatics_handler.find_matches(ligand_topology)" + ] + }, + { + "cell_type": "code", + "execution_count": 185, + "metadata": {}, + "outputs": [], + "source": [ + "for topology_atom_indices, electrostatics_match in electrostatics_matches.items():\n", + " print(topology_atom_indices, electrostatics_match.parameter_type.epsilon, electrostatics_match.parameter_type.sigma,\n", + " electrostatics_match.parameter_type.rmin_half)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Extract library charge parameters" + ] + }, + { + "cell_type": "code", + "execution_count": 186, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "LibraryCharges\n" + ] + } + ], + "source": [ + "from openforcefield.typing.engines.smirnoff.parameters import LibraryChargeHandler\n", + "\n", + "for handler in ordered_parameter_handlers:\n", + " if isinstance(handler, LibraryChargeHandler):\n", + " break\n", + "\n", + "library_charge_handler = handler\n", + "print(library_charge_handler._TAGNAME)" + ] + }, + { + "cell_type": "code", + "execution_count": 187, + "metadata": {}, + "outputs": [], + "source": [ + "library_charge_matches = library_charge_handler.find_matches(ligand_topology)" + ] + }, + { + "cell_type": "code", + "execution_count": 188, + "metadata": {}, + "outputs": [], + "source": [ + "for topology_atom_indices, library_charge_match in library_charge_matches.items():\n", + " print(topology_atom_indices, library_charge_match.parameter_type.epsilon, library_charge_match.parameter_type.sigma,\n", + " library_charge_match.parameter_type.rmin_half)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Extract ToolkitAM1BCC parameters" + ] + }, + { + "cell_type": "code", + "execution_count": 189, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "ToolkitAM1BCC\n" + ] + } + ], + "source": [ + "from openforcefield.typing.engines.smirnoff.parameters import ToolkitAM1BCCHandler\n", + "\n", + "for handler in ordered_parameter_handlers:\n", + " if isinstance(handler, ToolkitAM1BCCHandler):\n", + " break\n", + "\n", + "toolkit_AM1BCC_handler = handler\n", + "print(toolkit_AM1BCC_handler._TAGNAME)" + ] + }, + { + "cell_type": "code", + "execution_count": 190, + "metadata": {}, + "outputs": [], + "source": [ + "toolkit_AM1BCC_matches = toolkit_AM1BCC_handler.find_matches(ligand_topology)" + ] + }, + { + "cell_type": "code", + "execution_count": 191, + "metadata": {}, + "outputs": [], + "source": [ + "for topology_atom_indices, toolkit_AM1BCC_match in toolkit_AM1BCC_matches.items():\n", + " print(topology_atom_indices, library_charge_match.parameter_type.epsilon, library_charge_match.parameter_type.sigma,\n", + " library_charge_match.parameter_type.rmin_half)" + ] + }, + { + "cell_type": "code", + "execution_count": 192, + "metadata": {}, + "outputs": [ + { + "ename": "SyntaxError", + "evalue": "invalid syntax (, line 1)", + "output_type": "error", + "traceback": [ + "\u001b[0;36m File \u001b[0;32m\"\"\u001b[0;36m, line \u001b[0;32m1\u001b[0m\n\u001b[0;31m toolkit_AM1BCC_match.\u001b[0m\n\u001b[0m ^\u001b[0m\n\u001b[0;31mSyntaxError\u001b[0m\u001b[0;31m:\u001b[0m invalid syntax\n" + ] + } + ], + "source": [ + "toolkit_AM1BCC_match." + ] + }, + { + "cell_type": "code", + "execution_count": 169, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "" + ] + }, + "execution_count": 169, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "ligand_topology" + ] + }, + { + "cell_type": "code", + "execution_count": 177, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Molecule with name 'HYDROLASE' and SMILES '[H][c]1[c]([H])[c]([H])[c]([H])[c]([H])[c]1[H]'\n" + ] + } + ], + "source": [ + "for molecule in ligand_topology.reference_molecules:\n", + " print(molecule)" + ] + }, + { + "cell_type": "code", + "execution_count": 180, + "metadata": {}, + "outputs": [], + "source": [ + "molecule.compute_partial_charges_am1bcc()" + ] + }, + { + "cell_type": "code", + "execution_count": 182, + "metadata": {}, + "outputs": [ + { + "ename": "NotImplementedError", + "evalue": "", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mNotImplementedError\u001b[0m Traceback (most recent call last)", + "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0mmolecule\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mcompute_partial_charges\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", + "\u001b[0;32m~/environments/boost_1_68_0/lib/python3.7/site-packages/openforcefield-0.6.0+422.gd36894a-py3.7.egg/openforcefield/topology/molecule.py\u001b[0m in \u001b[0;36mcompute_partial_charges\u001b[0;34m(self, toolkit_registry)\u001b[0m\n\u001b[1;32m 2355\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 2356\u001b[0m \"\"\"\n\u001b[0;32m-> 2357\u001b[0;31m \u001b[0;32mraise\u001b[0m \u001b[0mNotImplementedError\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 2358\u001b[0m \u001b[0;31m# TODO: Implement this in a way that's compliant with SMIRNOFF's tag when the spec gets finalized\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 2359\u001b[0m \u001b[0;31m# if isinstance(toolkit_registry, ToolkitRegistry):\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;31mNotImplementedError\u001b[0m: " + ] + } + ], + "source": [ + "molecule.compute_partial_charges()" + ] + }, + { + "cell_type": "code", + "execution_count": 181, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "Quantity(value=array([-0.13, -0.13, -0.13, -0.13, -0.13, -0.13, 0.13, 0.13, 0.13,\n", + " 0.13, 0.13, 0.13]), unit=elementary charge)" + ] + }, + "execution_count": 181, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "molecule.partial_charges" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Extract bond parameters" + ] + }, + { + "cell_type": "code", + "execution_count": 90, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Bonds\n" + ] + } + ], + "source": [ + "from openforcefield.typing.engines.smirnoff.parameters import BondHandler\n", + "\n", + "for handler in ordered_parameter_handlers:\n", + " if isinstance(handler, BondHandler):\n", + " break\n", + "\n", + "bond_handler = handler\n", + "print(bond_handler._TAGNAME)" + ] + }, + { + "cell_type": "code", + "execution_count": 91, + "metadata": {}, + "outputs": [], + "source": [ + "bond_matches = bond_handler.find_matches(ligand_topology)" + ] + }, + { + "cell_type": "code", + "execution_count": 92, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "(0, 1) 1.388684811982 A 703.7861640732 kcal/(A**2 mol)\n", + "(0, 5) 1.388684811982 A 703.7861640732 kcal/(A**2 mol)\n", + "(0, 6) 1.085028902395 A 808.0585583296 kcal/(A**2 mol)\n", + "(1, 2) 1.388684811982 A 703.7861640732 kcal/(A**2 mol)\n", + "(1, 7) 1.085028902395 A 808.0585583296 kcal/(A**2 mol)\n", + "(2, 3) 1.388684811982 A 703.7861640732 kcal/(A**2 mol)\n", + "(2, 8) 1.085028902395 A 808.0585583296 kcal/(A**2 mol)\n", + "(3, 4) 1.388684811982 A 703.7861640732 kcal/(A**2 mol)\n", + "(3, 9) 1.085028902395 A 808.0585583296 kcal/(A**2 mol)\n", + "(4, 5) 1.388684811982 A 703.7861640732 kcal/(A**2 mol)\n", + "(4, 10) 1.085028902395 A 808.0585583296 kcal/(A**2 mol)\n", + "(5, 11) 1.085028902395 A 808.0585583296 kcal/(A**2 mol)\n" + ] + } + ], + "source": [ + "for topology_atom_indices, bond_match in bond_matches.items():\n", + " print(topology_atom_indices, bond_match.parameter_type.length, bond_match.parameter_type.k)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Extract angle parameters" + ] + }, + { + "cell_type": "code", + "execution_count": 93, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Angles\n" + ] + } + ], + "source": [ + "from openforcefield.typing.engines.smirnoff.parameters import AngleHandler\n", + "\n", + "for handler in ordered_parameter_handlers:\n", + " if isinstance(handler, AngleHandler):\n", + " break\n", + "\n", + "angle_handler = handler\n", + "print(angle_handler._TAGNAME)" + ] + }, + { + "cell_type": "code", + "execution_count": 98, + "metadata": {}, + "outputs": [], + "source": [ + "angle_matches = angle_handler.find_matches(ligand_topology)" + ] + }, + { + "cell_type": "code", + "execution_count": 100, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "(0, 1, 2) 132.0554838002 deg 153.7825131248 kcal/(mol rad**2)\n", + "(0, 1, 7) 137.9694119749 deg 66.76856405714 kcal/(mol rad**2)\n", + "(0, 5, 4) 132.0554838002 deg 153.7825131248 kcal/(mol rad**2)\n", + "(0, 5, 11) 137.9694119749 deg 66.76856405714 kcal/(mol rad**2)\n", + "(1, 0, 5) 132.0554838002 deg 153.7825131248 kcal/(mol rad**2)\n", + "(1, 0, 6) 137.9694119749 deg 66.76856405714 kcal/(mol rad**2)\n", + "(1, 2, 3) 132.0554838002 deg 153.7825131248 kcal/(mol rad**2)\n", + "(1, 2, 8) 137.9694119749 deg 66.76856405714 kcal/(mol rad**2)\n", + "(2, 1, 7) 137.9694119749 deg 66.76856405714 kcal/(mol rad**2)\n", + "(2, 3, 4) 132.0554838002 deg 153.7825131248 kcal/(mol rad**2)\n", + "(2, 3, 9) 137.9694119749 deg 66.76856405714 kcal/(mol rad**2)\n", + "(3, 2, 8) 137.9694119749 deg 66.76856405714 kcal/(mol rad**2)\n", + "(3, 4, 5) 132.0554838002 deg 153.7825131248 kcal/(mol rad**2)\n", + "(3, 4, 10) 137.9694119749 deg 66.76856405714 kcal/(mol rad**2)\n", + "(4, 3, 9) 137.9694119749 deg 66.76856405714 kcal/(mol rad**2)\n", + "(4, 5, 11) 137.9694119749 deg 66.76856405714 kcal/(mol rad**2)\n", + "(5, 0, 6) 137.9694119749 deg 66.76856405714 kcal/(mol rad**2)\n", + "(5, 4, 10) 137.9694119749 deg 66.76856405714 kcal/(mol rad**2)\n" + ] + } + ], + "source": [ + "for topology_atom_indices, angle_match in angle_matches.items():\n", + " print(topology_atom_indices, angle_match.parameter_type.angle, angle_match.parameter_type.k)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Extract proper torsion parameters" + ] + }, + { + "cell_type": "code", + "execution_count": 104, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "ProperTorsions\n" + ] + } + ], + "source": [ + "from openforcefield.typing.engines.smirnoff.parameters import ProperTorsionHandler\n", + "\n", + "for handler in ordered_parameter_handlers:\n", + " if isinstance(handler, ProperTorsionHandler):\n", + " break\n", + "\n", + "proper_torsion_handler = handler\n", + "print(proper_torsion_handler._TAGNAME)" + ] + }, + { + "cell_type": "code", + "execution_count": 105, + "metadata": {}, + "outputs": [], + "source": [ + "proper_torsion_matches = proper_torsion_handler.find_matches(ligand_topology)" + ] + }, + { + "cell_type": "code", + "execution_count": 110, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "(0, 1, 2, 3) [2] [Quantity(value=180.0, unit=degree)] [Quantity(value=2.639861699998, unit=kilocalorie/mole)]\n", + "(0, 1, 2, 8) [2] [Quantity(value=180.0, unit=degree)] [Quantity(value=2.639861699998, unit=kilocalorie/mole)]\n", + "(0, 5, 4, 3) [2] [Quantity(value=180.0, unit=degree)] [Quantity(value=2.639861699998, unit=kilocalorie/mole)]\n", + "(0, 5, 4, 10) [2] [Quantity(value=180.0, unit=degree)] [Quantity(value=2.639861699998, unit=kilocalorie/mole)]\n", + "(1, 0, 5, 4) [2] [Quantity(value=180.0, unit=degree)] [Quantity(value=2.639861699998, unit=kilocalorie/mole)]\n", + "(1, 0, 5, 11) [2] [Quantity(value=180.0, unit=degree)] [Quantity(value=2.639861699998, unit=kilocalorie/mole)]\n", + "(1, 2, 3, 4) [2] [Quantity(value=180.0, unit=degree)] [Quantity(value=2.639861699998, unit=kilocalorie/mole)]\n", + "(1, 2, 3, 9) [2] [Quantity(value=180.0, unit=degree)] [Quantity(value=2.639861699998, unit=kilocalorie/mole)]\n", + "(2, 1, 0, 5) [2] [Quantity(value=180.0, unit=degree)] [Quantity(value=2.639861699998, unit=kilocalorie/mole)]\n", + "(2, 1, 0, 6) [2] [Quantity(value=180.0, unit=degree)] [Quantity(value=2.639861699998, unit=kilocalorie/mole)]\n", + "(2, 3, 4, 5) [2] [Quantity(value=180.0, unit=degree)] [Quantity(value=2.639861699998, unit=kilocalorie/mole)]\n", + "(2, 3, 4, 10) [2] [Quantity(value=180.0, unit=degree)] [Quantity(value=2.639861699998, unit=kilocalorie/mole)]\n", + "(3, 2, 1, 7) [2] [Quantity(value=180.0, unit=degree)] [Quantity(value=2.639861699998, unit=kilocalorie/mole)]\n", + "(3, 4, 5, 11) [2] [Quantity(value=180.0, unit=degree)] [Quantity(value=2.639861699998, unit=kilocalorie/mole)]\n", + "(4, 3, 2, 8) [2] [Quantity(value=180.0, unit=degree)] [Quantity(value=2.639861699998, unit=kilocalorie/mole)]\n", + "(4, 5, 0, 6) [2] [Quantity(value=180.0, unit=degree)] [Quantity(value=2.639861699998, unit=kilocalorie/mole)]\n", + "(5, 0, 1, 7) [2] [Quantity(value=180.0, unit=degree)] [Quantity(value=2.639861699998, unit=kilocalorie/mole)]\n", + "(5, 4, 3, 9) [2] [Quantity(value=180.0, unit=degree)] [Quantity(value=2.639861699998, unit=kilocalorie/mole)]\n", + "(6, 0, 1, 7) [2] [Quantity(value=180.0, unit=degree)] [Quantity(value=2.639861699998, unit=kilocalorie/mole)]\n", + "(6, 0, 5, 11) [2] [Quantity(value=180.0, unit=degree)] [Quantity(value=2.639861699998, unit=kilocalorie/mole)]\n", + "(7, 1, 2, 8) [2] [Quantity(value=180.0, unit=degree)] [Quantity(value=2.639861699998, unit=kilocalorie/mole)]\n", + "(8, 2, 3, 9) [2] [Quantity(value=180.0, unit=degree)] [Quantity(value=2.639861699998, unit=kilocalorie/mole)]\n", + "(9, 3, 4, 10) [2] [Quantity(value=180.0, unit=degree)] [Quantity(value=2.639861699998, unit=kilocalorie/mole)]\n", + "(10, 4, 5, 11) [2] [Quantity(value=180.0, unit=degree)] [Quantity(value=2.639861699998, unit=kilocalorie/mole)]\n" + ] + } + ], + "source": [ + "for topology_atom_indices, proper_torsion_match in proper_torsion_matches.items():\n", + " print(topology_atom_indices, proper_torsion_match.parameter_type.periodicity,\n", + " proper_torsion_match.parameter_type.phase, proper_torsion_match.parameter_type.k)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Extract improper torsion parameters" + ] + }, + { + "cell_type": "code", + "execution_count": 111, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "ImproperTorsions\n" + ] + } + ], + "source": [ + "from openforcefield.typing.engines.smirnoff.parameters import ImproperTorsionHandler\n", + "\n", + "for handler in ordered_parameter_handlers:\n", + " if isinstance(handler, ImproperTorsionHandler):\n", + " break\n", + "\n", + "improper_torsion_handler = handler\n", + "print(improper_torsion_handler._TAGNAME)" + ] + }, + { + "cell_type": "code", + "execution_count": 112, + "metadata": {}, + "outputs": [], + "source": [ + "improper_torsion_matches = improper_torsion_handler.find_matches(ligand_topology)" + ] + }, + { + "cell_type": "code", + "execution_count": 113, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "(0, 1, 2, 7) [2] [Quantity(value=180.0, unit=degree)] [Quantity(value=1.1, unit=kilocalorie/mole)]\n", + "(0, 5, 4, 11) [2] [Quantity(value=180.0, unit=degree)] [Quantity(value=1.1, unit=kilocalorie/mole)]\n", + "(1, 0, 5, 6) [2] [Quantity(value=180.0, unit=degree)] [Quantity(value=1.1, unit=kilocalorie/mole)]\n", + "(1, 2, 3, 8) [2] [Quantity(value=180.0, unit=degree)] [Quantity(value=1.1, unit=kilocalorie/mole)]\n", + "(2, 3, 4, 9) [2] [Quantity(value=180.0, unit=degree)] [Quantity(value=1.1, unit=kilocalorie/mole)]\n", + "(3, 4, 5, 10) [2] [Quantity(value=180.0, unit=degree)] [Quantity(value=1.1, unit=kilocalorie/mole)]\n" + ] + } + ], + "source": [ + "for topology_atom_indices, improper_torsion_match in improper_torsion_matches.items():\n", + " print(topology_atom_indices, improper_torsion_match.parameter_type.periodicity,\n", + " improper_torsion_match.parameter_type.phase, improper_torsion_match.parameter_type.k)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.7.4" + } + }, + "nbformat": 4, + "nbformat_minor": 4 +} From 3262fa7e82ba91e4fbc8b67c0621bf52c697ddc0 Mon Sep 17 00:00:00 2001 From: Marti Municoy Date: Thu, 28 May 2020 16:01:58 +0200 Subject: [PATCH 02/67] Add data to run examples --- offPELE/__init__.py | 3 + offPELE/data/complexes/LYS_BNZ.pdb | 2645 ++++++++++++++++++++++++++++ offPELE/data/ligands/BNZ.mae | 184 ++ offPELE/data/ligands/BNZ.pdb | 53 + offPELE/data/ligands/TOL.mae | 190 ++ offPELE/data/ligands/ligand.pdb | 86 + offPELE/utils/__init__.py | 1 + offPELE/utils/utils.py | 15 + setup.py | 4 +- 9 files changed, 3179 insertions(+), 2 deletions(-) create mode 100644 offPELE/__init__.py create mode 100644 offPELE/data/complexes/LYS_BNZ.pdb create mode 100644 offPELE/data/ligands/BNZ.mae create mode 100644 offPELE/data/ligands/BNZ.pdb create mode 100644 offPELE/data/ligands/TOL.mae create mode 100644 offPELE/data/ligands/ligand.pdb create mode 100644 offPELE/utils/__init__.py create mode 100644 offPELE/utils/utils.py diff --git a/offPELE/__init__.py b/offPELE/__init__.py new file mode 100644 index 00000000..e44e9d15 --- /dev/null +++ b/offPELE/__init__.py @@ -0,0 +1,3 @@ +from ._version import get_versions +__version__ = get_versions()['version'] +del get_versions diff --git a/offPELE/data/complexes/LYS_BNZ.pdb b/offPELE/data/complexes/LYS_BNZ.pdb new file mode 100644 index 00000000..9c4c65de --- /dev/null +++ b/offPELE/data/complexes/LYS_BNZ.pdb @@ -0,0 +1,2645 @@ +ATOM 1 N MET A 1 -17.015 -3.198 8.833 1.00 27.99 N +ATOM 2 CA MET A 1 -17.680 -1.915 8.990 1.00 17.09 C +ATOM 3 C MET A 1 -19.093 -2.031 9.528 1.00 14.58 C +ATOM 4 O MET A 1 -19.828 -2.998 9.287 1.00 15.59 O +ATOM 5 CB MET A 1 -17.704 -1.151 7.670 1.00 20.59 C +ATOM 6 CG MET A 1 -18.342 0.205 7.812 1.00 18.49 C +ATOM 7 SD MET A 1 -17.069 1.411 8.088 1.00 21.19 S +ATOM 8 CE MET A 1 -16.073 0.894 6.671 1.00 17.18 C +ATOM 9 H MET A 1 -16.083 -3.053 8.473 1.00 0.00 H +ATOM 10 HA MET A 1 -17.101 -1.327 9.703 1.00 0.00 H +ATOM 11 HB3 MET A 1 -18.248 -1.731 6.925 1.00 0.00 H +ATOM 12 HB2 MET A 1 -16.685 -1.035 7.299 1.00 0.00 H +ATOM 13 HG3 MET A 1 -19.025 0.198 8.661 1.00 0.00 H +ATOM 14 HG2 MET A 1 -18.882 0.450 6.897 1.00 0.00 H +ATOM 15 HE1 MET A 1 -15.178 1.513 6.610 1.00 0.00 H +ATOM 16 HE2 MET A 1 -15.784 -0.150 6.791 1.00 0.00 H +ATOM 17 HE3 MET A 1 -16.655 1.006 5.757 1.00 0.00 H +ATOM 18 N ASN A 2 -19.472 -1.019 10.291 1.00 12.17 N +ATOM 19 CA ASN A 2 -20.807 -0.908 10.848 1.00 12.36 C +ATOM 20 C ASN A 2 -21.123 0.587 10.889 1.00 10.36 C +ATOM 21 O ASN A 2 -20.253 1.423 10.552 1.00 10.27 O +ATOM 22 CB ASN A 2 -20.846 -1.562 12.256 1.00 11.18 C +ATOM 23 CG ASN A 2 -19.863 -0.956 13.217 1.00 13.02 C +ATOM 24 OD1 ASN A 2 -19.896 0.251 13.476 1.00 10.88 O +ATOM 25 ND2 ASN A 2 -18.981 -1.769 13.761 1.00 13.43 N +ATOM 26 H ASN A 2 -18.820 -0.279 10.509 1.00 0.00 H +ATOM 27 HA ASN A 2 -21.518 -1.412 10.193 1.00 0.00 H +ATOM 28 HB3 ASN A 2 -20.651 -2.630 12.164 1.00 0.00 H +ATOM 29 HB2 ASN A 2 -21.852 -1.478 12.666 1.00 0.00 H +ATOM 30 HD22 ASN A 2 -18.299 -1.410 14.414 1.00 0.00 H +ATOM 31 HD21 ASN A 2 -18.987 -2.751 13.526 1.00 0.00 H +ATOM 32 N ILE A 3 -22.334 0.915 11.321 1.00 9.79 N +ATOM 33 CA ILE A 3 -22.779 2.297 11.273 1.00 9.72 C +ATOM 34 C ILE A 3 -21.923 3.224 12.141 1.00 9.92 C +ATOM 35 O ILE A 3 -21.722 4.406 11.803 1.00 9.48 O +ATOM 36 CB ILE A 3 -24.264 2.406 11.637 1.00 10.19 C +ATOM 37 CG1 ILE A 3 -24.778 3.836 11.513 1.00 10.40 C +ATOM 38 CG2 ILE A 3 -24.505 1.862 13.073 1.00 10.46 C +ATOM 39 CD1 ILE A 3 -24.643 4.476 10.102 1.00 10.46 C +ATOM 40 H ILE A 3 -22.950 0.203 11.685 1.00 0.00 H +ATOM 41 HA ILE A 3 -22.674 2.634 10.242 1.00 0.00 H +ATOM 42 HB ILE A 3 -24.828 1.784 10.942 1.00 0.00 H +ATOM 43 HG13 ILE A 3 -24.271 4.466 12.244 1.00 0.00 H +ATOM 44 HG12 ILE A 3 -25.821 3.872 11.826 1.00 0.00 H +ATOM 45 HG21 ILE A 3 -25.563 1.945 13.320 1.00 0.00 H +ATOM 46 HG22 ILE A 3 -24.202 0.816 13.122 1.00 0.00 H +ATOM 47 HG23 ILE A 3 -23.919 2.443 13.785 1.00 0.00 H +ATOM 48 HD11 ILE A 3 -25.038 5.492 10.124 1.00 0.00 H +ATOM 49 HD12 ILE A 3 -23.592 4.501 9.813 1.00 0.00 H +ATOM 50 HD13 ILE A 3 -25.204 3.884 9.379 1.00 0.00 H +ATOM 51 N PHE A 4 -21.419 2.730 13.267 1.00 8.01 N +ATOM 52 CA PHE A 4 -20.573 3.567 14.119 1.00 8.80 C +ATOM 53 C PHE A 4 -19.253 3.883 13.440 1.00 9.06 C +ATOM 54 O PHE A 4 -18.781 5.031 13.449 1.00 10.59 O +ATOM 55 CB PHE A 4 -20.387 2.892 15.487 1.00 9.48 C +ATOM 56 CG PHE A 4 -21.630 2.860 16.287 1.00 8.62 C +ATOM 57 CD1 PHE A 4 -21.962 3.964 17.069 1.00 12.97 C +ATOM 58 CD2 PHE A 4 -22.495 1.789 16.249 1.00 11.34 C +ATOM 59 CE1 PHE A 4 -23.136 3.976 17.803 1.00 13.94 C +ATOM 60 CE2 PHE A 4 -23.672 1.814 16.969 1.00 13.03 C +ATOM 61 CZ PHE A 4 -23.982 2.890 17.743 1.00 13.10 C +ATOM 62 H PHE A 4 -21.620 1.777 13.535 1.00 0.00 H +ATOM 63 HA PHE A 4 -21.096 4.509 14.282 1.00 0.00 H +ATOM 64 HB3 PHE A 4 -19.610 3.414 16.046 1.00 0.00 H +ATOM 65 HB2 PHE A 4 -20.023 1.875 15.342 1.00 0.00 H +ATOM 66 HD1 PHE A 4 -21.302 4.818 17.106 1.00 0.00 H +ATOM 67 HD2 PHE A 4 -22.254 0.921 15.653 1.00 0.00 H +ATOM 68 HE1 PHE A 4 -23.381 4.831 18.415 1.00 0.00 H +ATOM 69 HE2 PHE A 4 -24.353 0.977 16.920 1.00 0.00 H +ATOM 70 HZ PHE A 4 -24.899 2.888 18.313 1.00 0.00 H +ATOM 71 N GLU A 5 -18.619 2.885 12.839 1.00 9.78 N +ATOM 72 CA GLU A 5 -17.359 3.142 12.149 1.00 9.80 C +ATOM 73 C GLU A 5 -17.560 4.079 10.946 1.00 8.93 C +ATOM 74 O GLU A 5 -16.720 4.952 10.677 1.00 10.10 O +ATOM 75 CB GLU A 5 -16.709 1.824 11.683 1.00 10.24 C +ATOM 76 CG GLU A 5 -16.277 0.931 12.832 1.00 10.71 C +ATOM 77 CD GLU A 5 -15.685 -0.413 12.409 1.00 21.11 C +ATOM 78 OE1 GLU A 5 -15.784 -0.783 11.236 1.00 28.40 O +ATOM 79 OE2 GLU A 5 -15.095 -1.103 13.270 1.00 19.20 O +ATOM 80 H GLU A 5 -19.009 1.953 12.860 1.00 0.00 H +ATOM 81 HA GLU A 5 -16.680 3.628 12.850 1.00 0.00 H +ATOM 82 HB3 GLU A 5 -15.847 2.048 11.055 1.00 0.00 H +ATOM 83 HB2 GLU A 5 -17.407 1.282 11.046 1.00 0.00 H +ATOM 84 HG3 GLU A 5 -17.126 0.759 13.494 1.00 0.00 H +ATOM 85 HG2 GLU A 5 -15.556 1.464 13.452 1.00 0.00 H +ATOM 86 N MET A 6 -18.675 3.884 10.250 1.00 8.36 N +ATOM 87 CA MET A 6 -18.974 4.669 9.049 1.00 7.77 C +ATOM 88 C MET A 6 -19.141 6.144 9.437 1.00 9.23 C +ATOM 89 O MET A 6 -18.511 7.031 8.837 1.00 8.68 O +ATOM 90 CB MET A 6 -20.263 4.145 8.455 1.00 8.61 C +ATOM 91 CG MET A 6 -20.649 4.845 7.169 1.00 9.35 C +ATOM 92 SD MET A 6 -22.394 4.467 6.821 1.00 9.24 S +ATOM 93 CE MET A 6 -22.476 4.660 5.045 1.00 10.85 C +ATOM 94 H MET A 6 -19.339 3.182 10.545 1.00 0.00 H +ATOM 95 HA MET A 6 -18.164 4.565 8.327 1.00 0.00 H +ATOM 96 HB3 MET A 6 -21.068 4.254 9.182 1.00 0.00 H +ATOM 97 HB2 MET A 6 -20.168 3.075 8.270 1.00 0.00 H +ATOM 98 HG3 MET A 6 -20.028 4.475 6.354 1.00 0.00 H +ATOM 99 HG2 MET A 6 -20.528 5.921 7.291 1.00 0.00 H +ATOM 100 HE1 MET A 6 -23.491 4.457 4.703 1.00 0.00 H +ATOM 101 HE2 MET A 6 -22.200 5.680 4.777 1.00 0.00 H +ATOM 102 HE3 MET A 6 -21.787 3.961 4.571 1.00 0.00 H +ATOM 103 N LEU A 7 -19.979 6.424 10.441 1.00 9.13 N +ATOM 104 CA LEU A 7 -20.190 7.813 10.842 1.00 7.79 C +ATOM 105 C LEU A 7 -18.962 8.407 11.540 1.00 9.60 C +ATOM 106 O LEU A 7 -18.731 9.607 11.433 1.00 10.11 O +ATOM 107 CB LEU A 7 -21.440 7.932 11.709 1.00 9.03 C +ATOM 108 CG LEU A 7 -22.746 7.958 10.909 1.00 7.11 C +ATOM 109 CD1 LEU A 7 -23.923 7.721 11.871 1.00 9.99 C +ATOM 110 CD2 LEU A 7 -22.873 9.319 10.227 1.00 9.66 C +ATOM 111 H LEU A 7 -20.463 5.677 10.918 1.00 0.00 H +ATOM 112 HA LEU A 7 -20.364 8.393 9.935 1.00 0.00 H +ATOM 113 HB3 LEU A 7 -21.372 8.832 12.320 1.00 0.00 H +ATOM 114 HB2 LEU A 7 -21.467 7.106 12.419 1.00 0.00 H +ATOM 115 HG LEU A 7 -22.727 7.172 10.154 1.00 0.00 H +ATOM 116 HD11 LEU A 7 -24.859 7.737 11.312 1.00 0.00 H +ATOM 117 HD12 LEU A 7 -23.807 6.752 12.356 1.00 0.00 H +ATOM 118 HD13 LEU A 7 -23.938 8.506 12.627 1.00 0.00 H +ATOM 119 HD21 LEU A 7 -23.799 9.353 9.653 1.00 0.00 H +ATOM 120 HD22 LEU A 7 -22.885 10.105 10.982 1.00 0.00 H +ATOM 121 HD23 LEU A 7 -22.026 9.471 9.559 1.00 0.00 H +ATOM 122 N ARG A 8 -18.178 7.592 12.238 1.00 10.22 N +ATOM 123 CA ARG A 8 -16.926 8.100 12.827 1.00 10.78 C +ATOM 124 C ARG A 8 -15.984 8.605 11.728 1.00 10.43 C +ATOM 125 O ARG A 8 -15.300 9.633 11.890 1.00 11.98 O +ATOM 126 CB ARG A 8 -16.248 7.019 13.688 1.00 12.26 C +ATOM 127 CG ARG A 8 -14.867 7.377 14.206 1.00 15.20 C +ATOM 128 CD ARG A 8 -14.880 8.576 15.141 1.00 17.31 C +ATOM 129 NE ARG A 8 -13.517 8.787 15.647 1.00 20.40 N +ATOM 130 CZ ARG A 8 -12.559 9.396 14.951 1.00 25.62 C +ATOM 131 NH1 ARG A 8 -12.810 9.891 13.749 1.00 23.98 N +ATOM 132 NH2 ARG A 8 -11.336 9.528 15.467 1.00 28.70 N +ATOM 133 H ARG A 8 -18.440 6.625 12.365 1.00 0.00 H +ATOM 134 HA ARG A 8 -17.173 8.942 13.474 1.00 0.00 H +ATOM 135 HB3 ARG A 8 -16.190 6.090 13.121 1.00 0.00 H +ATOM 136 HB2 ARG A 8 -16.895 6.770 14.529 1.00 0.00 H +ATOM 137 HG3 ARG A 8 -14.206 7.582 13.364 1.00 0.00 H +ATOM 138 HG2 ARG A 8 -14.441 6.518 14.724 1.00 0.00 H +ATOM 139 HD3 ARG A 8 -15.551 8.377 15.977 1.00 0.00 H +ATOM 140 HD2 ARG A 8 -15.205 9.460 14.593 1.00 0.00 H +ATOM 141 HE ARG A 8 -13.324 8.441 16.576 1.00 0.00 H +ATOM 142 HH12 ARG A 8 -12.076 10.351 13.229 1.00 0.00 H +ATOM 143 HH11 ARG A 8 -13.735 9.808 13.352 1.00 0.00 H +ATOM 144 HH21 ARG A 8 -10.611 9.990 14.937 1.00 0.00 H +ATOM 145 HH22 ARG A 8 -11.135 9.166 16.388 1.00 0.00 H +ATOM 146 N ILE A 9 -15.931 7.904 10.595 1.00 9.64 N +ATOM 147 CA ILE A 9 -15.138 8.377 9.459 1.00 10.22 C +ATOM 148 C ILE A 9 -15.739 9.668 8.896 1.00 11.04 C +ATOM 149 O ILE A 9 -15.025 10.658 8.621 1.00 13.43 O +ATOM 150 CB ILE A 9 -15.098 7.270 8.361 1.00 11.18 C +ATOM 151 CG1 ILE A 9 -14.203 6.129 8.841 1.00 13.80 C +ATOM 152 CG2 ILE A 9 -14.626 7.824 6.995 1.00 13.42 C +ATOM 153 CD1 ILE A 9 -14.366 4.863 8.037 1.00 13.78 C +ATOM 154 H ILE A 9 -16.441 7.036 10.514 1.00 0.00 H +ATOM 155 HA ILE A 9 -14.121 8.578 9.796 1.00 0.00 H +ATOM 156 HB ILE A 9 -16.108 6.879 8.237 1.00 0.00 H +ATOM 157 HG13 ILE A 9 -14.413 5.921 9.890 1.00 0.00 H +ATOM 158 HG12 ILE A 9 -13.161 6.448 8.807 1.00 0.00 H +ATOM 159 HG21 ILE A 9 -14.613 7.019 6.260 1.00 0.00 H +ATOM 160 HG22 ILE A 9 -15.309 8.606 6.664 1.00 0.00 H +ATOM 161 HG23 ILE A 9 -13.623 8.238 7.097 1.00 0.00 H +ATOM 162 HD11 ILE A 9 -13.702 4.094 8.431 1.00 0.00 H +ATOM 163 HD12 ILE A 9 -15.398 4.520 8.104 1.00 0.00 H +ATOM 164 HD13 ILE A 9 -14.116 5.059 6.994 1.00 0.00 H +ATOM 165 N ASP A 10 -17.052 9.683 8.697 1.00 9.66 N +ATOM 166 CA ASP A 10 -17.646 10.856 8.069 1.00 10.85 C +ATOM 167 C ASP A 10 -17.662 12.115 8.958 1.00 10.54 C +ATOM 168 O ASP A 10 -17.612 13.240 8.451 1.00 13.50 O +ATOM 169 CB ASP A 10 -19.071 10.550 7.612 1.00 10.56 C +ATOM 170 CG ASP A 10 -19.115 9.654 6.394 1.00 11.96 C +ATOM 171 OD1 ASP A 10 -18.145 9.642 5.617 1.00 11.35 O +ATOM 172 OD2 ASP A 10 -20.122 8.959 6.185 1.00 11.17 O +ATOM 173 H ASP A 10 -17.615 8.893 8.979 1.00 0.00 H +ATOM 174 HA ASP A 10 -17.058 11.087 7.181 1.00 0.00 H +ATOM 175 HB3 ASP A 10 -19.590 11.484 7.394 1.00 0.00 H +ATOM 176 HB2 ASP A 10 -19.620 10.079 8.428 1.00 0.00 H +ATOM 177 N GLU A 11 -17.773 11.933 10.272 1.00 9.78 N +ATOM 178 CA GLU A 11 -17.902 13.081 11.186 1.00 9.81 C +ATOM 179 C GLU A 11 -16.634 13.442 11.932 1.00 11.06 C +ATOM 180 O GLU A 11 -16.542 14.568 12.429 1.00 12.68 O +ATOM 181 CB GLU A 11 -19.011 12.796 12.220 1.00 11.22 C +ATOM 182 CG GLU A 11 -20.409 12.551 11.628 1.00 10.81 C +ATOM 183 CD GLU A 11 -21.061 13.785 11.014 1.00 14.70 C +ATOM 184 OE1 GLU A 11 -20.529 14.922 11.173 1.00 17.91 O +ATOM 185 OE2 GLU A 11 -22.137 13.634 10.384 1.00 18.44 O +ATOM 186 H GLU A 11 -17.769 10.998 10.654 1.00 0.00 H +ATOM 187 HA GLU A 11 -18.205 13.947 10.598 1.00 0.00 H +ATOM 188 HB3 GLU A 11 -19.060 13.620 12.932 1.00 0.00 H +ATOM 189 HB2 GLU A 11 -18.723 11.940 12.831 1.00 0.00 H +ATOM 190 HG3 GLU A 11 -21.062 12.144 12.400 1.00 0.00 H +ATOM 191 HG2 GLU A 11 -20.350 11.763 10.878 1.00 0.00 H +ATOM 192 N GLY A 12 -15.687 12.522 12.052 1.00 11.55 N +ATOM 193 CA GLY A 12 -14.493 12.772 12.844 1.00 12.07 C +ATOM 194 C GLY A 12 -14.788 12.766 14.332 1.00 13.53 C +ATOM 195 O GLY A 12 -15.887 12.402 14.792 1.00 12.70 O +ATOM 196 H GLY A 12 -15.788 11.630 11.589 1.00 0.00 H +ATOM 197 HA3 GLY A 12 -14.066 13.735 12.563 1.00 0.00 H +ATOM 198 HA2 GLY A 12 -13.744 12.013 12.620 1.00 0.00 H +ATOM 199 N LEU A 13 -13.783 13.162 15.098 1.00 12.54 N +ATOM 200 CA LEU A 13 -13.927 13.238 16.546 1.00 14.24 C +ATOM 201 C LEU A 13 -13.180 14.494 16.983 1.00 14.73 C +ATOM 202 O LEU A 13 -11.964 14.609 16.770 1.00 17.02 O +ATOM 203 CB LEU A 13 -13.369 11.998 17.248 1.00 14.18 C +ATOM 204 CG LEU A 13 -13.198 12.171 18.768 1.00 17.49 C +ATOM 205 CD1 LEU A 13 -14.555 12.255 19.463 1.00 16.94 C +ATOM 206 CD2 LEU A 13 -12.387 11.004 19.326 1.00 23.36 C +ATOM 207 H LEU A 13 -12.900 13.417 14.680 1.00 0.00 H +ATOM 208 HA LEU A 13 -14.983 13.345 16.795 1.00 0.00 H +ATOM 209 HB3 LEU A 13 -12.410 11.732 16.804 1.00 0.00 H +ATOM 210 HB2 LEU A 13 -14.022 11.147 17.052 1.00 0.00 H +ATOM 211 HG LEU A 13 -12.652 13.096 18.955 1.00 0.00 H +ATOM 212 HD11 LEU A 13 -14.407 12.377 20.536 1.00 0.00 H +ATOM 213 HD12 LEU A 13 -15.111 13.108 19.074 1.00 0.00 H +ATOM 214 HD13 LEU A 13 -15.117 11.340 19.276 1.00 0.00 H +ATOM 215 HD21 LEU A 13 -12.266 11.127 20.402 1.00 0.00 H +ATOM 216 HD22 LEU A 13 -12.909 10.069 19.124 1.00 0.00 H +ATOM 217 HD23 LEU A 13 -11.406 10.982 18.851 1.00 0.00 H +ATOM 218 N ARG A 14 -13.920 15.420 17.592 1.00 12.91 N +ATOM 219 CA ARG A 14 -13.339 16.633 18.150 1.00 12.70 C +ATOM 220 C ARG A 14 -13.912 16.834 19.550 1.00 14.75 C +ATOM 221 O ARG A 14 -15.120 16.752 19.756 1.00 13.43 O +ATOM 222 CB ARG A 14 -13.590 17.853 17.237 1.00 13.75 C +ATOM 223 CG ARG A 14 -12.974 17.704 15.811 1.00 14.54 C +ATOM 224 CD ARG A 14 -13.144 18.957 14.892 1.00 16.91 C +ATOM 225 NE ARG A 14 -12.424 20.109 15.429 1.00 24.59 N +ATOM 226 CZ ARG A 14 -12.313 21.309 14.854 1.00 25.15 C +ATOM 227 NH1 ARG A 14 -12.870 21.585 13.672 1.00 17.63 N +ATOM 228 NH2 ARG A 14 -11.628 22.254 15.493 1.00 24.59 N +ATOM 229 H ARG A 14 -14.918 15.292 17.678 1.00 0.00 H +ATOM 230 HA ARG A 14 -12.262 16.487 18.238 1.00 0.00 H +ATOM 231 HB3 ARG A 14 -13.190 18.749 17.712 1.00 0.00 H +ATOM 232 HB2 ARG A 14 -14.663 18.026 17.151 1.00 0.00 H +ATOM 233 HG3 ARG A 14 -13.409 16.834 15.319 1.00 0.00 H +ATOM 234 HG2 ARG A 14 -11.915 17.462 15.899 1.00 0.00 H +ATOM 235 HD3 ARG A 14 -14.203 19.200 14.802 1.00 0.00 H +ATOM 236 HD2 ARG A 14 -12.770 18.728 13.894 1.00 0.00 H +ATOM 237 HE ARG A 14 -11.985 19.934 16.321 1.00 0.00 H +ATOM 238 HH12 ARG A 14 -12.765 22.504 13.267 1.00 0.00 H +ATOM 239 HH11 ARG A 14 -13.396 20.875 13.183 1.00 0.00 H +ATOM 240 HH21 ARG A 14 -11.528 23.171 15.081 1.00 0.00 H +ATOM 241 HH22 ARG A 14 -11.208 22.054 16.390 1.00 0.00 H +ATOM 242 N LEU A 15 -13.034 17.078 20.530 1.00 11.88 N +ATOM 243 CA LEU A 15 -13.463 17.142 21.929 1.00 11.96 C +ATOM 244 C LEU A 15 -13.766 18.545 22.438 1.00 14.67 C +ATOM 245 O LEU A 15 -14.239 18.720 23.566 1.00 15.59 O +ATOM 246 CB LEU A 15 -12.412 16.455 22.820 1.00 14.15 C +ATOM 247 CG LEU A 15 -12.182 14.973 22.536 1.00 13.59 C +ATOM 248 CD1 LEU A 15 -11.169 14.432 23.550 1.00 21.94 C +ATOM 249 CD2 LEU A 15 -13.492 14.165 22.581 1.00 16.25 C +ATOM 250 H LEU A 15 -12.059 17.221 20.310 1.00 0.00 H +ATOM 251 HA LEU A 15 -14.383 16.563 22.011 1.00 0.00 H +ATOM 252 HB3 LEU A 15 -12.688 16.583 23.867 1.00 0.00 H +ATOM 253 HB2 LEU A 15 -11.465 16.989 22.737 1.00 0.00 H +ATOM 254 HG LEU A 15 -11.754 14.877 21.538 1.00 0.00 H +ATOM 255 HD11 LEU A 15 -10.994 13.373 23.360 1.00 0.00 H +ATOM 256 HD12 LEU A 15 -10.231 14.978 23.453 1.00 0.00 H +ATOM 257 HD13 LEU A 15 -11.561 14.560 24.559 1.00 0.00 H +ATOM 258 HD21 LEU A 15 -13.280 13.116 22.373 1.00 0.00 H +ATOM 259 HD22 LEU A 15 -13.941 14.255 23.570 1.00 0.00 H +ATOM 260 HD23 LEU A 15 -14.183 14.551 21.832 1.00 0.00 H +ATOM 261 N LYS A 16 -13.551 19.544 21.588 1.00 11.67 N +ATOM 262 CA LYS A 16 -13.860 20.930 21.894 1.00 13.98 C +ATOM 263 C LYS A 16 -14.911 21.405 20.910 1.00 11.72 C +ATOM 264 O LYS A 16 -14.934 20.924 19.758 1.00 12.40 O +ATOM 265 CB LYS A 16 -12.579 21.783 21.780 1.00 16.47 C +ATOM 266 CG LYS A 16 -12.752 23.256 22.200 1.00 29.04 C +ATOM 267 CD LYS A 16 -11.420 24.016 22.276 1.00 27.10 C +ATOM 268 CE LYS A 16 -11.605 25.479 22.703 1.00 29.58 C +ATOM 269 NZ LYS A 16 -10.316 26.183 22.774 1.00 0.00 N +ATOM 270 H LYS A 16 -13.154 19.357 20.678 1.00 0.00 H +ATOM 271 HA LYS A 16 -14.254 20.999 22.908 1.00 0.00 H +ATOM 272 HB3 LYS A 16 -12.186 21.737 20.763 1.00 0.00 H +ATOM 273 HB2 LYS A 16 -11.819 21.334 22.421 1.00 0.00 H +ATOM 274 HG3 LYS A 16 -13.251 23.301 23.169 1.00 0.00 H +ATOM 275 HG2 LYS A 16 -13.407 23.768 21.494 1.00 0.00 H +ATOM 276 HD3 LYS A 16 -10.926 23.979 21.304 1.00 0.00 H +ATOM 277 HD2 LYS A 16 -10.754 23.514 22.979 1.00 0.00 H +ATOM 278 HE2 LYS A 16 -12.251 26.003 21.998 1.00 0.00 H +ATOM 279 HE3 LYS A 16 -12.085 25.531 23.681 1.00 0.00 H +ATOM 280 HZ1 LYS A 16 -9.717 25.729 23.446 1.00 0.00 H +ATOM 281 HZ2 LYS A 16 -9.872 26.171 21.868 1.00 0.00 H +ATOM 282 HZ3 LYS A 16 -10.468 27.140 23.057 1.00 0.00 H +ATOM 283 N ILE A 17 -15.774 22.328 21.320 1.00 10.97 N +ATOM 284 CA ILE A 17 -16.798 22.860 20.435 1.00 9.56 C +ATOM 285 C ILE A 17 -16.167 23.350 19.141 1.00 12.67 C +ATOM 286 O ILE A 17 -15.148 24.071 19.175 1.00 14.61 O +ATOM 287 CB ILE A 17 -17.566 23.991 21.102 1.00 11.28 C +ATOM 288 CG1 ILE A 17 -18.408 23.433 22.262 1.00 10.85 C +ATOM 289 CG2 ILE A 17 -18.444 24.714 20.105 1.00 14.22 C +ATOM 290 CD1 ILE A 17 -19.176 24.522 23.064 1.00 13.58 C +ATOM 291 H ILE A 17 -15.728 22.677 22.267 1.00 0.00 H +ATOM 292 HA ILE A 17 -17.499 22.060 20.197 1.00 0.00 H +ATOM 293 HB ILE A 17 -16.848 24.703 21.509 1.00 0.00 H +ATOM 294 HG13 ILE A 17 -17.764 22.872 22.939 1.00 0.00 H +ATOM 295 HG12 ILE A 17 -19.117 22.702 21.875 1.00 0.00 H +ATOM 296 HG21 ILE A 17 -18.981 25.517 20.609 1.00 0.00 H +ATOM 297 HG22 ILE A 17 -17.825 25.133 19.312 1.00 0.00 H +ATOM 298 HG23 ILE A 17 -19.159 24.013 19.675 1.00 0.00 H +ATOM 299 HD11 ILE A 17 -19.746 24.050 23.864 1.00 0.00 H +ATOM 300 HD12 ILE A 17 -18.464 25.228 23.493 1.00 0.00 H +ATOM 301 HD13 ILE A 17 -19.857 25.052 22.398 1.00 0.00 H +ATOM 302 N TYR A 18 -16.772 22.955 18.012 1.00 11.53 N +ATOM 303 CA TYR A 18 -16.308 23.372 16.696 1.00 11.67 C +ATOM 304 C TYR A 18 -17.519 23.759 15.873 1.00 12.20 C +ATOM 305 O TYR A 18 -18.644 23.534 16.272 1.00 12.52 O +ATOM 306 CB TYR A 18 -15.532 22.227 16.018 1.00 12.54 C +ATOM 307 CG TYR A 18 -16.299 20.947 15.712 1.00 12.91 C +ATOM 308 CD1 TYR A 18 -16.427 19.953 16.658 1.00 13.54 C +ATOM 309 CD2 TYR A 18 -16.829 20.712 14.424 1.00 15.43 C +ATOM 310 CE1 TYR A 18 -17.081 18.751 16.373 1.00 12.56 C +ATOM 311 CE2 TYR A 18 -17.498 19.511 14.124 1.00 12.40 C +ATOM 312 CZ TYR A 18 -17.638 18.551 15.115 1.00 14.18 C +ATOM 313 OH TYR A 18 -18.279 17.339 14.852 1.00 14.50 O +ATOM 314 H TYR A 18 -17.578 22.348 18.057 1.00 0.00 H +ATOM 315 HA TYR A 18 -15.653 24.237 16.802 1.00 0.00 H +ATOM 316 HB3 TYR A 18 -14.655 21.984 16.618 1.00 0.00 H +ATOM 317 HB2 TYR A 18 -15.075 22.598 15.101 1.00 0.00 H +ATOM 318 HD1 TYR A 18 -16.017 20.093 17.647 1.00 0.00 H +ATOM 319 HD2 TYR A 18 -16.724 21.460 13.652 1.00 0.00 H +ATOM 320 HE1 TYR A 18 -17.152 17.983 17.129 1.00 0.00 H +ATOM 321 HE2 TYR A 18 -17.894 19.347 13.133 1.00 0.00 H +ATOM 322 HH TYR A 18 -18.612 17.342 13.952 1.00 0.00 H +ATOM 323 N LYS A 19 -17.288 24.332 14.701 1.00 12.80 N +ATOM 324 CA LYS A 19 -18.373 24.558 13.769 1.00 12.57 C +ATOM 325 C LYS A 19 -18.376 23.499 12.704 1.00 12.83 C +ATOM 326 O LYS A 19 -17.307 23.145 12.162 1.00 15.03 O +ATOM 327 CB LYS A 19 -18.251 25.937 13.132 1.00 12.07 C +ATOM 328 CG LYS A 19 -18.595 27.064 14.068 1.00 13.97 C +ATOM 329 CD LYS A 19 -18.401 28.406 13.380 1.00 17.78 C +ATOM 330 CE LYS A 19 -18.820 29.560 14.287 1.00 19.56 C +ATOM 331 NZ LYS A 19 -18.713 30.832 13.518 1.00 23.39 N +ATOM 332 H LYS A 19 -16.350 24.614 14.453 1.00 0.00 H +ATOM 333 HA LYS A 19 -19.316 24.508 14.313 1.00 0.00 H +ATOM 334 HB3 LYS A 19 -18.894 25.988 12.253 1.00 0.00 H +ATOM 335 HB2 LYS A 19 -17.236 26.074 12.758 1.00 0.00 H +ATOM 336 HG3 LYS A 19 -17.956 27.012 14.949 1.00 0.00 H +ATOM 337 HG2 LYS A 19 -19.633 26.967 14.388 1.00 0.00 H +ATOM 338 HD3 LYS A 19 -18.990 28.432 12.464 1.00 0.00 H +ATOM 339 HD2 LYS A 19 -17.353 28.524 13.104 1.00 0.00 H +ATOM 340 HE3 LYS A 19 -18.157 29.601 15.151 1.00 0.00 H +ATOM 341 HE2 LYS A 19 -19.852 29.415 14.606 1.00 0.00 H +ATOM 342 HZ1 LYS A 19 -18.988 31.606 14.106 1.00 0.00 H +ATOM 343 HZ2 LYS A 19 -17.759 30.963 13.214 1.00 0.00 H +ATOM 344 HZ3 LYS A 19 -19.320 30.791 12.712 1.00 0.00 H +ATOM 345 N ASP A 20 -19.568 22.991 12.415 1.00 11.92 N +ATOM 346 CA ASP A 20 -19.753 21.985 11.387 1.00 10.71 C +ATOM 347 C ASP A 20 -19.673 22.593 9.982 1.00 10.75 C +ATOM 348 O ASP A 20 -19.358 23.784 9.818 1.00 13.29 O +ATOM 349 CB ASP A 20 -21.053 21.179 11.612 1.00 16.00 C +ATOM 350 CG ASP A 20 -22.334 21.963 11.295 1.00 16.07 C +ATOM 351 OD1 ASP A 20 -22.284 23.097 10.782 1.00 14.31 O +ATOM 352 OD2 ASP A 20 -23.451 21.445 11.570 1.00 19.24 O +ATOM 353 H ASP A 20 -20.386 23.304 12.918 1.00 0.00 H +ATOM 354 HA ASP A 20 -18.924 21.283 11.477 1.00 0.00 H +ATOM 355 HB3 ASP A 20 -21.088 20.831 12.644 1.00 0.00 H +ATOM 356 HB2 ASP A 20 -21.025 20.272 11.008 1.00 0.00 H +ATOM 357 N THR A 21 -19.974 21.789 8.977 1.00 12.09 N +ATOM 358 CA THR A 21 -19.810 22.254 7.591 1.00 12.06 C +ATOM 359 C THR A 21 -20.762 23.404 7.263 1.00 13.25 C +ATOM 360 O THR A 21 -20.518 24.165 6.308 1.00 14.08 O +ATOM 361 CB THR A 21 -20.032 21.102 6.563 1.00 13.37 C +ATOM 362 OG1 THR A 21 -21.407 20.708 6.550 1.00 16.81 O +ATOM 363 CG2 THR A 21 -19.146 19.895 6.883 1.00 13.85 C +ATOM 364 H THR A 21 -20.316 20.857 9.161 1.00 0.00 H +ATOM 365 HA THR A 21 -18.789 22.618 7.475 1.00 0.00 H +ATOM 366 HB THR A 21 -19.769 21.469 5.571 1.00 0.00 H +ATOM 367 HG1 THR A 21 -21.531 19.999 5.914 1.00 0.00 H +ATOM 368 HG21 THR A 21 -19.323 19.109 6.149 1.00 0.00 H +ATOM 369 HG22 THR A 21 -18.098 20.194 6.849 1.00 0.00 H +ATOM 370 HG23 THR A 21 -19.385 19.522 7.879 1.00 0.00 H +ATOM 371 N GLU A 22 -21.859 23.539 8.024 1.00 11.76 N +ATOM 372 CA GLU A 22 -22.812 24.618 7.814 1.00 11.13 C +ATOM 373 C GLU A 22 -22.572 25.841 8.708 1.00 12.08 C +ATOM 374 O GLU A 22 -23.344 26.809 8.695 1.00 14.78 O +ATOM 375 CB GLU A 22 -24.244 24.120 8.058 1.00 13.47 C +ATOM 376 CG GLU A 22 -24.652 22.971 7.156 1.00 17.05 C +ATOM 377 CD GLU A 22 -24.939 23.390 5.738 1.00 25.96 C +ATOM 378 OE1 GLU A 22 -25.071 24.603 5.461 1.00 25.34 O +ATOM 379 OE2 GLU A 22 -25.036 22.475 4.890 1.00 28.62 O +ATOM 380 H GLU A 22 -22.042 22.881 8.768 1.00 0.00 H +ATOM 381 HA GLU A 22 -22.737 24.938 6.775 1.00 0.00 H +ATOM 382 HB3 GLU A 22 -24.942 24.947 7.928 1.00 0.00 H +ATOM 383 HB2 GLU A 22 -24.349 23.817 9.100 1.00 0.00 H +ATOM 384 HG3 GLU A 22 -25.531 22.479 7.573 1.00 0.00 H +ATOM 385 HG2 GLU A 22 -23.868 22.214 7.158 1.00 0.00 H +ATOM 386 N GLY A 23 -21.505 25.786 9.494 1.00 11.31 N +ATOM 387 CA GLY A 23 -21.204 26.842 10.446 1.00 11.54 C +ATOM 388 C GLY A 23 -21.883 26.755 11.806 1.00 12.68 C +ATOM 389 O GLY A 23 -21.872 27.745 12.550 1.00 16.15 O +ATOM 390 H GLY A 23 -20.878 24.996 9.440 1.00 0.00 H +ATOM 391 HA3 GLY A 23 -21.430 27.808 9.994 1.00 0.00 H +ATOM 392 HA2 GLY A 23 -20.125 26.901 10.587 1.00 0.00 H +ATOM 393 N TYR A 24 -22.435 25.584 12.149 1.00 11.51 N +ATOM 394 CA TYR A 24 -23.173 25.458 13.411 1.00 12.47 C +ATOM 395 C TYR A 24 -22.324 24.809 14.481 1.00 10.46 C +ATOM 396 O TYR A 24 -21.593 23.864 14.225 1.00 11.26 O +ATOM 397 CB TYR A 24 -24.405 24.587 13.227 1.00 12.94 C +ATOM 398 CG TYR A 24 -25.406 25.135 12.247 1.00 15.81 C +ATOM 399 CD1 TYR A 24 -25.753 26.479 12.260 1.00 18.76 C +ATOM 400 CD2 TYR A 24 -26.006 24.304 11.314 1.00 19.75 C +ATOM 401 CE1 TYR A 24 -26.694 26.988 11.349 1.00 25.25 C +ATOM 402 CE2 TYR A 24 -26.936 24.801 10.408 1.00 19.74 C +ATOM 403 CZ TYR A 24 -27.272 26.136 10.429 1.00 29.41 C +ATOM 404 OH TYR A 24 -28.208 26.621 9.522 1.00 30.60 O +ATOM 405 H TYR A 24 -22.344 24.785 11.538 1.00 0.00 H +ATOM 406 HA TYR A 24 -23.480 26.448 13.748 1.00 0.00 H +ATOM 407 HB3 TYR A 24 -24.889 24.437 14.192 1.00 0.00 H +ATOM 408 HB2 TYR A 24 -24.099 23.590 12.911 1.00 0.00 H +ATOM 409 HD1 TYR A 24 -25.298 27.147 12.976 1.00 0.00 H +ATOM 410 HD2 TYR A 24 -25.753 23.254 11.284 1.00 0.00 H +ATOM 411 HE1 TYR A 24 -26.958 28.035 11.374 1.00 0.00 H +ATOM 412 HE2 TYR A 24 -27.395 24.140 9.688 1.00 0.00 H +ATOM 413 HH TYR A 24 -28.509 25.905 8.958 1.00 0.00 H +ATOM 414 N TYR A 25 -22.468 25.289 15.718 1.00 11.10 N +ATOM 415 CA TYR A 25 -21.707 24.746 16.837 1.00 9.98 C +ATOM 416 C TYR A 25 -22.095 23.293 17.105 1.00 10.34 C +ATOM 417 O TYR A 25 -23.279 22.966 17.213 1.00 10.65 O +ATOM 418 CB TYR A 25 -21.958 25.582 18.099 1.00 10.44 C +ATOM 419 CG TYR A 25 -21.350 26.961 18.008 1.00 11.50 C +ATOM 420 CD1 TYR A 25 -19.977 27.110 17.870 1.00 12.51 C +ATOM 421 CD2 TYR A 25 -22.159 28.103 18.093 1.00 15.24 C +ATOM 422 CE1 TYR A 25 -19.404 28.390 17.799 1.00 15.81 C +ATOM 423 CE2 TYR A 25 -21.591 29.381 18.024 1.00 16.74 C +ATOM 424 CZ TYR A 25 -20.226 29.493 17.883 1.00 17.83 C +ATOM 425 OH TYR A 25 -19.628 30.752 17.792 1.00 24.34 O +ATOM 426 H TYR A 25 -23.115 26.044 15.894 1.00 0.00 H +ATOM 427 HA TYR A 25 -20.645 24.787 16.593 1.00 0.00 H +ATOM 428 HB3 TYR A 25 -21.549 25.062 18.965 1.00 0.00 H +ATOM 429 HB2 TYR A 25 -23.031 25.670 18.268 1.00 0.00 H +ATOM 430 HD1 TYR A 25 -19.342 26.238 17.817 1.00 0.00 H +ATOM 431 HD2 TYR A 25 -23.227 28.000 18.212 1.00 0.00 H +ATOM 432 HE1 TYR A 25 -18.336 28.498 17.680 1.00 0.00 H +ATOM 433 HE2 TYR A 25 -22.222 30.256 18.081 1.00 0.00 H +ATOM 434 HH TYR A 25 -20.301 31.433 17.864 1.00 0.00 H +ATOM 435 N THR A 26 -21.052 22.481 17.238 1.00 8.84 N +ATOM 436 CA THR A 26 -21.100 21.034 17.244 1.00 9.88 C +ATOM 437 C THR A 26 -20.001 20.556 18.176 1.00 9.34 C +ATOM 438 O THR A 26 -19.054 21.293 18.488 1.00 9.74 O +ATOM 439 CB THR A 26 -20.850 20.537 15.792 1.00 9.52 C +ATOM 440 OG1 THR A 26 -21.864 21.096 14.970 1.00 11.60 O +ATOM 441 CG2 THR A 26 -20.945 19.006 15.652 1.00 10.90 C +ATOM 442 H THR A 26 -20.124 22.865 17.347 1.00 0.00 H +ATOM 443 HA THR A 26 -22.072 20.690 17.599 1.00 0.00 H +ATOM 444 HB THR A 26 -19.872 20.877 15.451 1.00 0.00 H +ATOM 445 HG1 THR A 26 -21.737 20.807 14.063 1.00 0.00 H +ATOM 446 HG21 THR A 26 -20.761 18.723 14.616 1.00 0.00 H +ATOM 447 HG22 THR A 26 -20.201 18.535 16.294 1.00 0.00 H +ATOM 448 HG23 THR A 26 -21.941 18.675 15.947 1.00 0.00 H +ATOM 449 N ILE A 27 -20.082 19.315 18.639 1.00 9.39 N +ATOM 450 CA ILE A 27 -18.986 18.738 19.414 1.00 9.19 C +ATOM 451 C ILE A 27 -18.947 17.231 19.188 1.00 9.69 C +ATOM 452 O ILE A 27 -19.925 16.655 18.715 1.00 9.92 O +ATOM 453 CB ILE A 27 -19.123 19.064 20.925 1.00 11.00 C +ATOM 454 CG1 ILE A 27 -17.776 18.881 21.653 1.00 12.33 C +ATOM 455 CG2 ILE A 27 -20.257 18.241 21.538 1.00 12.63 C +ATOM 456 CD1 ILE A 27 -17.663 19.615 23.001 1.00 14.22 C +ATOM 457 H ILE A 27 -20.906 18.761 18.457 1.00 0.00 H +ATOM 458 HA ILE A 27 -18.049 19.164 19.054 1.00 0.00 H +ATOM 459 HB ILE A 27 -19.400 20.115 21.009 1.00 0.00 H +ATOM 460 HG13 ILE A 27 -16.966 19.202 20.998 1.00 0.00 H +ATOM 461 HG12 ILE A 27 -17.589 17.818 21.805 1.00 0.00 H +ATOM 462 HG21 ILE A 27 -20.345 18.477 22.599 1.00 0.00 H +ATOM 463 HG22 ILE A 27 -21.193 18.480 21.034 1.00 0.00 H +ATOM 464 HG23 ILE A 27 -20.041 17.179 21.419 1.00 0.00 H +ATOM 465 HD11 ILE A 27 -16.682 19.427 23.437 1.00 0.00 H +ATOM 466 HD12 ILE A 27 -17.791 20.686 22.844 1.00 0.00 H +ATOM 467 HD13 ILE A 27 -18.436 19.253 23.678 1.00 0.00 H +ATOM 468 N GLY A 28 -17.827 16.598 19.536 1.00 9.52 N +ATOM 469 CA GLY A 28 -17.767 15.144 19.525 1.00 9.45 C +ATOM 470 C GLY A 28 -17.745 14.598 18.121 1.00 10.39 C +ATOM 471 O GLY A 28 -16.973 15.043 17.284 1.00 12.57 O +ATOM 472 H GLY A 28 -17.012 17.128 19.810 1.00 0.00 H +ATOM 473 HA3 GLY A 28 -18.629 14.741 20.057 1.00 0.00 H +ATOM 474 HA2 GLY A 28 -16.875 14.814 20.057 1.00 0.00 H +ATOM 475 N ILE A 29 -18.592 13.601 17.895 1.00 8.62 N +ATOM 476 CA ILE A 29 -18.727 12.939 16.600 1.00 8.80 C +ATOM 477 C ILE A 29 -19.977 13.492 15.950 1.00 8.33 C +ATOM 478 O ILE A 29 -21.009 12.841 15.830 1.00 9.38 O +ATOM 479 CB ILE A 29 -18.753 11.414 16.795 1.00 9.73 C +ATOM 480 CG1 ILE A 29 -17.509 10.995 17.592 1.00 10.97 C +ATOM 481 CG2 ILE A 29 -18.768 10.717 15.434 1.00 12.56 C +ATOM 482 CD1 ILE A 29 -17.525 9.579 18.158 1.00 16.11 C +ATOM 483 H ILE A 29 -19.185 13.264 18.640 1.00 0.00 H +ATOM 484 HA ILE A 29 -17.867 13.199 15.983 1.00 0.00 H +ATOM 485 HB ILE A 29 -19.648 11.137 17.352 1.00 0.00 H +ATOM 486 HG13 ILE A 29 -17.346 11.705 18.403 1.00 0.00 H +ATOM 487 HG12 ILE A 29 -16.623 11.124 16.970 1.00 0.00 H +ATOM 488 HG21 ILE A 29 -18.786 9.637 15.579 1.00 0.00 H +ATOM 489 HG22 ILE A 29 -19.654 11.024 14.878 1.00 0.00 H +ATOM 490 HG23 ILE A 29 -17.874 10.993 14.874 1.00 0.00 H +ATOM 491 HD11 ILE A 29 -16.598 9.394 18.701 1.00 0.00 H +ATOM 492 HD12 ILE A 29 -18.371 9.468 18.836 1.00 0.00 H +ATOM 493 HD13 ILE A 29 -17.618 8.862 17.342 1.00 0.00 H +ATOM 494 N GLY A 30 -19.879 14.742 15.495 1.00 8.94 N +ATOM 495 CA GLY A 30 -21.003 15.339 14.798 1.00 9.03 C +ATOM 496 C GLY A 30 -22.242 15.617 15.634 1.00 8.29 C +ATOM 497 O GLY A 30 -23.342 15.638 15.093 1.00 10.97 O +ATOM 498 H GLY A 30 -19.027 15.266 15.637 1.00 0.00 H +ATOM 499 HA3 GLY A 30 -21.275 14.710 13.950 1.00 0.00 H +ATOM 500 HA2 GLY A 30 -20.679 16.262 14.318 1.00 0.00 H +ATOM 501 N HID A 31 -22.087 15.858 16.940 1.00 8.51 N +ATOM 502 CA HID A 31 -23.250 16.178 17.748 1.00 8.17 C +ATOM 503 C HID A 31 -23.571 17.667 17.646 1.00 8.85 C +ATOM 504 O HID A 31 -22.855 18.508 18.205 1.00 10.93 O +ATOM 505 CB HID A 31 -23.004 15.826 19.214 1.00 10.23 C +ATOM 506 CG HID A 31 -24.192 16.121 20.070 1.00 10.70 C +ATOM 507 ND1 HID A 31 -25.286 15.287 20.110 1.00 12.37 N +ATOM 508 CD2 HID A 31 -24.504 17.201 20.831 1.00 12.16 C +ATOM 509 CE1 HID A 31 -26.206 15.821 20.902 1.00 13.38 C +ATOM 510 NE2 HID A 31 -25.762 16.986 21.342 1.00 14.08 N +ATOM 511 H HID A 31 -21.167 15.817 17.356 1.00 0.00 H +ATOM 512 HA HID A 31 -24.103 15.605 17.384 1.00 0.00 H +ATOM 513 HB3 HID A 31 -22.144 16.386 19.582 1.00 0.00 H +ATOM 514 HB2 HID A 31 -22.752 14.769 19.296 1.00 0.00 H +ATOM 515 HD1 HID A 31 -25.285 14.427 19.581 1.00 0.00 H +ATOM 516 HD2 HID A 31 -23.799 18.013 20.931 1.00 0.00 H +ATOM 517 HE1 HID A 31 -27.132 15.296 21.085 1.00 0.00 H +ATOM 518 N LEU A 32 -24.619 17.998 16.928 1.00 9.15 N +ATOM 519 CA LEU A 32 -25.038 19.403 16.797 1.00 10.33 C +ATOM 520 C LEU A 32 -25.522 19.945 18.116 1.00 11.33 C +ATOM 521 O LEU A 32 -26.359 19.323 18.782 1.00 12.15 O +ATOM 522 CB LEU A 32 -26.196 19.488 15.801 1.00 11.58 C +ATOM 523 CG LEU A 32 -26.891 20.834 15.642 1.00 13.83 C +ATOM 524 CD1 LEU A 32 -25.953 21.847 15.019 1.00 11.92 C +ATOM 525 CD2 LEU A 32 -28.145 20.641 14.782 1.00 15.85 C +ATOM 526 H LEU A 32 -25.153 17.283 16.454 1.00 0.00 H +ATOM 527 HA LEU A 32 -24.202 20.003 16.439 1.00 0.00 H +ATOM 528 HB3 LEU A 32 -26.938 18.729 16.050 1.00 0.00 H +ATOM 529 HB2 LEU A 32 -25.854 19.144 14.825 1.00 0.00 H +ATOM 530 HG LEU A 32 -27.192 21.193 16.626 1.00 0.00 H +ATOM 531 HD11 LEU A 32 -26.467 22.802 14.913 1.00 0.00 H +ATOM 532 HD12 LEU A 32 -25.079 21.974 15.657 1.00 0.00 H +ATOM 533 HD13 LEU A 32 -25.637 21.495 14.037 1.00 0.00 H +ATOM 534 HD21 LEU A 32 -28.653 21.598 14.660 1.00 0.00 H +ATOM 535 HD22 LEU A 32 -27.859 20.254 13.804 1.00 0.00 H +ATOM 536 HD23 LEU A 32 -28.816 19.934 15.270 1.00 0.00 H +ATOM 537 N LEU A 33 -24.992 21.098 18.527 1.00 9.44 N +ATOM 538 CA LEU A 33 -25.421 21.683 19.790 1.00 10.51 C +ATOM 539 C LEU A 33 -26.524 22.698 19.573 1.00 12.85 C +ATOM 540 O LEU A 33 -27.515 22.728 20.341 1.00 15.57 O +ATOM 541 CB LEU A 33 -24.206 22.333 20.462 1.00 11.00 C +ATOM 542 CG LEU A 33 -23.195 21.341 21.002 1.00 12.33 C +ATOM 543 CD1 LEU A 33 -21.879 22.108 21.374 1.00 12.44 C +ATOM 544 CD2 LEU A 33 -23.779 20.626 22.217 1.00 11.22 C +ATOM 545 H LEU A 33 -24.295 21.563 17.963 1.00 0.00 H +ATOM 546 HA LEU A 33 -25.796 20.889 20.435 1.00 0.00 H +ATOM 547 HB3 LEU A 33 -24.544 22.981 21.271 1.00 0.00 H +ATOM 548 HB2 LEU A 33 -23.715 23.000 19.753 1.00 0.00 H +ATOM 549 HG LEU A 33 -22.971 20.605 20.230 1.00 0.00 H +ATOM 550 HD11 LEU A 33 -21.145 21.403 21.764 1.00 0.00 H +ATOM 551 HD12 LEU A 33 -21.478 22.595 20.485 1.00 0.00 H +ATOM 552 HD13 LEU A 33 -22.098 22.860 22.132 1.00 0.00 H +ATOM 553 HD21 LEU A 33 -23.051 19.913 22.604 1.00 0.00 H +ATOM 554 HD22 LEU A 33 -24.017 21.357 22.990 1.00 0.00 H +ATOM 555 HD23 LEU A 33 -24.686 20.096 21.926 1.00 0.00 H +ATOM 556 N THR A 34 -26.369 23.558 18.557 1.00 12.51 N +ATOM 557 CA THR A 34 -27.375 24.597 18.305 1.00 13.40 C +ATOM 558 C THR A 34 -27.113 25.228 16.964 1.00 15.27 C +ATOM 559 O THR A 34 -25.983 25.221 16.459 1.00 16.00 O +ATOM 560 CB THR A 34 -27.335 25.709 19.408 1.00 18.63 C +ATOM 561 OG1 THR A 34 -28.354 26.678 19.123 1.00 19.74 O +ATOM 562 CG2 THR A 34 -25.974 26.392 19.478 1.00 17.12 C +ATOM 563 H THR A 34 -25.557 23.493 17.960 1.00 0.00 H +ATOM 564 HA THR A 34 -28.364 24.140 18.296 1.00 0.00 H +ATOM 565 HB THR A 34 -27.547 25.252 20.374 1.00 0.00 H +ATOM 566 HG1 THR A 34 -28.339 27.365 19.793 1.00 0.00 H +ATOM 567 HG21 THR A 34 -25.990 27.156 20.255 1.00 0.00 H +ATOM 568 HG22 THR A 34 -25.208 25.653 19.711 1.00 0.00 H +ATOM 569 HG23 THR A 34 -25.750 26.856 18.518 1.00 0.00 H +ATOM 570 N LYS A 35 -28.157 25.804 16.393 1.00 14.48 N +ATOM 571 CA LYS A 35 -27.976 26.589 15.176 1.00 16.17 C +ATOM 572 C LYS A 35 -27.834 28.078 15.470 1.00 17.05 C +ATOM 573 O LYS A 35 -27.597 28.893 14.554 1.00 22.19 O +ATOM 574 CB LYS A 35 -29.101 26.323 14.175 1.00 19.86 C +ATOM 575 CG LYS A 35 -29.052 24.917 13.605 1.00 17.90 C +ATOM 576 CD LYS A 35 -30.106 24.754 12.536 1.00 24.75 C +ATOM 577 CE LYS A 35 -30.142 23.342 12.042 1.00 26.34 C +ATOM 578 NZ LYS A 35 -31.145 23.215 10.948 1.00 32.58 N +ATOM 579 H LYS A 35 -29.076 25.700 16.799 1.00 0.00 H +ATOM 580 HA LYS A 35 -27.046 26.260 14.713 1.00 0.00 H +ATOM 581 HB3 LYS A 35 -29.041 27.046 13.362 1.00 0.00 H +ATOM 582 HB2 LYS A 35 -30.064 26.484 14.661 1.00 0.00 H +ATOM 583 HG3 LYS A 35 -29.229 24.196 14.403 1.00 0.00 H +ATOM 584 HG2 LYS A 35 -28.067 24.734 13.175 1.00 0.00 H +ATOM 585 HD3 LYS A 35 -29.886 25.424 11.705 1.00 0.00 H +ATOM 586 HD2 LYS A 35 -31.081 25.021 12.944 1.00 0.00 H +ATOM 587 HE3 LYS A 35 -30.413 22.677 12.862 1.00 0.00 H +ATOM 588 HE2 LYS A 35 -29.157 23.064 11.666 1.00 0.00 H +ATOM 589 HZ1 LYS A 35 -31.165 22.261 10.618 1.00 0.00 H +ATOM 590 HZ2 LYS A 35 -32.058 23.470 11.296 1.00 0.00 H +ATOM 591 HZ3 LYS A 35 -30.893 23.828 10.186 1.00 0.00 H +ATOM 592 N SER A 36 -27.937 28.421 16.737 1.00 20.56 N +ATOM 593 CA SER A 36 -27.719 29.793 17.175 1.00 21.88 C +ATOM 594 C SER A 36 -26.281 30.231 16.930 1.00 21.60 C +ATOM 595 O SER A 36 -25.341 29.470 17.157 1.00 19.10 O +ATOM 596 CB SER A 36 -28.008 29.897 18.666 1.00 23.61 C +ATOM 597 OG SER A 36 -27.640 31.181 19.152 1.00 23.95 O +ATOM 598 H SER A 36 -28.172 27.726 17.431 1.00 0.00 H +ATOM 599 HA SER A 36 -28.393 30.455 16.632 1.00 0.00 H +ATOM 600 HB3 SER A 36 -27.444 29.132 19.199 1.00 0.00 H +ATOM 601 HB2 SER A 36 -29.071 29.733 18.842 1.00 0.00 H +ATOM 602 HG SER A 36 -27.827 31.234 20.092 1.00 0.00 H +ATOM 603 N PRO A 37 -26.089 31.483 16.482 1.00 21.63 N +ATOM 604 CA PRO A 37 -24.718 31.997 16.358 1.00 20.80 C +ATOM 605 C PRO A 37 -23.999 32.278 17.679 1.00 19.04 C +ATOM 606 O PRO A 37 -22.818 32.618 17.686 1.00 27.60 O +ATOM 607 CB PRO A 37 -24.901 33.304 15.577 1.00 23.22 C +ATOM 608 CG PRO A 37 -26.296 33.714 15.859 1.00 30.86 C +ATOM 609 CD PRO A 37 -27.100 32.446 16.022 1.00 25.19 C +ATOM 610 HA PRO A 37 -24.124 31.302 15.764 1.00 0.00 H +ATOM 611 HB3 PRO A 37 -24.791 33.106 14.511 1.00 0.00 H +ATOM 612 HB2 PRO A 37 -24.217 34.057 15.968 1.00 0.00 H +ATOM 613 HG3 PRO A 37 -26.684 34.283 15.014 1.00 0.00 H +ATOM 614 HG2 PRO A 37 -26.326 34.284 16.788 1.00 0.00 H +ATOM 615 HD2 PRO A 37 -27.842 32.590 16.807 1.00 0.00 H +ATOM 616 HD3 PRO A 37 -27.478 32.133 15.049 1.00 0.00 H +ATOM 617 N SER A 38 -24.688 32.085 18.801 1.00 18.94 N +ATOM 618 CA SER A 38 -24.098 32.380 20.106 1.00 22.60 C +ATOM 619 C SER A 38 -23.293 31.206 20.686 1.00 18.49 C +ATOM 620 O SER A 38 -23.877 30.145 20.977 1.00 17.17 O +ATOM 621 CB SER A 38 -25.212 32.772 21.087 1.00 21.71 C +ATOM 622 OG SER A 38 -24.748 32.783 22.430 1.00 27.71 O +ATOM 623 H SER A 38 -25.633 31.730 18.759 1.00 0.00 H +ATOM 624 HA SER A 38 -23.427 33.232 19.993 1.00 0.00 H +ATOM 625 HB3 SER A 38 -26.040 32.069 20.995 1.00 0.00 H +ATOM 626 HB2 SER A 38 -25.593 33.759 20.827 1.00 0.00 H +ATOM 627 HG SER A 38 -25.467 33.031 23.015 1.00 0.00 H +ATOM 628 N LEU A 39 -21.984 31.382 20.875 1.00 19.98 N +ATOM 629 CA LEU A 39 -21.167 30.367 21.534 1.00 17.19 C +ATOM 630 C LEU A 39 -21.692 30.103 22.952 1.00 17.84 C +ATOM 631 O LEU A 39 -21.649 28.963 23.449 1.00 17.10 O +ATOM 632 CB LEU A 39 -19.678 30.772 21.580 1.00 18.98 C +ATOM 633 CG LEU A 39 -18.742 29.790 22.279 1.00 19.40 C +ATOM 634 CD1 LEU A 39 -18.761 28.449 21.554 1.00 17.35 C +ATOM 635 CD2 LEU A 39 -17.302 30.301 22.387 1.00 28.90 C +ATOM 636 H LEU A 39 -21.538 32.232 20.560 1.00 0.00 H +ATOM 637 HA LEU A 39 -21.250 29.442 20.964 1.00 0.00 H +ATOM 638 HB3 LEU A 39 -19.586 31.752 22.048 1.00 0.00 H +ATOM 639 HB2 LEU A 39 -19.322 30.948 20.565 1.00 0.00 H +ATOM 640 HG LEU A 39 -19.118 29.630 23.290 1.00 0.00 H +ATOM 641 HD11 LEU A 39 -18.091 27.753 22.058 1.00 0.00 H +ATOM 642 HD12 LEU A 39 -19.774 28.046 21.560 1.00 0.00 H +ATOM 643 HD13 LEU A 39 -18.432 28.588 20.524 1.00 0.00 H +ATOM 644 HD21 LEU A 39 -16.689 29.556 22.894 1.00 0.00 H +ATOM 645 HD22 LEU A 39 -16.904 30.481 21.388 1.00 0.00 H +ATOM 646 HD23 LEU A 39 -17.288 31.231 22.956 1.00 0.00 H +ATOM 647 N ASN A 40 -22.186 31.143 23.623 1.00 18.36 N +ATOM 648 CA ASN A 40 -22.686 30.913 24.984 1.00 16.83 C +ATOM 649 C ASN A 40 -23.905 29.981 24.976 1.00 18.76 C +ATOM 650 O ASN A 40 -24.048 29.129 25.858 1.00 18.35 O +ATOM 651 CB ASN A 40 -23.037 32.238 25.667 1.00 24.01 C +ATOM 652 CG ASN A 40 -21.825 32.931 26.250 1.00 31.56 C +ATOM 653 OD1 ASN A 40 -20.761 32.324 26.421 1.00 32.66 O +ATOM 654 ND2 ASN A 40 -21.984 34.210 26.582 1.00 40.31 N +ATOM 655 H ASN A 40 -22.209 32.057 23.193 1.00 0.00 H +ATOM 656 HA ASN A 40 -21.895 30.433 25.560 1.00 0.00 H +ATOM 657 HB3 ASN A 40 -23.766 32.056 26.457 1.00 0.00 H +ATOM 658 HB2 ASN A 40 -23.521 32.899 24.948 1.00 0.00 H +ATOM 659 HD22 ASN A 40 -21.213 34.729 26.976 1.00 0.00 H +ATOM 660 HD21 ASN A 40 -22.876 34.662 26.440 1.00 0.00 H +ATOM 661 N ALA A 41 -24.782 30.155 23.995 1.00 16.20 N +ATOM 662 CA ALA A 41 -25.927 29.263 23.814 1.00 16.06 C +ATOM 663 C ALA A 41 -25.445 27.836 23.570 1.00 18.46 C +ATOM 664 O ALA A 41 -25.981 26.874 24.142 1.00 16.68 O +ATOM 665 CB ALA A 41 -26.801 29.725 22.676 1.00 19.38 C +ATOM 666 H ALA A 41 -24.669 30.921 23.347 1.00 0.00 H +ATOM 667 HA ALA A 41 -26.519 29.274 24.729 1.00 0.00 H +ATOM 668 HB1 ALA A 41 -27.644 29.043 22.565 1.00 0.00 H +ATOM 669 HB2 ALA A 41 -27.171 30.728 22.886 1.00 0.00 H +ATOM 670 HB3 ALA A 41 -26.221 29.738 21.753 1.00 0.00 H +ATOM 671 N ALA A 42 -24.435 27.686 22.725 1.00 13.52 N +ATOM 672 CA ALA A 42 -23.895 26.348 22.480 1.00 12.45 C +ATOM 673 C ALA A 42 -23.291 25.720 23.740 1.00 14.27 C +ATOM 674 O ALA A 42 -23.475 24.535 23.989 1.00 13.32 O +ATOM 675 CB ALA A 42 -22.865 26.384 21.347 1.00 12.96 C +ATOM 676 H ALA A 42 -24.045 28.491 22.257 1.00 0.00 H +ATOM 677 HA ALA A 42 -24.720 25.713 22.157 1.00 0.00 H +ATOM 678 HB1 ALA A 42 -22.474 25.381 21.179 1.00 0.00 H +ATOM 679 HB2 ALA A 42 -23.340 26.746 20.435 1.00 0.00 H +ATOM 680 HB3 ALA A 42 -22.047 27.051 21.620 1.00 0.00 H +ATOM 681 N LYS A 43 -22.574 26.510 24.550 1.00 14.42 N +ATOM 682 CA LYS A 43 -22.013 26.008 25.795 1.00 12.24 C +ATOM 683 C LYS A 43 -23.104 25.580 26.783 1.00 10.75 C +ATOM 684 O LYS A 43 -22.953 24.571 27.481 1.00 12.89 O +ATOM 685 CB LYS A 43 -21.110 27.059 26.424 1.00 14.93 C +ATOM 686 CG LYS A 43 -19.791 27.148 25.708 1.00 15.21 C +ATOM 687 CD LYS A 43 -19.036 28.368 26.217 1.00 21.16 C +ATOM 688 CE LYS A 43 -17.604 28.328 25.733 1.00 29.93 C +ATOM 689 NZ LYS A 43 -16.802 29.445 26.283 1.00 39.17 N +ATOM 690 H LYS A 43 -22.413 27.476 24.301 1.00 0.00 H +ATOM 691 HA LYS A 43 -21.404 25.134 25.564 1.00 0.00 H +ATOM 692 HB3 LYS A 43 -20.938 26.810 27.471 1.00 0.00 H +ATOM 693 HB2 LYS A 43 -21.606 28.029 26.393 1.00 0.00 H +ATOM 694 HG3 LYS A 43 -19.966 27.250 24.637 1.00 0.00 H +ATOM 695 HG2 LYS A 43 -19.207 26.250 25.909 1.00 0.00 H +ATOM 696 HD3 LYS A 43 -19.051 28.375 27.307 1.00 0.00 H +ATOM 697 HD2 LYS A 43 -19.519 29.273 25.849 1.00 0.00 H +ATOM 698 HE3 LYS A 43 -17.588 28.372 24.644 1.00 0.00 H +ATOM 699 HE2 LYS A 43 -17.150 27.380 26.021 1.00 0.00 H +ATOM 700 HZ1 LYS A 43 -15.855 29.383 25.937 1.00 0.00 H +ATOM 701 HZ2 LYS A 43 -17.207 30.324 25.996 1.00 0.00 H +ATOM 702 HZ3 LYS A 43 -16.796 29.391 27.292 1.00 0.00 H +ATOM 703 N SER A 44 -24.201 26.319 26.785 1.00 12.89 N +ATOM 704 CA SER A 44 -25.331 25.960 27.643 1.00 13.20 C +ATOM 705 C SER A 44 -25.958 24.636 27.185 1.00 13.67 C +ATOM 706 O SER A 44 -26.204 23.743 27.992 1.00 14.23 O +ATOM 707 CB SER A 44 -26.391 27.063 27.631 1.00 18.11 C +ATOM 708 OG SER A 44 -27.434 26.722 28.524 1.00 21.89 O +ATOM 709 H SER A 44 -24.261 27.135 26.193 1.00 0.00 H +ATOM 710 HA SER A 44 -24.968 25.838 28.663 1.00 0.00 H +ATOM 711 HB3 SER A 44 -26.795 27.167 26.624 1.00 0.00 H +ATOM 712 HB2 SER A 44 -25.939 28.004 27.943 1.00 0.00 H +ATOM 713 HG SER A 44 -28.100 27.413 28.518 1.00 0.00 H +ATOM 714 N GLU A 45 -26.142 24.482 25.875 1.00 13.07 N +ATOM 715 CA GLU A 45 -26.655 23.206 25.367 1.00 12.61 C +ATOM 716 C GLU A 45 -25.701 22.067 25.672 1.00 12.29 C +ATOM 717 O GLU A 45 -26.121 20.948 26.022 1.00 12.99 O +ATOM 718 CB GLU A 45 -26.894 23.280 23.854 1.00 12.32 C +ATOM 719 CG GLU A 45 -28.044 24.209 23.481 1.00 13.16 C +ATOM 720 CD GLU A 45 -29.391 23.702 23.992 1.00 21.12 C +ATOM 721 OE1 GLU A 45 -29.723 22.522 23.745 1.00 17.82 O +ATOM 722 OE2 GLU A 45 -30.116 24.476 24.665 1.00 22.85 O +ATOM 723 H GLU A 45 -25.929 25.240 25.243 1.00 0.00 H +ATOM 724 HA GLU A 45 -27.607 22.998 25.856 1.00 0.00 H +ATOM 725 HB3 GLU A 45 -27.097 22.280 23.470 1.00 0.00 H +ATOM 726 HB2 GLU A 45 -25.982 23.615 23.359 1.00 0.00 H +ATOM 727 HG3 GLU A 45 -28.085 24.318 22.397 1.00 0.00 H +ATOM 728 HG2 GLU A 45 -27.853 25.203 23.887 1.00 0.00 H +ATOM 729 N LEU A 46 -24.401 22.327 25.547 1.00 10.45 N +ATOM 730 CA LEU A 46 -23.438 21.300 25.895 1.00 10.59 C +ATOM 731 C LEU A 46 -23.546 20.835 27.352 1.00 11.59 C +ATOM 732 O LEU A 46 -23.547 19.649 27.634 1.00 12.09 O +ATOM 733 CB LEU A 46 -22.008 21.784 25.589 1.00 10.54 C +ATOM 734 CG LEU A 46 -20.933 20.764 25.971 1.00 12.92 C +ATOM 735 CD1 LEU A 46 -21.120 19.446 25.158 1.00 13.31 C +ATOM 736 CD2 LEU A 46 -19.520 21.312 25.719 1.00 13.07 C +ATOM 737 H LEU A 46 -24.096 23.230 25.213 1.00 0.00 H +ATOM 738 HA LEU A 46 -23.635 20.437 25.260 1.00 0.00 H +ATOM 739 HB3 LEU A 46 -21.822 22.720 26.116 1.00 0.00 H +ATOM 740 HB2 LEU A 46 -21.924 22.018 24.528 1.00 0.00 H +ATOM 741 HG LEU A 46 -21.033 20.535 27.032 1.00 0.00 H +ATOM 742 HD11 LEU A 46 -20.348 18.731 25.441 1.00 0.00 H +ATOM 743 HD12 LEU A 46 -22.102 19.023 25.371 1.00 0.00 H +ATOM 744 HD13 LEU A 46 -21.042 19.662 24.092 1.00 0.00 H +ATOM 745 HD21 LEU A 46 -18.783 20.561 26.002 1.00 0.00 H +ATOM 746 HD22 LEU A 46 -19.406 21.552 24.662 1.00 0.00 H +ATOM 747 HD23 LEU A 46 -19.367 22.212 26.314 1.00 0.00 H +ATOM 748 N ASP A 47 -23.584 21.784 28.281 1.00 13.38 N +ATOM 749 CA ASP A 47 -23.646 21.408 29.681 1.00 11.98 C +ATOM 750 C ASP A 47 -24.934 20.626 29.969 1.00 10.65 C +ATOM 751 O ASP A 47 -24.888 19.685 30.777 1.00 14.40 O +ATOM 752 CB ASP A 47 -23.587 22.673 30.529 1.00 13.96 C +ATOM 753 CG ASP A 47 -22.226 23.342 30.485 1.00 20.03 C +ATOM 754 OD1 ASP A 47 -21.288 22.769 29.898 1.00 18.42 O +ATOM 755 OD2 ASP A 47 -22.091 24.430 31.102 1.00 21.45 O +ATOM 756 H ASP A 47 -23.570 22.757 28.010 1.00 0.00 H +ATOM 757 HA ASP A 47 -22.788 20.780 29.919 1.00 0.00 H +ATOM 758 HB3 ASP A 47 -23.838 22.429 31.561 1.00 0.00 H +ATOM 759 HB2 ASP A 47 -24.347 23.375 30.186 1.00 0.00 H +ATOM 760 N LYS A 48 -26.034 20.995 29.319 1.00 11.85 N +ATOM 761 CA LYS A 48 -27.319 20.315 29.508 1.00 12.44 C +ATOM 762 C LYS A 48 -27.201 18.871 28.970 1.00 12.54 C +ATOM 763 O LYS A 48 -27.693 17.909 29.579 1.00 11.12 O +ATOM 764 CB LYS A 48 -28.399 21.095 28.752 1.00 16.14 C +ATOM 765 CG LYS A 48 -29.755 20.450 28.694 1.00 17.87 C +ATOM 766 CD LYS A 48 -30.874 21.462 28.322 1.00 14.61 C +ATOM 767 CE LYS A 48 -30.678 22.133 26.975 1.00 20.11 C +ATOM 768 NZ LYS A 48 -31.086 21.252 25.870 1.00 15.63 N +ATOM 769 H LYS A 48 -26.001 21.768 28.669 1.00 0.00 H +ATOM 770 HA LYS A 48 -27.565 20.289 30.570 1.00 0.00 H +ATOM 771 HB3 LYS A 48 -28.053 21.297 27.738 1.00 0.00 H +ATOM 772 HB2 LYS A 48 -28.493 22.091 29.185 1.00 0.00 H +ATOM 773 HG3 LYS A 48 -29.982 19.997 29.659 1.00 0.00 H +ATOM 774 HG2 LYS A 48 -29.741 19.641 27.964 1.00 0.00 H +ATOM 775 HD3 LYS A 48 -30.945 22.224 29.098 1.00 0.00 H +ATOM 776 HD2 LYS A 48 -31.839 20.955 28.336 1.00 0.00 H +ATOM 777 HE3 LYS A 48 -29.629 22.405 26.854 1.00 0.00 H +ATOM 778 HE2 LYS A 48 -31.261 23.053 26.940 1.00 0.00 H +ATOM 779 HZ1 LYS A 48 -30.943 21.727 24.990 1.00 0.00 H +ATOM 780 HZ2 LYS A 48 -30.532 20.408 25.890 1.00 0.00 H +ATOM 781 HZ3 LYS A 48 -32.063 21.016 25.970 1.00 0.00 H +ATOM 782 N ALA A 49 -26.542 18.732 27.823 1.00 12.03 N +ATOM 783 CA ALA A 49 -26.404 17.404 27.214 1.00 12.11 C +ATOM 784 C ALA A 49 -25.514 16.443 27.997 1.00 12.01 C +ATOM 785 O ALA A 49 -25.764 15.242 28.044 1.00 11.71 O +ATOM 786 CB ALA A 49 -25.849 17.554 25.780 1.00 11.32 C +ATOM 787 H ALA A 49 -26.137 19.540 27.372 1.00 0.00 H +ATOM 788 HA ALA A 49 -27.398 16.961 27.145 1.00 0.00 H +ATOM 789 HB1 ALA A 49 -25.745 16.569 25.325 1.00 0.00 H +ATOM 790 HB2 ALA A 49 -26.535 18.158 25.186 1.00 0.00 H +ATOM 791 HB3 ALA A 49 -24.875 18.041 25.816 1.00 0.00 H +ATOM 792 N ILE A 50 -24.456 16.963 28.596 1.00 11.70 N +ATOM 793 CA ILE A 50 -23.501 16.133 29.300 1.00 10.37 C +ATOM 794 C ILE A 50 -23.842 15.993 30.775 1.00 11.64 C +ATOM 795 O ILE A 50 -23.478 15.007 31.404 1.00 15.51 O +ATOM 796 CB ILE A 50 -22.082 16.790 29.173 1.00 13.24 C +ATOM 797 CG1 ILE A 50 -21.730 16.950 27.688 1.00 13.76 C +ATOM 798 CG2 ILE A 50 -21.025 15.982 29.895 1.00 13.14 C +ATOM 799 CD1 ILE A 50 -21.599 15.625 26.956 1.00 15.47 C +ATOM 800 H ILE A 50 -24.300 17.960 28.569 1.00 0.00 H +ATOM 801 HA ILE A 50 -23.480 15.144 28.842 1.00 0.00 H +ATOM 802 HB ILE A 50 -22.122 17.782 29.624 1.00 0.00 H +ATOM 803 HG13 ILE A 50 -20.799 17.508 27.595 1.00 0.00 H +ATOM 804 HG12 ILE A 50 -22.490 17.560 27.200 1.00 0.00 H +ATOM 805 HG21 ILE A 50 -20.056 16.469 29.784 1.00 0.00 H +ATOM 806 HG22 ILE A 50 -21.278 15.914 30.953 1.00 0.00 H +ATOM 807 HG23 ILE A 50 -20.978 14.980 29.468 1.00 0.00 H +ATOM 808 HD11 ILE A 50 -21.349 15.810 25.911 1.00 0.00 H +ATOM 809 HD12 ILE A 50 -20.811 15.031 27.418 1.00 0.00 H +ATOM 810 HD13 ILE A 50 -22.543 15.083 27.013 1.00 0.00 H +ATOM 811 N GLY A 51 -24.545 16.974 31.330 1.00 12.97 N +ATOM 812 CA GLY A 51 -24.929 16.942 32.740 1.00 13.41 C +ATOM 813 C GLY A 51 -23.894 17.525 33.690 1.00 17.37 C +ATOM 814 O GLY A 51 -23.895 17.206 34.889 1.00 20.28 O +ATOM 815 H GLY A 51 -24.828 17.769 30.775 1.00 0.00 H +ATOM 816 HA3 GLY A 51 -25.148 15.915 33.031 1.00 0.00 H +ATOM 817 HA2 GLY A 51 -25.874 17.469 32.869 1.00 0.00 H +ATOM 818 N ARG A 52 -22.997 18.364 33.176 1.00 14.28 N +ATOM 819 CA ARG A 52 -22.036 19.050 34.049 1.00 16.34 C +ATOM 820 C ARG A 52 -21.546 20.286 33.343 1.00 19.09 C +ATOM 821 O ARG A 52 -21.824 20.479 32.151 1.00 15.23 O +ATOM 822 CB ARG A 52 -20.846 18.168 34.366 1.00 16.47 C +ATOM 823 CG ARG A 52 -19.969 17.872 33.124 1.00 15.78 C +ATOM 824 CD ARG A 52 -18.812 16.903 33.399 1.00 16.62 C +ATOM 825 NE ARG A 52 -18.027 16.604 32.193 1.00 17.24 N +ATOM 826 CZ ARG A 52 -17.011 17.346 31.762 1.00 21.42 C +ATOM 827 NH1 ARG A 52 -16.631 18.437 32.442 1.00 19.73 N +ATOM 828 NH2 ARG A 52 -16.382 17.021 30.640 1.00 18.00 N +ATOM 829 H ARG A 52 -22.975 18.532 32.180 1.00 0.00 H +ATOM 830 HA ARG A 52 -22.531 19.336 34.977 1.00 0.00 H +ATOM 831 HB3 ARG A 52 -21.195 17.229 34.795 1.00 0.00 H +ATOM 832 HB2 ARG A 52 -20.237 18.644 35.134 1.00 0.00 H +ATOM 833 HG3 ARG A 52 -19.571 18.808 32.731 1.00 0.00 H +ATOM 834 HG2 ARG A 52 -20.595 17.471 32.327 1.00 0.00 H +ATOM 835 HD3 ARG A 52 -19.207 15.975 33.813 1.00 0.00 H +ATOM 836 HD2 ARG A 52 -18.158 17.327 34.161 1.00 0.00 H +ATOM 837 HE ARG A 52 -18.301 15.777 31.682 1.00 0.00 H +ATOM 838 HH12 ARG A 52 -15.859 18.996 32.109 1.00 0.00 H +ATOM 839 HH11 ARG A 52 -17.117 18.700 33.287 1.00 0.00 H +ATOM 840 HH21 ARG A 52 -15.610 17.584 30.312 1.00 0.00 H +ATOM 841 HH22 ARG A 52 -16.675 16.210 30.114 1.00 0.00 H +ATOM 842 N ASN A 53 -20.816 21.138 34.066 1.00 16.14 N +ATOM 843 CA ASN A 53 -20.272 22.337 33.458 1.00 15.86 C +ATOM 844 C ASN A 53 -18.986 22.002 32.729 1.00 17.12 C +ATOM 845 O ASN A 53 -17.951 21.740 33.347 1.00 19.17 O +ATOM 846 CB ASN A 53 -20.006 23.390 34.528 1.00 20.81 C +ATOM 847 CG ASN A 53 -21.277 23.914 35.145 1.00 21.99 C +ATOM 848 OD1 ASN A 53 -22.325 23.971 34.496 1.00 27.50 O +ATOM 849 ND2 ASN A 53 -21.192 24.313 36.407 1.00 28.13 N +ATOM 850 H ASN A 53 -20.640 20.949 35.042 1.00 0.00 H +ATOM 851 HA ASN A 53 -20.994 22.732 32.743 1.00 0.00 H +ATOM 852 HB3 ASN A 53 -19.447 24.218 34.091 1.00 0.00 H +ATOM 853 HB2 ASN A 53 -19.374 22.964 35.307 1.00 0.00 H +ATOM 854 HD22 ASN A 53 -22.009 24.675 36.878 1.00 0.00 H +ATOM 855 HD21 ASN A 53 -20.311 24.255 36.897 1.00 0.00 H +ATOM 856 N CYS A 54 -19.061 22.004 31.389 1.00 15.81 N +ATOM 857 CA CYS A 54 -17.969 21.493 30.564 1.00 16.95 C +ATOM 858 C CYS A 54 -17.012 22.558 30.084 1.00 14.09 C +ATOM 859 O CYS A 54 -15.914 22.215 29.652 1.00 15.55 O +ATOM 860 CB CYS A 54 -18.511 20.789 29.297 1.00 14.68 C +ATOM 861 SG CYS A 54 -19.535 19.361 29.678 1.00 16.97 S +ATOM 862 H CYS A 54 -19.885 22.364 30.930 1.00 0.00 H +ATOM 863 HA CYS A 54 -17.408 20.764 31.149 1.00 0.00 H +ATOM 864 HB3 CYS A 54 -17.675 20.478 28.670 1.00 0.00 H +ATOM 865 HB2 CYS A 54 -19.087 21.501 28.706 1.00 0.00 H +ATOM 866 HG CYS A 54 -19.966 18.806 28.542 1.00 0.00 H +ATOM 867 N ASN A 55 -17.489 23.807 30.080 1.00 16.74 N +ATOM 868 CA ASN A 55 -16.753 24.924 29.472 1.00 20.42 C +ATOM 869 C ASN A 55 -16.237 24.599 28.067 1.00 18.18 C +ATOM 870 O ASN A 55 -15.084 24.884 27.709 1.00 19.69 O +ATOM 871 CB ASN A 55 -15.574 25.319 30.339 1.00 20.96 C +ATOM 872 CG ASN A 55 -15.046 26.712 30.004 1.00 27.93 C +ATOM 873 OD1 ASN A 55 -15.779 27.576 29.490 1.00 32.07 O +ATOM 874 ND2 ASN A 55 -13.773 26.924 30.274 1.00 28.28 N +ATOM 875 H ASN A 55 -18.383 24.007 30.504 1.00 0.00 H +ATOM 876 HA ASN A 55 -17.426 25.778 29.400 1.00 0.00 H +ATOM 877 HB3 ASN A 55 -14.774 24.589 30.217 1.00 0.00 H +ATOM 878 HB2 ASN A 55 -15.868 25.286 31.388 1.00 0.00 H +ATOM 879 HD22 ASN A 55 -13.358 27.824 30.078 1.00 0.00 H +ATOM 880 HD21 ASN A 55 -13.213 26.187 30.677 1.00 0.00 H +ATOM 881 N GLY A 56 -17.095 23.961 27.303 1.00 15.08 N +ATOM 882 CA GLY A 56 -16.809 23.730 25.892 1.00 13.89 C +ATOM 883 C GLY A 56 -15.919 22.560 25.539 1.00 14.20 C +ATOM 884 O GLY A 56 -15.534 22.441 24.383 1.00 14.94 O +ATOM 885 H GLY A 56 -17.964 23.624 27.692 1.00 0.00 H +ATOM 886 HA3 GLY A 56 -16.393 24.639 25.458 1.00 0.00 H +ATOM 887 HA2 GLY A 56 -17.749 23.642 25.346 1.00 0.00 H +ATOM 888 N VAL A 57 -15.607 21.684 26.482 1.00 13.13 N +ATOM 889 CA VAL A 57 -14.712 20.570 26.252 1.00 15.26 C +ATOM 890 C VAL A 57 -15.291 19.325 26.908 1.00 14.66 C +ATOM 891 O VAL A 57 -15.808 19.403 28.030 1.00 14.94 O +ATOM 892 CB VAL A 57 -13.330 20.841 26.866 1.00 18.67 C +ATOM 893 CG1 VAL A 57 -12.347 19.766 26.450 1.00 17.30 C +ATOM 894 CG2 VAL A 57 -12.837 22.230 26.473 1.00 18.59 C +ATOM 895 H VAL A 57 -15.999 21.778 27.408 1.00 0.00 H +ATOM 896 HA VAL A 57 -14.608 20.402 25.180 1.00 0.00 H +ATOM 897 HB VAL A 57 -13.428 20.810 27.951 1.00 0.00 H +ATOM 898 HG11 VAL A 57 -11.373 19.973 26.893 1.00 0.00 H +ATOM 899 HG12 VAL A 57 -12.703 18.795 26.793 1.00 0.00 H +ATOM 900 HG13 VAL A 57 -12.257 19.756 25.364 1.00 0.00 H +ATOM 901 HG21 VAL A 57 -11.857 22.407 26.916 1.00 0.00 H +ATOM 902 HG22 VAL A 57 -12.762 22.296 25.388 1.00 0.00 H +ATOM 903 HG23 VAL A 57 -13.539 22.981 26.834 1.00 0.00 H +ATOM 904 N ILE A 58 -15.196 18.187 26.217 1.00 12.69 N +ATOM 905 CA ILE A 58 -15.671 16.916 26.754 1.00 10.27 C +ATOM 906 C ILE A 58 -14.619 15.832 26.615 1.00 13.62 C +ATOM 907 O ILE A 58 -13.596 16.028 25.938 1.00 15.19 O +ATOM 908 CB ILE A 58 -16.980 16.445 26.074 1.00 9.98 C +ATOM 909 CG1 ILE A 58 -16.755 16.154 24.572 1.00 12.05 C +ATOM 910 CG2 ILE A 58 -18.139 17.440 26.366 1.00 12.16 C +ATOM 911 CD1 ILE A 58 -18.046 15.674 23.870 1.00 12.81 C +ATOM 912 H ILE A 58 -14.786 18.189 25.294 1.00 0.00 H +ATOM 913 HA ILE A 58 -15.874 17.054 27.816 1.00 0.00 H +ATOM 914 HB ILE A 58 -17.253 15.498 26.540 1.00 0.00 H +ATOM 915 HG13 ILE A 58 -15.979 15.396 24.462 1.00 0.00 H +ATOM 916 HG12 ILE A 58 -16.388 17.054 24.079 1.00 0.00 H +ATOM 917 HG21 ILE A 58 -19.050 17.091 25.879 1.00 0.00 H +ATOM 918 HG22 ILE A 58 -18.303 17.502 27.442 1.00 0.00 H +ATOM 919 HG23 ILE A 58 -17.878 18.426 25.982 1.00 0.00 H +ATOM 920 HD11 ILE A 58 -17.838 15.482 22.817 1.00 0.00 H +ATOM 921 HD12 ILE A 58 -18.398 14.757 24.343 1.00 0.00 H +ATOM 922 HD13 ILE A 58 -18.813 16.443 23.954 1.00 0.00 H +ATOM 923 N THR A 59 -14.848 14.701 27.286 1.00 12.93 N +ATOM 924 CA THR A 59 -13.964 13.563 27.145 1.00 13.17 C +ATOM 925 C THR A 59 -14.346 12.679 25.970 1.00 14.36 C +ATOM 926 O THR A 59 -15.454 12.785 25.439 1.00 13.70 O +ATOM 927 CB THR A 59 -13.988 12.697 28.419 1.00 15.83 C +ATOM 928 OG1 THR A 59 -15.293 12.132 28.570 1.00 16.54 O +ATOM 929 CG2 THR A 59 -13.660 13.557 29.651 1.00 19.12 C +ATOM 930 H THR A 59 -15.646 14.632 27.901 1.00 0.00 H +ATOM 931 HA THR A 59 -12.948 13.928 26.991 1.00 0.00 H +ATOM 932 HB THR A 59 -13.254 11.897 28.328 1.00 0.00 H +ATOM 933 HG1 THR A 59 -15.318 11.590 29.362 1.00 0.00 H +ATOM 934 HG21 THR A 59 -13.680 12.934 30.545 1.00 0.00 H +ATOM 935 HG22 THR A 59 -12.668 13.995 29.536 1.00 0.00 H +ATOM 936 HG23 THR A 59 -14.399 14.353 29.746 1.00 0.00 H +ATOM 937 N LYS A 60 -13.433 11.804 25.560 1.00 12.86 N +ATOM 938 CA LYS A 60 -13.743 10.854 24.498 1.00 13.27 C +ATOM 939 C LYS A 60 -14.937 9.984 24.916 1.00 12.94 C +ATOM 940 O LYS A 60 -15.844 9.752 24.095 1.00 13.60 O +ATOM 941 CB LYS A 60 -12.519 10.008 24.135 1.00 18.36 C +ATOM 942 CG LYS A 60 -12.753 8.952 23.037 1.00 17.75 C +ATOM 943 CD LYS A 60 -11.440 8.345 22.519 1.00 25.78 C +ATOM 944 CE LYS A 60 -11.671 7.180 21.547 1.00 34.06 C +ATOM 945 NZ LYS A 60 -10.402 6.679 20.997 1.00 0.00 N +ATOM 946 H LYS A 60 -12.517 11.794 25.985 1.00 0.00 H +ATOM 947 HA LYS A 60 -14.034 11.421 23.614 1.00 0.00 H +ATOM 948 HB3 LYS A 60 -12.136 9.508 25.026 1.00 0.00 H +ATOM 949 HB2 LYS A 60 -11.731 10.685 23.804 1.00 0.00 H +ATOM 950 HG3 LYS A 60 -13.306 9.394 22.207 1.00 0.00 H +ATOM 951 HG2 LYS A 60 -13.384 8.153 23.430 1.00 0.00 H +ATOM 952 HD3 LYS A 60 -10.837 8.002 23.360 1.00 0.00 H +ATOM 953 HD2 LYS A 60 -10.859 9.122 22.020 1.00 0.00 H +ATOM 954 HE2 LYS A 60 -12.170 6.357 22.059 1.00 0.00 H +ATOM 955 HE3 LYS A 60 -12.312 7.490 20.722 1.00 0.00 H +ATOM 956 HZ1 LYS A 60 -9.935 7.418 20.494 1.00 0.00 H +ATOM 957 HZ2 LYS A 60 -9.810 6.359 21.748 1.00 0.00 H +ATOM 958 HZ3 LYS A 60 -10.588 5.913 20.369 1.00 0.00 H +ATOM 959 N ASP A 61 -14.993 9.524 26.175 1.00 15.96 N +ATOM 960 CA ASP A 61 -16.124 8.706 26.613 1.00 14.48 C +ATOM 961 C ASP A 61 -17.443 9.470 26.478 1.00 14.50 C +ATOM 962 O ASP A 61 -18.470 8.900 26.075 1.00 13.50 O +ATOM 963 CB ASP A 61 -15.953 8.222 28.063 1.00 16.03 C +ATOM 964 CG ASP A 61 -14.790 7.261 28.234 1.00 22.87 C +ATOM 965 OD1 ASP A 61 -14.221 6.793 27.225 1.00 29.56 O +ATOM 966 OD2 ASP A 61 -14.447 6.976 29.400 1.00 30.48 O +ATOM 967 H ASP A 61 -14.252 9.742 26.826 1.00 0.00 H +ATOM 968 HA ASP A 61 -16.175 7.828 25.968 1.00 0.00 H +ATOM 969 HB3 ASP A 61 -16.873 7.740 28.395 1.00 0.00 H +ATOM 970 HB2 ASP A 61 -15.811 9.082 28.717 1.00 0.00 H +ATOM 971 N GLU A 62 -17.418 10.766 26.815 1.00 12.20 N +ATOM 972 CA GLU A 62 -18.623 11.587 26.698 1.00 10.60 C +ATOM 973 C GLU A 62 -19.042 11.752 25.237 1.00 10.82 C +ATOM 974 O GLU A 62 -20.238 11.656 24.921 1.00 11.11 O +ATOM 975 CB GLU A 62 -18.419 12.949 27.369 1.00 10.33 C +ATOM 976 CG GLU A 62 -18.495 12.829 28.890 1.00 13.53 C +ATOM 977 CD GLU A 62 -17.948 14.024 29.608 1.00 17.67 C +ATOM 978 OE1 GLU A 62 -17.246 14.846 28.998 1.00 15.15 O +ATOM 979 OE2 GLU A 62 -18.206 14.115 30.838 1.00 17.19 O +ATOM 980 H GLU A 62 -16.563 11.184 27.153 1.00 0.00 H +ATOM 981 HA GLU A 62 -19.430 11.074 27.221 1.00 0.00 H +ATOM 982 HB3 GLU A 62 -19.184 13.643 27.021 1.00 0.00 H +ATOM 983 HB2 GLU A 62 -17.447 13.351 27.085 1.00 0.00 H +ATOM 984 HG3 GLU A 62 -17.957 11.937 29.210 1.00 0.00 H +ATOM 985 HG2 GLU A 62 -19.531 12.670 29.189 1.00 0.00 H +ATOM 986 N ALA A 63 -18.064 11.976 24.362 1.00 11.65 N +ATOM 987 CA ALA A 63 -18.372 12.061 22.937 1.00 9.70 C +ATOM 988 C ALA A 63 -18.990 10.767 22.433 1.00 9.60 C +ATOM 989 O ALA A 63 -19.931 10.799 21.646 1.00 10.05 O +ATOM 990 CB ALA A 63 -17.121 12.403 22.162 1.00 10.52 C +ATOM 991 H ALA A 63 -17.113 12.086 24.685 1.00 0.00 H +ATOM 992 HA ALA A 63 -19.094 12.864 22.791 1.00 0.00 H +ATOM 993 HB1 ALA A 63 -17.357 12.465 21.100 1.00 0.00 H +ATOM 994 HB2 ALA A 63 -16.732 13.362 22.504 1.00 0.00 H +ATOM 995 HB3 ALA A 63 -16.371 11.629 22.322 1.00 0.00 H +ATOM 996 N GLU A 64 -18.453 9.632 22.874 1.00 10.57 N +ATOM 997 CA GLU A 64 -18.968 8.341 22.401 1.00 8.80 C +ATOM 998 C GLU A 64 -20.373 8.092 22.937 1.00 8.68 C +ATOM 999 O GLU A 64 -21.231 7.530 22.244 1.00 10.71 O +ATOM 1000 CB GLU A 64 -17.987 7.206 22.749 1.00 12.16 C +ATOM 1001 CG GLU A 64 -16.738 7.326 21.875 1.00 13.40 C +ATOM 1002 CD GLU A 64 -15.607 6.433 22.328 1.00 25.53 C +ATOM 1003 OE1 GLU A 64 -15.646 5.936 23.489 1.00 24.40 O +ATOM 1004 OE2 GLU A 64 -14.683 6.234 21.507 1.00 25.71 O +ATOM 1005 H GLU A 64 -17.690 9.658 23.535 1.00 0.00 H +ATOM 1006 HA GLU A 64 -19.036 8.394 21.314 1.00 0.00 H +ATOM 1007 HB3 GLU A 64 -18.466 6.244 22.568 1.00 0.00 H +ATOM 1008 HB2 GLU A 64 -17.704 7.280 23.799 1.00 0.00 H +ATOM 1009 HG3 GLU A 64 -16.400 8.362 21.867 1.00 0.00 H +ATOM 1010 HG2 GLU A 64 -16.995 7.089 20.842 1.00 0.00 H +ATOM 1011 N LYS A 65 -20.657 8.567 24.156 1.00 8.59 N +ATOM 1012 CA LYS A 65 -22.005 8.416 24.690 1.00 9.23 C +ATOM 1013 C LYS A 65 -23.029 9.238 23.883 1.00 8.94 C +ATOM 1014 O LYS A 65 -24.112 8.744 23.545 1.00 10.90 O +ATOM 1015 CB LYS A 65 -22.064 8.770 26.185 1.00 11.14 C +ATOM 1016 CG LYS A 65 -23.406 8.431 26.778 1.00 13.37 C +ATOM 1017 CD LYS A 65 -23.389 8.594 28.297 1.00 17.26 C +ATOM 1018 CE LYS A 65 -24.693 8.090 28.917 1.00 18.99 C +ATOM 1019 NZ LYS A 65 -24.538 8.220 30.401 1.00 18.36 N +ATOM 1020 H LYS A 65 -19.940 9.026 24.699 1.00 0.00 H +ATOM 1021 HA LYS A 65 -22.279 7.366 24.592 1.00 0.00 H +ATOM 1022 HB3 LYS A 65 -21.869 9.835 26.314 1.00 0.00 H +ATOM 1023 HB2 LYS A 65 -21.284 8.226 26.718 1.00 0.00 H +ATOM 1024 HG3 LYS A 65 -23.665 7.402 26.526 1.00 0.00 H +ATOM 1025 HG2 LYS A 65 -24.167 9.085 26.351 1.00 0.00 H +ATOM 1026 HD3 LYS A 65 -23.251 9.646 28.548 1.00 0.00 H +ATOM 1027 HD2 LYS A 65 -22.550 8.036 28.713 1.00 0.00 H +ATOM 1028 HE3 LYS A 65 -24.836 7.041 28.658 1.00 0.00 H +ATOM 1029 HE2 LYS A 65 -25.519 8.717 28.583 1.00 0.00 H +ATOM 1030 HZ1 LYS A 65 -25.379 7.897 30.857 1.00 0.00 H +ATOM 1031 HZ2 LYS A 65 -23.754 7.662 30.708 1.00 0.00 H +ATOM 1032 HZ3 LYS A 65 -24.376 9.188 30.640 1.00 0.00 H +ATOM 1033 N LEU A 66 -22.690 10.497 23.582 1.00 9.21 N +ATOM 1034 CA LEU A 66 -23.551 11.302 22.703 1.00 9.60 C +ATOM 1035 C LEU A 66 -23.745 10.609 21.374 1.00 8.90 C +ATOM 1036 O LEU A 66 -24.833 10.624 20.825 1.00 9.35 O +ATOM 1037 CB LEU A 66 -22.964 12.709 22.440 1.00 9.27 C +ATOM 1038 CG LEU A 66 -22.869 13.635 23.670 1.00 11.73 C +ATOM 1039 CD1 LEU A 66 -22.180 14.953 23.272 1.00 15.24 C +ATOM 1040 CD2 LEU A 66 -24.227 13.902 24.311 1.00 13.78 C +ATOM 1041 H LEU A 66 -21.842 10.895 23.959 1.00 0.00 H +ATOM 1042 HA LEU A 66 -24.524 11.416 23.180 1.00 0.00 H +ATOM 1043 HB3 LEU A 66 -23.547 13.202 21.662 1.00 0.00 H +ATOM 1044 HB2 LEU A 66 -21.977 12.609 21.988 1.00 0.00 H +ATOM 1045 HG LEU A 66 -22.241 13.141 24.412 1.00 0.00 H +ATOM 1046 HD11 LEU A 66 -22.114 15.606 24.142 1.00 0.00 H +ATOM 1047 HD12 LEU A 66 -21.178 14.742 22.900 1.00 0.00 H +ATOM 1048 HD13 LEU A 66 -22.760 15.446 22.492 1.00 0.00 H +ATOM 1049 HD21 LEU A 66 -24.100 14.559 25.171 1.00 0.00 H +ATOM 1050 HD22 LEU A 66 -24.885 14.379 23.584 1.00 0.00 H +ATOM 1051 HD23 LEU A 66 -24.668 12.959 24.636 1.00 0.00 H +ATOM 1052 N PHE A 67 -22.659 10.035 20.847 1.00 8.47 N +ATOM 1053 CA PHE A 67 -22.735 9.375 19.545 1.00 8.10 C +ATOM 1054 C PHE A 67 -23.693 8.184 19.599 1.00 9.11 C +ATOM 1055 O PHE A 67 -24.535 8.013 18.693 1.00 10.09 O +ATOM 1056 CB PHE A 67 -21.324 8.931 19.177 1.00 9.68 C +ATOM 1057 CG PHE A 67 -21.154 8.365 17.772 1.00 9.98 C +ATOM 1058 CD1 PHE A 67 -21.860 8.857 16.677 1.00 10.06 C +ATOM 1059 CD2 PHE A 67 -20.208 7.389 17.562 1.00 10.45 C +ATOM 1060 CE1 PHE A 67 -21.659 8.320 15.396 1.00 9.50 C +ATOM 1061 CE2 PHE A 67 -19.971 6.893 16.265 1.00 10.87 C +ATOM 1062 CZ PHE A 67 -20.709 7.372 15.194 1.00 9.01 C +ATOM 1063 H PHE A 67 -21.783 10.057 21.349 1.00 0.00 H +ATOM 1064 HA PHE A 67 -23.092 10.088 18.802 1.00 0.00 H +ATOM 1065 HB3 PHE A 67 -20.976 8.198 19.905 1.00 0.00 H +ATOM 1066 HB2 PHE A 67 -20.637 9.766 19.314 1.00 0.00 H +ATOM 1067 HD1 PHE A 67 -22.570 9.660 16.809 1.00 0.00 H +ATOM 1068 HD2 PHE A 67 -19.641 6.998 18.394 1.00 0.00 H +ATOM 1069 HE1 PHE A 67 -22.261 8.661 14.567 1.00 0.00 H +ATOM 1070 HE2 PHE A 67 -19.214 6.139 16.105 1.00 0.00 H +ATOM 1071 HZ PHE A 67 -20.529 6.992 14.199 1.00 0.00 H +ATOM 1072 N ASN A 68 -23.624 7.378 20.656 1.00 9.18 N +ATOM 1073 CA ASN A 68 -24.568 6.274 20.818 1.00 10.37 C +ATOM 1074 C ASN A 68 -26.009 6.794 20.835 1.00 10.21 C +ATOM 1075 O ASN A 68 -26.941 6.250 20.190 1.00 11.12 O +ATOM 1076 CB ASN A 68 -24.280 5.511 22.133 1.00 11.15 C +ATOM 1077 CG ASN A 68 -23.084 4.578 22.019 1.00 13.70 C +ATOM 1078 OD1 ASN A 68 -22.848 4.011 20.962 1.00 16.16 O +ATOM 1079 ND2 ASN A 68 -22.340 4.395 23.112 1.00 15.00 N +ATOM 1080 H ASN A 68 -22.913 7.526 21.358 1.00 0.00 H +ATOM 1081 HA ASN A 68 -24.452 5.587 19.980 1.00 0.00 H +ATOM 1082 HB3 ASN A 68 -25.161 4.937 22.419 1.00 0.00 H +ATOM 1083 HB2 ASN A 68 -24.106 6.227 22.936 1.00 0.00 H +ATOM 1084 HD22 ASN A 68 -21.537 3.784 23.080 1.00 0.00 H +ATOM 1085 HD21 ASN A 68 -22.580 4.868 23.971 1.00 0.00 H +ATOM 1086 N GLN A 69 -26.217 7.865 21.605 1.00 9.54 N +ATOM 1087 CA GLN A 69 -27.548 8.463 21.655 1.00 9.43 C +ATOM 1088 C GLN A 69 -28.023 8.964 20.310 1.00 8.36 C +ATOM 1089 O GLN A 69 -29.195 8.816 19.960 1.00 11.79 O +ATOM 1090 CB GLN A 69 -27.587 9.615 22.672 1.00 9.12 C +ATOM 1091 CG GLN A 69 -27.373 9.134 24.093 1.00 9.40 C +ATOM 1092 CD GLN A 69 -27.226 10.254 25.092 1.00 10.92 C +ATOM 1093 OE1 GLN A 69 -27.133 11.451 24.715 1.00 15.00 O +ATOM 1094 NE2 GLN A 69 -27.205 9.885 26.356 1.00 10.61 N +ATOM 1095 H GLN A 69 -25.457 8.254 22.146 1.00 0.00 H +ATOM 1096 HA GLN A 69 -28.246 7.697 21.992 1.00 0.00 H +ATOM 1097 HB3 GLN A 69 -28.547 10.127 22.603 1.00 0.00 H +ATOM 1098 HB2 GLN A 69 -26.822 10.348 22.418 1.00 0.00 H +ATOM 1099 HG3 GLN A 69 -26.489 8.498 24.130 1.00 0.00 H +ATOM 1100 HG2 GLN A 69 -28.205 8.494 24.387 1.00 0.00 H +ATOM 1101 HE22 GLN A 69 -27.109 10.579 27.083 1.00 0.00 H +ATOM 1102 HE21 GLN A 69 -27.285 8.908 26.598 1.00 0.00 H +ATOM 1103 N ASP A 70 -27.109 9.570 19.552 1.00 8.67 N +ATOM 1104 CA ASP A 70 -27.476 10.146 18.271 1.00 9.60 C +ATOM 1105 C ASP A 70 -27.764 9.090 17.193 1.00 9.14 C +ATOM 1106 O ASP A 70 -28.678 9.274 16.387 1.00 10.19 O +ATOM 1107 CB ASP A 70 -26.365 11.098 17.807 1.00 9.50 C +ATOM 1108 CG ASP A 70 -26.265 12.344 18.675 1.00 13.75 C +ATOM 1109 OD1 ASP A 70 -27.259 12.674 19.382 1.00 14.04 O +ATOM 1110 OD2 ASP A 70 -25.198 13.006 18.617 1.00 12.70 O +ATOM 1111 H ASP A 70 -26.152 9.631 19.867 1.00 0.00 H +ATOM 1112 HA ASP A 70 -28.383 10.734 18.415 1.00 0.00 H +ATOM 1113 HB3 ASP A 70 -26.547 11.390 16.773 1.00 0.00 H +ATOM 1114 HB2 ASP A 70 -25.410 10.572 17.816 1.00 0.00 H +ATOM 1115 N VAL A 71 -26.993 8.012 17.195 1.00 8.04 N +ATOM 1116 CA VAL A 71 -27.285 6.901 16.262 1.00 7.36 C +ATOM 1117 C VAL A 71 -28.632 6.273 16.622 1.00 9.63 C +ATOM 1118 O VAL A 71 -29.470 6.020 15.725 1.00 11.14 O +ATOM 1119 CB VAL A 71 -26.157 5.875 16.287 1.00 9.56 C +ATOM 1120 CG1 VAL A 71 -26.550 4.658 15.436 1.00 11.37 C +ATOM 1121 CG2 VAL A 71 -24.865 6.501 15.691 1.00 11.28 C +ATOM 1122 H VAL A 71 -26.211 7.952 17.831 1.00 0.00 H +ATOM 1123 HA VAL A 71 -27.355 7.309 15.254 1.00 0.00 H +ATOM 1124 HB VAL A 71 -25.971 5.560 17.314 1.00 0.00 H +ATOM 1125 HG11 VAL A 71 -25.743 3.925 15.454 1.00 0.00 H +ATOM 1126 HG12 VAL A 71 -27.457 4.209 15.840 1.00 0.00 H +ATOM 1127 HG13 VAL A 71 -26.729 4.975 14.409 1.00 0.00 H +ATOM 1128 HG21 VAL A 71 -24.061 5.765 15.711 1.00 0.00 H +ATOM 1129 HG22 VAL A 71 -25.051 6.808 14.662 1.00 0.00 H +ATOM 1130 HG23 VAL A 71 -24.576 7.370 16.282 1.00 0.00 H +ATOM 1131 N ASP A 72 -28.852 6.028 17.921 1.00 11.74 N +ATOM 1132 CA ASP A 72 -30.135 5.474 18.372 1.00 12.78 C +ATOM 1133 C ASP A 72 -31.273 6.402 17.910 1.00 12.10 C +ATOM 1134 O ASP A 72 -32.273 5.958 17.327 1.00 12.65 O +ATOM 1135 CB ASP A 72 -30.050 5.339 19.905 1.00 12.30 C +ATOM 1136 CG ASP A 72 -31.217 4.598 20.532 1.00 24.33 C +ATOM 1137 OD1 ASP A 72 -30.978 3.848 21.505 1.00 22.75 O +ATOM 1138 OD2 ASP A 72 -32.364 4.811 20.133 1.00 20.00 O +ATOM 1139 H ASP A 72 -28.132 6.224 18.601 1.00 0.00 H +ATOM 1140 HA ASP A 72 -30.275 4.487 17.931 1.00 0.00 H +ATOM 1141 HB3 ASP A 72 -29.970 6.330 20.351 1.00 0.00 H +ATOM 1142 HB2 ASP A 72 -29.119 4.839 20.172 1.00 0.00 H +ATOM 1143 N ALA A 73 -31.119 7.711 18.092 1.00 11.70 N +ATOM 1144 CA ALA A 73 -32.156 8.643 17.684 1.00 12.52 C +ATOM 1145 C ALA A 73 -32.415 8.632 16.180 1.00 10.84 C +ATOM 1146 O ALA A 73 -33.569 8.783 15.732 1.00 13.50 O +ATOM 1147 CB ALA A 73 -31.817 10.077 18.167 1.00 14.90 C +ATOM 1148 H ALA A 73 -30.275 8.066 18.518 1.00 0.00 H +ATOM 1149 HA ALA A 73 -33.080 8.341 18.177 1.00 0.00 H +ATOM 1150 HB1 ALA A 73 -32.604 10.762 17.853 1.00 0.00 H +ATOM 1151 HB2 ALA A 73 -31.741 10.086 19.254 1.00 0.00 H +ATOM 1152 HB3 ALA A 73 -30.868 10.392 17.734 1.00 0.00 H +ATOM 1153 N ALA A 74 -31.365 8.468 15.385 1.00 10.62 N +ATOM 1154 CA ALA A 74 -31.549 8.397 13.938 1.00 10.40 C +ATOM 1155 C ALA A 74 -32.335 7.153 13.556 1.00 9.15 C +ATOM 1156 O ALA A 74 -33.238 7.230 12.726 1.00 11.54 O +ATOM 1157 CB ALA A 74 -30.197 8.400 13.233 1.00 10.80 C +ATOM 1158 H ALA A 74 -30.439 8.392 15.781 1.00 0.00 H +ATOM 1159 HA ALA A 74 -32.110 9.274 13.616 1.00 0.00 H +ATOM 1160 HB1 ALA A 74 -30.349 8.347 12.155 1.00 0.00 H +ATOM 1161 HB2 ALA A 74 -29.660 9.316 13.479 1.00 0.00 H +ATOM 1162 HB3 ALA A 74 -29.614 7.539 13.560 1.00 0.00 H +ATOM 1163 N VAL A 75 -31.985 6.019 14.166 1.00 9.68 N +ATOM 1164 CA VAL A 75 -32.725 4.790 13.875 1.00 10.83 C +ATOM 1165 C VAL A 75 -34.179 4.914 14.316 1.00 12.27 C +ATOM 1166 O VAL A 75 -35.091 4.540 13.570 1.00 12.69 O +ATOM 1167 CB VAL A 75 -32.092 3.600 14.587 1.00 10.11 C +ATOM 1168 CG1 VAL A 75 -32.991 2.360 14.432 1.00 15.66 C +ATOM 1169 CG2 VAL A 75 -30.686 3.296 14.025 1.00 12.06 C +ATOM 1170 H VAL A 75 -31.216 6.014 14.821 1.00 0.00 H +ATOM 1171 HA VAL A 75 -32.698 4.611 12.800 1.00 0.00 H +ATOM 1172 HB VAL A 75 -32.001 3.835 15.647 1.00 0.00 H +ATOM 1173 HG11 VAL A 75 -32.534 1.513 14.943 1.00 0.00 H +ATOM 1174 HG12 VAL A 75 -33.969 2.562 14.869 1.00 0.00 H +ATOM 1175 HG13 VAL A 75 -33.108 2.126 13.374 1.00 0.00 H +ATOM 1176 HG21 VAL A 75 -30.260 2.442 14.552 1.00 0.00 H +ATOM 1177 HG22 VAL A 75 -30.761 3.065 12.962 1.00 0.00 H +ATOM 1178 HG23 VAL A 75 -30.043 4.165 14.163 1.00 0.00 H +ATOM 1179 N ARG A 76 -34.415 5.436 15.512 1.00 13.54 N +ATOM 1180 CA ARG A 76 -35.799 5.645 15.945 1.00 16.29 C +ATOM 1181 C ARG A 76 -36.573 6.596 15.059 1.00 15.54 C +ATOM 1182 O ARG A 76 -37.773 6.388 14.816 1.00 17.25 O +ATOM 1183 CB ARG A 76 -35.800 6.168 17.368 1.00 17.73 C +ATOM 1184 CG ARG A 76 -35.399 5.116 18.310 1.00 23.50 C +ATOM 1185 CD ARG A 76 -35.986 5.413 19.660 1.00 34.26 C +ATOM 1186 NE ARG A 76 -35.424 4.543 20.677 1.00 26.07 N +ATOM 1187 CZ ARG A 76 -36.040 3.475 21.168 1.00 33.24 C +ATOM 1188 NH1 ARG A 76 -37.245 3.124 20.733 1.00 27.55 N +ATOM 1189 NH2 ARG A 76 -35.439 2.757 22.098 1.00 19.80 N +ATOM 1190 H ARG A 76 -33.644 5.686 16.115 1.00 0.00 H +ATOM 1191 HA ARG A 76 -36.308 4.681 15.936 1.00 0.00 H +ATOM 1192 HB3 ARG A 76 -36.798 6.523 17.624 1.00 0.00 H +ATOM 1193 HB2 ARG A 76 -35.110 7.008 17.446 1.00 0.00 H +ATOM 1194 HG3 ARG A 76 -34.312 5.090 18.384 1.00 0.00 H +ATOM 1195 HG2 ARG A 76 -35.768 4.153 17.957 1.00 0.00 H +ATOM 1196 HD3 ARG A 76 -37.067 5.277 19.623 1.00 0.00 H +ATOM 1197 HD2 ARG A 76 -35.787 6.452 19.921 1.00 0.00 H +ATOM 1198 HE ARG A 76 -34.504 4.794 21.011 1.00 0.00 H +ATOM 1199 HH12 ARG A 76 -37.702 2.309 21.116 1.00 0.00 H +ATOM 1200 HH11 ARG A 76 -37.704 3.672 20.020 1.00 0.00 H +ATOM 1201 HH21 ARG A 76 -35.896 1.942 22.481 1.00 0.00 H +ATOM 1202 HH22 ARG A 76 -34.522 3.023 22.427 1.00 0.00 H +ATOM 1203 N GLY A 77 -35.910 7.628 14.557 1.00 13.54 N +ATOM 1204 CA GLY A 77 -36.538 8.578 13.665 1.00 15.72 C +ATOM 1205 C GLY A 77 -37.005 7.898 12.390 1.00 17.32 C +ATOM 1206 O GLY A 77 -38.089 8.171 11.866 1.00 18.78 O +ATOM 1207 H GLY A 77 -34.938 7.768 14.795 1.00 0.00 H +ATOM 1208 HA3 GLY A 77 -35.828 9.367 13.416 1.00 0.00 H +ATOM 1209 HA2 GLY A 77 -37.391 9.036 14.165 1.00 0.00 H +ATOM 1210 N ILE A 78 -36.183 6.986 11.886 1.00 10.94 N +ATOM 1211 CA ILE A 78 -36.582 6.222 10.734 1.00 10.92 C +ATOM 1212 C ILE A 78 -37.774 5.324 11.043 1.00 13.98 C +ATOM 1213 O ILE A 78 -38.724 5.283 10.265 1.00 13.18 O +ATOM 1214 CB ILE A 78 -35.401 5.380 10.249 1.00 10.52 C +ATOM 1215 CG1 ILE A 78 -34.371 6.290 9.581 1.00 10.56 C +ATOM 1216 CG2 ILE A 78 -35.879 4.318 9.244 1.00 12.09 C +ATOM 1217 CD1 ILE A 78 -33.038 5.601 9.375 1.00 13.01 C +ATOM 1218 H ILE A 78 -35.280 6.830 12.311 1.00 0.00 H +ATOM 1219 HA ILE A 78 -36.865 6.913 9.940 1.00 0.00 H +ATOM 1220 HB ILE A 78 -34.940 4.884 11.103 1.00 0.00 H +ATOM 1221 HG13 ILE A 78 -34.227 7.183 10.190 1.00 0.00 H +ATOM 1222 HG12 ILE A 78 -34.756 6.629 8.619 1.00 0.00 H +ATOM 1223 HG21 ILE A 78 -35.028 3.726 8.907 1.00 0.00 H +ATOM 1224 HG22 ILE A 78 -36.608 3.665 9.724 1.00 0.00 H +ATOM 1225 HG23 ILE A 78 -36.341 4.809 8.388 1.00 0.00 H +ATOM 1226 HD11 ILE A 78 -32.342 6.291 8.897 1.00 0.00 H +ATOM 1227 HD12 ILE A 78 -32.636 5.290 10.339 1.00 0.00 H +ATOM 1228 HD13 ILE A 78 -33.175 4.726 8.740 1.00 0.00 H +ATOM 1229 N LEU A 79 -37.701 4.593 12.150 1.00 13.17 N +ATOM 1230 CA LEU A 79 -38.764 3.625 12.454 1.00 13.04 C +ATOM 1231 C LEU A 79 -40.103 4.286 12.746 1.00 18.80 C +ATOM 1232 O LEU A 79 -41.164 3.680 12.486 1.00 18.83 O +ATOM 1233 CB LEU A 79 -38.355 2.709 13.602 1.00 15.18 C +ATOM 1234 CG LEU A 79 -37.135 1.833 13.323 1.00 17.34 C +ATOM 1235 CD1 LEU A 79 -36.760 1.007 14.564 1.00 23.27 C +ATOM 1236 CD2 LEU A 79 -37.294 0.919 12.101 1.00 22.50 C +ATOM 1237 H LEU A 79 -36.918 4.704 12.778 1.00 0.00 H +ATOM 1238 HA LEU A 79 -38.896 3.000 11.571 1.00 0.00 H +ATOM 1239 HB3 LEU A 79 -39.199 2.076 13.876 1.00 0.00 H +ATOM 1240 HB2 LEU A 79 -38.172 3.308 14.494 1.00 0.00 H +ATOM 1241 HG LEU A 79 -36.299 2.502 13.118 1.00 0.00 H +ATOM 1242 HD11 LEU A 79 -35.889 0.391 14.341 1.00 0.00 H +ATOM 1243 HD12 LEU A 79 -36.528 1.678 15.391 1.00 0.00 H +ATOM 1244 HD13 LEU A 79 -37.597 0.365 14.841 1.00 0.00 H +ATOM 1245 HD21 LEU A 79 -36.387 0.329 11.968 1.00 0.00 H +ATOM 1246 HD22 LEU A 79 -38.142 0.252 12.254 1.00 0.00 H +ATOM 1247 HD23 LEU A 79 -37.465 1.526 11.212 1.00 0.00 H +ATOM 1248 N ARG A 80 -40.083 5.526 13.226 1.00 15.28 N +ATOM 1249 CA ARG A 80 -41.337 6.245 13.505 1.00 15.76 C +ATOM 1250 C ARG A 80 -41.918 7.005 12.313 1.00 20.51 C +ATOM 1251 O ARG A 80 -43.014 7.580 12.396 1.00 21.93 O +ATOM 1252 CB ARG A 80 -41.143 7.222 14.681 1.00 20.11 C +ATOM 1253 CG ARG A 80 -40.331 8.493 14.390 1.00 0.00 C +ATOM 1254 CD ARG A 80 -39.956 9.268 15.657 1.00 0.00 C +ATOM 1255 NE ARG A 80 -39.307 10.536 15.315 1.00 0.00 N +ATOM 1256 CZ ARG A 80 -38.760 11.423 16.155 1.00 0.00 C +ATOM 1257 NH1 ARG A 80 -38.814 11.258 17.481 1.00 0.00 N +ATOM 1258 NH2 ARG A 80 -38.147 12.485 15.632 1.00 0.00 N +ATOM 1259 H ARG A 80 -39.201 5.985 13.403 1.00 0.00 H +ATOM 1260 HA ARG A 80 -42.076 5.506 13.813 1.00 0.00 H +ATOM 1261 HB2 ARG A 80 -42.125 7.526 15.046 1.00 0.00 H +ATOM 1262 HB3 ARG A 80 -40.681 6.679 15.507 1.00 0.00 H +ATOM 1263 HG2 ARG A 80 -39.407 8.135 13.955 1.00 0.00 H +ATOM 1264 HG3 ARG A 80 -40.779 9.146 13.639 1.00 0.00 H +ATOM 1265 HD2 ARG A 80 -40.789 9.374 16.351 1.00 0.00 H +ATOM 1266 HD3 ARG A 80 -39.178 8.705 16.176 1.00 0.00 H +ATOM 1267 HE ARG A 80 -39.206 10.732 14.316 1.00 0.00 H +ATOM 1268 HH11 ARG A 80 -38.397 11.930 18.108 1.00 0.00 H +ATOM 1269 HH12 ARG A 80 -39.281 10.457 17.877 1.00 0.00 H +ATOM 1270 HH21 ARG A 80 -37.714 13.195 16.204 1.00 0.00 H +ATOM 1271 HH22 ARG A 80 -38.088 12.555 14.619 1.00 0.00 H +ATOM 1272 N ASN A 81 -41.193 7.058 11.201 1.00 15.53 N +ATOM 1273 CA ASN A 81 -41.605 7.886 10.100 1.00 13.88 C +ATOM 1274 C ASN A 81 -42.251 7.027 9.030 1.00 15.86 C +ATOM 1275 O ASN A 81 -41.647 6.091 8.515 1.00 16.04 O +ATOM 1276 CB ASN A 81 -40.376 8.613 9.529 1.00 16.21 C +ATOM 1277 CG ASN A 81 -40.736 9.611 8.461 1.00 19.59 C +ATOM 1278 OD1 ASN A 81 -41.071 9.238 7.337 1.00 19.84 O +ATOM 1279 ND2 ASN A 81 -40.623 10.896 8.788 1.00 20.64 N +ATOM 1280 H ASN A 81 -40.345 6.514 11.124 1.00 0.00 H +ATOM 1281 HA ASN A 81 -42.326 8.623 10.454 1.00 0.00 H +ATOM 1282 HB3 ASN A 81 -39.679 7.881 9.121 1.00 0.00 H +ATOM 1283 HB2 ASN A 81 -39.848 9.121 10.336 1.00 0.00 H +ATOM 1284 HD22 ASN A 81 -40.851 11.611 8.112 1.00 0.00 H +ATOM 1285 HD21 ASN A 81 -40.310 11.156 9.712 1.00 0.00 H +ATOM 1286 N ALA A 82 -43.488 7.344 8.676 1.00 18.97 N +ATOM 1287 CA ALA A 82 -44.223 6.489 7.763 1.00 19.91 C +ATOM 1288 C ALA A 82 -43.641 6.424 6.355 1.00 17.00 C +ATOM 1289 O ALA A 82 -43.895 5.445 5.625 1.00 20.50 O +ATOM 1290 CB ALA A 82 -45.687 6.945 7.710 1.00 23.17 C +ATOM 1291 H ALA A 82 -43.919 8.181 9.042 1.00 0.00 H +ATOM 1292 HA ALA A 82 -44.207 5.479 8.173 1.00 0.00 H +ATOM 1293 HB1 ALA A 82 -46.243 6.305 7.025 1.00 0.00 H +ATOM 1294 HB2 ALA A 82 -46.125 6.878 8.706 1.00 0.00 H +ATOM 1295 HB3 ALA A 82 -45.734 7.977 7.362 1.00 0.00 H +ATOM 1296 N LYS A 83 -42.882 7.449 5.961 1.00 16.57 N +ATOM 1297 CA LYS A 83 -42.227 7.458 4.650 1.00 15.12 C +ATOM 1298 C LYS A 83 -40.915 6.697 4.676 1.00 16.62 C +ATOM 1299 O LYS A 83 -40.552 6.013 3.709 1.00 21.55 O +ATOM 1300 CB LYS A 83 -41.971 8.880 4.139 1.00 20.93 C +ATOM 1301 CG LYS A 83 -43.232 9.651 3.756 1.00 29.65 C +ATOM 1302 CD LYS A 83 -42.859 10.908 2.966 1.00 27.41 C +ATOM 1303 CE LYS A 83 -42.054 10.558 1.710 1.00 25.99 C +ATOM 1304 NZ LYS A 83 -41.733 11.737 0.851 1.00 20.47 N +ATOM 1305 H LYS A 83 -42.748 8.242 6.572 1.00 0.00 H +ATOM 1306 HA LYS A 83 -42.889 6.961 3.941 1.00 0.00 H +ATOM 1307 HB3 LYS A 83 -41.298 8.840 3.282 1.00 0.00 H +ATOM 1308 HB2 LYS A 83 -41.420 9.441 4.894 1.00 0.00 H +ATOM 1309 HG3 LYS A 83 -43.771 9.937 4.659 1.00 0.00 H +ATOM 1310 HG2 LYS A 83 -43.874 9.016 3.146 1.00 0.00 H +ATOM 1311 HD3 LYS A 83 -42.272 11.574 3.599 1.00 0.00 H +ATOM 1312 HD2 LYS A 83 -43.767 11.439 2.679 1.00 0.00 H +ATOM 1313 HE3 LYS A 83 -42.602 9.821 1.123 1.00 0.00 H +ATOM 1314 HE2 LYS A 83 -41.129 10.060 2.001 1.00 0.00 H +ATOM 1315 HZ1 LYS A 83 -41.204 11.433 0.046 1.00 0.00 H +ATOM 1316 HZ2 LYS A 83 -42.590 12.174 0.545 1.00 0.00 H +ATOM 1317 HZ3 LYS A 83 -41.187 12.401 1.381 1.00 0.00 H +ATOM 1318 N LEU A 84 -40.212 6.766 5.797 1.00 11.62 N +ATOM 1319 CA LEU A 84 -38.883 6.177 5.848 1.00 11.69 C +ATOM 1320 C LEU A 84 -38.878 4.709 6.237 1.00 10.57 C +ATOM 1321 O LEU A 84 -38.112 3.921 5.688 1.00 11.67 O +ATOM 1322 CB LEU A 84 -37.993 6.936 6.846 1.00 9.65 C +ATOM 1323 CG LEU A 84 -37.745 8.409 6.463 1.00 12.18 C +ATOM 1324 CD1 LEU A 84 -36.910 9.087 7.566 1.00 12.42 C +ATOM 1325 CD2 LEU A 84 -37.084 8.614 5.093 1.00 15.80 C +ATOM 1326 H LEU A 84 -40.600 7.225 6.609 1.00 0.00 H +ATOM 1327 HA LEU A 84 -38.435 6.267 4.858 1.00 0.00 H +ATOM 1328 HB3 LEU A 84 -37.037 6.421 6.942 1.00 0.00 H +ATOM 1329 HB2 LEU A 84 -38.442 6.891 7.838 1.00 0.00 H +ATOM 1330 HG LEU A 84 -38.714 8.907 6.435 1.00 0.00 H +ATOM 1331 HD11 LEU A 84 -36.732 10.129 7.299 1.00 0.00 H +ATOM 1332 HD12 LEU A 84 -37.451 9.042 8.511 1.00 0.00 H +ATOM 1333 HD13 LEU A 84 -35.955 8.571 7.669 1.00 0.00 H +ATOM 1334 HD21 LEU A 84 -36.949 9.680 4.910 1.00 0.00 H +ATOM 1335 HD22 LEU A 84 -36.113 8.118 5.079 1.00 0.00 H +ATOM 1336 HD23 LEU A 84 -37.719 8.190 4.315 1.00 0.00 H +ATOM 1337 N LYS A 85 -39.722 4.329 7.179 1.00 11.05 N +ATOM 1338 CA LYS A 85 -39.695 2.955 7.658 1.00 10.94 C +ATOM 1339 C LYS A 85 -39.860 1.897 6.561 1.00 11.57 C +ATOM 1340 O LYS A 85 -39.077 0.955 6.526 1.00 11.30 O +ATOM 1341 CB LYS A 85 -40.727 2.716 8.768 1.00 13.11 C +ATOM 1342 CG LYS A 85 -40.594 1.314 9.362 1.00 15.03 C +ATOM 1343 CD LYS A 85 -41.516 1.097 10.546 1.00 20.58 C +ATOM 1344 CE LYS A 85 -41.225 -0.271 11.196 1.00 25.27 C +ATOM 1345 NZ LYS A 85 -41.664 -1.401 10.351 1.00 31.47 N +ATOM 1346 H LYS A 85 -40.381 4.991 7.563 1.00 0.00 H +ATOM 1347 HA LYS A 85 -38.713 2.796 8.103 1.00 0.00 H +ATOM 1348 HB3 LYS A 85 -41.731 2.845 8.364 1.00 0.00 H +ATOM 1349 HB2 LYS A 85 -40.592 3.458 9.555 1.00 0.00 H +ATOM 1350 HG3 LYS A 85 -39.562 1.148 9.671 1.00 0.00 H +ATOM 1351 HG2 LYS A 85 -40.811 0.573 8.593 1.00 0.00 H +ATOM 1352 HD3 LYS A 85 -42.552 1.126 10.209 1.00 0.00 H +ATOM 1353 HD2 LYS A 85 -41.358 1.888 11.279 1.00 0.00 H +ATOM 1354 HE3 LYS A 85 -41.725 -0.326 12.163 1.00 0.00 H +ATOM 1355 HE2 LYS A 85 -40.156 -0.359 11.392 1.00 0.00 H +ATOM 1356 HZ1 LYS A 85 -41.453 -2.272 10.817 1.00 0.00 H +ATOM 1357 HZ2 LYS A 85 -42.659 -1.337 10.193 1.00 0.00 H +ATOM 1358 HZ3 LYS A 85 -41.180 -1.368 9.465 1.00 0.00 H +ATOM 1359 N PRO A 86 -40.859 2.036 5.668 1.00 11.27 N +ATOM 1360 CA PRO A 86 -40.961 0.945 4.685 1.00 11.61 C +ATOM 1361 C PRO A 86 -39.730 0.833 3.784 1.00 10.85 C +ATOM 1362 O PRO A 86 -39.342 -0.282 3.393 1.00 12.63 O +ATOM 1363 CB PRO A 86 -42.199 1.310 3.844 1.00 13.35 C +ATOM 1364 CG PRO A 86 -42.620 2.679 4.310 1.00 20.80 C +ATOM 1365 CD PRO A 86 -42.005 2.954 5.635 1.00 13.36 C +ATOM 1366 HA PRO A 86 -41.130 -0.001 5.199 1.00 0.00 H +ATOM 1367 HB3 PRO A 86 -42.998 0.597 4.048 1.00 0.00 H +ATOM 1368 HB2 PRO A 86 -41.921 1.356 2.791 1.00 0.00 H +ATOM 1369 HG3 PRO A 86 -43.706 2.714 4.399 1.00 0.00 H +ATOM 1370 HG2 PRO A 86 -42.284 3.426 3.591 1.00 0.00 H +ATOM 1371 HD2 PRO A 86 -41.643 3.982 5.657 1.00 0.00 H +ATOM 1372 HD3 PRO A 86 -42.708 2.680 6.422 1.00 0.00 H +ATOM 1373 N VAL A 87 -39.121 1.963 3.433 1.00 9.74 N +ATOM 1374 CA VAL A 87 -37.930 1.885 2.597 1.00 11.11 C +ATOM 1375 C VAL A 87 -36.791 1.237 3.383 1.00 10.32 C +ATOM 1376 O VAL A 87 -36.100 0.331 2.895 1.00 10.16 O +ATOM 1377 CB VAL A 87 -37.509 3.272 2.127 1.00 11.98 C +ATOM 1378 CG1 VAL A 87 -36.333 3.139 1.142 1.00 12.58 C +ATOM 1379 CG2 VAL A 87 -38.699 3.987 1.446 1.00 15.36 C +ATOM 1380 H VAL A 87 -39.486 2.851 3.746 1.00 0.00 H +ATOM 1381 HA VAL A 87 -38.151 1.270 1.725 1.00 0.00 H +ATOM 1382 HB VAL A 87 -37.188 3.857 2.988 1.00 0.00 H +ATOM 1383 HG11 VAL A 87 -36.028 4.129 0.803 1.00 0.00 H +ATOM 1384 HG12 VAL A 87 -35.495 2.652 1.640 1.00 0.00 H +ATOM 1385 HG13 VAL A 87 -36.642 2.541 0.285 1.00 0.00 H +ATOM 1386 HG21 VAL A 87 -38.387 4.977 1.114 1.00 0.00 H +ATOM 1387 HG22 VAL A 87 -39.030 3.404 0.587 1.00 0.00 H +ATOM 1388 HG23 VAL A 87 -39.520 4.085 2.157 1.00 0.00 H +ATOM 1389 N TYR A 88 -36.578 1.680 4.621 1.00 9.24 N +ATOM 1390 CA TYR A 88 -35.568 1.080 5.450 1.00 9.49 C +ATOM 1391 C TYR A 88 -35.744 -0.418 5.621 1.00 10.08 C +ATOM 1392 O TYR A 88 -34.789 -1.173 5.455 1.00 10.93 O +ATOM 1393 CB TYR A 88 -35.580 1.814 6.810 1.00 9.85 C +ATOM 1394 CG TYR A 88 -34.530 1.370 7.804 1.00 11.01 C +ATOM 1395 CD1 TYR A 88 -33.233 1.889 7.762 1.00 10.83 C +ATOM 1396 CD2 TYR A 88 -34.837 0.430 8.768 1.00 14.94 C +ATOM 1397 CE1 TYR A 88 -32.281 1.491 8.659 1.00 12.39 C +ATOM 1398 CE2 TYR A 88 -33.891 0.039 9.684 1.00 17.74 C +ATOM 1399 CZ TYR A 88 -32.609 0.578 9.613 1.00 16.57 C +ATOM 1400 OH TYR A 88 -31.644 0.173 10.516 1.00 20.05 O +ATOM 1401 H TYR A 88 -37.128 2.444 4.986 1.00 0.00 H +ATOM 1402 HA TYR A 88 -34.600 1.254 4.981 1.00 0.00 H +ATOM 1403 HB3 TYR A 88 -36.567 1.718 7.262 1.00 0.00 H +ATOM 1404 HB2 TYR A 88 -35.485 2.887 6.641 1.00 0.00 H +ATOM 1405 HD1 TYR A 88 -32.967 2.618 7.011 1.00 0.00 H +ATOM 1406 HD2 TYR A 88 -35.826 -0.002 8.805 1.00 0.00 H +ATOM 1407 HE1 TYR A 88 -31.283 1.901 8.605 1.00 0.00 H +ATOM 1408 HE2 TYR A 88 -34.145 -0.680 10.449 1.00 0.00 H +ATOM 1409 HH TYR A 88 -32.022 -0.468 11.122 1.00 0.00 H +ATOM 1410 N ASP A 89 -36.968 -0.825 5.922 1.00 10.85 N +ATOM 1411 CA ASP A 89 -37.242 -2.263 6.121 1.00 12.20 C +ATOM 1412 C ASP A 89 -36.980 -3.058 4.864 1.00 10.75 C +ATOM 1413 O ASP A 89 -36.626 -4.239 4.925 1.00 13.53 O +ATOM 1414 CB ASP A 89 -38.688 -2.441 6.527 1.00 12.62 C +ATOM 1415 CG ASP A 89 -38.923 -2.110 8.000 1.00 17.65 C +ATOM 1416 OD1 ASP A 89 -37.928 -1.960 8.753 1.00 19.29 O +ATOM 1417 OD2 ASP A 89 -40.115 -2.040 8.374 1.00 23.76 O +ATOM 1418 H ASP A 89 -37.715 -0.152 6.016 1.00 0.00 H +ATOM 1419 HA ASP A 89 -36.601 -2.639 6.918 1.00 0.00 H +ATOM 1420 HB3 ASP A 89 -38.995 -3.469 6.333 1.00 0.00 H +ATOM 1421 HB2 ASP A 89 -39.319 -1.804 5.907 1.00 0.00 H +ATOM 1422 N SER A 90 -37.136 -2.419 3.705 1.00 9.14 N +ATOM 1423 CA SER A 90 -36.879 -3.110 2.446 1.00 10.21 C +ATOM 1424 C SER A 90 -35.409 -3.350 2.130 1.00 9.53 C +ATOM 1425 O SER A 90 -35.063 -4.173 1.262 1.00 9.81 O +ATOM 1426 CB SER A 90 -37.569 -2.354 1.291 1.00 11.48 C +ATOM 1427 OG SER A 90 -36.779 -1.255 0.806 1.00 11.23 O +ATOM 1428 H SER A 90 -37.433 -1.454 3.697 1.00 0.00 H +ATOM 1429 HA SER A 90 -37.354 -4.088 2.516 1.00 0.00 H +ATOM 1430 HB3 SER A 90 -38.537 -1.983 1.628 1.00 0.00 H +ATOM 1431 HB2 SER A 90 -37.768 -3.046 0.473 1.00 0.00 H +ATOM 1432 HG SER A 90 -37.246 -0.816 0.091 1.00 0.00 H +ATOM 1433 N LEU A 91 -34.526 -2.607 2.808 1.00 9.62 N +ATOM 1434 CA LEU A 91 -33.102 -2.614 2.457 1.00 8.41 C +ATOM 1435 C LEU A 91 -32.346 -3.751 3.149 1.00 8.40 C +ATOM 1436 O LEU A 91 -32.765 -4.229 4.211 1.00 11.20 O +ATOM 1437 CB LEU A 91 -32.449 -1.283 2.891 1.00 9.23 C +ATOM 1438 CG LEU A 91 -32.958 -0.037 2.149 1.00 9.80 C +ATOM 1439 CD1 LEU A 91 -32.397 1.224 2.837 1.00 10.87 C +ATOM 1440 CD2 LEU A 91 -32.538 -0.052 0.699 1.00 12.15 C +ATOM 1441 H LEU A 91 -34.837 -2.029 3.576 1.00 0.00 H +ATOM 1442 HA LEU A 91 -33.002 -2.725 1.377 1.00 0.00 H +ATOM 1443 HB3 LEU A 91 -31.368 -1.356 2.773 1.00 0.00 H +ATOM 1444 HB2 LEU A 91 -32.588 -1.146 3.963 1.00 0.00 H +ATOM 1445 HG LEU A 91 -34.046 -0.014 2.202 1.00 0.00 H +ATOM 1446 HD11 LEU A 91 -32.754 2.112 2.316 1.00 0.00 H +ATOM 1447 HD12 LEU A 91 -32.732 1.252 3.874 1.00 0.00 H +ATOM 1448 HD13 LEU A 91 -31.308 1.200 2.808 1.00 0.00 H +ATOM 1449 HD21 LEU A 91 -32.914 0.843 0.202 1.00 0.00 H +ATOM 1450 HD22 LEU A 91 -31.450 -0.073 0.636 1.00 0.00 H +ATOM 1451 HD23 LEU A 91 -32.947 -0.937 0.211 1.00 0.00 H +ATOM 1452 N ASP A 92 -31.223 -4.137 2.556 1.00 9.38 N +ATOM 1453 CA ASP A 92 -30.227 -4.975 3.226 1.00 8.64 C +ATOM 1454 C ASP A 92 -29.428 -4.216 4.289 1.00 11.74 C +ATOM 1455 O ASP A 92 -29.512 -2.977 4.385 1.00 11.32 O +ATOM 1456 CB ASP A 92 -29.254 -5.455 2.166 1.00 10.71 C +ATOM 1457 CG ASP A 92 -28.596 -4.311 1.472 1.00 11.43 C +ATOM 1458 OD1 ASP A 92 -29.205 -3.816 0.494 1.00 12.40 O +ATOM 1459 OD2 ASP A 92 -27.491 -3.905 1.936 1.00 14.11 O +ATOM 1460 H ASP A 92 -31.030 -3.852 1.606 1.00 0.00 H +ATOM 1461 HA ASP A 92 -30.720 -5.833 3.684 1.00 0.00 H +ATOM 1462 HB3 ASP A 92 -29.785 -6.065 1.436 1.00 0.00 H +ATOM 1463 HB2 ASP A 92 -28.494 -6.084 2.629 1.00 0.00 H +ATOM 1464 N ALA A 93 -28.640 -4.947 5.071 1.00 12.02 N +ATOM 1465 CA ALA A 93 -27.956 -4.344 6.204 1.00 11.28 C +ATOM 1466 C ALA A 93 -26.991 -3.213 5.849 1.00 11.41 C +ATOM 1467 O ALA A 93 -26.898 -2.225 6.594 1.00 13.83 O +ATOM 1468 CB ALA A 93 -27.229 -5.423 7.038 1.00 14.12 C +ATOM 1469 H ALA A 93 -28.512 -5.931 4.881 1.00 0.00 H +ATOM 1470 HA ALA A 93 -28.725 -3.914 6.845 1.00 0.00 H +ATOM 1471 HB1 ALA A 93 -26.723 -4.952 7.881 1.00 0.00 H +ATOM 1472 HB2 ALA A 93 -27.955 -6.147 7.409 1.00 0.00 H +ATOM 1473 HB3 ALA A 93 -26.495 -5.932 6.413 1.00 0.00 H +ATOM 1474 N VAL A 94 -26.242 -3.349 4.765 1.00 11.09 N +ATOM 1475 CA VAL A 94 -25.271 -2.318 4.402 1.00 9.75 C +ATOM 1476 C VAL A 94 -26.018 -1.063 3.969 1.00 10.30 C +ATOM 1477 O VAL A 94 -25.687 0.065 4.404 1.00 9.95 O +ATOM 1478 CB VAL A 94 -24.320 -2.834 3.344 1.00 10.86 C +ATOM 1479 CG1 VAL A 94 -23.366 -1.704 2.889 1.00 13.22 C +ATOM 1480 CG2 VAL A 94 -23.535 -4.017 3.902 1.00 14.22 C +ATOM 1481 H VAL A 94 -26.340 -4.169 4.183 1.00 0.00 H +ATOM 1482 HA VAL A 94 -24.688 -2.075 5.290 1.00 0.00 H +ATOM 1483 HB VAL A 94 -24.900 -3.171 2.485 1.00 0.00 H +ATOM 1484 HG11 VAL A 94 -22.686 -2.086 2.128 1.00 0.00 H +ATOM 1485 HG12 VAL A 94 -23.948 -0.881 2.475 1.00 0.00 H +ATOM 1486 HG13 VAL A 94 -22.791 -1.348 3.743 1.00 0.00 H +ATOM 1487 HG21 VAL A 94 -22.849 -4.390 3.141 1.00 0.00 H +ATOM 1488 HG22 VAL A 94 -22.968 -3.697 4.776 1.00 0.00 H +ATOM 1489 HG23 VAL A 94 -24.226 -4.810 4.188 1.00 0.00 H +ATOM 1490 N ARG A 95 -27.041 -1.214 3.129 1.00 9.57 N +ATOM 1491 CA ARG A 95 -27.755 -0.034 2.688 1.00 7.98 C +ATOM 1492 C ARG A 95 -28.536 0.607 3.843 1.00 8.27 C +ATOM 1493 O ARG A 95 -28.735 1.836 3.851 1.00 8.62 O +ATOM 1494 CB ARG A 95 -28.653 -0.381 1.500 1.00 8.60 C +ATOM 1495 CG ARG A 95 -27.826 -0.775 0.290 1.00 8.12 C +ATOM 1496 CD ARG A 95 -28.764 -1.004 -0.891 1.00 10.22 C +ATOM 1497 NE ARG A 95 -28.055 -1.160 -2.154 1.00 9.19 N +ATOM 1498 CZ ARG A 95 -27.723 -2.342 -2.690 1.00 9.67 C +ATOM 1499 NH1 ARG A 95 -27.993 -3.480 -2.063 1.00 11.88 N +ATOM 1500 NH2 ARG A 95 -27.113 -2.355 -3.870 1.00 11.17 N +ATOM 1501 H ARG A 95 -27.303 -2.137 2.814 1.00 0.00 H +ATOM 1502 HA ARG A 95 -27.017 0.691 2.345 1.00 0.00 H +ATOM 1503 HB3 ARG A 95 -29.274 0.480 1.251 1.00 0.00 H +ATOM 1504 HB2 ARG A 95 -29.313 -1.205 1.772 1.00 0.00 H +ATOM 1505 HG3 ARG A 95 -27.283 -1.695 0.506 1.00 0.00 H +ATOM 1506 HG2 ARG A 95 -27.129 0.028 0.050 1.00 0.00 H +ATOM 1507 HD3 ARG A 95 -29.461 -0.169 -0.967 1.00 0.00 H +ATOM 1508 HD2 ARG A 95 -29.371 -1.890 -0.705 1.00 0.00 H +ATOM 1509 HE ARG A 95 -27.813 -0.303 -2.631 1.00 0.00 H +ATOM 1510 HH12 ARG A 95 -27.735 -4.362 -2.483 1.00 0.00 H +ATOM 1511 HH11 ARG A 95 -28.457 -3.465 -1.166 1.00 0.00 H +ATOM 1512 HH21 ARG A 95 -26.853 -3.234 -4.294 1.00 0.00 H +ATOM 1513 HH22 ARG A 95 -26.909 -1.486 -4.343 1.00 0.00 H +ATOM 1514 N ARG A 96 -28.937 -0.177 4.854 1.00 7.92 N +ATOM 1515 CA ARG A 96 -29.588 0.409 6.036 1.00 8.20 C +ATOM 1516 C ARG A 96 -28.616 1.370 6.736 1.00 8.25 C +ATOM 1517 O ARG A 96 -29.051 2.405 7.241 1.00 9.93 O +ATOM 1518 CB ARG A 96 -30.033 -0.662 7.013 1.00 9.47 C +ATOM 1519 CG ARG A 96 -31.324 -1.317 6.565 1.00 9.48 C +ATOM 1520 CD ARG A 96 -31.779 -2.377 7.577 1.00 9.93 C +ATOM 1521 NE ARG A 96 -32.995 -3.022 7.076 1.00 12.50 N +ATOM 1522 CZ ARG A 96 -33.479 -4.154 7.574 1.00 15.95 C +ATOM 1523 NH1 ARG A 96 -32.879 -4.726 8.612 1.00 18.19 N +ATOM 1524 NH2 ARG A 96 -34.581 -4.689 7.063 1.00 13.57 N +ATOM 1525 H ARG A 96 -28.793 -1.176 4.807 1.00 0.00 H +ATOM 1526 HA ARG A 96 -30.463 0.972 5.711 1.00 0.00 H +ATOM 1527 HB3 ARG A 96 -30.174 -0.218 7.998 1.00 0.00 H +ATOM 1528 HB2 ARG A 96 -29.254 -1.419 7.101 1.00 0.00 H +ATOM 1529 HG3 ARG A 96 -31.175 -1.785 5.592 1.00 0.00 H +ATOM 1530 HG2 ARG A 96 -32.099 -0.558 6.461 1.00 0.00 H +ATOM 1531 HD3 ARG A 96 -31.989 -1.899 8.534 1.00 0.00 H +ATOM 1532 HD2 ARG A 96 -30.995 -3.124 7.697 1.00 0.00 H +ATOM 1533 HE ARG A 96 -33.470 -2.562 6.313 1.00 0.00 H +ATOM 1534 HH12 ARG A 96 -33.243 -5.587 8.994 1.00 0.00 H +ATOM 1535 HH11 ARG A 96 -32.059 -4.300 9.019 1.00 0.00 H +ATOM 1536 HH21 ARG A 96 -34.948 -5.550 7.443 1.00 0.00 H +ATOM 1537 HH22 ARG A 96 -35.053 -4.235 6.294 1.00 0.00 H +ATOM 1538 N CYS A 97 -27.319 1.046 6.704 1.00 9.45 N +ATOM 1539 CA CYS A 97 -26.341 1.964 7.298 1.00 10.22 C +ATOM 1540 C CYS A 97 -26.265 3.277 6.522 1.00 8.60 C +ATOM 1541 O CYS A 97 -26.163 4.350 7.123 1.00 8.75 O +ATOM 1542 CB CYS A 97 -24.946 1.368 7.328 1.00 8.42 C +ATOM 1543 SG CYS A 97 -24.822 0.004 8.491 1.00 12.29 S +ATOM 1544 H CYS A 97 -27.025 0.180 6.275 1.00 0.00 H +ATOM 1545 HA CYS A 97 -26.647 2.183 8.321 1.00 0.00 H +ATOM 1546 HB3 CYS A 97 -24.227 2.141 7.598 1.00 0.00 H +ATOM 1547 HB2 CYS A 97 -24.679 1.019 6.330 1.00 0.00 H +ATOM 1548 HG CYS A 97 -23.578 -0.482 8.477 1.00 0.00 H +ATOM 1549 N ALA A 98 -26.329 3.208 5.197 1.00 7.97 N +ATOM 1550 CA ALA A 98 -26.371 4.433 4.403 1.00 7.52 C +ATOM 1551 C ALA A 98 -27.586 5.286 4.755 1.00 8.46 C +ATOM 1552 O ALA A 98 -27.478 6.516 4.839 1.00 8.40 O +ATOM 1553 CB ALA A 98 -26.342 4.088 2.927 1.00 8.17 C +ATOM 1554 H ALA A 98 -26.349 2.308 4.739 1.00 0.00 H +ATOM 1555 HA ALA A 98 -25.476 5.012 4.631 1.00 0.00 H +ATOM 1556 HB1 ALA A 98 -26.373 5.005 2.338 1.00 0.00 H +ATOM 1557 HB2 ALA A 98 -25.427 3.542 2.699 1.00 0.00 H +ATOM 1558 HB3 ALA A 98 -27.205 3.469 2.681 1.00 0.00 H +ATOM 1559 N ALA A 99 -28.726 4.633 4.982 1.00 7.80 N +ATOM 1560 CA ALA A 99 -29.914 5.373 5.383 1.00 8.04 C +ATOM 1561 C ALA A 99 -29.740 6.056 6.723 1.00 8.65 C +ATOM 1562 O ALA A 99 -30.160 7.200 6.895 1.00 9.35 O +ATOM 1563 CB ALA A 99 -31.122 4.413 5.448 1.00 9.95 C +ATOM 1564 H ALA A 99 -28.763 3.629 4.876 1.00 0.00 H +ATOM 1565 HA ALA A 99 -30.118 6.135 4.630 1.00 0.00 H +ATOM 1566 HB1 ALA A 99 -32.011 4.967 5.748 1.00 0.00 H +ATOM 1567 HB2 ALA A 99 -31.286 3.968 4.467 1.00 0.00 H +ATOM 1568 HB3 ALA A 99 -30.922 3.626 6.175 1.00 0.00 H +ATOM 1569 N ILE A 100 -29.201 5.316 7.700 1.00 7.65 N +ATOM 1570 CA ILE A 100 -28.989 5.909 9.010 1.00 7.60 C +ATOM 1571 C ILE A 100 -28.032 7.087 8.891 1.00 9.00 C +ATOM 1572 O ILE A 100 -28.224 8.127 9.542 1.00 9.28 O +ATOM 1573 CB ILE A 100 -28.471 4.871 10.004 1.00 6.78 C +ATOM 1574 CG1 ILE A 100 -29.532 3.810 10.248 1.00 8.89 C +ATOM 1575 CG2 ILE A 100 -28.145 5.579 11.339 1.00 10.76 C +ATOM 1576 CD1 ILE A 100 -28.912 2.541 10.847 1.00 11.03 C +ATOM 1577 H ILE A 100 -28.946 4.355 7.523 1.00 0.00 H +ATOM 1578 HA ILE A 100 -29.946 6.282 9.374 1.00 0.00 H +ATOM 1579 HB ILE A 100 -27.570 4.403 9.608 1.00 0.00 H +ATOM 1580 HG13 ILE A 100 -30.023 3.564 9.306 1.00 0.00 H +ATOM 1581 HG12 ILE A 100 -30.287 4.202 10.930 1.00 0.00 H +ATOM 1582 HG21 ILE A 100 -27.774 4.848 12.057 1.00 0.00 H +ATOM 1583 HG22 ILE A 100 -27.384 6.341 11.170 1.00 0.00 H +ATOM 1584 HG23 ILE A 100 -29.047 6.048 11.732 1.00 0.00 H +ATOM 1585 HD11 ILE A 100 -29.692 1.798 11.012 1.00 0.00 H +ATOM 1586 HD12 ILE A 100 -28.168 2.140 10.159 1.00 0.00 H +ATOM 1587 HD13 ILE A 100 -28.435 2.783 11.797 1.00 0.00 H +ATOM 1588 N ASN A 101 -27.003 6.942 8.060 1.00 7.66 N +ATOM 1589 CA ASN A 101 -26.024 8.029 7.881 1.00 7.90 C +ATOM 1590 C ASN A 101 -26.726 9.298 7.378 1.00 9.22 C +ATOM 1591 O ASN A 101 -26.524 10.383 7.926 1.00 9.01 O +ATOM 1592 CB ASN A 101 -24.929 7.530 6.908 1.00 7.84 C +ATOM 1593 CG ASN A 101 -23.726 8.441 6.834 1.00 9.14 C +ATOM 1594 OD1 ASN A 101 -23.843 9.656 6.643 1.00 9.74 O +ATOM 1595 ND2 ASN A 101 -22.547 7.849 6.982 1.00 9.16 N +ATOM 1596 H ASN A 101 -26.887 6.081 7.545 1.00 0.00 H +ATOM 1597 HA ASN A 101 -25.562 8.245 8.845 1.00 0.00 H +ATOM 1598 HB3 ASN A 101 -25.356 7.413 5.912 1.00 0.00 H +ATOM 1599 HB2 ASN A 101 -24.609 6.531 7.205 1.00 0.00 H +ATOM 1600 HD22 ASN A 101 -21.699 8.396 6.944 1.00 0.00 H +ATOM 1601 HD21 ASN A 101 -22.498 6.851 7.133 1.00 0.00 H +ATOM 1602 N MET A 102 -27.586 9.178 6.366 1.00 8.68 N +ATOM 1603 CA MET A 102 -28.295 10.348 5.856 1.00 7.73 C +ATOM 1604 C MET A 102 -29.156 10.997 6.932 1.00 8.86 C +ATOM 1605 O MET A 102 -29.196 12.220 7.045 1.00 9.20 O +ATOM 1606 CB MET A 102 -29.232 9.980 4.690 1.00 10.00 C +ATOM 1607 CG MET A 102 -28.491 9.624 3.450 1.00 10.68 C +ATOM 1608 SD MET A 102 -29.635 9.514 2.028 1.00 14.72 S +ATOM 1609 CE MET A 102 -29.978 11.229 1.620 1.00 15.79 C +ATOM 1610 H MET A 102 -27.750 8.274 5.947 1.00 0.00 H +ATOM 1611 HA MET A 102 -27.564 11.076 5.504 1.00 0.00 H +ATOM 1612 HB3 MET A 102 -29.901 10.816 4.485 1.00 0.00 H +ATOM 1613 HB2 MET A 102 -29.867 9.144 4.985 1.00 0.00 H +ATOM 1614 HG3 MET A 102 -27.991 8.665 3.589 1.00 0.00 H +ATOM 1615 HG2 MET A 102 -27.734 10.382 3.249 1.00 0.00 H +ATOM 1616 HE1 MET A 102 -30.661 11.272 0.772 1.00 0.00 H +ATOM 1617 HE2 MET A 102 -30.434 11.723 2.478 1.00 0.00 H +ATOM 1618 HE3 MET A 102 -29.048 11.735 1.362 1.00 0.00 H +ATOM 1619 N VAL A 103 -29.888 10.174 7.681 1.00 8.57 N +ATOM 1620 CA VAL A 103 -30.761 10.714 8.732 1.00 9.34 C +ATOM 1621 C VAL A 103 -29.935 11.359 9.837 1.00 9.13 C +ATOM 1622 O VAL A 103 -30.322 12.409 10.378 1.00 10.67 O +ATOM 1623 CB VAL A 103 -31.698 9.625 9.267 1.00 9.11 C +ATOM 1624 CG1 VAL A 103 -32.446 10.099 10.534 1.00 12.24 C +ATOM 1625 CG2 VAL A 103 -32.706 9.260 8.175 1.00 11.17 C +ATOM 1626 H VAL A 103 -29.843 9.177 7.527 1.00 0.00 H +ATOM 1627 HA VAL A 103 -31.379 11.492 8.283 1.00 0.00 H +ATOM 1628 HB VAL A 103 -31.109 8.742 9.514 1.00 0.00 H +ATOM 1629 HG11 VAL A 103 -33.102 9.304 10.888 1.00 0.00 H +ATOM 1630 HG12 VAL A 103 -31.724 10.347 11.312 1.00 0.00 H +ATOM 1631 HG13 VAL A 103 -33.041 10.981 10.297 1.00 0.00 H +ATOM 1632 HG21 VAL A 103 -33.378 8.486 8.544 1.00 0.00 H +ATOM 1633 HG22 VAL A 103 -33.284 10.143 7.904 1.00 0.00 H +ATOM 1634 HG23 VAL A 103 -32.174 8.891 7.298 1.00 0.00 H +ATOM 1635 N PHE A 104 -28.789 10.788 10.159 1.00 8.45 N +ATOM 1636 CA PHE A 104 -27.876 11.414 11.129 1.00 8.76 C +ATOM 1637 C PHE A 104 -27.437 12.788 10.636 1.00 9.67 C +ATOM 1638 O PHE A 104 -27.439 13.766 11.400 1.00 11.69 O +ATOM 1639 CB PHE A 104 -26.691 10.463 11.398 1.00 7.45 C +ATOM 1640 CG PHE A 104 -25.729 10.945 12.472 1.00 8.30 C +ATOM 1641 CD1 PHE A 104 -24.789 11.915 12.173 1.00 12.07 C +ATOM 1642 CD2 PHE A 104 -25.711 10.335 13.709 1.00 11.74 C +ATOM 1643 CE1 PHE A 104 -23.875 12.345 13.149 1.00 13.95 C +ATOM 1644 CE2 PHE A 104 -24.806 10.744 14.694 1.00 11.85 C +ATOM 1645 CZ PHE A 104 -23.891 11.742 14.387 1.00 13.15 C +ATOM 1646 H PHE A 104 -28.527 9.908 9.738 1.00 0.00 H +ATOM 1647 HA PHE A 104 -28.419 11.549 12.064 1.00 0.00 H +ATOM 1648 HB3 PHE A 104 -26.143 10.298 10.470 1.00 0.00 H +ATOM 1649 HB2 PHE A 104 -27.072 9.479 11.670 1.00 0.00 H +ATOM 1650 HD1 PHE A 104 -24.755 12.347 11.184 1.00 0.00 H +ATOM 1651 HD2 PHE A 104 -26.401 9.532 13.925 1.00 0.00 H +ATOM 1652 HE1 PHE A 104 -23.175 13.136 12.922 1.00 0.00 H +ATOM 1653 HE2 PHE A 104 -24.828 10.285 15.671 1.00 0.00 H +ATOM 1654 HZ PHE A 104 -23.182 12.043 15.144 1.00 0.00 H +ATOM 1655 N GLN A 105 -27.100 12.917 9.360 1.00 8.76 N +ATOM 1656 CA GLN A 105 -26.589 14.194 8.880 1.00 8.93 C +ATOM 1657 C GLN A 105 -27.686 15.245 8.722 1.00 12.25 C +ATOM 1658 O GLN A 105 -27.492 16.418 9.074 1.00 13.62 O +ATOM 1659 CB GLN A 105 -25.894 13.985 7.528 1.00 10.52 C +ATOM 1660 CG GLN A 105 -25.243 15.287 7.008 1.00 10.45 C +ATOM 1661 CD GLN A 105 -24.508 15.102 5.702 1.00 10.87 C +ATOM 1662 OE1 GLN A 105 -24.457 14.025 5.137 1.00 10.56 O +ATOM 1663 NE2 GLN A 105 -23.996 16.203 5.165 1.00 13.45 N +ATOM 1664 H GLN A 105 -27.199 12.134 8.730 1.00 0.00 H +ATOM 1665 HA GLN A 105 -25.854 14.564 9.595 1.00 0.00 H +ATOM 1666 HB3 GLN A 105 -26.620 13.626 6.799 1.00 0.00 H +ATOM 1667 HB2 GLN A 105 -25.131 13.213 7.628 1.00 0.00 H +ATOM 1668 HG3 GLN A 105 -24.554 15.672 7.760 1.00 0.00 H +ATOM 1669 HG2 GLN A 105 -26.010 16.052 6.886 1.00 0.00 H +ATOM 1670 HE22 GLN A 105 -23.492 16.151 4.292 1.00 0.00 H +ATOM 1671 HE21 GLN A 105 -24.111 17.092 5.630 1.00 0.00 H +ATOM 1672 N MET A 106 -28.819 14.849 8.163 1.00 11.26 N +ATOM 1673 CA MET A 106 -29.800 15.857 7.777 1.00 11.02 C +ATOM 1674 C MET A 106 -31.127 15.802 8.520 1.00 12.18 C +ATOM 1675 O MET A 106 -31.973 16.688 8.328 1.00 14.70 O +ATOM 1676 CB MET A 106 -29.994 15.903 6.249 1.00 17.80 C +ATOM 1677 CG MET A 106 -30.586 14.674 5.651 1.00 14.93 C +ATOM 1678 SD MET A 106 -30.835 14.747 3.855 1.00 21.47 S +ATOM 1679 CE MET A 106 -29.182 14.403 3.257 1.00 17.33 C +ATOM 1680 H MET A 106 -28.990 13.865 8.011 1.00 0.00 H +ATOM 1681 HA MET A 106 -29.355 16.815 8.044 1.00 0.00 H +ATOM 1682 HB3 MET A 106 -29.037 16.112 5.770 1.00 0.00 H +ATOM 1683 HB2 MET A 106 -30.611 16.763 5.990 1.00 0.00 H +ATOM 1684 HG3 MET A 106 -31.537 14.457 6.139 1.00 0.00 H +ATOM 1685 HG2 MET A 106 -29.959 13.816 5.894 1.00 0.00 H +ATOM 1686 HE1 MET A 106 -29.180 14.415 2.167 1.00 0.00 H +ATOM 1687 HE2 MET A 106 -28.495 15.163 3.630 1.00 0.00 H +ATOM 1688 HE3 MET A 106 -28.864 13.422 3.610 1.00 0.00 H +ATOM 1689 N GLY A 107 -31.295 14.815 9.392 1.00 10.95 N +ATOM 1690 CA GLY A 107 -32.515 14.654 10.154 1.00 12.63 C +ATOM 1691 C GLY A 107 -33.597 13.897 9.401 1.00 12.45 C +ATOM 1692 O GLY A 107 -33.593 13.821 8.164 1.00 12.78 O +ATOM 1693 H GLY A 107 -30.556 14.143 9.542 1.00 0.00 H +ATOM 1694 HA3 GLY A 107 -32.893 15.635 10.443 1.00 0.00 H +ATOM 1695 HA2 GLY A 107 -32.293 14.136 11.087 1.00 0.00 H +ATOM 1696 N GLU A 108 -34.517 13.338 10.179 1.00 14.59 N +ATOM 1697 CA GLU A 108 -35.633 12.542 9.665 1.00 15.30 C +ATOM 1698 C GLU A 108 -36.472 13.295 8.638 1.00 16.59 C +ATOM 1699 O GLU A 108 -36.770 12.780 7.560 1.00 16.40 O +ATOM 1700 CB GLU A 108 -36.501 12.059 10.856 1.00 19.85 C +ATOM 1701 CG GLU A 108 -37.861 11.523 10.509 1.00 29.08 C +ATOM 1702 CD GLU A 108 -38.820 11.470 11.696 1.00 27.06 C +ATOM 1703 OE1 GLU A 108 -40.041 11.401 11.440 1.00 28.33 O +ATOM 1704 OE2 GLU A 108 -38.373 11.505 12.876 1.00 28.92 O +ATOM 1705 H GLU A 108 -34.468 13.452 11.181 1.00 0.00 H +ATOM 1706 HA GLU A 108 -35.217 11.661 9.176 1.00 0.00 H +ATOM 1707 HB3 GLU A 108 -36.607 12.871 11.576 1.00 0.00 H +ATOM 1708 HB2 GLU A 108 -35.951 11.305 11.419 1.00 0.00 H +ATOM 1709 HG3 GLU A 108 -37.758 10.525 10.082 1.00 0.00 H +ATOM 1710 HG2 GLU A 108 -38.298 12.132 9.718 1.00 0.00 H +ATOM 1711 N THR A 109 -36.889 14.513 8.959 1.00 18.94 N +ATOM 1712 CA THR A 109 -37.770 15.273 8.082 1.00 21.59 C +ATOM 1713 C THR A 109 -37.114 15.592 6.736 1.00 18.49 C +ATOM 1714 O THR A 109 -37.747 15.493 5.665 1.00 18.67 O +ATOM 1715 CB THR A 109 -38.226 16.572 8.781 1.00 19.41 C +ATOM 1716 OG1 THR A 109 -38.779 16.246 10.065 1.00 21.83 O +ATOM 1717 CG2 THR A 109 -39.267 17.295 7.941 1.00 22.83 C +ATOM 1718 H THR A 109 -36.596 14.934 9.829 1.00 0.00 H +ATOM 1719 HA THR A 109 -38.655 14.667 7.889 1.00 0.00 H +ATOM 1720 HB THR A 109 -37.364 17.224 8.919 1.00 0.00 H +ATOM 1721 HG1 THR A 109 -39.064 17.050 10.505 1.00 0.00 H +ATOM 1722 HG21 THR A 109 -39.576 18.208 8.451 1.00 0.00 H +ATOM 1723 HG22 THR A 109 -38.840 17.548 6.971 1.00 0.00 H +ATOM 1724 HG23 THR A 109 -40.133 16.648 7.799 1.00 0.00 H +ATOM 1725 N GLY A 110 -35.838 15.971 6.790 1.00 19.11 N +ATOM 1726 CA GLY A 110 -35.082 16.268 5.583 1.00 19.05 C +ATOM 1727 C GLY A 110 -35.004 15.065 4.661 1.00 17.46 C +ATOM 1728 O GLY A 110 -35.276 15.158 3.455 1.00 18.25 O +ATOM 1729 H GLY A 110 -35.374 16.058 7.683 1.00 0.00 H +ATOM 1730 HA3 GLY A 110 -34.074 16.583 5.854 1.00 0.00 H +ATOM 1731 HA2 GLY A 110 -35.551 17.099 5.056 1.00 0.00 H +ATOM 1732 N VAL A 111 -34.641 13.912 5.211 1.00 14.46 N +ATOM 1733 CA VAL A 111 -34.518 12.732 4.375 1.00 11.88 C +ATOM 1734 C VAL A 111 -35.876 12.282 3.831 1.00 12.90 C +ATOM 1735 O VAL A 111 -35.977 11.789 2.695 1.00 13.74 O +ATOM 1736 CB VAL A 111 -33.861 11.568 5.125 1.00 12.73 C +ATOM 1737 CG1 VAL A 111 -33.796 10.333 4.227 1.00 13.29 C +ATOM 1738 CG2 VAL A 111 -32.451 11.955 5.559 1.00 14.91 C +ATOM 1739 H VAL A 111 -34.453 13.862 6.202 1.00 0.00 H +ATOM 1740 HA VAL A 111 -33.883 12.986 3.526 1.00 0.00 H +ATOM 1741 HB VAL A 111 -34.454 11.334 6.009 1.00 0.00 H +ATOM 1742 HG11 VAL A 111 -33.327 9.512 4.770 1.00 0.00 H +ATOM 1743 HG12 VAL A 111 -34.805 10.044 3.932 1.00 0.00 H +ATOM 1744 HG13 VAL A 111 -33.209 10.561 3.337 1.00 0.00 H +ATOM 1745 HG21 VAL A 111 -31.992 11.122 6.091 1.00 0.00 H +ATOM 1746 HG22 VAL A 111 -31.853 12.197 4.680 1.00 0.00 H +ATOM 1747 HG23 VAL A 111 -32.498 12.823 6.216 1.00 0.00 H +ATOM 1748 N ALA A 112 -36.917 12.413 4.653 1.00 13.34 N +ATOM 1749 CA ALA A 112 -38.253 12.006 4.211 1.00 15.71 C +ATOM 1750 C ALA A 112 -38.728 12.831 3.011 1.00 17.01 C +ATOM 1751 O ALA A 112 -39.635 12.407 2.258 1.00 19.90 O +ATOM 1752 CB ALA A 112 -39.246 12.073 5.396 1.00 15.00 C +ATOM 1753 H ALA A 112 -36.784 12.793 5.580 1.00 0.00 H +ATOM 1754 HA ALA A 112 -38.191 10.966 3.892 1.00 0.00 H +ATOM 1755 HB1 ALA A 112 -40.237 11.769 5.058 1.00 0.00 H +ATOM 1756 HB2 ALA A 112 -38.912 11.404 6.189 1.00 0.00 H +ATOM 1757 HB3 ALA A 112 -39.290 13.093 5.777 1.00 0.00 H +ATOM 1758 N GLY A 113 -38.084 13.972 2.788 1.00 14.91 N +ATOM 1759 CA GLY A 113 -38.371 14.782 1.610 1.00 19.24 C +ATOM 1760 C GLY A 113 -37.795 14.250 0.300 1.00 20.95 C +ATOM 1761 O GLY A 113 -38.163 14.723 -0.783 1.00 20.13 O +ATOM 1762 H GLY A 113 -37.382 14.292 3.440 1.00 0.00 H +ATOM 1763 HA3 GLY A 113 -38.012 15.798 1.775 1.00 0.00 H +ATOM 1764 HA2 GLY A 113 -39.450 14.900 1.508 1.00 0.00 H +ATOM 1765 N PHE A 114 -36.883 13.276 0.379 1.00 15.66 N +ATOM 1766 CA PHE A 114 -36.214 12.754 -0.812 1.00 13.79 C +ATOM 1767 C PHE A 114 -37.159 11.722 -1.466 1.00 12.36 C +ATOM 1768 O PHE A 114 -36.778 10.590 -1.732 1.00 12.88 O +ATOM 1769 CB PHE A 114 -34.887 12.086 -0.418 1.00 12.14 C +ATOM 1770 CG PHE A 114 -33.679 13.016 -0.346 1.00 12.24 C +ATOM 1771 CD1 PHE A 114 -32.588 12.827 -1.204 1.00 12.77 C +ATOM 1772 CD2 PHE A 114 -33.618 14.051 0.580 1.00 17.98 C +ATOM 1773 CE1 PHE A 114 -31.446 13.657 -1.154 1.00 15.61 C +ATOM 1774 CE2 PHE A 114 -32.473 14.889 0.631 1.00 17.24 C +ATOM 1775 CZ PHE A 114 -31.399 14.675 -0.218 1.00 15.50 C +ATOM 1776 H PHE A 114 -36.641 12.882 1.277 1.00 0.00 H +ATOM 1777 HA PHE A 114 -36.021 13.568 -1.510 1.00 0.00 H +ATOM 1778 HB3 PHE A 114 -34.674 11.272 -1.111 1.00 0.00 H +ATOM 1779 HB2 PHE A 114 -35.009 11.580 0.539 1.00 0.00 H +ATOM 1780 HD1 PHE A 114 -32.604 12.028 -1.931 1.00 0.00 H +ATOM 1781 HD2 PHE A 114 -34.441 14.217 1.259 1.00 0.00 H +ATOM 1782 HE1 PHE A 114 -30.628 13.492 -1.839 1.00 0.00 H +ATOM 1783 HE2 PHE A 114 -32.432 15.705 1.338 1.00 0.00 H +ATOM 1784 HZ PHE A 114 -30.524 15.304 -0.148 1.00 0.00 H +ATOM 1785 N THR A 115 -38.375 12.151 -1.806 1.00 15.17 N +ATOM 1786 CA THR A 115 -39.431 11.246 -2.251 1.00 16.80 C +ATOM 1787 C THR A 115 -39.055 10.344 -3.416 1.00 13.81 C +ATOM 1788 O THR A 115 -39.264 9.124 -3.374 1.00 15.25 O +ATOM 1789 CB THR A 115 -40.705 12.039 -2.638 1.00 17.04 C +ATOM 1790 OG1 THR A 115 -41.120 12.817 -1.511 1.00 24.24 O +ATOM 1791 CG2 THR A 115 -41.839 11.084 -3.052 1.00 20.81 C +ATOM 1792 H THR A 115 -38.594 13.136 -1.761 1.00 0.00 H +ATOM 1793 HA THR A 115 -39.688 10.603 -1.409 1.00 0.00 H +ATOM 1794 HB THR A 115 -40.475 12.705 -3.469 1.00 0.00 H +ATOM 1795 HG1 THR A 115 -41.910 13.314 -1.738 1.00 0.00 H +ATOM 1796 HG21 THR A 115 -42.723 11.663 -3.319 1.00 0.00 H +ATOM 1797 HG22 THR A 115 -41.521 10.491 -3.910 1.00 0.00 H +ATOM 1798 HG23 THR A 115 -42.078 10.421 -2.221 1.00 0.00 H +ATOM 1799 N ASN A 116 -38.489 10.917 -4.473 1.00 13.24 N +ATOM 1800 CA ASN A 116 -38.196 10.117 -5.633 1.00 14.40 C +ATOM 1801 C ASN A 116 -37.034 9.140 -5.377 1.00 12.17 C +ATOM 1802 O ASN A 116 -37.087 7.997 -5.810 1.00 14.04 O +ATOM 1803 CB ASN A 116 -37.964 11.020 -6.852 1.00 14.53 C +ATOM 1804 CG ASN A 116 -39.187 11.894 -7.146 1.00 29.69 C +ATOM 1805 OD1 ASN A 116 -40.322 11.406 -7.112 1.00 27.50 O +ATOM 1806 ND2 ASN A 116 -38.968 13.194 -7.381 1.00 21.28 N +ATOM 1807 H ASN A 116 -38.270 11.903 -4.456 1.00 0.00 H +ATOM 1808 HA ASN A 116 -39.081 9.516 -5.841 1.00 0.00 H +ATOM 1809 HB3 ASN A 116 -37.741 10.404 -7.723 1.00 0.00 H +ATOM 1810 HB2 ASN A 116 -37.098 11.657 -6.672 1.00 0.00 H +ATOM 1811 HD22 ASN A 116 -39.744 13.809 -7.580 1.00 0.00 H +ATOM 1812 HD21 ASN A 116 -38.027 13.559 -7.360 1.00 0.00 H +ATOM 1813 N SER A 117 -36.008 9.582 -4.645 1.00 11.74 N +ATOM 1814 CA SER A 117 -34.911 8.682 -4.301 1.00 11.26 C +ATOM 1815 C SER A 117 -35.391 7.533 -3.437 1.00 10.10 C +ATOM 1816 O SER A 117 -34.955 6.385 -3.629 1.00 10.99 O +ATOM 1817 CB SER A 117 -33.806 9.407 -3.533 1.00 12.64 C +ATOM 1818 OG SER A 117 -33.078 10.262 -4.414 1.00 20.75 O +ATOM 1819 H SER A 117 -35.990 10.541 -4.328 1.00 0.00 H +ATOM 1820 HA SER A 117 -34.490 8.276 -5.221 1.00 0.00 H +ATOM 1821 HB3 SER A 117 -33.128 8.675 -3.095 1.00 0.00 H +ATOM 1822 HB2 SER A 117 -34.249 10.001 -2.734 1.00 0.00 H +ATOM 1823 HG SER A 117 -32.387 10.713 -3.924 1.00 0.00 H +ATOM 1824 N LEU A 118 -36.253 7.839 -2.476 1.00 10.63 N +ATOM 1825 CA LEU A 118 -36.776 6.792 -1.583 1.00 10.30 C +ATOM 1826 C LEU A 118 -37.526 5.743 -2.386 1.00 11.22 C +ATOM 1827 O LEU A 118 -37.380 4.543 -2.114 1.00 12.32 O +ATOM 1828 CB LEU A 118 -37.708 7.397 -0.539 1.00 11.60 C +ATOM 1829 CG LEU A 118 -36.983 8.232 0.523 1.00 12.09 C +ATOM 1830 CD1 LEU A 118 -37.979 9.063 1.302 1.00 14.33 C +ATOM 1831 CD2 LEU A 118 -36.180 7.340 1.488 1.00 14.24 C +ATOM 1832 H LEU A 118 -36.554 8.795 -2.354 1.00 0.00 H +ATOM 1833 HA LEU A 118 -35.940 6.314 -1.073 1.00 0.00 H +ATOM 1834 HB3 LEU A 118 -38.270 6.601 -0.051 1.00 0.00 H +ATOM 1835 HB2 LEU A 118 -38.456 8.015 -1.036 1.00 0.00 H +ATOM 1836 HG LEU A 118 -36.291 8.906 0.019 1.00 0.00 H +ATOM 1837 HD11 LEU A 118 -37.453 9.652 2.053 1.00 0.00 H +ATOM 1838 HD12 LEU A 118 -38.507 9.731 0.621 1.00 0.00 H +ATOM 1839 HD13 LEU A 118 -38.696 8.405 1.793 1.00 0.00 H +ATOM 1840 HD21 LEU A 118 -35.679 7.964 2.228 1.00 0.00 H +ATOM 1841 HD22 LEU A 118 -36.856 6.650 1.993 1.00 0.00 H +ATOM 1842 HD23 LEU A 118 -35.437 6.774 0.927 1.00 0.00 H +ATOM 1843 N ARG A 119 -38.343 6.172 -3.345 1.00 10.74 N +ATOM 1844 CA ARG A 119 -39.086 5.217 -4.170 1.00 12.16 C +ATOM 1845 C ARG A 119 -38.100 4.344 -4.945 1.00 12.50 C +ATOM 1846 O ARG A 119 -38.261 3.132 -5.035 1.00 12.23 O +ATOM 1847 CB ARG A 119 -40.020 5.942 -5.155 1.00 14.91 C +ATOM 1848 CG ARG A 119 -40.976 5.021 -5.931 1.00 17.26 C +ATOM 1849 CD ARG A 119 -41.698 5.772 -7.073 1.00 25.89 C +ATOM 1850 NE ARG A 119 -40.745 6.413 -7.981 1.00 30.48 N +ATOM 1851 CZ ARG A 119 -40.478 7.716 -7.995 1.00 25.59 C +ATOM 1852 NH1 ARG A 119 -41.113 8.537 -7.168 1.00 30.05 N +ATOM 1853 NH2 ARG A 119 -39.580 8.201 -8.843 1.00 28.19 N +ATOM 1854 H ARG A 119 -38.454 7.163 -3.508 1.00 0.00 H +ATOM 1855 HA ARG A 119 -39.685 4.580 -3.519 1.00 0.00 H +ATOM 1856 HB3 ARG A 119 -39.422 6.519 -5.861 1.00 0.00 H +ATOM 1857 HB2 ARG A 119 -40.599 6.692 -4.617 1.00 0.00 H +ATOM 1858 HG3 ARG A 119 -41.715 4.606 -5.246 1.00 0.00 H +ATOM 1859 HG2 ARG A 119 -40.416 4.183 -6.346 1.00 0.00 H +ATOM 1860 HD3 ARG A 119 -42.359 6.528 -6.649 1.00 0.00 H +ATOM 1861 HD2 ARG A 119 -42.318 5.072 -7.633 1.00 0.00 H +ATOM 1862 HE ARG A 119 -40.276 5.794 -8.627 1.00 0.00 H +ATOM 1863 HH12 ARG A 119 -40.908 9.526 -7.182 1.00 0.00 H +ATOM 1864 HH11 ARG A 119 -41.802 8.173 -6.525 1.00 0.00 H +ATOM 1865 HH21 ARG A 119 -39.378 9.190 -8.853 1.00 0.00 H +ATOM 1866 HH22 ARG A 119 -39.099 7.581 -9.478 1.00 0.00 H +ATOM 1867 N MET A 120 -37.075 4.954 -5.530 1.00 10.30 N +ATOM 1868 CA MET A 120 -36.135 4.173 -6.315 1.00 10.69 C +ATOM 1869 C MET A 120 -35.377 3.185 -5.445 1.00 10.03 C +ATOM 1870 O MET A 120 -35.106 2.058 -5.864 1.00 10.98 O +ATOM 1871 CB MET A 120 -35.150 5.070 -7.055 1.00 11.13 C +ATOM 1872 CG MET A 120 -35.860 5.971 -8.036 1.00 13.50 C +ATOM 1873 SD MET A 120 -34.693 7.154 -8.740 1.00 15.40 S +ATOM 1874 CE MET A 120 -35.806 8.292 -9.569 1.00 21.87 C +ATOM 1875 H MET A 120 -36.955 5.952 -5.427 1.00 0.00 H +ATOM 1876 HA MET A 120 -36.700 3.608 -7.056 1.00 0.00 H +ATOM 1877 HB3 MET A 120 -34.426 4.453 -7.587 1.00 0.00 H +ATOM 1878 HB2 MET A 120 -34.602 5.678 -6.335 1.00 0.00 H +ATOM 1879 HG3 MET A 120 -36.657 6.509 -7.523 1.00 0.00 H +ATOM 1880 HG2 MET A 120 -36.293 5.369 -8.835 1.00 0.00 H +ATOM 1881 HE1 MET A 120 -35.228 9.080 -10.051 1.00 0.00 H +ATOM 1882 HE2 MET A 120 -36.383 7.754 -10.321 1.00 0.00 H +ATOM 1883 HE3 MET A 120 -36.484 8.735 -8.839 1.00 0.00 H +ATOM 1884 N LEU A 121 -35.039 3.601 -4.222 1.00 9.47 N +ATOM 1885 CA LEU A 121 -34.400 2.675 -3.295 1.00 10.23 C +ATOM 1886 C LEU A 121 -35.322 1.514 -2.940 1.00 10.86 C +ATOM 1887 O LEU A 121 -34.865 0.361 -2.926 1.00 10.75 O +ATOM 1888 CB LEU A 121 -33.922 3.420 -2.015 1.00 8.64 C +ATOM 1889 CG LEU A 121 -32.748 4.385 -2.211 1.00 9.72 C +ATOM 1890 CD1 LEU A 121 -32.564 5.183 -0.897 1.00 10.86 C +ATOM 1891 CD2 LEU A 121 -31.429 3.682 -2.587 1.00 11.47 C +ATOM 1892 H LEU A 121 -35.226 4.553 -3.943 1.00 0.00 H +ATOM 1893 HA LEU A 121 -33.520 2.263 -3.789 1.00 0.00 H +ATOM 1894 HB3 LEU A 121 -33.663 2.689 -1.249 1.00 0.00 H +ATOM 1895 HB2 LEU A 121 -34.762 3.959 -1.577 1.00 0.00 H +ATOM 1896 HG LEU A 121 -33.005 5.084 -3.006 1.00 0.00 H +ATOM 1897 HD11 LEU A 121 -31.733 5.880 -1.008 1.00 0.00 H +ATOM 1898 HD12 LEU A 121 -33.476 5.738 -0.678 1.00 0.00 H +ATOM 1899 HD13 LEU A 121 -32.353 4.494 -0.079 1.00 0.00 H +ATOM 1900 HD21 LEU A 121 -30.642 4.426 -2.710 1.00 0.00 H +ATOM 1901 HD22 LEU A 121 -31.150 2.986 -1.796 1.00 0.00 H +ATOM 1902 HD23 LEU A 121 -31.561 3.136 -3.521 1.00 0.00 H +ATOM 1903 N GLN A 122 -36.591 1.816 -2.645 1.00 8.96 N +ATOM 1904 CA GLN A 122 -37.547 0.731 -2.325 1.00 11.61 C +ATOM 1905 C GLN A 122 -37.682 -0.235 -3.496 1.00 12.20 C +ATOM 1906 O GLN A 122 -37.834 -1.448 -3.278 1.00 13.34 O +ATOM 1907 CB GLN A 122 -38.905 1.273 -1.899 1.00 15.33 C +ATOM 1908 CG GLN A 122 -39.798 0.118 -1.366 1.00 20.49 C +ATOM 1909 CD GLN A 122 -40.827 0.527 -0.343 1.00 22.32 C +ATOM 1910 OE1 GLN A 122 -40.846 1.660 0.121 1.00 24.99 O +ATOM 1911 NE2 GLN A 122 -41.699 -0.412 0.017 1.00 28.63 N +ATOM 1912 H GLN A 122 -36.893 2.780 -2.641 1.00 0.00 H +ATOM 1913 HA GLN A 122 -37.138 0.171 -1.484 1.00 0.00 H +ATOM 1914 HB3 GLN A 122 -39.392 1.744 -2.753 1.00 0.00 H +ATOM 1915 HB2 GLN A 122 -38.769 2.018 -1.115 1.00 0.00 H +ATOM 1916 HG3 GLN A 122 -39.164 -0.664 -0.947 1.00 0.00 H +ATOM 1917 HG2 GLN A 122 -40.297 -0.368 -2.204 1.00 0.00 H +ATOM 1918 HE22 GLN A 122 -42.414 -0.202 0.699 1.00 0.00 H +ATOM 1919 HE21 GLN A 122 -41.645 -1.334 -0.391 1.00 0.00 H +ATOM 1920 N GLN A 123 -37.598 0.293 -4.716 1.00 11.47 N +ATOM 1921 CA GLN A 123 -37.730 -0.544 -5.918 1.00 10.25 C +ATOM 1922 C GLN A 123 -36.419 -1.256 -6.290 1.00 11.40 C +ATOM 1923 O GLN A 123 -36.363 -1.994 -7.289 1.00 13.07 O +ATOM 1924 CB GLN A 123 -38.153 0.324 -7.103 1.00 12.93 C +ATOM 1925 CG GLN A 123 -39.564 0.866 -7.060 1.00 17.36 C +ATOM 1926 CD GLN A 123 -39.801 1.832 -8.234 1.00 17.11 C +ATOM 1927 OE1 GLN A 123 -38.931 2.645 -8.567 1.00 20.47 O +ATOM 1928 NE2 GLN A 123 -40.960 1.744 -8.852 1.00 37.76 N +ATOM 1929 H GLN A 123 -37.441 1.284 -4.827 1.00 0.00 H +ATOM 1930 HA GLN A 123 -38.500 -1.295 -5.740 1.00 0.00 H +ATOM 1931 HB3 GLN A 123 -38.011 -0.236 -8.027 1.00 0.00 H +ATOM 1932 HB2 GLN A 123 -37.453 1.152 -7.210 1.00 0.00 H +ATOM 1933 HG3 GLN A 123 -39.722 1.393 -6.119 1.00 0.00 H +ATOM 1934 HG2 GLN A 123 -40.272 0.040 -7.121 1.00 0.00 H +ATOM 1935 HE22 GLN A 123 -41.166 2.355 -9.629 1.00 0.00 H +ATOM 1936 HE21 GLN A 123 -41.644 1.065 -8.549 1.00 0.00 H +ATOM 1937 N LYS A 124 -35.344 -1.004 -5.538 1.00 10.74 N +ATOM 1938 CA LYS A 124 -34.024 -1.565 -5.806 1.00 10.90 C +ATOM 1939 C LYS A 124 -33.455 -1.190 -7.160 1.00 9.32 C +ATOM 1940 O LYS A 124 -32.703 -1.950 -7.762 1.00 10.64 O +ATOM 1941 CB LYS A 124 -34.006 -3.088 -5.577 1.00 10.83 C +ATOM 1942 CG LYS A 124 -34.473 -3.427 -4.149 1.00 11.23 C +ATOM 1943 CD LYS A 124 -34.075 -4.874 -3.781 1.00 13.89 C +ATOM 1944 CE LYS A 124 -34.571 -5.234 -2.397 1.00 12.96 C +ATOM 1945 NZ LYS A 124 -33.971 -4.316 -1.347 1.00 12.72 N +ATOM 1946 H LYS A 124 -35.421 -0.396 -4.735 1.00 0.00 H +ATOM 1947 HA LYS A 124 -33.352 -1.136 -5.062 1.00 0.00 H +ATOM 1948 HB3 LYS A 124 -32.995 -3.466 -5.727 1.00 0.00 H +ATOM 1949 HB2 LYS A 124 -34.665 -3.571 -6.299 1.00 0.00 H +ATOM 1950 HG3 LYS A 124 -35.556 -3.321 -4.087 1.00 0.00 H +ATOM 1951 HG2 LYS A 124 -34.015 -2.734 -3.443 1.00 0.00 H +ATOM 1952 HD3 LYS A 124 -32.990 -4.972 -3.814 1.00 0.00 H +ATOM 1953 HD2 LYS A 124 -34.500 -5.564 -4.510 1.00 0.00 H +ATOM 1954 HE3 LYS A 124 -34.303 -6.266 -2.172 1.00 0.00 H +ATOM 1955 HE2 LYS A 124 -35.658 -5.156 -2.369 1.00 0.00 H +ATOM 1956 HZ1 LYS A 124 -34.317 -4.576 -0.434 1.00 0.00 H +ATOM 1957 HZ2 LYS A 124 -32.965 -4.400 -1.362 1.00 0.00 H +ATOM 1958 HZ3 LYS A 124 -34.232 -3.361 -1.546 1.00 0.00 H +ATOM 1959 N ARG A 125 -33.792 0.025 -7.578 1.00 10.06 N +ATOM 1960 CA ARG A 125 -33.238 0.585 -8.808 1.00 9.81 C +ATOM 1961 C ARG A 125 -32.018 1.413 -8.411 1.00 9.27 C +ATOM 1962 O ARG A 125 -32.058 2.652 -8.312 1.00 10.93 O +ATOM 1963 CB ARG A 125 -34.302 1.391 -9.549 1.00 11.90 C +ATOM 1964 CG ARG A 125 -35.409 0.538 -10.182 1.00 12.58 C +ATOM 1965 CD ARG A 125 -36.581 1.400 -10.663 1.00 15.10 C +ATOM 1966 NE ARG A 125 -37.531 0.651 -11.494 1.00 19.92 N +ATOM 1967 CZ ARG A 125 -37.498 0.560 -12.832 1.00 0.00 C +ATOM 1968 NH1 ARG A 125 -36.563 1.188 -13.556 1.00 0.00 N +ATOM 1969 NH2 ARG A 125 -38.422 -0.175 -13.455 1.00 0.00 N +ATOM 1970 H ARG A 125 -34.443 0.581 -7.042 1.00 0.00 H +ATOM 1971 HA ARG A 125 -32.911 -0.234 -9.449 1.00 0.00 H +ATOM 1972 HB3 ARG A 125 -33.818 1.964 -10.337 1.00 0.00 H +ATOM 1973 HB2 ARG A 125 -34.736 2.126 -8.869 1.00 0.00 H +ATOM 1974 HG3 ARG A 125 -35.794 -0.102 -9.387 1.00 0.00 H +ATOM 1975 HG2 ARG A 125 -35.041 -0.133 -10.959 1.00 0.00 H +ATOM 1976 HD3 ARG A 125 -36.319 2.391 -11.035 1.00 0.00 H +ATOM 1977 HD2 ARG A 125 -37.161 1.585 -9.767 1.00 0.00 H +ATOM 1978 HE ARG A 125 -38.243 0.144 -10.986 1.00 0.00 H +ATOM 1979 HH11 ARG A 125 -36.549 1.116 -14.562 1.00 0.00 H +ATOM 1980 HH12 ARG A 125 -35.841 1.763 -13.116 1.00 0.00 H +ATOM 1981 HH21 ARG A 125 -38.425 -0.263 -14.461 1.00 0.00 H +ATOM 1982 HH22 ARG A 125 -39.140 -0.657 -12.935 1.00 0.00 H +ATOM 1984 N TRP A 126 -30.916 0.710 -8.174 1.00 9.13 N +ATOM 1985 CA TRP A 126 -29.805 1.340 -7.455 1.00 9.03 C +ATOM 1986 C TRP A 126 -29.093 2.428 -8.217 1.00 9.72 C +ATOM 1987 O TRP A 126 -28.754 3.460 -7.631 1.00 11.16 O +ATOM 1988 CB TRP A 126 -28.802 0.289 -6.997 1.00 9.41 C +ATOM 1989 CG TRP A 126 -29.385 -0.871 -6.239 1.00 10.06 C +ATOM 1990 CD1 TRP A 126 -29.256 -2.207 -6.558 1.00 10.56 C +ATOM 1991 CD2 TRP A 126 -30.154 -0.828 -5.012 1.00 8.67 C +ATOM 1992 NE1 TRP A 126 -29.895 -2.978 -5.618 1.00 10.63 N +ATOM 1993 CE2 TRP A 126 -30.461 -2.167 -4.664 1.00 9.55 C +ATOM 1994 CE3 TRP A 126 -30.619 0.202 -4.193 1.00 9.45 C +ATOM 1995 CZ2 TRP A 126 -31.170 -2.503 -3.521 1.00 10.91 C +ATOM 1996 CZ3 TRP A 126 -31.352 -0.129 -3.070 1.00 9.96 C +ATOM 1997 CH2 TRP A 126 -31.639 -1.477 -2.739 1.00 10.45 C +ATOM 1998 H TRP A 126 -30.851 -0.248 -8.488 1.00 0.00 H +ATOM 1999 HA TRP A 126 -30.222 1.797 -6.558 1.00 0.00 H +ATOM 2000 HB3 TRP A 126 -28.033 0.766 -6.390 1.00 0.00 H +ATOM 2001 HB2 TRP A 126 -28.252 -0.085 -7.861 1.00 0.00 H +ATOM 2002 HD1 TRP A 126 -28.711 -2.501 -7.443 1.00 0.00 H +ATOM 2003 HE1 TRP A 126 -29.892 -3.984 -5.704 1.00 0.00 H +ATOM 2004 HE3 TRP A 126 -30.403 1.230 -4.443 1.00 0.00 H +ATOM 2005 HZ2 TRP A 126 -31.336 -3.541 -3.274 1.00 0.00 H +ATOM 2006 HZ3 TRP A 126 -31.722 0.649 -2.418 1.00 0.00 H +ATOM 2007 HH2 TRP A 126 -32.232 -1.693 -1.863 1.00 0.00 H +ATOM 2008 N ASP A 127 -28.829 2.198 -9.502 1.00 10.84 N +ATOM 2009 CA ASP A 127 -28.135 3.231 -10.255 1.00 9.72 C +ATOM 2010 C ASP A 127 -29.019 4.449 -10.429 1.00 11.00 C +ATOM 2011 O ASP A 127 -28.529 5.592 -10.337 1.00 11.46 O +ATOM 2012 CB ASP A 127 -27.711 2.727 -11.641 1.00 11.86 C +ATOM 2013 CG ASP A 127 -26.495 1.802 -11.599 1.00 19.95 C +ATOM 2014 OD1 ASP A 127 -26.117 1.291 -10.524 1.00 21.66 O +ATOM 2015 OD2 ASP A 127 -25.932 1.506 -12.686 1.00 22.45 O +ATOM 2016 H ASP A 127 -29.109 1.326 -9.927 1.00 0.00 H +ATOM 2017 HA ASP A 127 -27.242 3.524 -9.703 1.00 0.00 H +ATOM 2018 HB3 ASP A 127 -27.495 3.579 -12.286 1.00 0.00 H +ATOM 2019 HB2 ASP A 127 -28.547 2.205 -12.108 1.00 0.00 H +ATOM 2020 N GLU A 128 -30.313 4.234 -10.647 1.00 11.40 N +ATOM 2021 CA GLU A 128 -31.212 5.373 -10.764 1.00 12.46 C +ATOM 2022 C GLU A 128 -31.288 6.135 -9.448 1.00 12.06 C +ATOM 2023 O GLU A 128 -31.317 7.373 -9.454 1.00 11.82 O +ATOM 2024 CB GLU A 128 -32.610 4.913 -11.164 1.00 15.53 C +ATOM 2025 CG GLU A 128 -32.648 4.349 -12.583 1.00 20.20 C +ATOM 2026 CD GLU A 128 -34.041 3.890 -12.936 1.00 23.65 C +ATOM 2027 OE1 GLU A 128 -34.825 4.713 -13.454 1.00 31.20 O +ATOM 2028 OE2 GLU A 128 -34.368 2.717 -12.662 1.00 24.17 O +ATOM 2029 H GLU A 128 -30.661 3.289 -10.729 1.00 0.00 H +ATOM 2030 HA GLU A 128 -30.830 6.043 -11.535 1.00 0.00 H +ATOM 2031 HB3 GLU A 128 -33.303 5.751 -11.088 1.00 0.00 H +ATOM 2032 HB2 GLU A 128 -32.956 4.154 -10.463 1.00 0.00 H +ATOM 2033 HG3 GLU A 128 -31.959 3.508 -12.658 1.00 0.00 H +ATOM 2034 HG2 GLU A 128 -32.330 5.117 -13.288 1.00 0.00 H +ATOM 2035 N ALA A 129 -31.363 5.409 -8.329 1.00 9.74 N +ATOM 2036 CA ALA A 129 -31.395 6.074 -7.022 1.00 9.87 C +ATOM 2037 C ALA A 129 -30.151 6.904 -6.832 1.00 10.55 C +ATOM 2038 O ALA A 129 -30.238 8.034 -6.336 1.00 10.45 O +ATOM 2039 CB ALA A 129 -31.467 5.040 -5.916 1.00 10.37 C +ATOM 2040 H ALA A 129 -31.398 4.401 -8.382 1.00 0.00 H +ATOM 2041 HA ALA A 129 -32.271 6.720 -6.968 1.00 0.00 H +ATOM 2042 HB1 ALA A 129 -31.490 5.543 -4.949 1.00 0.00 H +ATOM 2043 HB2 ALA A 129 -32.370 4.441 -6.036 1.00 0.00 H +ATOM 2044 HB3 ALA A 129 -30.592 4.391 -5.967 1.00 0.00 H +ATOM 2045 N ALA A 130 -29.006 6.339 -7.206 1.00 9.06 N +ATOM 2046 CA ALA A 130 -27.749 7.033 -7.011 1.00 10.78 C +ATOM 2047 C ALA A 130 -27.722 8.333 -7.816 1.00 12.30 C +ATOM 2048 O ALA A 130 -27.281 9.367 -7.302 1.00 11.99 O +ATOM 2049 CB ALA A 130 -26.598 6.132 -7.397 1.00 14.52 C +ATOM 2050 H ALA A 130 -29.010 5.422 -7.628 1.00 0.00 H +ATOM 2051 HA ALA A 130 -27.653 7.281 -5.954 1.00 0.00 H +ATOM 2052 HB1 ALA A 130 -25.656 6.660 -7.248 1.00 0.00 H +ATOM 2053 HB2 ALA A 130 -26.613 5.236 -6.777 1.00 0.00 H +ATOM 2054 HB3 ALA A 130 -26.693 5.849 -8.445 1.00 0.00 H +ATOM 2055 N VAL A 131 -28.210 8.291 -9.064 1.00 9.70 N +ATOM 2056 CA VAL A 131 -28.255 9.504 -9.881 1.00 11.06 C +ATOM 2057 C VAL A 131 -29.194 10.513 -9.232 1.00 12.72 C +ATOM 2058 O VAL A 131 -28.874 11.698 -9.117 1.00 13.39 O +ATOM 2059 CB VAL A 131 -28.721 9.174 -11.307 1.00 12.24 C +ATOM 2060 CG1 VAL A 131 -29.054 10.451 -12.077 1.00 17.06 C +ATOM 2061 CG2 VAL A 131 -27.636 8.386 -12.017 1.00 15.82 C +ATOM 2062 H VAL A 131 -28.549 7.419 -9.445 1.00 0.00 H +ATOM 2063 HA VAL A 131 -27.254 9.934 -9.928 1.00 0.00 H +ATOM 2064 HB VAL A 131 -29.618 8.558 -11.248 1.00 0.00 H +ATOM 2065 HG11 VAL A 131 -29.382 10.194 -13.084 1.00 0.00 H +ATOM 2066 HG12 VAL A 131 -29.850 10.989 -11.563 1.00 0.00 H +ATOM 2067 HG13 VAL A 131 -28.168 11.083 -12.134 1.00 0.00 H +ATOM 2068 HG21 VAL A 131 -27.962 8.149 -13.030 1.00 0.00 H +ATOM 2069 HG22 VAL A 131 -26.723 8.980 -12.059 1.00 0.00 H +ATOM 2070 HG23 VAL A 131 -27.442 7.462 -11.473 1.00 0.00 H +ATOM 2071 N ASN A 132 -30.354 10.062 -8.774 1.00 9.79 N +ATOM 2072 CA ASN A 132 -31.290 11.006 -8.176 1.00 9.18 C +ATOM 2073 C ASN A 132 -30.783 11.638 -6.883 1.00 10.67 C +ATOM 2074 O ASN A 132 -30.997 12.812 -6.645 1.00 11.34 O +ATOM 2075 CB ASN A 132 -32.649 10.319 -7.961 1.00 11.16 C +ATOM 2076 CG ASN A 132 -33.726 11.289 -7.538 1.00 13.80 C +ATOM 2077 OD1 ASN A 132 -34.011 11.487 -6.341 1.00 15.04 O +ATOM 2078 ND2 ASN A 132 -34.314 11.951 -8.529 1.00 15.72 N +ATOM 2079 H ASN A 132 -30.576 9.079 -8.843 1.00 0.00 H +ATOM 2080 HA ASN A 132 -31.443 11.812 -8.894 1.00 0.00 H +ATOM 2081 HB3 ASN A 132 -32.546 9.540 -7.205 1.00 0.00 H +ATOM 2082 HB2 ASN A 132 -32.952 9.820 -8.881 1.00 0.00 H +ATOM 2083 HD22 ASN A 132 -35.045 12.618 -8.327 1.00 0.00 H +ATOM 2084 HD21 ASN A 132 -34.030 11.787 -9.484 1.00 0.00 H +ATOM 2085 N LEU A 133 -30.123 10.829 -6.051 1.00 9.82 N +ATOM 2086 CA LEU A 133 -29.618 11.305 -4.764 1.00 9.73 C +ATOM 2087 C LEU A 133 -28.620 12.418 -4.954 1.00 11.56 C +ATOM 2088 O LEU A 133 -28.538 13.301 -4.089 1.00 12.22 O +ATOM 2089 CB LEU A 133 -28.981 10.150 -3.964 1.00 10.25 C +ATOM 2090 CG LEU A 133 -29.943 9.177 -3.280 1.00 9.93 C +ATOM 2091 CD1 LEU A 133 -29.214 7.873 -2.962 1.00 9.87 C +ATOM 2092 CD2 LEU A 133 -30.534 9.764 -2.002 1.00 12.27 C +ATOM 2093 H LEU A 133 -29.963 9.865 -6.305 1.00 0.00 H +ATOM 2094 HA LEU A 133 -30.459 11.695 -4.190 1.00 0.00 H +ATOM 2095 HB3 LEU A 133 -28.299 10.562 -3.221 1.00 0.00 H +ATOM 2096 HB2 LEU A 133 -28.308 9.591 -4.614 1.00 0.00 H +ATOM 2097 HG LEU A 133 -30.759 8.957 -3.968 1.00 0.00 H +ATOM 2098 HD11 LEU A 133 -29.901 7.181 -2.475 1.00 0.00 H +ATOM 2099 HD12 LEU A 133 -28.845 7.428 -3.886 1.00 0.00 H +ATOM 2100 HD13 LEU A 133 -28.374 8.078 -2.298 1.00 0.00 H +ATOM 2101 HD21 LEU A 133 -31.211 9.040 -1.548 1.00 0.00 H +ATOM 2102 HD22 LEU A 133 -29.731 9.997 -1.303 1.00 0.00 H +ATOM 2103 HD23 LEU A 133 -31.083 10.675 -2.240 1.00 0.00 H +ATOM 2104 N ALA A 134 -27.858 12.367 -6.046 1.00 10.28 N +ATOM 2105 CA ALA A 134 -26.842 13.390 -6.318 1.00 11.26 C +ATOM 2106 C ALA A 134 -27.415 14.717 -6.808 1.00 11.68 C +ATOM 2107 O ALA A 134 -26.683 15.725 -6.802 1.00 13.42 O +ATOM 2108 CB ALA A 134 -25.778 12.857 -7.287 1.00 12.62 C +ATOM 2109 H ALA A 134 -27.973 11.613 -6.708 1.00 0.00 H +ATOM 2110 HA ALA A 134 -26.337 13.593 -5.374 1.00 0.00 H +ATOM 2111 HB1 ALA A 134 -25.035 13.632 -7.474 1.00 0.00 H +ATOM 2112 HB2 ALA A 134 -25.291 11.986 -6.849 1.00 0.00 H +ATOM 2113 HB3 ALA A 134 -26.251 12.574 -8.227 1.00 0.00 H +ATOM 2114 N LYS A 135 -28.682 14.724 -7.212 1.00 10.84 N +ATOM 2115 CA LYS A 135 -29.357 15.964 -7.644 1.00 11.45 C +ATOM 2116 C LYS A 135 -29.892 16.692 -6.413 1.00 10.69 C +ATOM 2117 O LYS A 135 -31.094 16.791 -6.200 1.00 12.16 O +ATOM 2118 CB LYS A 135 -30.486 15.651 -8.633 1.00 11.68 C +ATOM 2119 CG LYS A 135 -29.953 15.050 -9.901 1.00 14.35 C +ATOM 2120 CD LYS A 135 -31.092 14.664 -10.827 1.00 19.41 C +ATOM 2121 CE LYS A 135 -30.583 13.829 -11.985 1.00 27.57 C +ATOM 2122 NZ LYS A 135 -31.721 13.512 -12.899 1.00 26.15 N +ATOM 2123 H LYS A 135 -29.211 13.864 -7.229 1.00 0.00 H +ATOM 2124 HA LYS A 135 -28.627 16.605 -8.139 1.00 0.00 H +ATOM 2125 HB3 LYS A 135 -31.029 16.567 -8.866 1.00 0.00 H +ATOM 2126 HB2 LYS A 135 -31.191 14.959 -8.172 1.00 0.00 H +ATOM 2127 HG3 LYS A 135 -29.363 14.165 -9.663 1.00 0.00 H +ATOM 2128 HG2 LYS A 135 -29.307 15.772 -10.401 1.00 0.00 H +ATOM 2129 HD3 LYS A 135 -31.569 15.566 -11.212 1.00 0.00 H +ATOM 2130 HD2 LYS A 135 -31.836 14.096 -10.269 1.00 0.00 H +ATOM 2131 HE3 LYS A 135 -30.155 12.902 -11.604 1.00 0.00 H +ATOM 2132 HE2 LYS A 135 -29.824 14.390 -12.531 1.00 0.00 H +ATOM 2133 HZ1 LYS A 135 -31.387 12.955 -13.673 1.00 0.00 H +ATOM 2134 HZ2 LYS A 135 -32.426 12.995 -12.393 1.00 0.00 H +ATOM 2135 HZ3 LYS A 135 -32.121 14.371 -13.250 1.00 0.00 H +ATOM 2136 N SER A 136 -28.983 17.137 -5.562 1.00 9.72 N +ATOM 2137 CA SER A 136 -29.398 17.617 -4.240 1.00 8.18 C +ATOM 2138 C SER A 136 -28.431 18.644 -3.693 1.00 9.54 C +ATOM 2139 O SER A 136 -27.234 18.603 -3.997 1.00 9.39 O +ATOM 2140 CB SER A 136 -29.473 16.447 -3.221 1.00 9.86 C +ATOM 2141 OG SER A 136 -28.198 15.820 -3.071 1.00 10.30 O +ATOM 2142 H SER A 136 -28.008 17.145 -5.824 1.00 0.00 H +ATOM 2143 HA SER A 136 -30.384 18.073 -4.325 1.00 0.00 H +ATOM 2144 HB3 SER A 136 -30.201 15.712 -3.565 1.00 0.00 H +ATOM 2145 HB2 SER A 136 -29.806 16.827 -2.255 1.00 0.00 H +ATOM 2146 HG SER A 136 -28.267 15.101 -2.438 1.00 0.00 H +ATOM 2147 N ARG A 137 -28.938 19.540 -2.848 1.00 8.79 N +ATOM 2148 CA ARG A 137 -28.049 20.428 -2.117 1.00 8.58 C +ATOM 2149 C ARG A 137 -27.063 19.615 -1.295 1.00 9.48 C +ATOM 2150 O ARG A 137 -25.864 19.949 -1.214 1.00 11.67 O +ATOM 2151 CB ARG A 137 -28.845 21.374 -1.213 1.00 9.54 C +ATOM 2152 CG ARG A 137 -27.875 22.305 -0.421 1.00 13.10 C +ATOM 2153 CD ARG A 137 -28.577 23.288 0.493 1.00 16.72 C +ATOM 2154 NE ARG A 137 -27.616 24.228 1.089 1.00 17.53 N +ATOM 2155 CZ ARG A 137 -26.854 23.961 2.152 1.00 18.49 C +ATOM 2156 NH1 ARG A 137 -26.918 22.792 2.767 1.00 19.80 N +ATOM 2157 NH2 ARG A 137 -26.012 24.888 2.598 1.00 21.79 N +ATOM 2158 H ARG A 137 -29.938 19.601 -2.717 1.00 0.00 H +ATOM 2159 HA ARG A 137 -27.489 21.026 -2.836 1.00 0.00 H +ATOM 2160 HB3 ARG A 137 -29.441 20.790 -0.512 1.00 0.00 H +ATOM 2161 HB2 ARG A 137 -29.514 21.981 -1.823 1.00 0.00 H +ATOM 2162 HG3 ARG A 137 -27.244 22.851 -1.123 1.00 0.00 H +ATOM 2163 HG2 ARG A 137 -27.186 21.696 0.164 1.00 0.00 H +ATOM 2164 HD3 ARG A 137 -29.091 22.744 1.285 1.00 0.00 H +ATOM 2165 HD2 ARG A 137 -29.323 23.843 -0.076 1.00 0.00 H +ATOM 2166 HE ARG A 137 -27.554 25.129 0.637 1.00 0.00 H +ATOM 2167 HH12 ARG A 137 -26.332 22.611 3.570 1.00 0.00 H +ATOM 2168 HH11 ARG A 137 -27.553 22.080 2.434 1.00 0.00 H +ATOM 2169 HH21 ARG A 137 -25.430 24.697 3.401 1.00 0.00 H +ATOM 2170 HH22 ARG A 137 -25.954 25.783 2.133 1.00 0.00 H +ATOM 2171 N TRP A 138 -27.546 18.518 -0.699 1.00 9.35 N +ATOM 2172 CA TRP A 138 -26.677 17.644 0.066 1.00 9.98 C +ATOM 2173 C TRP A 138 -25.415 17.267 -0.702 1.00 11.06 C +ATOM 2174 O TRP A 138 -24.284 17.414 -0.198 1.00 12.31 O +ATOM 2175 CB TRP A 138 -27.483 16.384 0.378 1.00 9.95 C +ATOM 2176 CG TRP A 138 -26.731 15.268 1.009 1.00 9.03 C +ATOM 2177 CD1 TRP A 138 -25.990 15.323 2.173 1.00 12.24 C +ATOM 2178 CD2 TRP A 138 -26.715 13.908 0.579 1.00 8.60 C +ATOM 2179 NE1 TRP A 138 -25.507 14.056 2.476 1.00 11.68 N +ATOM 2180 CE2 TRP A 138 -25.948 13.175 1.525 1.00 8.37 C +ATOM 2181 CE3 TRP A 138 -27.284 13.226 -0.502 1.00 9.69 C +ATOM 2182 CZ2 TRP A 138 -25.725 11.818 1.417 1.00 9.38 C +ATOM 2183 CZ3 TRP A 138 -27.070 11.848 -0.605 1.00 11.32 C +ATOM 2184 CH2 TRP A 138 -26.285 11.161 0.352 1.00 11.10 C +ATOM 2185 H TRP A 138 -28.527 18.290 -0.779 1.00 0.00 H +ATOM 2186 HA TRP A 138 -26.400 18.136 0.998 1.00 0.00 H +ATOM 2187 HB3 TRP A 138 -27.959 16.026 -0.535 1.00 0.00 H +ATOM 2188 HB2 TRP A 138 -28.332 16.647 1.009 1.00 0.00 H +ATOM 2189 HD1 TRP A 138 -25.867 16.263 2.691 1.00 0.00 H +ATOM 2190 HE1 TRP A 138 -24.930 13.918 3.293 1.00 0.00 H +ATOM 2191 HE3 TRP A 138 -27.872 13.764 -1.231 1.00 0.00 H +ATOM 2192 HZ2 TRP A 138 -25.126 11.309 2.157 1.00 0.00 H +ATOM 2193 HZ3 TRP A 138 -27.506 11.293 -1.423 1.00 0.00 H +ATOM 2194 HH2 TRP A 138 -26.131 10.099 0.231 1.00 0.00 H +ATOM 2195 N TYR A 139 -25.577 16.762 -1.909 1.00 9.45 N +ATOM 2196 CA TYR A 139 -24.434 16.322 -2.678 1.00 8.54 C +ATOM 2197 C TYR A 139 -23.543 17.516 -3.033 1.00 11.49 C +ATOM 2198 O TYR A 139 -22.301 17.430 -2.949 1.00 13.34 O +ATOM 2199 CB TYR A 139 -24.927 15.615 -3.939 1.00 12.25 C +ATOM 2200 CG TYR A 139 -23.877 15.191 -4.921 1.00 12.34 C +ATOM 2201 CD1 TYR A 139 -23.263 13.954 -4.821 1.00 15.22 C +ATOM 2202 CD2 TYR A 139 -23.552 16.016 -5.984 1.00 18.94 C +ATOM 2203 CE1 TYR A 139 -22.324 13.556 -5.766 1.00 18.88 C +ATOM 2204 CE2 TYR A 139 -22.622 15.633 -6.928 1.00 25.02 C +ATOM 2205 CZ TYR A 139 -22.015 14.401 -6.810 1.00 26.38 C +ATOM 2206 OH TYR A 139 -21.074 14.023 -7.753 1.00 41.59 O +ATOM 2207 H TYR A 139 -26.504 16.680 -2.302 1.00 0.00 H +ATOM 2208 HA TYR A 139 -23.857 15.616 -2.080 1.00 0.00 H +ATOM 2209 HB3 TYR A 139 -25.656 16.249 -4.444 1.00 0.00 H +ATOM 2210 HB2 TYR A 139 -25.524 14.748 -3.655 1.00 0.00 H +ATOM 2211 HD1 TYR A 139 -23.513 13.292 -4.005 1.00 0.00 H +ATOM 2212 HD2 TYR A 139 -24.030 16.979 -6.086 1.00 0.00 H +ATOM 2213 HE1 TYR A 139 -21.844 12.592 -5.678 1.00 0.00 H +ATOM 2214 HE2 TYR A 139 -22.378 16.295 -7.746 1.00 0.00 H +ATOM 2215 HH TYR A 139 -20.978 14.719 -8.407 1.00 0.00 H +ATOM 2216 N ASN A 140 -24.155 18.629 -3.443 1.00 9.45 N +ATOM 2217 CA ASN A 140 -23.337 19.743 -3.864 1.00 10.94 C +ATOM 2218 C ASN A 140 -22.553 20.393 -2.715 1.00 11.92 C +ATOM 2219 O ASN A 140 -21.408 20.857 -2.909 1.00 13.99 O +ATOM 2220 CB ASN A 140 -24.197 20.783 -4.584 1.00 12.05 C +ATOM 2221 CG ASN A 140 -24.582 20.323 -5.965 1.00 15.24 C +ATOM 2222 OD1 ASN A 140 -25.704 19.864 -6.227 1.00 18.24 O +ATOM 2223 ND2 ASN A 140 -23.619 20.399 -6.873 1.00 17.11 N +ATOM 2224 H ASN A 140 -25.164 18.676 -3.453 1.00 0.00 H +ATOM 2225 HA ASN A 140 -22.611 19.363 -4.583 1.00 0.00 H +ATOM 2226 HB3 ASN A 140 -23.648 21.722 -4.654 1.00 0.00 H +ATOM 2227 HB2 ASN A 140 -25.098 20.975 -4.001 1.00 0.00 H +ATOM 2228 HD22 ASN A 140 -23.798 20.109 -7.824 1.00 0.00 H +ATOM 2229 HD21 ASN A 140 -22.707 20.747 -6.614 1.00 0.00 H +ATOM 2230 N GLN A 141 -23.125 20.394 -1.513 1.00 8.33 N +ATOM 2231 CA GLN A 141 -22.451 21.036 -0.385 1.00 8.31 C +ATOM 2232 C GLN A 141 -21.447 20.121 0.309 1.00 11.58 C +ATOM 2233 O GLN A 141 -20.430 20.594 0.840 1.00 13.79 O +ATOM 2234 CB GLN A 141 -23.466 21.554 0.630 1.00 12.16 C +ATOM 2235 CG GLN A 141 -24.430 22.587 0.061 1.00 14.81 C +ATOM 2236 CD GLN A 141 -23.749 23.853 -0.470 1.00 13.29 C +ATOM 2237 OE1 GLN A 141 -23.989 24.249 -1.622 1.00 17.92 O +ATOM 2238 NE2 GLN A 141 -22.852 24.429 0.334 1.00 17.61 N +ATOM 2239 H GLN A 141 -24.023 19.952 -1.381 1.00 0.00 H +ATOM 2240 HA GLN A 141 -21.903 21.895 -0.772 1.00 0.00 H +ATOM 2241 HB3 GLN A 141 -22.939 21.982 1.482 1.00 0.00 H +ATOM 2242 HB2 GLN A 141 -24.032 20.715 1.035 1.00 0.00 H +ATOM 2243 HG3 GLN A 141 -25.158 22.861 0.825 1.00 0.00 H +ATOM 2244 HG2 GLN A 141 -25.018 22.132 -0.736 1.00 0.00 H +ATOM 2245 HE22 GLN A 141 -22.371 25.266 0.037 1.00 0.00 H +ATOM 2246 HE21 GLN A 141 -22.654 24.028 1.239 1.00 0.00 H +ATOM 2247 N THR A 142 -21.726 18.818 0.355 1.00 10.11 N +ATOM 2248 CA THR A 142 -20.785 17.865 0.967 1.00 11.26 C +ATOM 2249 C THR A 142 -20.578 16.714 -0.012 1.00 11.92 C +ATOM 2250 O THR A 142 -21.028 15.571 0.217 1.00 10.58 O +ATOM 2251 CB THR A 142 -21.227 17.328 2.383 1.00 11.30 C +ATOM 2252 OG1 THR A 142 -22.561 16.799 2.313 1.00 13.59 O +ATOM 2253 CG2 THR A 142 -21.222 18.433 3.434 1.00 12.07 C +ATOM 2254 H THR A 142 -22.592 18.473 -0.033 1.00 0.00 H +ATOM 2255 HA THR A 142 -19.829 18.374 1.088 1.00 0.00 H +ATOM 2256 HB THR A 142 -20.545 16.537 2.694 1.00 0.00 H +ATOM 2257 HG1 THR A 142 -22.823 16.474 3.178 1.00 0.00 H +ATOM 2258 HG21 THR A 142 -21.532 18.023 4.395 1.00 0.00 H +ATOM 2259 HG22 THR A 142 -20.217 18.846 3.523 1.00 0.00 H +ATOM 2260 HG23 THR A 142 -21.913 19.222 3.136 1.00 0.00 H +ATOM 2261 N PRO A 143 -19.872 16.974 -1.111 1.00 9.72 N +ATOM 2262 CA PRO A 143 -19.845 15.956 -2.169 1.00 8.94 C +ATOM 2263 C PRO A 143 -19.020 14.737 -1.810 1.00 10.10 C +ATOM 2264 O PRO A 143 -19.393 13.630 -2.197 1.00 10.26 O +ATOM 2265 CB PRO A 143 -19.241 16.691 -3.383 1.00 10.57 C +ATOM 2266 CG PRO A 143 -18.526 17.864 -2.772 1.00 10.55 C +ATOM 2267 CD PRO A 143 -19.353 18.273 -1.585 1.00 10.05 C +ATOM 2268 HA PRO A 143 -20.864 15.648 -2.402 1.00 0.00 H +ATOM 2269 HB3 PRO A 143 -20.046 17.053 -4.022 1.00 0.00 H +ATOM 2270 HB2 PRO A 143 -18.515 16.042 -3.873 1.00 0.00 H +ATOM 2271 HG3 PRO A 143 -18.494 18.683 -3.491 1.00 0.00 H +ATOM 2272 HG2 PRO A 143 -17.538 17.550 -2.434 1.00 0.00 H +ATOM 2273 HD2 PRO A 143 -18.700 18.698 -0.823 1.00 0.00 H +ATOM 2274 HD3 PRO A 143 -20.186 18.890 -1.924 1.00 0.00 H +ATOM 2275 N ASN A 144 -17.909 14.884 -1.102 1.00 9.89 N +ATOM 2276 CA ASN A 144 -17.131 13.674 -0.820 1.00 10.59 C +ATOM 2277 C ASN A 144 -17.890 12.709 0.096 1.00 8.57 C +ATOM 2278 O ASN A 144 -17.883 11.497 -0.147 1.00 10.12 O +ATOM 2279 CB ASN A 144 -15.769 14.016 -0.225 1.00 11.33 C +ATOM 2280 CG ASN A 144 -14.825 14.617 -1.265 1.00 16.00 C +ATOM 2281 OD1 ASN A 144 -15.135 14.642 -2.454 1.00 22.70 O +ATOM 2282 ND2 ASN A 144 -13.655 15.026 -0.826 1.00 18.94 N +ATOM 2283 H ASN A 144 -17.632 15.801 -0.782 1.00 0.00 H +ATOM 2284 HA ASN A 144 -16.959 13.164 -1.768 1.00 0.00 H +ATOM 2285 HB3 ASN A 144 -15.320 13.116 0.195 1.00 0.00 H +ATOM 2286 HB2 ASN A 144 -15.899 14.720 0.597 1.00 0.00 H +ATOM 2287 HD22 ASN A 144 -12.989 15.432 -1.467 1.00 0.00 H +ATOM 2288 HD21 ASN A 144 -13.422 14.934 0.153 1.00 0.00 H +ATOM 2289 N ARG A 145 -18.547 13.262 1.107 1.00 8.42 N +ATOM 2290 CA ARG A 145 -19.332 12.416 2.001 1.00 8.88 C +ATOM 2291 C ARG A 145 -20.550 11.870 1.267 1.00 9.47 C +ATOM 2292 O ARG A 145 -20.859 10.672 1.394 1.00 9.46 O +ATOM 2293 CB ARG A 145 -19.782 13.184 3.224 1.00 10.16 C +ATOM 2294 CG ARG A 145 -20.403 12.213 4.231 1.00 15.20 C +ATOM 2295 CD ARG A 145 -21.443 12.887 4.893 1.00 20.27 C +ATOM 2296 NE ARG A 145 -22.050 12.106 5.963 1.00 12.68 N +ATOM 2297 CZ ARG A 145 -22.159 12.591 7.180 1.00 12.04 C +ATOM 2298 NH1 ARG A 145 -21.663 13.800 7.487 1.00 16.30 N +ATOM 2299 NH2 ARG A 145 -22.815 11.902 8.093 1.00 10.91 N +ATOM 2300 H ARG A 145 -18.502 14.260 1.253 1.00 0.00 H +ATOM 2301 HA ARG A 145 -18.713 11.578 2.322 1.00 0.00 H +ATOM 2302 HB3 ARG A 145 -20.523 13.928 2.933 1.00 0.00 H +ATOM 2303 HB2 ARG A 145 -18.923 13.678 3.678 1.00 0.00 H +ATOM 2304 HG3 ARG A 145 -19.648 11.910 4.956 1.00 0.00 H +ATOM 2305 HG2 ARG A 145 -20.809 11.351 3.701 1.00 0.00 H +ATOM 2306 HD3 ARG A 145 -22.209 13.168 4.171 1.00 0.00 H +ATOM 2307 HD2 ARG A 145 -21.065 13.825 5.299 1.00 0.00 H +ATOM 2308 HE ARG A 145 -22.390 11.177 5.757 1.00 0.00 H +ATOM 2309 HH12 ARG A 145 -21.754 14.160 8.426 1.00 0.00 H +ATOM 2310 HH11 ARG A 145 -21.199 14.350 6.779 1.00 0.00 H +ATOM 2311 HH21 ARG A 145 -22.905 12.265 9.031 1.00 0.00 H +ATOM 2312 HH22 ARG A 145 -23.227 11.012 7.854 1.00 0.00 H +ATOM 2313 N ALA A 146 -21.255 12.720 0.516 1.00 8.80 N +ATOM 2314 CA ALA A 146 -22.425 12.229 -0.207 1.00 8.81 C +ATOM 2315 C ALA A 146 -22.034 11.151 -1.179 1.00 9.79 C +ATOM 2316 O ALA A 146 -22.753 10.145 -1.305 1.00 11.13 O +ATOM 2317 CB ALA A 146 -23.183 13.373 -0.950 1.00 10.64 C +ATOM 2318 H ALA A 146 -20.977 13.689 0.453 1.00 0.00 H +ATOM 2319 HA ALA A 146 -23.109 11.792 0.520 1.00 0.00 H +ATOM 2320 HB1 ALA A 146 -24.045 12.959 -1.473 1.00 0.00 H +ATOM 2321 HB2 ALA A 146 -23.520 14.116 -0.227 1.00 0.00 H +ATOM 2322 HB3 ALA A 146 -22.514 13.845 -1.670 1.00 0.00 H +ATOM 2323 N LYS A 147 -20.906 11.316 -1.877 1.00 9.35 N +ATOM 2324 CA LYS A 147 -20.464 10.280 -2.808 1.00 9.74 C +ATOM 2325 C LYS A 147 -20.243 8.953 -2.086 1.00 9.19 C +ATOM 2326 O LYS A 147 -20.573 7.892 -2.638 1.00 10.60 O +ATOM 2327 CB LYS A 147 -19.182 10.692 -3.556 1.00 11.55 C +ATOM 2328 CG LYS A 147 -19.397 11.771 -4.627 1.00 14.82 C +ATOM 2329 CD LYS A 147 -18.093 12.488 -5.007 1.00 20.88 C +ATOM 2330 CE LYS A 147 -18.325 13.661 -5.966 1.00 23.76 C +ATOM 2331 NZ LYS A 147 -17.087 14.429 -6.174 1.00 0.00 N +ATOM 2332 H LYS A 147 -20.359 12.157 -1.761 1.00 0.00 H +ATOM 2333 HA LYS A 147 -21.252 10.134 -3.547 1.00 0.00 H +ATOM 2334 HB3 LYS A 147 -18.741 9.823 -4.047 1.00 0.00 H +ATOM 2335 HB2 LYS A 147 -18.444 11.023 -2.824 1.00 0.00 H +ATOM 2336 HG3 LYS A 147 -20.120 12.503 -4.270 1.00 0.00 H +ATOM 2337 HG2 LYS A 147 -19.841 11.318 -5.514 1.00 0.00 H +ATOM 2338 HD3 LYS A 147 -17.404 11.775 -5.462 1.00 0.00 H +ATOM 2339 HD2 LYS A 147 -17.600 12.853 -4.105 1.00 0.00 H +ATOM 2340 HE2 LYS A 147 -18.683 13.297 -6.929 1.00 0.00 H +ATOM 2341 HE3 LYS A 147 -19.086 14.333 -5.568 1.00 0.00 H +ATOM 2342 HZ1 LYS A 147 -16.752 14.779 -5.288 1.00 0.00 H +ATOM 2343 HZ2 LYS A 147 -16.383 13.833 -6.583 1.00 0.00 H +ATOM 2344 HZ3 LYS A 147 -17.269 15.203 -6.794 1.00 0.00 H +ATOM 2345 N ARG A 148 -19.696 8.983 -0.867 1.00 9.28 N +ATOM 2346 CA ARG A 148 -19.492 7.712 -0.135 1.00 8.19 C +ATOM 2347 C ARG A 148 -20.806 7.056 0.224 1.00 9.02 C +ATOM 2348 O ARG A 148 -20.948 5.847 0.094 1.00 9.51 O +ATOM 2349 CB ARG A 148 -18.668 7.894 1.137 1.00 7.47 C +ATOM 2350 CG ARG A 148 -17.210 8.252 0.888 1.00 8.84 C +ATOM 2351 CD ARG A 148 -16.392 8.145 2.189 1.00 9.25 C +ATOM 2352 NE ARG A 148 -16.709 9.216 3.140 1.00 9.79 N +ATOM 2353 CZ ARG A 148 -16.125 10.415 3.148 1.00 10.35 C +ATOM 2354 NH1 ARG A 148 -15.204 10.730 2.213 1.00 12.18 N +ATOM 2355 NH2 ARG A 148 -16.485 11.306 4.073 1.00 11.16 N +ATOM 2356 H ARG A 148 -19.427 9.865 -0.456 1.00 0.00 H +ATOM 2357 HA ARG A 148 -18.948 7.033 -0.791 1.00 0.00 H +ATOM 2358 HB3 ARG A 148 -18.720 6.984 1.734 1.00 0.00 H +ATOM 2359 HB2 ARG A 148 -19.128 8.663 1.758 1.00 0.00 H +ATOM 2360 HG3 ARG A 148 -17.147 9.269 0.502 1.00 0.00 H +ATOM 2361 HG2 ARG A 148 -16.793 7.577 0.141 1.00 0.00 H +ATOM 2362 HD3 ARG A 148 -15.329 8.174 1.952 1.00 0.00 H +ATOM 2363 HD2 ARG A 148 -16.579 7.178 2.656 1.00 0.00 H +ATOM 2364 HE ARG A 148 -17.422 8.997 3.821 1.00 0.00 H +ATOM 2365 HH12 ARG A 148 -14.765 11.639 2.223 1.00 0.00 H +ATOM 2366 HH11 ARG A 148 -14.954 10.056 1.503 1.00 0.00 H +ATOM 2367 HH21 ARG A 148 -16.051 12.218 4.091 1.00 0.00 H +ATOM 2368 HH22 ARG A 148 -17.191 11.069 4.755 1.00 0.00 H +ATOM 2369 N VAL A 149 -21.741 7.863 0.693 1.00 9.50 N +ATOM 2370 CA VAL A 149 -23.035 7.332 1.118 1.00 8.37 C +ATOM 2371 C VAL A 149 -23.768 6.817 -0.130 1.00 9.51 C +ATOM 2372 O VAL A 149 -24.334 5.718 -0.111 1.00 8.99 O +ATOM 2373 CB VAL A 149 -23.831 8.425 1.817 1.00 7.77 C +ATOM 2374 CG1 VAL A 149 -25.294 7.952 2.088 1.00 10.72 C +ATOM 2375 CG2 VAL A 149 -23.123 8.772 3.136 1.00 9.23 C +ATOM 2376 H VAL A 149 -21.565 8.855 0.760 1.00 0.00 H +ATOM 2377 HA VAL A 149 -22.875 6.504 1.809 1.00 0.00 H +ATOM 2378 HB VAL A 149 -23.855 9.310 1.182 1.00 0.00 H +ATOM 2379 HG11 VAL A 149 -25.847 8.747 2.588 1.00 0.00 H +ATOM 2380 HG12 VAL A 149 -25.780 7.712 1.142 1.00 0.00 H +ATOM 2381 HG13 VAL A 149 -25.278 7.066 2.723 1.00 0.00 H +ATOM 2382 HG21 VAL A 149 -23.679 9.555 3.652 1.00 0.00 H +ATOM 2383 HG22 VAL A 149 -23.074 7.885 3.767 1.00 0.00 H +ATOM 2384 HG23 VAL A 149 -22.113 9.123 2.925 1.00 0.00 H +ATOM 2385 N ILE A 150 -23.719 7.571 -1.224 1.00 8.85 N +ATOM 2386 CA ILE A 150 -24.377 7.134 -2.461 1.00 7.78 C +ATOM 2387 C ILE A 150 -23.768 5.855 -3.009 1.00 10.48 C +ATOM 2388 O ILE A 150 -24.495 4.967 -3.473 1.00 10.59 O +ATOM 2389 CB ILE A 150 -24.378 8.264 -3.529 1.00 9.11 C +ATOM 2390 CG1 ILE A 150 -25.263 9.405 -3.041 1.00 10.75 C +ATOM 2391 CG2 ILE A 150 -24.881 7.738 -4.887 1.00 12.20 C +ATOM 2392 CD1 ILE A 150 -25.158 10.684 -3.904 1.00 10.73 C +ATOM 2393 H ILE A 150 -23.226 8.452 -1.208 1.00 0.00 H +ATOM 2394 HA ILE A 150 -25.417 6.919 -2.216 1.00 0.00 H +ATOM 2395 HB ILE A 150 -23.360 8.635 -3.650 1.00 0.00 H +ATOM 2396 HG13 ILE A 150 -25.009 9.644 -2.008 1.00 0.00 H +ATOM 2397 HG12 ILE A 150 -26.300 9.072 -3.013 1.00 0.00 H +ATOM 2398 HG21 ILE A 150 -24.872 8.548 -5.617 1.00 0.00 H +ATOM 2399 HG22 ILE A 150 -24.230 6.934 -5.229 1.00 0.00 H +ATOM 2400 HG23 ILE A 150 -25.897 7.360 -4.777 1.00 0.00 H +ATOM 2401 HD11 ILE A 150 -25.815 11.453 -3.497 1.00 0.00 H +ATOM 2402 HD12 ILE A 150 -24.129 11.045 -3.896 1.00 0.00 H +ATOM 2403 HD13 ILE A 150 -25.455 10.457 -4.928 1.00 0.00 H +ATOM 2404 N THR A 151 -22.440 5.730 -2.966 1.00 10.86 N +ATOM 2405 CA THR A 151 -21.811 4.494 -3.455 1.00 10.52 C +ATOM 2406 C THR A 151 -22.277 3.321 -2.611 1.00 11.49 C +ATOM 2407 O THR A 151 -22.444 2.198 -3.119 1.00 11.34 O +ATOM 2408 CB THR A 151 -20.294 4.607 -3.395 1.00 11.50 C +ATOM 2409 OG1 THR A 151 -19.906 5.508 -4.437 1.00 15.21 O +ATOM 2410 CG2 THR A 151 -19.604 3.247 -3.643 1.00 13.51 C +ATOM 2411 H THR A 151 -21.874 6.482 -2.599 1.00 0.00 H +ATOM 2412 HA THR A 151 -22.113 4.328 -4.489 1.00 0.00 H +ATOM 2413 HB THR A 151 -19.990 5.006 -2.427 1.00 0.00 H +ATOM 2414 HG1 THR A 151 -18.951 5.608 -4.435 1.00 0.00 H +ATOM 2415 HG21 THR A 151 -18.523 3.373 -3.591 1.00 0.00 H +ATOM 2416 HG22 THR A 151 -19.923 2.533 -2.883 1.00 0.00 H +ATOM 2417 HG23 THR A 151 -19.879 2.874 -4.630 1.00 0.00 H +ATOM 2418 N THR A 152 -22.481 3.559 -1.325 1.00 9.58 N +ATOM 2419 CA THR A 152 -22.964 2.522 -0.427 1.00 9.75 C +ATOM 2420 C THR A 152 -24.386 2.097 -0.814 1.00 11.73 C +ATOM 2421 O THR A 152 -24.679 0.889 -0.849 1.00 11.16 O +ATOM 2422 CB THR A 152 -22.891 2.970 1.054 1.00 8.01 C +ATOM 2423 OG1 THR A 152 -21.567 3.469 1.319 1.00 9.50 O +ATOM 2424 CG2 THR A 152 -23.179 1.809 1.964 1.00 11.46 C +ATOM 2425 H THR A 152 -22.301 4.478 -0.947 1.00 0.00 H +ATOM 2426 HA THR A 152 -22.315 1.654 -0.543 1.00 0.00 H +ATOM 2427 HB THR A 152 -23.620 3.761 1.231 1.00 0.00 H +ATOM 2428 HG1 THR A 152 -21.508 3.750 2.235 1.00 0.00 H +ATOM 2429 HG21 THR A 152 -23.124 2.138 3.002 1.00 0.00 H +ATOM 2430 HG22 THR A 152 -24.178 1.424 1.758 1.00 0.00 H +ATOM 2431 HG23 THR A 152 -22.444 1.022 1.794 1.00 0.00 H +ATOM 2432 N PHE A 153 -25.264 3.061 -1.106 1.00 10.02 N +ATOM 2433 CA PHE A 153 -26.583 2.701 -1.657 1.00 10.71 C +ATOM 2434 C PHE A 153 -26.493 2.029 -3.022 1.00 12.61 C +ATOM 2435 O PHE A 153 -27.307 1.136 -3.343 1.00 13.17 O +ATOM 2436 CB PHE A 153 -27.466 3.956 -1.817 1.00 9.94 C +ATOM 2437 CG PHE A 153 -28.119 4.443 -0.554 1.00 9.62 C +ATOM 2438 CD1 PHE A 153 -28.957 3.598 0.192 1.00 9.76 C +ATOM 2439 CD2 PHE A 153 -27.987 5.768 -0.153 1.00 10.75 C +ATOM 2440 CE1 PHE A 153 -29.633 4.080 1.317 1.00 10.31 C +ATOM 2441 CE2 PHE A 153 -28.647 6.258 0.992 1.00 10.93 C +ATOM 2442 CZ PHE A 153 -29.471 5.388 1.729 1.00 8.86 C +ATOM 2443 H PHE A 153 -25.022 4.029 -0.949 1.00 0.00 H +ATOM 2444 HA PHE A 153 -27.074 2.017 -0.965 1.00 0.00 H +ATOM 2445 HB3 PHE A 153 -28.232 3.764 -2.568 1.00 0.00 H +ATOM 2446 HB2 PHE A 153 -26.873 4.761 -2.250 1.00 0.00 H +ATOM 2447 HD1 PHE A 153 -29.084 2.566 -0.102 1.00 0.00 H +ATOM 2448 HD2 PHE A 153 -27.368 6.446 -0.723 1.00 0.00 H +ATOM 2449 HE1 PHE A 153 -30.290 3.427 1.873 1.00 0.00 H +ATOM 2450 HE2 PHE A 153 -28.516 7.287 1.292 1.00 0.00 H +ATOM 2451 HZ PHE A 153 -29.976 5.741 2.616 1.00 0.00 H +ATOM 2452 N ARG A 154 -25.589 2.474 -3.884 1.00 9.73 N +ATOM 2453 CA ARG A 154 -25.541 1.918 -5.234 1.00 12.08 C +ATOM 2454 C ARG A 154 -25.117 0.465 -5.205 1.00 12.46 C +ATOM 2455 O ARG A 154 -25.692 -0.367 -5.921 1.00 14.08 O +ATOM 2456 CB ARG A 154 -24.582 2.714 -6.116 1.00 11.89 C +ATOM 2457 CG ARG A 154 -24.513 2.172 -7.558 1.00 9.93 C +ATOM 2458 CD ARG A 154 -23.628 3.039 -8.443 1.00 11.70 C +ATOM 2459 NE ARG A 154 -22.241 3.119 -7.981 1.00 18.53 N +ATOM 2460 CZ ARG A 154 -21.308 2.205 -8.234 1.00 19.53 C +ATOM 2461 NH1 ARG A 154 -21.612 1.116 -8.936 1.00 19.56 N +ATOM 2462 NH2 ARG A 154 -20.072 2.380 -7.778 1.00 24.35 N +ATOM 2463 H ARG A 154 -24.938 3.194 -3.606 1.00 0.00 H +ATOM 2464 HA ARG A 154 -26.539 1.978 -5.668 1.00 0.00 H +ATOM 2465 HB3 ARG A 154 -23.585 2.697 -5.675 1.00 0.00 H +ATOM 2466 HB2 ARG A 154 -24.891 3.759 -6.136 1.00 0.00 H +ATOM 2467 HG3 ARG A 154 -25.518 2.131 -7.979 1.00 0.00 H +ATOM 2468 HG2 ARG A 154 -24.125 1.153 -7.544 1.00 0.00 H +ATOM 2469 HD3 ARG A 154 -24.048 4.043 -8.502 1.00 0.00 H +ATOM 2470 HD2 ARG A 154 -23.648 2.654 -9.463 1.00 0.00 H +ATOM 2471 HE ARG A 154 -22.011 3.937 -7.435 1.00 0.00 H +ATOM 2472 HH12 ARG A 154 -20.902 0.424 -9.127 1.00 0.00 H +ATOM 2473 HH11 ARG A 154 -22.553 0.982 -9.278 1.00 0.00 H +ATOM 2474 HH21 ARG A 154 -19.361 1.688 -7.968 1.00 0.00 H +ATOM 2475 HH22 ARG A 154 -19.844 3.205 -7.241 1.00 0.00 H +ATOM 2476 N THR A 155 -24.121 0.153 -4.369 1.00 11.82 N +ATOM 2477 CA THR A 155 -23.432 -1.153 -4.434 1.00 11.13 C +ATOM 2478 C THR A 155 -23.810 -2.115 -3.337 1.00 12.79 C +ATOM 2479 O THR A 155 -23.644 -3.332 -3.491 1.00 14.23 O +ATOM 2480 CB THR A 155 -21.903 -1.007 -4.377 1.00 13.18 C +ATOM 2481 OG1 THR A 155 -21.508 -0.480 -3.087 1.00 12.49 O +ATOM 2482 CG2 THR A 155 -21.403 -0.065 -5.493 1.00 12.47 C +ATOM 2483 H THR A 155 -23.821 0.818 -3.670 1.00 0.00 H +ATOM 2484 HA THR A 155 -23.687 -1.617 -5.387 1.00 0.00 H +ATOM 2485 HB THR A 155 -21.449 -1.988 -4.512 1.00 0.00 H +ATOM 2486 HG1 THR A 155 -20.553 -0.391 -3.056 1.00 0.00 H +ATOM 2487 HG21 THR A 155 -20.318 0.025 -5.435 1.00 0.00 H +ATOM 2488 HG22 THR A 155 -21.682 -0.472 -6.465 1.00 0.00 H +ATOM 2489 HG23 THR A 155 -21.855 0.919 -5.369 1.00 0.00 H +ATOM 2490 N GLY A 156 -24.254 -1.604 -2.202 1.00 11.00 N +ATOM 2491 CA GLY A 156 -24.526 -2.470 -1.084 1.00 11.15 C +ATOM 2492 C GLY A 156 -23.264 -3.047 -0.462 1.00 10.83 C +ATOM 2493 O GLY A 156 -23.320 -4.090 0.210 1.00 12.73 O +ATOM 2494 H GLY A 156 -24.402 -0.608 -2.120 1.00 0.00 H +ATOM 2495 HA3 GLY A 156 -25.176 -3.284 -1.406 1.00 0.00 H +ATOM 2496 HA2 GLY A 156 -25.084 -1.919 -0.327 1.00 0.00 H +ATOM 2497 N THR A 157 -22.132 -2.380 -0.705 1.00 11.40 N +ATOM 2498 CA THR A 157 -20.846 -2.782 -0.157 1.00 12.02 C +ATOM 2499 C THR A 157 -20.249 -1.586 0.547 1.00 10.19 C +ATOM 2500 O THR A 157 -20.737 -0.460 0.415 1.00 10.74 O +ATOM 2501 CB THR A 157 -19.821 -3.153 -1.229 1.00 11.76 C +ATOM 2502 OG1 THR A 157 -19.372 -1.977 -1.933 1.00 13.71 O +ATOM 2503 CG2 THR A 157 -20.396 -4.180 -2.216 1.00 16.00 C +ATOM 2504 H THR A 157 -22.146 -1.558 -1.292 1.00 0.00 H +ATOM 2505 HA THR A 157 -20.975 -3.607 0.544 1.00 0.00 H +ATOM 2506 HB THR A 157 -18.960 -3.602 -0.734 1.00 0.00 H +ATOM 2507 HG1 THR A 157 -18.730 -2.229 -2.601 1.00 0.00 H +ATOM 2508 HG21 THR A 157 -19.644 -4.424 -2.966 1.00 0.00 H +ATOM 2509 HG22 THR A 157 -20.678 -5.085 -1.677 1.00 0.00 H +ATOM 2510 HG23 THR A 157 -21.275 -3.761 -2.706 1.00 0.00 H +ATOM 2511 N TRP A 158 -19.185 -1.860 1.291 1.00 11.35 N +ATOM 2512 CA TRP A 158 -18.457 -0.834 2.015 1.00 10.10 C +ATOM 2513 C TRP A 158 -17.278 -0.297 1.203 1.00 11.24 C +ATOM 2514 O TRP A 158 -16.365 0.316 1.770 1.00 12.71 O +ATOM 2515 CB TRP A 158 -17.922 -1.427 3.321 1.00 11.06 C +ATOM 2516 CG TRP A 158 -18.988 -1.715 4.302 1.00 10.24 C +ATOM 2517 CD1 TRP A 158 -19.385 -2.941 4.752 1.00 11.29 C +ATOM 2518 CD2 TRP A 158 -19.790 -0.749 5.000 1.00 10.47 C +ATOM 2519 NE1 TRP A 158 -20.411 -2.802 5.670 1.00 12.15 N +ATOM 2520 CE2 TRP A 158 -20.656 -1.466 5.863 1.00 10.44 C +ATOM 2521 CE3 TRP A 158 -19.846 0.653 4.984 1.00 11.86 C +ATOM 2522 CZ2 TRP A 158 -21.576 -0.836 6.694 1.00 11.59 C +ATOM 2523 CZ3 TRP A 158 -20.748 1.283 5.809 1.00 13.14 C +ATOM 2524 CH2 TRP A 158 -21.601 0.547 6.668 1.00 13.77 C +ATOM 2525 H TRP A 158 -18.854 -2.811 1.369 1.00 0.00 H +ATOM 2526 HA TRP A 158 -19.134 -0.012 2.247 1.00 0.00 H +ATOM 2527 HB3 TRP A 158 -17.200 -0.739 3.762 1.00 0.00 H +ATOM 2528 HB2 TRP A 158 -17.372 -2.343 3.104 1.00 0.00 H +ATOM 2529 HD1 TRP A 158 -18.903 -3.834 4.382 1.00 0.00 H +ATOM 2530 HE1 TRP A 158 -20.842 -3.621 6.073 1.00 0.00 H +ATOM 2531 HE3 TRP A 158 -19.190 1.212 4.334 1.00 0.00 H +ATOM 2532 HZ2 TRP A 158 -22.229 -1.425 7.321 1.00 0.00 H +ATOM 2533 HZ3 TRP A 158 -20.817 2.361 5.811 1.00 0.00 H +ATOM 2534 HH2 TRP A 158 -22.280 1.087 7.311 1.00 0.00 H +ATOM 2535 N ASP A 159 -17.278 -0.490 -0.105 1.00 12.94 N +ATOM 2536 CA ASP A 159 -16.104 -0.102 -0.896 1.00 12.18 C +ATOM 2537 C ASP A 159 -15.676 1.364 -0.740 1.00 15.27 C +ATOM 2538 O ASP A 159 -14.476 1.682 -0.767 1.00 15.28 O +ATOM 2539 CB ASP A 159 -16.338 -0.408 -2.356 1.00 16.20 C +ATOM 2540 CG ASP A 159 -16.310 -1.907 -2.657 1.00 26.11 C +ATOM 2541 OD1 ASP A 159 -16.052 -2.723 -1.742 1.00 26.42 O +ATOM 2542 OD2 ASP A 159 -16.528 -2.263 -3.831 1.00 31.25 O +ATOM 2543 H ASP A 159 -18.083 -0.902 -0.555 1.00 0.00 H +ATOM 2544 HA ASP A 159 -15.270 -0.721 -0.564 1.00 0.00 H +ATOM 2545 HB3 ASP A 159 -15.582 0.096 -2.958 1.00 0.00 H +ATOM 2546 HB2 ASP A 159 -17.299 0.005 -2.663 1.00 0.00 H +ATOM 2547 N ALA A 160 -16.637 2.271 -0.582 1.00 10.95 N +ATOM 2548 CA ALA A 160 -16.275 3.688 -0.448 1.00 13.56 C +ATOM 2549 C ALA A 160 -15.592 4.011 0.873 1.00 15.35 C +ATOM 2550 O ALA A 160 -14.970 5.077 0.980 1.00 19.29 O +ATOM 2551 CB ALA A 160 -17.517 4.586 -0.616 1.00 13.87 C +ATOM 2552 H ALA A 160 -17.604 1.982 -0.555 1.00 0.00 H +ATOM 2553 HA ALA A 160 -15.578 3.931 -1.250 1.00 0.00 H +ATOM 2554 HB1 ALA A 160 -17.227 5.632 -0.513 1.00 0.00 H +ATOM 2555 HB2 ALA A 160 -17.951 4.425 -1.603 1.00 0.00 H +ATOM 2556 HB3 ALA A 160 -18.252 4.337 0.149 1.00 0.00 H +ATOM 2557 N TYR A 161 -15.728 3.150 1.871 1.00 11.90 N +ATOM 2558 CA TYR A 161 -15.154 3.402 3.197 1.00 12.98 C +ATOM 2559 C TYR A 161 -13.884 2.595 3.433 1.00 23.12 C +ATOM 2560 O TYR A 161 -13.190 2.820 4.424 1.00 24.89 O +ATOM 2561 CB TYR A 161 -16.188 3.101 4.284 1.00 12.98 C +ATOM 2562 CG TYR A 161 -17.259 4.167 4.315 1.00 11.12 C +ATOM 2563 CD1 TYR A 161 -18.392 4.081 3.484 1.00 9.90 C +ATOM 2564 CD2 TYR A 161 -17.110 5.306 5.121 1.00 9.82 C +ATOM 2565 CE1 TYR A 161 -19.339 5.077 3.478 1.00 9.35 C +ATOM 2566 CE2 TYR A 161 -18.079 6.298 5.137 1.00 9.00 C +ATOM 2567 CZ TYR A 161 -19.186 6.181 4.308 1.00 9.57 C +ATOM 2568 OH TYR A 161 -20.137 7.166 4.289 1.00 10.18 O +ATOM 2569 H TYR A 161 -16.239 2.290 1.730 1.00 0.00 H +ATOM 2570 HA TYR A 161 -14.898 4.460 3.258 1.00 0.00 H +ATOM 2571 HB3 TYR A 161 -15.692 3.056 5.254 1.00 0.00 H +ATOM 2572 HB2 TYR A 161 -16.647 2.131 4.090 1.00 0.00 H +ATOM 2573 HD1 TYR A 161 -18.526 3.224 2.840 1.00 0.00 H +ATOM 2574 HD2 TYR A 161 -16.232 5.419 5.740 1.00 0.00 H +ATOM 2575 HE1 TYR A 161 -20.199 5.000 2.829 1.00 0.00 H +ATOM 2576 HE2 TYR A 161 -17.968 7.151 5.790 1.00 0.00 H +ATOM 2577 HH TYR A 161 -19.895 7.857 4.910 1.00 0.00 H +ATOM 2578 N LYS A 162 -13.569 1.679 2.529 1.00 17.89 N +ATOM 2579 CA LYS A 162 -12.418 0.805 2.748 1.00 23.71 C +ATOM 2580 C LYS A 162 -11.038 1.456 2.596 1.00 29.39 C +ATOM 2581 O LYS A 162 -10.153 1.203 3.408 1.00 41.48 O +ATOM 2582 CB LYS A 162 -12.557 -0.499 1.969 1.00 32.16 C +ATOM 2583 CG LYS A 162 -13.457 -1.524 2.696 1.00 28.29 C +ATOM 2584 CD LYS A 162 -13.500 -2.920 2.049 1.00 0.00 C +ATOM 2585 CE LYS A 162 -14.244 -2.944 0.710 1.00 0.00 C +ATOM 2586 NZ LYS A 162 -14.346 -4.300 0.152 1.00 0.00 N +ATOM 2587 H LYS A 162 -14.124 1.586 1.690 1.00 0.00 H +ATOM 2588 HA LYS A 162 -12.479 0.515 3.797 1.00 0.00 H +ATOM 2589 HB3 LYS A 162 -11.571 -0.958 1.870 1.00 0.00 H +ATOM 2590 HB2 LYS A 162 -12.898 -0.303 0.952 1.00 0.00 H +ATOM 2591 HG2 LYS A 162 -13.099 -1.649 3.719 1.00 0.00 H +ATOM 2592 HG3 LYS A 162 -14.468 -1.129 2.790 1.00 0.00 H +ATOM 2593 HD2 LYS A 162 -12.484 -3.289 1.908 1.00 0.00 H +ATOM 2594 HD3 LYS A 162 -13.978 -3.615 2.740 1.00 0.00 H +ATOM 2595 HE2 LYS A 162 -15.255 -2.561 0.845 1.00 0.00 H +ATOM 2596 HE3 LYS A 162 -13.741 -2.313 -0.022 1.00 0.00 H +ATOM 2597 HZ1 LYS A 162 -13.426 -4.667 -0.039 1.00 0.00 H +ATOM 2598 HZ2 LYS A 162 -14.828 -4.905 0.799 1.00 0.00 H +ATOM 2599 HZ3 LYS A 162 -14.874 -4.236 -0.708 1.00 0.00 H +ATOM 2600 N ASN A 163 -10.838 2.291 1.586 1.00 40.68 N +ATOM 2601 CA ASN A 163 -9.633 3.108 1.581 1.00 42.65 C +ATOM 2602 C ASN A 163 -9.742 4.042 2.775 1.00 48.18 C +ATOM 2603 O ASN A 163 -8.793 4.207 3.546 1.00 49.88 O +ATOM 2604 CB ASN A 163 -9.508 3.914 0.290 1.00 35.97 C +ATOM 2605 CG ASN A 163 -9.187 3.086 -0.957 1.00 0.00 C +ATOM 2606 OD1 ASN A 163 -8.824 1.916 -0.880 1.00 0.00 O +ATOM 2607 ND2 ASN A 163 -9.308 3.687 -2.134 1.00 0.00 N +ATOM 2608 H ASN A 163 -11.515 2.351 0.839 1.00 0.00 H +ATOM 2609 HA ASN A 163 -8.758 2.468 1.697 1.00 0.00 H +ATOM 2610 HB2 ASN A 163 -10.410 4.502 0.113 1.00 0.00 H +ATOM 2611 HB3 ASN A 163 -8.691 4.630 0.399 1.00 0.00 H +ATOM 2612 HD21 ASN A 163 -9.103 3.179 -2.981 1.00 0.00 H +ATOM 2613 HD22 ASN A 163 -9.600 4.650 -2.204 1.00 0.00 H +ATOM 2614 N LEU A 164 -10.938 4.615 2.910 1.00 50.88 N +ATOM 2615 CA LEU A 164 -11.336 5.528 3.983 1.00 44.75 C +ATOM 2616 C LEU A 164 -11.751 6.872 3.393 1.00 39.98 C +ATOM 2617 O LEU A 164 -12.901 7.295 3.530 1.00 34.36 O +ATOM 2618 CB LEU A 164 -10.240 5.712 5.035 1.00 45.54 C +ATOM 2619 CG LEU A 164 -9.999 4.643 6.116 1.00 49.89 C +ATOM 2620 CD1 LEU A 164 -10.511 5.099 7.481 1.00 32.09 C +ATOM 2621 CD2 LEU A 164 -10.580 3.281 5.742 1.00 45.87 C +ATOM 2622 H LEU A 164 -11.665 4.431 2.234 1.00 0.00 H +ATOM 2623 HA LEU A 164 -12.206 5.099 4.480 1.00 0.00 H +ATOM 2624 HB3 LEU A 164 -10.375 6.679 5.519 1.00 0.00 H +ATOM 2625 HB2 LEU A 164 -9.297 5.921 4.529 1.00 0.00 H +ATOM 2626 HG LEU A 164 -8.920 4.517 6.205 1.00 0.00 H +ATOM 2627 HD11 LEU A 164 -10.324 4.319 8.219 1.00 0.00 H +ATOM 2628 HD12 LEU A 164 -9.993 6.011 7.778 1.00 0.00 H +ATOM 2629 HD13 LEU A 164 -11.582 5.293 7.422 1.00 0.00 H +ATOM 2630 HD21 LEU A 164 -10.379 2.568 6.542 1.00 0.00 H +ATOM 2631 HD22 LEU A 164 -11.657 3.372 5.598 1.00 0.00 H +ATOM 2632 HD23 LEU A 164 -10.119 2.930 4.819 1.00 0.00 H +TER +HETATM 2633 C1 BNZ L 1 -32.969 6.196 2.877 1.00 15.06 C +HETATM 2634 C2 BNZ L 1 -32.945 7.046 3.973 1.00 12.84 C +HETATM 2635 C3 BNZ L 1 -33.719 6.798 5.113 1.00 12.24 C +HETATM 2636 C4 BNZ L 1 -34.540 5.680 5.143 1.00 13.09 C +HETATM 2637 C5 BNZ L 1 -34.545 4.825 4.044 1.00 12.54 C +HETATM 2638 C6 BNZ L 1 -33.787 5.069 2.915 1.00 14.23 C +HETATM 2639 H1 BNZ L 1 -32.360 6.413 2.012 1.00 0.00 H +HETATM 2640 H2 BNZ L 1 -32.318 7.925 3.961 1.00 0.00 H +HETATM 2641 H3 BNZ L 1 -33.672 7.473 5.955 1.00 0.00 H +HETATM 2642 H4 BNZ L 1 -35.158 5.487 6.007 1.00 0.00 H +HETATM 2643 H5 BNZ L 1 -35.156 3.935 4.055 1.00 0.00 H +HETATM 2644 H6 BNZ L 1 -33.823 4.399 2.069 1.00 0.00 H +TER diff --git a/offPELE/data/ligands/BNZ.mae b/offPELE/data/ligands/BNZ.mae new file mode 100644 index 00000000..04bae5a6 --- /dev/null +++ b/offPELE/data/ligands/BNZ.mae @@ -0,0 +1,184 @@ +{ + s_m_m2io_version + ::: + 2.0.0 +} + +f_m_ct { + s_m_title + s_m_entry_id + s_m_entry_name + s_pdb_PDB_TITLE + s_pdb_PDB_ID + r_pdb_PDB_CRYST1_a + r_pdb_PDB_CRYST1_b + r_pdb_PDB_CRYST1_c + r_pdb_PDB_CRYST1_alpha + r_pdb_PDB_CRYST1_beta + r_pdb_PDB_CRYST1_gamma + s_pdb_PDB_CRYST1_Space_Group + i_pdb_PDB_CRYST1_z + s_pdb_PDB_CLASSIFICATION + s_pdb_PDB_DEPOSITION_DATE + s_pdb_PDB_format_version + r_pdb_PDB_R + r_pdb_PDB_Rfree + r_pdb_PDB_RESOLUTION + s_pdb_PDB_EXPDTA + r_pdb_PDB_EXPDTA_TEMPERATURE + r_pdb_PDB_EXPDTA_PH + s_pdb_PDB_REMARK_350_Biomolecule_1_Chains + s_pdb_PDB_REMARK_350_Biomolecule_1_Transformation_1 + s_m_Source_Path + s_m_Source_File + i_m_Source_File_Index + s_ppw_entry_id_backup + b_ppw_prepared + s_ppw_prepared_with_version + b_ppw_assigned_bond_orders + b_ppw_added_hydrogens + b_ppw_treated_metals + b_ppw_created_disulfur + b_ppw_deleted_far_waters + i_psp_model_num + r_psp_Prime_Coulomb + r_psp_Prime_Covalent + r_psp_Prime_Solv_GB + r_psp_Prime_Lipo + s_psp_Prime_Energy_Force_Field + s_psp_Prime_Energy_Solvent_Model + r_psp_Prime_Hbond + r_psp_Prime_Packing + r_psp_Prime_SelfCont + i_m_ct_format + ::: + "4W52 - preprocessed" + 4 + 4w52.1 + "T4 LYSOZYME L99A WITH BENZENE BOUND" + 4W52 + 60.35 + 60.35 + 96.61 + 90 + 90 + 120 + "P 32 2 1" + 6 + HYDROLASE + 16-AUG-14 + 3.30 + 0.165000006556511 + 0.181999996304512 + 1.5 + "X-RAY DIFFRACTION" + 100 + 7.5 + A + "1.000000 0.000000 0.000000 0.000000;0.000000 1.000000 0.000000 0.000000;0.000000 0.000000 1.000000 0.000000" + /home/municoy/builds/PELE/FEPSimulation + 4w52.pdb + 1 + 2 + 1 + 2018-2 + 1 + 1 + 1 + 1 + 1 + 0 + inf + 687.113646057117 + -1117.61415217671 + -410.651549686176 + OPLS3e + VSGB2.1 + -107.883308693242 + -14.5414873816691 + -34.8272744969634 + 2 + m_atom[12] { + # First column is atom index # + i_m_mmod_type + r_m_x_coord + r_m_y_coord + r_m_z_coord + i_m_residue_number + s_m_chain_name + i_m_color + r_m_charge1 + r_m_charge2 + s_m_pdb_residue_name + s_m_pdb_atom_name + i_m_atomic_number + i_m_representation + s_m_color_rgb + s_m_atom_name + s_m_label_format + i_m_label_color + s_m_label_user_text + r_m_pdb_occupancy + r_m_pdb_tfactor + i_m_Hcount + i_m_pdb_convert_problem + i_pdb_PDB_serial + i_ppw_anum + i_ppw_het + i_psp_resnum + s_ppw_CCD_assignment_status + ::: + 1 2 -32.969000 6.196000 2.877000 1 L 10 -0.12885 -0.12885 "BNZ " " C1 " 6 3 1EE11E "C1288" "%UT" 10 "" 0.7 15.06 1 4 1360 1309 3 200 "CCD match" + 2 2 -32.945000 7.046000 3.973000 1 L 10 -0.12885 -0.12885 "BNZ " " C2 " 6 3 1EE11E "C1289" "%UT" 10 "" 0.7 12.84 1 4 1361 1310 3 200 "CCD match" + 3 2 -33.719000 6.798000 5.113000 1 L 10 -0.12885 -0.12885 "BNZ " " C3 " 6 3 1EE11E "C1290" "%UT" 10 "" 0.7 12.24 1 4 1362 1311 3 200 "CCD match" + 4 2 -34.540000 5.680000 5.143000 1 L 10 -0.12885 -0.12885 "BNZ " " C4 " 6 3 1EE11E "C1291" "%UT" 10 "" 0.7 13.09 1 4 1363 1312 3 200 "CCD match" + 5 2 -34.545000 4.825000 4.044000 1 L 10 -0.12885 -0.12885 "BNZ " " C5 " 6 3 1EE11E "C1292" "%UT" 10 "" 0.7 12.54 1 4 1364 1313 3 200 "CCD match" + 6 2 -33.787000 5.069000 2.915000 1 L 10 -0.12885 -0.12885 "BNZ " " C6 " 6 3 1EE11E "C1293" "%UT" 10 "" 0.7 14.23 1 4 1365 1314 3 200 "CCD match" + 7 41 -32.359568 6.412714 2.012114 1 L 21 0.12885 0.12885 "BNZ " " H1 " 1 3 FFFFFF "" "" 21 "" <> <> 0 <> <> <> <> 200 <> + 8 41 -32.318044 7.925305 3.960797 1 L 21 0.12885 0.12885 "BNZ " " H2 " 1 3 FFFFFF "" "" 21 "" <> <> 0 <> <> <> <> 200 <> + 9 41 -33.672323 7.473059 5.954735 1 L 21 0.12885 0.12885 "BNZ " " H3 " 1 3 FFFFFF "" "" 21 "" <> <> 0 <> <> <> <> 200 <> + 10 41 -35.158445 5.487222 6.007154 1 L 21 0.12885 0.12885 "BNZ " " H4 " 1 3 FFFFFF "" "" 21 "" <> <> 0 <> <> <> <> 200 <> + 11 41 -35.156258 3.934698 4.055241 1 L 21 0.12885 0.12885 "BNZ " " H5 " 1 3 FFFFFF "" "" 21 "" <> <> 0 <> <> <> <> 200 <> + 12 41 -33.822915 4.399036 2.068680 1 L 21 0.12885 0.12885 "BNZ " " H6 " 1 3 FFFFFF "" "" 21 "" <> <> 0 <> <> <> <> 200 <> + ::: + } + m_bond[12] { + # First column is bond index # + i_m_from + i_m_to + i_m_order + i_m_from_rep + i_m_to_rep + ::: + 1 1 2 2 3 3 + 2 1 6 1 3 3 + 3 1 7 1 3 3 + 4 2 3 1 3 3 + 5 2 8 1 3 3 + 6 3 4 2 3 3 + 7 3 9 1 3 3 + 8 4 5 1 3 3 + 9 4 10 1 3 3 + 10 5 6 2 3 3 + 11 5 11 1 3 3 + 12 6 12 1 3 3 + ::: + } + m_PDB_SEQRES[1] { + s_pdb_chain_id + s_pdb_SEQRES + ::: + 1 A "MET ASN ILE PHE GLU MET LEU ARG ILE ASP GLU GLY LEU ARG LEU LYS ILE TYR LYS ASP THR GLU GLY TYR TYR THR ILE GLY ILE GLY HIS LEU LEU THR LYS SER PRO SER LEU ASN ALA ALA LYS SER GLU LEU ASP LYS ALA ILE GLY ARG ASN CYS ASN GLY VAL ILE THR LYS ASP GLU ALA GLU LYS LEU PHE ASN GLN ASP VAL ASP ALA ALA VAL ARG GLY ILE LEU ARG ASN ALA LYS LEU LYS PRO VAL TYR ASP SER LEU ASP ALA VAL ARG ARG CYS ALA ALA ILE ASN MET VAL PHE GLN MET GLY GLU THR GLY VAL ALA GLY PHE THR ASN SER LEU ARG MET LEU GLN GLN LYS ARG TRP ASP GLU ALA ALA VAL ASN LEU ALA LYS SER ARG TRP TYR ASN GLN THR PRO ASN ARG ALA LYS ARG VAL ILE THR THR PHE ARG THR GLY THR TRP ASP ALA TYR LYS ASN LEU LEU GLU HIS HIS HIS HIS HIS HIS " + ::: + } + m_PDB_het_residues[2] { + s_pdb_het_id + s_pdb_het_name + s_pdb_het_formula + ::: + 1 BNZ "BENZENE" "C6 H6" + 2 EPE "4-(2-HYDROXYETHYL)-1-PIPERAZINE ETHANESULFONIC ACID" "C8 H18 N2 O4 S" + ::: + } +} + diff --git a/offPELE/data/ligands/BNZ.pdb b/offPELE/data/ligands/BNZ.pdb new file mode 100644 index 00000000..cdcfdcd0 --- /dev/null +++ b/offPELE/data/ligands/BNZ.pdb @@ -0,0 +1,53 @@ +HEADER HYDROLASE 16-AUG-14 4W52 +REMARK 4 4W52 COMPLIES WITH FORMAT V. 3.30, +REMARK 888 +REMARK 888 WRITTEN BY MAESTRO (A PRODUCT OF SCHRODINGER, LLC) +TITLE T4 LYSOZYME L99A WITH BENZENE BOUND +EXPDTA X-RAY DIFFRACTION +REMARK 2 RESOLUTION. 1.50 ANGSTROMS +REMARK 3 R VALUE : 0.165000 +REMARK 3 FREE R VALUE : 0.182000 +REMARK 200 TEMPERATURE (KELVIN) : 100.00 +REMARK 200 PH : 7.50 +REMARK 350 BIOMOLECULE: 1 +REMARK 350 APPLY THE FOLLOWING TO CHAINS: A +REMARK 350 BIOMT1 1 1.000000 0.000000 0.000000 0.000000 +REMARK 350 BIOMT2 1 0.000000 1.000000 0.000000 0.000000 +REMARK 350 BIOMT3 1 0.000000 0.000000 1.000000 0.000000 +CRYST1 60.350 60.350 96.610 90.00 90.00 120.00 P 32 2 1 6 +HET BNZ L 1 12 +HETNAM BNZ BENZENE +FORMUL 1 BNZ C6 H6 +MODEL 1 +HETATM 1 C1 BNZ L 1 -32.969 6.196 2.877 0.70 15.06 C +HETATM 2 C2 BNZ L 1 -32.945 7.046 3.973 0.70 12.84 C +HETATM 3 C3 BNZ L 1 -33.719 6.798 5.113 0.70 12.24 C +HETATM 4 C4 BNZ L 1 -34.540 5.680 5.143 0.70 13.09 C +HETATM 5 C5 BNZ L 1 -34.545 4.825 4.044 0.70 12.54 C +HETATM 6 C6 BNZ L 1 -33.787 5.069 2.915 0.70 14.23 C +HETATM 7 H1 BNZ L 1 -32.360 6.413 2.012 1.00 0.00 H +HETATM 8 H2 BNZ L 1 -32.318 7.925 3.961 1.00 0.00 H +HETATM 9 H3 BNZ L 1 -33.672 7.473 5.955 1.00 0.00 H +HETATM 10 H4 BNZ L 1 -35.158 5.487 6.007 1.00 0.00 H +HETATM 11 H5 BNZ L 1 -35.156 3.935 4.055 1.00 0.00 H +HETATM 12 H6 BNZ L 1 -33.823 4.399 2.069 1.00 0.00 H +CONECT 1 2 6 7 +CONECT 1 2 +CONECT 2 1 3 8 +CONECT 2 1 +CONECT 3 2 4 9 +CONECT 3 4 +CONECT 4 3 5 10 +CONECT 4 3 +CONECT 5 4 6 11 +CONECT 5 6 +CONECT 6 1 5 12 +CONECT 6 5 +CONECT 7 1 +CONECT 8 2 +CONECT 9 3 +CONECT 10 4 +CONECT 11 5 +CONECT 12 6 +ENDMDL +END diff --git a/offPELE/data/ligands/TOL.mae b/offPELE/data/ligands/TOL.mae new file mode 100644 index 00000000..32786bb4 --- /dev/null +++ b/offPELE/data/ligands/TOL.mae @@ -0,0 +1,190 @@ +{ + s_m_m2io_version + ::: + 2.0.0 +} + +f_m_ct { + s_m_title + s_m_entry_id + s_m_entry_name + s_pdb_PDB_TITLE + s_pdb_PDB_ID + r_pdb_PDB_CRYST1_a + r_pdb_PDB_CRYST1_b + r_pdb_PDB_CRYST1_c + r_pdb_PDB_CRYST1_alpha + r_pdb_PDB_CRYST1_beta + r_pdb_PDB_CRYST1_gamma + s_pdb_PDB_CRYST1_Space_Group + i_pdb_PDB_CRYST1_z + s_pdb_PDB_CLASSIFICATION + s_pdb_PDB_DEPOSITION_DATE + s_pdb_PDB_format_version + r_pdb_PDB_R + r_pdb_PDB_Rfree + r_pdb_PDB_RESOLUTION + s_pdb_PDB_EXPDTA + r_pdb_PDB_EXPDTA_TEMPERATURE + r_pdb_PDB_EXPDTA_PH + s_pdb_PDB_REMARK_350_Biomolecule_1_Chains + s_pdb_PDB_REMARK_350_Biomolecule_1_Transformation_1 + s_m_Source_Path + s_m_Source_File + i_m_Source_File_Index + s_ppw_entry_id_backup + b_ppw_prepared + s_ppw_prepared_with_version + b_ppw_assigned_bond_orders + b_ppw_added_hydrogens + b_ppw_treated_metals + b_ppw_created_disulfur + b_ppw_deleted_far_waters + i_psp_model_num + r_psp_Prime_Coulomb + r_psp_Prime_Covalent + r_psp_Prime_Solv_GB + r_psp_Prime_Lipo + s_psp_Prime_Energy_Force_Field + s_psp_Prime_Energy_Solvent_Model + r_psp_Prime_Hbond + r_psp_Prime_Packing + r_psp_Prime_SelfCont + i_m_ct_format + ::: + "4W52 - preprocessed" + 3 + 4w52.1 + "T4 LYSOZYME L99A WITH BENZENE BOUND" + 4W52 + 60.35 + 60.35 + 96.61 + 90 + 90 + 120 + "P 32 2 1" + 6 + HYDROLASE + 16-AUG-14 + 3.30 + 0.165000006556511 + 0.181999996304512 + 1.5 + "X-RAY DIFFRACTION" + 100 + 7.5 + A + "1.000000 0.000000 0.000000 0.000000;0.000000 1.000000 0.000000 0.000000;0.000000 0.000000 1.000000 0.000000" + /home/municoy/builds/PELE/FEPSimulation + 4w52.pdb + 1 + 2 + 1 + 2018-2 + 1 + 1 + 1 + 1 + 1 + 0 + inf + 687.113646057117 + -1117.61415217671 + -410.651549686176 + OPLS3e + VSGB2.1 + -107.883308693242 + -14.5414873816691 + -34.8272744969634 + 2 + m_atom[15] { + # First column is atom index # + i_m_mmod_type + r_m_x_coord + r_m_y_coord + r_m_z_coord + i_m_residue_number + s_m_chain_name + i_m_color + r_m_charge1 + r_m_charge2 + s_m_pdb_residue_name + s_m_pdb_atom_name + i_m_atomic_number + i_m_representation + s_m_color_rgb + s_m_atom_name + s_m_label_format + i_m_label_color + s_m_label_user_text + r_m_pdb_occupancy + r_m_pdb_tfactor + i_m_Hcount + i_m_pdb_convert_problem + i_pdb_PDB_serial + i_ppw_anum + i_ppw_het + i_psp_resnum + s_ppw_CCD_assignment_status + ::: + 1 2 -32.969000 6.196000 2.877000 1 P 134 -0.12885 -0.12885 "TOL " " C1 " 6 3 96FF2E "C1288" "%UT" 134 "" 0.7 15.06 1 4 1360 1309 3 200 "CCD match" + 2 2 -32.945000 7.046000 3.973000 1 P 134 -0.12885 -0.12885 "TOL " " C2 " 6 3 96FF2E "C1289" "%UT" 134 "" 0.7 12.84 1 4 1361 1310 3 200 "CCD match" + 3 2 -33.719000 6.798000 5.113000 1 P 134 -0.12885 -0.12885 "TOL " " C3 " 6 3 96FF2E "C1290" "%UT" 134 "" 0.7 12.24 1 4 1362 1311 3 200 "CCD match" + 4 2 -34.540000 5.680000 5.143000 1 P 134 -0.12885 -0.12885 "TOL " " C4 " 6 3 96FF2E "C1291" "%UT" 134 "" 0.7 13.09 1 4 1363 1312 3 200 "CCD match" + 5 2 -34.545000 4.825000 4.044000 1 P 134 -0.12885 -0.12885 "TOL " " C5 " 6 3 96FF2E "C1292" "%UT" 134 "" 0.7 12.54 1 4 1364 1313 3 200 "CCD match" + 6 2 -33.787000 5.069000 2.915000 1 P 134 -0.12885 -0.12885 "TOL " " C6 " 6 3 96FF2E "C1293" "%UT" 134 "" 0.7 14.23 1 4 1365 1314 3 200 "CCD match" + 7 3 -32.099995 6.505018 1.643737 1 P 134 0.12885 0.12885 "TOL " " C7 " 6 3 96FF2E "C2625" "" 134 "" <> <> 0 <> <> <> <> 200 <> + 8 41 -32.318044 7.925305 3.960797 1 P 134 0.12885 0.12885 "TOL " " H1 " 1 3 96FF2E "" "" 134 "" <> <> 0 <> <> <> <> 200 <> + 9 41 -33.672323 7.473059 5.954735 1 P 134 0.12885 0.12885 "TOL " " H2 " 1 3 96FF2E "" "" 134 "" <> <> 0 <> <> <> <> 200 <> + 10 41 -35.158445 5.487222 6.007154 1 P 134 0.12885 0.12885 "TOL " " H3 " 1 3 96FF2E "" "" 134 "" <> <> 0 <> <> <> <> 200 <> + 11 41 -35.156258 3.934698 4.055241 1 P 134 0.12885 0.12885 "TOL " " H4 " 1 3 96FF2E "" "" 134 "" <> <> 0 <> <> <> <> 200 <> + 12 41 -33.822915 4.399036 2.068680 1 P 134 0.12885 0.12885 "TOL " " H5 " 1 3 96FF2E "" "" 134 "" <> <> 0 <> <> <> <> 200 <> + 13 41 -32.249950 5.732008 0.890034 1 P 134 0.00000 0.00000 "TOL " " H6 " 1 3 96FF2E "" "" 134 "" <> <> <> <> <> <> <> <> <> + 14 41 -32.384126 7.473364 1.231819 1 P 134 0.00000 0.00000 "TOL " " H7 " 1 3 96FF2E "" "" 134 "" <> <> <> <> <> <> <> <> <> + 15 41 -31.049960 6.528714 1.935224 1 P 134 0.00000 0.00000 "TOL " " H8 " 1 3 96FF2E "" "" 134 "" <> <> <> <> <> <> <> <> <> + ::: + } + m_bond[15] { + # First column is bond index # + i_m_from + i_m_to + i_m_order + i_m_from_rep + i_m_to_rep + ::: + 1 1 2 2 3 3 + 2 1 6 1 3 3 + 3 1 7 1 3 3 + 4 2 3 1 3 3 + 5 2 8 1 3 3 + 6 3 4 2 3 3 + 7 3 9 1 3 3 + 8 4 5 1 3 3 + 9 4 10 1 3 3 + 10 5 6 2 3 3 + 11 5 11 1 3 3 + 12 6 12 1 3 3 + 13 7 13 1 3 3 + 14 7 14 1 3 3 + 15 7 15 1 3 3 + ::: + } + m_PDB_SEQRES[1] { + s_pdb_chain_id + s_pdb_SEQRES + ::: + 1 A "MET ASN ILE PHE GLU MET LEU ARG ILE ASP GLU GLY LEU ARG LEU LYS ILE TYR LYS ASP THR GLU GLY TYR TYR THR ILE GLY ILE GLY HIS LEU LEU THR LYS SER PRO SER LEU ASN ALA ALA LYS SER GLU LEU ASP LYS ALA ILE GLY ARG ASN CYS ASN GLY VAL ILE THR LYS ASP GLU ALA GLU LYS LEU PHE ASN GLN ASP VAL ASP ALA ALA VAL ARG GLY ILE LEU ARG ASN ALA LYS LEU LYS PRO VAL TYR ASP SER LEU ASP ALA VAL ARG ARG CYS ALA ALA ILE ASN MET VAL PHE GLN MET GLY GLU THR GLY VAL ALA GLY PHE THR ASN SER LEU ARG MET LEU GLN GLN LYS ARG TRP ASP GLU ALA ALA VAL ASN LEU ALA LYS SER ARG TRP TYR ASN GLN THR PRO ASN ARG ALA LYS ARG VAL ILE THR THR PHE ARG THR GLY THR TRP ASP ALA TYR LYS ASN LEU LEU GLU HIS HIS HIS HIS HIS HIS " + ::: + } + m_PDB_het_residues[2] { + s_pdb_het_id + s_pdb_het_name + s_pdb_het_formula + ::: + 1 BNZ "BENZENE" "C6 H6" + 2 EPE "4-(2-HYDROXYETHYL)-1-PIPERAZINE ETHANESULFONIC ACID" "C8 H18 N2 O4 S" + ::: + } +} + diff --git a/offPELE/data/ligands/ligand.pdb b/offPELE/data/ligands/ligand.pdb new file mode 100644 index 00000000..fbaf1a97 --- /dev/null +++ b/offPELE/data/ligands/ligand.pdb @@ -0,0 +1,86 @@ +HETATM 1 C1 LIG L 1 3.059 -18.343 108.323 1.00 0.00 C +HETATM 2 C2 LIG L 1 1.548 -18.176 108.440 1.00 0.00 C +HETATM 3 N1 LIG L 1 3.540 -19.171 107.184 1.00 0.00 N +HETATM 4 C3 LIG L 1 0.795 -18.167 109.624 1.00 0.00 C +HETATM 5 C4 LIG L 1 -0.549 -18.073 109.302 1.00 0.00 C +HETATM 6 N2 LIG L 1 -0.668 -17.983 107.940 1.00 0.00 N +HETATM 7 C5 LIG L 1 0.604 -18.027 107.426 1.00 0.00 C +HETATM 8 C6 LIG L 1 4.657 -18.794 106.498 1.00 0.00 C +HETATM 9 O1 LIG L 1 5.159 -17.673 106.630 1.00 0.00 O +HETATM 10 C7 LIG L 1 5.385 -19.829 105.598 1.00 0.00 C +HETATM 11 N3 LIG L 1 6.630 -19.338 105.015 1.00 0.00 N +HETATM 12 N4 LIG L 1 7.822 -19.667 105.553 1.00 0.00 N +HETATM 13 N5 LIG L 1 8.801 -18.954 104.899 1.00 0.00 N +HETATM 14 C8 LIG L 1 8.188 -18.196 103.946 1.00 0.00 C +HETATM 15 C9 LIG L 1 6.797 -18.438 103.976 1.00 0.00 C +HETATM 16 C10 LIG L 1 8.717 -17.272 103.039 1.00 0.00 C +HETATM 17 C11 LIG L 1 7.839 -16.625 102.170 1.00 0.00 C +HETATM 18 C12 LIG L 1 6.470 -16.887 102.200 1.00 0.00 C +HETATM 19 C13 LIG L 1 5.910 -17.795 103.105 1.00 0.00 C +HETATM 20 C14 LIG L 1 2.757 -20.273 106.770 1.00 0.00 C +HETATM 21 C15 LIG L 1 2.433 -21.274 107.686 1.00 0.00 C +HETATM 22 C16 LIG L 1 1.602 -22.321 107.301 1.00 0.00 C +HETATM 23 C17 LIG L 1 1.082 -22.389 106.001 1.00 0.00 C +HETATM 24 C18 LIG L 1 1.409 -21.375 105.094 1.00 0.00 C +HETATM 25 C19 LIG L 1 2.230 -20.321 105.474 1.00 0.00 C +HETATM 26 C20 LIG L 1 -1.903 -17.915 107.180 1.00 0.00 C +HETATM 27 C21 LIG L 1 0.206 -23.524 105.585 1.00 0.00 C +HETATM 28 C22 LIG L 1 -0.810 -23.333 104.636 1.00 0.00 C +HETATM 29 C23 LIG L 1 -1.601 -24.396 104.212 1.00 0.00 C +HETATM 30 C24 LIG L 1 -1.382 -25.663 104.739 1.00 0.00 C +HETATM 31 C25 LIG L 1 -0.397 -25.870 105.700 1.00 0.00 C +HETATM 32 C26 LIG L 1 0.394 -24.807 106.119 1.00 0.00 C +HETATM 33 H1 LIG L 1 3.419 -18.837 109.227 1.00 0.00 H +HETATM 34 H2 LIG L 1 3.516 -17.354 108.329 1.00 0.00 H +HETATM 35 H3 LIG L 1 1.198 -18.253 110.624 1.00 0.00 H +HETATM 36 H4 LIG L 1 -1.430 -18.075 109.927 1.00 0.00 H +HETATM 37 H5 LIG L 1 0.743 -17.986 106.355 1.00 0.00 H +HETATM 38 H6 LIG L 1 4.754 -20.140 104.766 1.00 0.00 H +HETATM 39 H7 LIG L 1 5.600 -20.719 106.191 1.00 0.00 H +HETATM 40 H8 LIG L 1 9.768 -17.043 103.040 1.00 0.00 H +HETATM 41 H9 LIG L 1 8.220 -15.893 101.474 1.00 0.00 H +HETATM 42 H10 LIG L 1 5.820 -16.357 101.519 1.00 0.00 H +HETATM 43 H11 LIG L 1 4.846 -17.969 103.137 1.00 0.00 H +HETATM 44 H12 LIG L 1 2.811 -21.240 108.696 1.00 0.00 H +HETATM 45 H13 LIG L 1 1.354 -23.079 108.030 1.00 0.00 H +HETATM 46 H14 LIG L 1 1.034 -21.396 104.082 1.00 0.00 H +HETATM 47 H15 LIG L 1 2.444 -19.539 104.759 1.00 0.00 H +HETATM 48 H16 LIG L 1 -2.709 -18.403 107.733 1.00 0.00 H +HETATM 49 H17 LIG L 1 -1.771 -18.406 106.213 1.00 0.00 H +HETATM 50 H18 LIG L 1 -2.161 -16.866 107.016 1.00 0.00 H +HETATM 51 H19 LIG L 1 -0.998 -22.355 104.219 1.00 0.00 H +HETATM 52 H20 LIG L 1 -2.383 -24.237 103.485 1.00 0.00 H +HETATM 53 H21 LIG L 1 -2.001 -26.487 104.419 1.00 0.00 H +HETATM 54 H22 LIG L 1 -0.249 -26.853 106.123 1.00 0.00 H +HETATM 55 H23 LIG L 1 1.167 -25.000 106.852 1.00 0.00 H +CONECT 1 2 3 33 34 +CONECT 2 4 7 7 +CONECT 3 8 20 +CONECT 4 5 5 35 +CONECT 5 6 36 +CONECT 6 7 26 +CONECT 7 37 +CONECT 8 9 9 10 +CONECT 10 11 38 39 +CONECT 11 12 15 +CONECT 12 13 13 +CONECT 13 14 +CONECT 14 15 15 16 +CONECT 15 19 +CONECT 16 17 17 40 +CONECT 17 18 41 +CONECT 18 19 19 42 +CONECT 19 43 +CONECT 20 21 21 25 +CONECT 21 22 44 +CONECT 22 23 23 45 +CONECT 23 24 27 +CONECT 24 25 25 46 +CONECT 25 47 +CONECT 26 48 49 50 +CONECT 27 28 28 32 +CONECT 28 29 51 +CONECT 29 30 30 52 +CONECT 30 31 53 +CONECT 31 32 32 54 +CONECT 32 55 diff --git a/offPELE/utils/__init__.py b/offPELE/utils/__init__.py new file mode 100644 index 00000000..16281fe0 --- /dev/null +++ b/offPELE/utils/__init__.py @@ -0,0 +1 @@ +from .utils import * diff --git a/offPELE/utils/utils.py b/offPELE/utils/utils.py new file mode 100644 index 00000000..143e3285 --- /dev/null +++ b/offPELE/utils/utils.py @@ -0,0 +1,15 @@ +from pkg_resources import resource_filename +import os + + +def get_data_file_path(relative_path): + + fn = resource_filename('offPELE', os.path.join( + 'data', relative_path)) + + if not os.path.exists(fn): + raise ValueError( + "Sorry! {fn} does not exist. If you just added it, you'll have to " + + " re-install") + + return fn diff --git a/setup.py b/setup.py index 820e6c29..d1614a76 100644 --- a/setup.py +++ b/setup.py @@ -35,9 +35,9 @@ def find_package_data(data_root, package_root): "License :: OSI Approved :: MIT", "Programming Language :: Python :: 3", "Operating System :: Unix" - ] + ], version=versioneer.get_version(), cmdclass=versioneer.get_cmdclass(), package_data={'offPELE': find_package_data( - 'offPELE')} + 'offPELE/data', 'offPELE')}, ) From cc2bfacc2412c938baae9268c7712957580dbd2d Mon Sep 17 00:00:00 2001 From: Marti Municoy Date: Fri, 19 Jun 2020 15:31:17 +0200 Subject: [PATCH 03/67] Initial class definitions for molecule, atom and IMPACT template --- offPELE/template/__init__.py | 1 + offPELE/template/impact.py | 52 ++++++++++++++ offPELE/topology/__init__.py | 1 + offPELE/topology/molecule.py | 135 +++++++++++++++++++++++++++++++++++ 4 files changed, 189 insertions(+) create mode 100644 offPELE/template/__init__.py create mode 100644 offPELE/template/impact.py create mode 100644 offPELE/topology/__init__.py create mode 100644 offPELE/topology/molecule.py diff --git a/offPELE/template/__init__.py b/offPELE/template/__init__.py new file mode 100644 index 00000000..58d08455 --- /dev/null +++ b/offPELE/template/__init__.py @@ -0,0 +1 @@ +from .impact import Impact diff --git a/offPELE/template/impact.py b/offPELE/template/impact.py new file mode 100644 index 00000000..cd7770a3 --- /dev/null +++ b/offPELE/template/impact.py @@ -0,0 +1,52 @@ + +# Global imports +import offPELE + + +class Impact(object): + def __init__(self, molecule): + if isinstance(molecule, offPELE.topology.Molecule): + self._initialize_from_molecule(molecule) + else: + raise Exception('Invalid input molecule for Impact template') + + def _initialize_from_molecule(self, molecule): + self._molecule = molecule + + def write(self, path): + with open(path) as file: + self._write_header(file) + self._write_resx(file) + self._write_nbon(file) + self._write_bond(file) + self._write_thet(file) + self._write_phi(file) + self._write_iphi(file) + self._write_end(file) + + def _write_header(self, file): + file.write('* LIGAND DATABASE FILE ({})\n'.format( + self.molecule.forcefield)) + file.write('* File generated with offPELE {}\n'.format( + offPELE.__version__)) + + def _write_resx(self, file): + pass + + def _write_nbon(self, file): + pass + + def _write_bond(self, file): + pass + + def _write_thet(self, file): + pass + + def _write_phi(self, file): + pass + + def _write_iphi(self, file): + pass + + def _write_end(self, file): + file.write('END\n') diff --git a/offPELE/topology/__init__.py b/offPELE/topology/__init__.py new file mode 100644 index 00000000..836146e1 --- /dev/null +++ b/offPELE/topology/__init__.py @@ -0,0 +1 @@ +from .molecule import Molecule diff --git a/offPELE/topology/molecule.py b/offPELE/topology/molecule.py new file mode 100644 index 00000000..30edd7e9 --- /dev/null +++ b/offPELE/topology/molecule.py @@ -0,0 +1,135 @@ + +# Global imports + +# Local imports +from offPELE.template import Impact + + +class Atom(object): + def __init__(self, _id=-1, OPLS_type=None, PDB_name=None, unknown=None, + z_matrix_x=None, z_matrix_y=None, z_matrix_z=None, + sigma=None, epsilon=None, charge=None, born_radius=None, + SASA_radius=None, nonpolar_gamma=None, nonpolar_alpha=None): + self.id = _id + self.OPLS_type = OPLS_type + self.PDB_name = PDB_name + self.unknown = unknown + self.z_matrix_x = z_matrix_x + self.z_matrix_y = z_matrix_y + self.z_matrix_z = z_matrix_z + self.sigma = sigma + self.epsilon = epsilon + self.charge = charge + self.born_radius = born_radius # Rad. Non Polar SGB + self.SASA_radius = SASA_radius # Rad. Non Polar Type + self.nonpolar_gamma = nonpolar_gamma # SGB Non Polar gamma + self.nonpolar_alpha = nonpolar_alpha # SGB Non Polar type + + +class Molecule(object): + def __init__(self, path=None): + if isinstance(path, str): + from pathlib import Path + extension = Path(path).suffix + extension = extension.strip('.') + if extension == 'pdb': + self._initialize_from_pdb(path) + else: + raise ValueError( + '{} is not a valid extension'.format(extension)) + else: + self._initialize() + + def _initialize(self): + self._name = '' + self._forcefield = '' + self._atoms = list() + self._bonds = list() + self._angles = list() + self._dihedrals = list() + self._impropers = list() + self._rdkit_molecule = None + self._off_molecule = None + + def _initialize_from_pdb(self, path): + self._initialize() + print(' - Loading molecule from RDKit') + + try: + from rdkit import Chem + except ImportError: + raise Exception('RDKit Python API not found') + + self._rdkit_molecule = Chem.rdmolfiles.MolFromPDBFile(path, + removeHs=False) + + try: + from openforcefield.topology.molecule import Molecule as \ + OFFMolecule + except ImportError: + raise Exception('OpenForceField package not found') + + self._off_molecule = OFFMolecule.from_rdkit(self.rdkit_molecule) + + def parameterize(self, forcefield): + try: + from openforcefield.topology.molecule import Molecule as \ + OFFMolecule + from openforcefield.typing.engines.smirnoff import ForceField as \ + OFFForceField + except ImportError: + raise Exception('OpenForceField package not found') + + if not isinstance(self._off_molecule, OFFMolecule): + raise Exception('OpenForceField molecule was not initialized ' + + 'correctly') + + print(' - Loading forcefield') + if isinstance(forcefield, str): + forcefield = OFFForceField(forcefield) + elif isinstance(forcefield, OFFForceField): + pass + else: + raise Exception('Invalid forcefield type') + + print(' - Computing partial charges with am1bcc') + self._off_molecule.compute_partial_charges_am1bcc() + + self._build_atoms() + + def _assert_parameterized(self): + try: + assert self.off_molecule is not None + except AssertionError: + raise Exception('Molecule not parameterized') + + def _build_atoms(self): + self._assert_parameterized() + + for atom in self.off_molecule.atoms: + self._add_atom(Atom()) + + def _add_atom(self, atom): + self._atoms.append(atom) + + def get_pdb_atom_names(self): + self._assert_parameterized() + + pdb_atom_names = list() + + for atom in self.rdkit_molecule.GetAtoms(): + pdb_info = atom.GetPDBResidueInfo() + pdb_atom_names.append(pdb_info.GetName()) + + return pdb_atom_names + + def to_impact(self, path): + pass + + @property + def off_molecule(self): + return self._off_molecule + + @property + def rdkit_molecule(self): + return self._rdkit_molecule From ba3f65c46868d5b664d3a01484daef5047f81caa Mon Sep 17 00:00:00 2001 From: Marti Municoy Date: Fri, 19 Jun 2020 15:46:19 +0200 Subject: [PATCH 04/67] Rotamer and RotamerLibrary classes are added --- offPELE/topology/rotamer.py | 56 +++++++++++++++++++++++++++++++++++++ 1 file changed, 56 insertions(+) create mode 100644 offPELE/topology/rotamer.py diff --git a/offPELE/topology/rotamer.py b/offPELE/topology/rotamer.py new file mode 100644 index 00000000..97f2d03f --- /dev/null +++ b/offPELE/topology/rotamer.py @@ -0,0 +1,56 @@ +# Global imports +from collections import defaultdict + + +class Rotamer(object): + def __init__(self, atom1, atom2, resolution=30): + self.atom1 = atom1 + self.atom2 = atom2 + self.resolution = resolution + + @property + def atom1(self): + return self._atom1 + + @property + def atom2(self): + return self._atom2 + + @property + def resolution(self): + return self._resolution + + +class RotamerLibrary(object): + def __init__(self, residue_name): + self._residue_name = residue_name + self._rotamers = defaultdict(list) + + def add_rotamer(self, rotamer, group_id): + self._rotamers[group_id].append(rotamer) + + def to_file(self, path): + with open(path, 'w') as file: + file.write('rot assign res {} &\n') + for i, group in enumerate(self.rotamers.keys()): + if i > 0: + file.write(' newgrp &\n') + for rotamer in self.rotamers[group]: + file.write(' sidelib FREE{} {} {} &\n'.format( + rotamer.atom1, rotamer.atom2, rotamer.resolution)) + + @property + def residue_name(self): + return self._residue_name + + @property + def rotamers(self): + return self._rotamers + + +class RotamerLibraryBuilder(object): + def build_from_molecule(self, molecule): + try: + from rdkit import Chem + except ImportError: + raise Exception('RDKit Python API not found') From 895a612d3455488f716983292f981aa092d8f4bf Mon Sep 17 00:00:00 2001 From: Marti Municoy Date: Sun, 21 Jun 2020 18:19:59 +0200 Subject: [PATCH 05/67] Creation of the rotamer library builder --- offPELE/topology/molecule.py | 282 +++++++++++++++++++++++++++++++++-- offPELE/topology/rotamer.py | 20 +-- 2 files changed, 277 insertions(+), 25 deletions(-) diff --git a/offPELE/topology/molecule.py b/offPELE/topology/molecule.py index 30edd7e9..23e2b8a0 100644 --- a/offPELE/topology/molecule.py +++ b/offPELE/topology/molecule.py @@ -1,16 +1,19 @@ # Global imports - -# Local imports -from offPELE.template import Impact +from collections import defaultdict +from copy import deepcopy +from pathlib import Path +from .rotamer import RotamerLibrary, Rotamer class Atom(object): - def __init__(self, _id=-1, OPLS_type=None, PDB_name=None, unknown=None, - z_matrix_x=None, z_matrix_y=None, z_matrix_z=None, - sigma=None, epsilon=None, charge=None, born_radius=None, - SASA_radius=None, nonpolar_gamma=None, nonpolar_alpha=None): - self.id = _id + def __init__(self, index=-1, core=None, OPLS_type=None, PDB_name=None, + unknown=None, z_matrix_x=None, z_matrix_y=None, + z_matrix_z=None, sigma=None, epsilon=None, charge=None, + born_radius=None, SASA_radius=None, nonpolar_gamma=None, + nonpolar_alpha=None): + self.index = index + self.core = core self.OPLS_type = OPLS_type self.PDB_name = PDB_name self.unknown = unknown @@ -25,6 +28,12 @@ def __init__(self, _id=-1, OPLS_type=None, PDB_name=None, unknown=None, self.nonpolar_gamma = nonpolar_gamma # SGB Non Polar gamma self.nonpolar_alpha = nonpolar_alpha # SGB Non Polar type + def set_as_core(self): + self.core = True + + def set_as_branch(self): + self.core = False + class Molecule(object): def __init__(self, path=None): @@ -50,6 +59,7 @@ def _initialize(self): self._impropers = list() self._rdkit_molecule = None self._off_molecule = None + self._rotamer_library = None def _initialize_from_pdb(self, path): self._initialize() @@ -60,9 +70,16 @@ def _initialize_from_pdb(self, path): except ImportError: raise Exception('RDKit Python API not found') + filename = Path(path).stem + if len(filename) > 2: + self._name = filename[0:3].upper() + self._rdkit_molecule = Chem.rdmolfiles.MolFromPDBFile(path, removeHs=False) + # RDKit must generate stereochemistry specifically from 3D coords + Chem.rdmolops.AssignStereochemistryFrom3D(self._rdkit_molecule) + try: from openforcefield.topology.molecule import Molecule as \ OFFMolecule @@ -93,10 +110,237 @@ def parameterize(self, forcefield): raise Exception('Invalid forcefield type') print(' - Computing partial charges with am1bcc') - self._off_molecule.compute_partial_charges_am1bcc() + # self._off_molecule.compute_partial_charges_am1bcc() self._build_atoms() + def _compute_rotamer_graph(self, rot_bonds_atom_ids): + import networkx as nx + graph = nx.Graph() + + for atom in self.rdkit_molecule.GetAtoms(): + pdb_info = atom.GetPDBResidueInfo() + graph.add_node(atom.GetIdx(), pdb_name=pdb_info.GetName(), + nrot_neighbors=list()) + + for bond in self.rdkit_molecule.GetBonds(): + atom1 = bond.GetBeginAtomIdx() + atom2 = bond.GetEndAtomIdx() + if ((atom1, atom2) in rot_bonds_atom_ids + or (atom2, atom2) in rot_bonds_atom_ids): + rotatable = True + else: + rotatable = False + graph.nodes[atom1]['nrot_neighbors'].append(atom2) + graph.nodes[atom2]['nrot_neighbors'].append(atom1) + + graph.add_edge(bond.GetBeginAtomIdx(), + bond.GetEndAtomIdx(), + weight=int(rotatable)) + + for i, j in rot_bonds_atom_ids: + graph[i][j]['weight'] = 1 + graph.nodes[i]['rotatable'] = True + graph.nodes[j]['rotatable'] = True + + return graph + + def _set_core(self, graph, rot_bonds_atom_ids): + def get_all_nrot_neighbors(atom_id, visited_neighbors): + if atom_id in visited_neighbors: + return visited_neighbors + visited_neighbors.add(atom_id) + nrot_neighbors = graph.nodes[atom_id]['nrot_neighbors'] + for nrot_neighbor in nrot_neighbors: + visited_neighbors = get_all_nrot_neighbors( + nrot_neighbor, visited_neighbors) + return visited_neighbors + + from networkx.algorithms.shortest_paths.generic import \ + shortest_path_length + from networkx.algorithms.distance_measures import eccentricity + + # Calculate graph distances according to weight values + weighted_distances = dict(shortest_path_length(graph, weight="weight")) + + # Calculate eccentricites using weighted distances + eccentricities = eccentricity(graph, sp=weighted_distances) + + # Group nodes by eccentricity + nodes_by_eccentricities = defaultdict(list) + for node, ecc in eccentricities.items(): + nodes_by_eccentricities[ecc].append(node) + + # Core atoms must have the minimum eccentricity + _, centered_nodes = sorted(nodes_by_eccentricities.items())[0] + + # Construct nrot groups with centered nodes + already_visited = set() + centered_node_groups = list() + for node in centered_nodes: + if node in already_visited: + continue + centered_node_groups.append(get_all_nrot_neighbors(node, set())) + + # In case of more than one group, core will be the largest + node_group = sorted(centered_node_groups, key=len, reverse=True)[0] + + for atom in self.atoms: + if atom.index in node_group: + atom.set_as_core() + else: + atom.set_as_branch() + + def _get_rot_bonds_per_group(self, graph, branch_groups): + rot_bonds_per_group = list() + for group in branch_groups: + rot_bonds = list() + visited_bonds = set() + for node in group: + bonds = graph.edges(node) + for bond in bonds: + if bond in visited_bonds: + continue + if graph[bond[0]][bond[1]]['weight'] == 1: + rot_bonds.append(bond) + visited_bonds.add(bond) + visited_bonds.add((bond[1], bond[0])) + rot_bonds_per_group.append(rot_bonds) + + return rot_bonds_per_group + + def _get_core_atom_per_group(self, rot_bonds_per_group, core_indexes): + core_atom_per_group = list() + for rot_bonds in rot_bonds_per_group: + for (a1, a2) in rot_bonds: + if a1 in core_indexes: + core_atom_per_group.append(a1) + break + elif a2 in core_indexes: + core_atom_per_group.append(a2) + break + else: + core_atom_per_group.append(None) + + return core_atom_per_group + + def _get_sorted_bonds_per_group(self, core_atom_per_group, + rot_bonds_per_group, distances): + sorted_rot_bonds_per_group = list() + for core_atom, rot_bonds in zip(core_atom_per_group, + rot_bonds_per_group): + sorting_dict = dict() + for bond in rot_bonds: + min_d = min([distances[core_atom][bond[0]], + distances[core_atom][bond[1]]]) + sorting_dict[bond] = min_d + + sorted_rot_bonds_per_group.append( + [i[0] for i in + sorted(sorting_dict.items(), key=lambda item: item[1])]) + + return sorted_rot_bonds_per_group + + def _build_rotamer_library(self, graph, resolution): + import networkx as nx + + core_atoms = set() + for atom in self.atoms: + if atom.core: + core_atoms.add(atom) + core_indexes = [atom.index for atom in core_atoms] + + assert len(core_atoms) > 0, 'No core atoms were found' + + branch_graph = deepcopy(graph) + + for core_atom in core_atoms: + branch_graph.remove_node(core_atom.index) + + branch_groups = list(nx.connected_components(branch_graph)) + + rot_bonds_per_group = self._get_rot_bonds_per_group( + graph, branch_groups) + + core_atom_per_group = self._get_core_atom_per_group( + rot_bonds_per_group, core_indexes) + + distances = dict(nx.shortest_path_length(graph)) + + sorted_rot_bonds_per_group = self._get_sorted_bonds_per_group( + core_atom_per_group, rot_bonds_per_group, distances) + + self._rotamer_library = RotamerLibrary(self.name) + + # PELE needs underscores instead of whitespaces + pdb_atom_names = [name.replace(' ', '_',) + for name in self.get_pdb_atom_names()] + + for group_id, rot_bonds in enumerate(sorted_rot_bonds_per_group): + for (atom1_index, atom2_index) in rot_bonds: + atom1_name = pdb_atom_names[atom1_index] + atom2_name = pdb_atom_names[atom2_index] + rotamer = Rotamer(atom1_name, atom2_name, resolution) + self.rotamer_library.add_rotamer(rotamer, group_id) + + def build_rotamer_library(self, resolution): + self._assert_parameterized() + + try: + from rdkit import Chem + except ImportError: + raise Exception('RDKit Python API not found') + + print(' - Generating rotamer library') + + # Fins rotatable bond ids as in Lipinski module in RDKit + # https://github.com/rdkit/rdkit/blob/1bf6ef3d65f5c7b06b56862b3fb9116a3839b229/rdkit/Chem/Lipinski.py#L47 + rot_bonds_atom_ids = self._rdkit_molecule.GetSubstructMatches( + Chem.MolFromSmarts('[!$(*#*)&!D1]-&!@[!$(*#*)&!D1]')) + + graph = self._compute_rotamer_graph(rot_bonds_atom_ids) + + self._set_core(graph, rot_bonds_atom_ids) + + self._build_rotamer_library(graph, resolution) + + def plot_rotamer_graph(self): + self._assert_parameterized() + + try: + from rdkit import Chem + except ImportError: + raise Exception('RDKit Python API not found') + + # Fins rotatable bond ids as in Lipinski module in RDKit + # https://github.com/rdkit/rdkit/blob/1bf6ef3d65f5c7b06b56862b3fb9116a3839b229/rdkit/Chem/Lipinski.py#L47 + rot_bonds_atom_ids = self._rdkit_molecule.GetSubstructMatches( + Chem.MolFromSmarts('[!$(*#*)&!D1]-&!@[!$(*#*)&!D1]')) + + graph = self._compute_rotamer_graph(rot_bonds_atom_ids) + + rot_edges = [(u, v) for (u, v, d) in graph.edges(data=True) + if d['weight'] == 1] + nrot_edges = [(u, v) for (u, v, d) in graph.edges(data=True) + if d['weight'] == 0] + + import networkx as nx + + pos = nx.circular_layout(graph) + + nx.draw_networkx_nodes(graph, pos, node_size=400) + nx.draw_networkx_edges(graph, pos, edgelist=rot_edges, + width=4) + nx.draw_networkx_edges(graph, pos, edgelist=nrot_edges, + width=4, alpha=0.5, edge_color='b', + style='dashed') + nx.draw_networkx_labels(graph, pos, font_size=10, + font_family='sans-serif') + + import matplotlib.pyplot as plt + plt.axis('off') + plt.show() + def _assert_parameterized(self): try: assert self.off_molecule is not None @@ -106,8 +350,12 @@ def _assert_parameterized(self): def _build_atoms(self): self._assert_parameterized() - for atom in self.off_molecule.atoms: - self._add_atom(Atom()) + # PELE needs underscores instead of whitespaces + pdb_atom_names = [name.replace(' ', '_',) + for name in self.get_pdb_atom_names()] + + for index, atom in enumerate(self.off_molecule.atoms): + self._add_atom(Atom(index=index, PDB_name=pdb_atom_names[index])) def _add_atom(self, atom): self._atoms.append(atom) @@ -133,3 +381,15 @@ def off_molecule(self): @property def rdkit_molecule(self): return self._rdkit_molecule + + @property + def rotamer_library(self): + return self._rotamer_library + + @property + def name(self): + return self._name + + @property + def atoms(self): + return self._atoms diff --git a/offPELE/topology/rotamer.py b/offPELE/topology/rotamer.py index 97f2d03f..bb35c70e 100644 --- a/offPELE/topology/rotamer.py +++ b/offPELE/topology/rotamer.py @@ -4,9 +4,9 @@ class Rotamer(object): def __init__(self, atom1, atom2, resolution=30): - self.atom1 = atom1 - self.atom2 = atom2 - self.resolution = resolution + self._atom1 = atom1 + self._atom2 = atom2 + self._resolution = resolution @property def atom1(self): @@ -22,7 +22,7 @@ def resolution(self): class RotamerLibrary(object): - def __init__(self, residue_name): + def __init__(self, residue_name='LIG'): self._residue_name = residue_name self._rotamers = defaultdict(list) @@ -31,13 +31,13 @@ def add_rotamer(self, rotamer, group_id): def to_file(self, path): with open(path, 'w') as file: - file.write('rot assign res {} &\n') + file.write('rot assign res {} &\n'.format(self.residue_name)) for i, group in enumerate(self.rotamers.keys()): if i > 0: file.write(' newgrp &\n') for rotamer in self.rotamers[group]: file.write(' sidelib FREE{} {} {} &\n'.format( - rotamer.atom1, rotamer.atom2, rotamer.resolution)) + rotamer.resolution, rotamer.atom1, rotamer.atom2)) @property def residue_name(self): @@ -46,11 +46,3 @@ def residue_name(self): @property def rotamers(self): return self._rotamers - - -class RotamerLibraryBuilder(object): - def build_from_molecule(self, molecule): - try: - from rdkit import Chem - except ImportError: - raise Exception('RDKit Python API not found') From d0a8be6fe87d315bb53858ee8847cefa0e34ce3d Mon Sep 17 00:00:00 2001 From: Marti Municoy Date: Mon, 22 Jun 2020 13:25:19 +0200 Subject: [PATCH 06/67] Connectivity problems of OFF's am1bcc implementation are solved --- offPELE/topology/molecule.py | 86 ++++++++++++++++++++++++++++++++++-- offPELE/utils/utils.py | 11 +++++ 2 files changed, 93 insertions(+), 4 deletions(-) diff --git a/offPELE/topology/molecule.py b/offPELE/topology/molecule.py index 23e2b8a0..5da2f536 100644 --- a/offPELE/topology/molecule.py +++ b/offPELE/topology/molecule.py @@ -3,7 +3,15 @@ from collections import defaultdict from copy import deepcopy from pathlib import Path +import subprocess +import tempfile +import os + +import numpy as np +from simtk import unit + from .rotamer import RotamerLibrary, Rotamer +from offPELE.utils import temporary_cd class Atom(object): @@ -35,6 +43,16 @@ def set_as_branch(self): self.core = False +class Bond(object): + def __init__(self, index=-1, atom1_idx=None, atom2_idx=None, + spring_constant=None, eq_dist=None): + self.index = index + self.atom1_idx = atom1_idx + self.atom2_idx = atom2_idx + self.spring_constant = spring_constant + self.eq_dist = eq_dist + + class Molecule(object): def __init__(self, path=None): if isinstance(path, str): @@ -49,6 +67,10 @@ def __init__(self, path=None): else: self._initialize() + class ChargeCalculationError(Exception): + """An external error when calculating charges""" + pass + def _initialize(self): self._name = '' self._forcefield = '' @@ -110,10 +132,18 @@ def parameterize(self, forcefield): raise Exception('Invalid forcefield type') print(' - Computing partial charges with am1bcc') - # self._off_molecule.compute_partial_charges_am1bcc() + self._calculate_am1bcc_charges() self._build_atoms() + self._build_bonds() + + self._build_angles() + + self._build_dihedrals() + + self._build_impropers() + def _compute_rotamer_graph(self, rot_bonds_atom_ids): import networkx as nx graph = nx.Graph() @@ -347,15 +377,60 @@ def _assert_parameterized(self): except AssertionError: raise Exception('Molecule not parameterized') - def _build_atoms(self): - self._assert_parameterized() + def _calculate_am1bcc_charges(self): + try: + from rdkit import Chem + except ImportError: + raise Exception('RDKit Python API not found') + + with tempfile.TemporaryDirectory() as tmpdir: + with temporary_cd(tmpdir): + net_charge = self.off_molecule.total_charge / \ + unit.elementary_charge + with open('molecule.sdf', 'w') as f: + writer = Chem.SDWriter(f) + writer.write(self.rdkit_molecule) + writer.close() + subprocess.check_output([ + "antechamber", "-i", "molecule.sdf", "-fi", "sdf", + "-o", "charged.ac", "-fo", "ac", "-pf", "yes", "-dr", "n", + "-c", "bcc", "-nc", str(net_charge)]) + # Write out just charges + subprocess.check_output([ + "antechamber", "-dr", "n", "-i", "charged.ac", "-fi", "ac", + "-o", "charged2.ac", "-fo", "ac", "-c", "wc", + "-cf", "charges.txt", "-pf", "yes"]) + if not os.path.exists('charges.txt'): + # TODO: copy files into local directory to aid debugging? + raise self.ChargeCalculationError( + "Antechamber/sqm partial charge calculation failed on " + "molecule {} (SMILES {})".format( + self.off_molecule.name, + self.off_molecule.to_smiles())) + # Read the charges + with open('charges.txt', 'r') as infile: + contents = infile.read() + text_charges = contents.split() + charges = np.zeros([self.off_molecule.n_atoms], np.float64) + for index, token in enumerate(text_charges): + charges[index] = float(token) + + charges = unit.Quantity(charges, unit.elementary_charge) + self.off_molecule.partial_charges = charges + def _build_atoms(self): # PELE needs underscores instead of whitespaces pdb_atom_names = [name.replace(' ', '_',) for name in self.get_pdb_atom_names()] for index, atom in enumerate(self.off_molecule.atoms): - self._add_atom(Atom(index=index, PDB_name=pdb_atom_names[index])) + self._add_atom(Atom(index=index, PDB_name=pdb_atom_names[index], + OPLS_type=None, unknown=None, z_matrix_x=None, + z_matrix_y=None, z_matrix_z=None, + sigma=None, epsilon=None, + charge=None, born_radius=None, + SASA_radius=None, nonpolar_gamma=None, + nonpolar_alpha=None)) def _add_atom(self, atom): self._atoms.append(atom) @@ -371,6 +446,9 @@ def get_pdb_atom_names(self): return pdb_atom_names + def _build_bonds(self): + pass + def to_impact(self, path): pass diff --git a/offPELE/utils/utils.py b/offPELE/utils/utils.py index 143e3285..2bac787f 100644 --- a/offPELE/utils/utils.py +++ b/offPELE/utils/utils.py @@ -1,5 +1,6 @@ from pkg_resources import resource_filename import os +import contextlib def get_data_file_path(relative_path): @@ -13,3 +14,13 @@ def get_data_file_path(relative_path): + " re-install") return fn + + +@contextlib.contextmanager +def temporary_cd(path): + old_path = os.getcwd() + os.chdir(os.path.abspath(path)) + try: + yield + finally: + os.chdir(old_path) From 21da7c49075121784e6b7efdf66d0041b1437147 Mon Sep 17 00:00:00 2001 From: Marti Municoy Date: Mon, 22 Jun 2020 16:34:40 +0200 Subject: [PATCH 07/67] Toolkit wrappers are defined --- offPELE/topology/molecule.py | 85 ++++++----------- offPELE/utils/toolkits.py | 176 +++++++++++++++++++++++++++++++++++ 2 files changed, 203 insertions(+), 58 deletions(-) create mode 100644 offPELE/utils/toolkits.py diff --git a/offPELE/topology/molecule.py b/offPELE/topology/molecule.py index 5da2f536..4336789c 100644 --- a/offPELE/topology/molecule.py +++ b/offPELE/topology/molecule.py @@ -3,15 +3,9 @@ from collections import defaultdict from copy import deepcopy from pathlib import Path -import subprocess -import tempfile -import os - -import numpy as np -from simtk import unit from .rotamer import RotamerLibrary, Rotamer -from offPELE.utils import temporary_cd +from offPELE.utils.toolkits import AmberToolkitWrapper class Atom(object): @@ -67,10 +61,6 @@ def __init__(self, path=None): else: self._initialize() - class ChargeCalculationError(Exception): - """An external error when calculating charges""" - pass - def _initialize(self): self._name = '' self._forcefield = '' @@ -378,44 +368,10 @@ def _assert_parameterized(self): raise Exception('Molecule not parameterized') def _calculate_am1bcc_charges(self): - try: - from rdkit import Chem - except ImportError: - raise Exception('RDKit Python API not found') + ambertoolkit = AmberToolkitWrapper() + + charges = ambertoolkit.compute_partial_charges_am1bcc(self) - with tempfile.TemporaryDirectory() as tmpdir: - with temporary_cd(tmpdir): - net_charge = self.off_molecule.total_charge / \ - unit.elementary_charge - with open('molecule.sdf', 'w') as f: - writer = Chem.SDWriter(f) - writer.write(self.rdkit_molecule) - writer.close() - subprocess.check_output([ - "antechamber", "-i", "molecule.sdf", "-fi", "sdf", - "-o", "charged.ac", "-fo", "ac", "-pf", "yes", "-dr", "n", - "-c", "bcc", "-nc", str(net_charge)]) - # Write out just charges - subprocess.check_output([ - "antechamber", "-dr", "n", "-i", "charged.ac", "-fi", "ac", - "-o", "charged2.ac", "-fo", "ac", "-c", "wc", - "-cf", "charges.txt", "-pf", "yes"]) - if not os.path.exists('charges.txt'): - # TODO: copy files into local directory to aid debugging? - raise self.ChargeCalculationError( - "Antechamber/sqm partial charge calculation failed on " - "molecule {} (SMILES {})".format( - self.off_molecule.name, - self.off_molecule.to_smiles())) - # Read the charges - with open('charges.txt', 'r') as infile: - contents = infile.read() - text_charges = contents.split() - charges = np.zeros([self.off_molecule.n_atoms], np.float64) - for index, token in enumerate(text_charges): - charges[index] = float(token) - - charges = unit.Quantity(charges, unit.elementary_charge) self.off_molecule.partial_charges = charges def _build_atoms(self): @@ -424,17 +380,33 @@ def _build_atoms(self): for name in self.get_pdb_atom_names()] for index, atom in enumerate(self.off_molecule.atoms): - self._add_atom(Atom(index=index, PDB_name=pdb_atom_names[index], - OPLS_type=None, unknown=None, z_matrix_x=None, - z_matrix_y=None, z_matrix_z=None, - sigma=None, epsilon=None, - charge=None, born_radius=None, - SASA_radius=None, nonpolar_gamma=None, - nonpolar_alpha=None)) + atom = Atom(index=index, PDB_name=pdb_atom_names[index], + OPLS_type=None, unknown=None, z_matrix_x=None, + z_matrix_y=None, z_matrix_z=None, + sigma=None, + epsilon=None, + charge=self.off_molecule.partial_charges[index], + born_radius=None, + SASA_radius=None, + nonpolar_gamma=None, + nonpolar_alpha=None) + self._add_atom(atom) def _add_atom(self, atom): self._atoms.append(atom) + def _build_bonds(self): + pass + + def _build_angles(self): + pass + + def _build_dihedrals(self): + pass + + def _build_impropers(self): + pass + def get_pdb_atom_names(self): self._assert_parameterized() @@ -446,9 +418,6 @@ def get_pdb_atom_names(self): return pdb_atom_names - def _build_bonds(self): - pass - def to_impact(self, path): pass diff --git a/offPELE/utils/toolkits.py b/offPELE/utils/toolkits.py new file mode 100644 index 00000000..8c455a30 --- /dev/null +++ b/offPELE/utils/toolkits.py @@ -0,0 +1,176 @@ +import importlib +from distutils.spawn import find_executable +import tempfile +import os +import subprocess + +import numpy as np +from simtk import unit + +from offPELE.utils import temporary_cd + + +# Exceptions +class ToolkitUnavailableException(Exception): + """The requested toolkit is unavailable.""" + pass + + +class ChargeCalculationError(Exception): + """An external error when calculating charges""" + pass + + +class ToolkitWrapper(object): + """ + Toolkit wrapper base class. + """ + _is_available = None + _toolkit_name = None + + @property + def toolkit_name(self): + return self._toolkit_name + + @staticmethod + def is_available(): + """ + Check whether the corresponding toolkit can be imported + Returns + ------- + is_installed : bool + True if corresponding toolkit is installed, False otherwise. + """ + return NotImplementedError + + +class RDKitToolkitWrapper(ToolkitWrapper): + _toolkit_name = 'RDKit Toolkit' + + def __init__(self): + super().__init__() + + if not self.is_available(): + raise ToolkitUnavailableException( + 'The required toolkit {self.toolkit_name} is not ' + 'available.') + + @staticmethod + def is_available(): + """ + Check whether the RDKit toolkit can be imported + Returns + ------- + is_installed : bool + True if RDKit is installed, False otherwise. + """ + try: + importlib.import_module('rdkit', 'Chem') + return True + except ImportError: + return False + + def to_sfd_file(self, molecule, path): + from rdkit import Chem + + rdkit_molecule = molecule.rdkit_molecule + + with open('molecule.sdf', 'w') as f: + writer = Chem.SDWriter(f) + writer.write(rdkit_molecule) + writer.close() + + +class AmberToolkitWrapper(ToolkitWrapper): + _toolkit_name = 'Amber Toolkit' + + def __init__(self): + super().__init__() + + if not self.is_available(): + raise ToolkitUnavailableException( + 'The required toolkit {self.toolkit_name} is not ' + 'available.') + + self._rdkit_toolkit_wrapper = RDKitToolkitWrapper() + + @staticmethod + def is_available(): + """ + Check whether the AmberTools toolkit is installed + Returns + ------- + is_installed : bool + True if AmberTools is installed, False otherwise. + """ + ANTECHAMBER_PATH = find_executable("antechamber") + if ANTECHAMBER_PATH is None: + return False + if not(RDKitToolkitWrapper.is_available()): + return False + return True + + def compute_partial_charges_am1bcc(self, molecule): + off_molecule = molecule.off_molecule + + with tempfile.TemporaryDirectory() as tmpdir: + with temporary_cd(tmpdir): + net_charge = off_molecule.total_charge / \ + unit.elementary_charge + + self._rdkit_toolkit_wrapper.to_sfd_file(molecule, tmpdir) + + subprocess.check_output([ + "antechamber", "-i", "molecule.sdf", "-fi", "sdf", + "-o", "charged.ac", "-fo", "ac", "-pf", "yes", "-dr", "n", + "-c", "bcc", "-nc", str(net_charge)]) + # Write out just charges + subprocess.check_output([ + "antechamber", "-dr", "n", "-i", "charged.ac", "-fi", "ac", + "-o", "charged2.ac", "-fo", "ac", "-c", "wc", + "-cf", "charges.txt", "-pf", "yes"]) + + if not os.path.exists('charges.txt'): + # TODO: copy files into local directory to aid debugging? + raise ChargeCalculationError( + "Antechamber/sqm partial charge calculation failed on " + "molecule {} (SMILES {})".format( + off_molecule.name, off_molecule.to_smiles())) + + # Read the charges + with open('charges.txt', 'r') as infile: + contents = infile.read() + + text_charges = contents.split() + charges = np.zeros([molecule.n_atoms], np.float64) + for index, token in enumerate(text_charges): + charges[index] = float(token) + + charges = unit.Quantity(charges, unit.elementary_charge) + + +class OpenForceFieldToolkitWrapper(ToolkitWrapper): + _toolkit_name = 'OpenForceField Toolkit' + + def __init__(self): + super().__init__() + + if not self.is_available(): + raise ToolkitUnavailableException( + 'The required toolkit {self.toolkit_name} is not ' + 'available.') + + @staticmethod + def is_available(): + """ + Check whether the OpenForceField toolkit is installed + Returns + ------- + is_installed : bool + True if OpenForceField is installed, False otherwise. + """ + try: + importlib.import_module('openforcefield') + return True + except ImportError: + return False From 70250e6c2a95e996161f398e6dd14ee03aa57155 Mon Sep 17 00:00:00 2001 From: Marti Municoy Date: Mon, 22 Jun 2020 18:19:19 +0200 Subject: [PATCH 08/67] Toolkit migration and addition of an OpenForceField parameter handler --- offPELE/topology/molecule.py | 58 ++++------ offPELE/utils/toolkits.py | 213 ++++++++++++++++++++++++++++++++++- 2 files changed, 236 insertions(+), 35 deletions(-) diff --git a/offPELE/topology/molecule.py b/offPELE/topology/molecule.py index 4336789c..4952a060 100644 --- a/offPELE/topology/molecule.py +++ b/offPELE/topology/molecule.py @@ -5,7 +5,9 @@ from pathlib import Path from .rotamer import RotamerLibrary, Rotamer -from offPELE.utils.toolkits import AmberToolkitWrapper +from offPELE.utils.toolkits import (AmberToolkitWrapper, + RDKitToolkitWrapper, + OpenForceFieldToolkitWrapper) class Atom(object): @@ -77,49 +79,39 @@ def _initialize_from_pdb(self, path): self._initialize() print(' - Loading molecule from RDKit') - try: - from rdkit import Chem - except ImportError: - raise Exception('RDKit Python API not found') + rdkit_toolkit = RDKitToolkitWrapper() + self._rdkit_molecule = rdkit_toolkit.from_pdb(path) - filename = Path(path).stem - if len(filename) > 2: - self._name = filename[0:3].upper() + # RDKit must generate stereochemistry specifically from 3D coords + rdkit_toolkit.assign_stereochemistry_from_3D(self) - self._rdkit_molecule = Chem.rdmolfiles.MolFromPDBFile(path, - removeHs=False) + openforcefield_toolkit = OpenForceFieldToolkitWrapper() - # RDKit must generate stereochemistry specifically from 3D coords - Chem.rdmolops.AssignStereochemistryFrom3D(self._rdkit_molecule) + self._off_molecule = openforcefield_toolkit.from_rdkit(self) - try: - from openforcefield.topology.molecule import Molecule as \ - OFFMolecule - except ImportError: - raise Exception('OpenForceField package not found') + name = Path(path).stem + if len(name) > 2: + self.set_name(name) - self._off_molecule = OFFMolecule.from_rdkit(self.rdkit_molecule) + def set_name(self, name): + if isinstance(name, str) and len(name) > 2: + name = name[0:3].upper() + self._name = name - def parameterize(self, forcefield): - try: - from openforcefield.topology.molecule import Molecule as \ - OFFMolecule - from openforcefield.typing.engines.smirnoff import ForceField as \ - OFFForceField - except ImportError: - raise Exception('OpenForceField package not found') + if self.off_molecule: + self.off_molecule.name = name - if not isinstance(self._off_molecule, OFFMolecule): + def parameterize(self, forcefield): + if not self.off_molecule and not self.rdkit_molecule: raise Exception('OpenForceField molecule was not initialized ' + 'correctly') print(' - Loading forcefield') - if isinstance(forcefield, str): - forcefield = OFFForceField(forcefield) - elif isinstance(forcefield, OFFForceField): - pass - else: - raise Exception('Invalid forcefield type') + openforcefield_toolkit = OpenForceFieldToolkitWrapper() + parameters = openforcefield_toolkit.get_parameters_from_forcefield( + forcefield, self) + + self.parameters = parameters print(' - Computing partial charges with am1bcc') self._calculate_am1bcc_charges() diff --git a/offPELE/utils/toolkits.py b/offPELE/utils/toolkits.py index 8c455a30..6f9c527b 100644 --- a/offPELE/utils/toolkits.py +++ b/offPELE/utils/toolkits.py @@ -70,11 +70,21 @@ def is_available(): except ImportError: return False - def to_sfd_file(self, molecule, path): + def from_pdb(self, path): + from rdkit import Chem + + return Chem.rdmolfiles.MolFromPDBFile(path, removeHs=False) + + def assign_stereochemistry_from_3D(self, molecule): from rdkit import Chem rdkit_molecule = molecule.rdkit_molecule + Chem.rdmolops.AssignStereochemistryFrom3D(rdkit_molecule) + + def to_sfd_file(self, molecule, path): + from rdkit import Chem + rdkit_molecule = molecule.rdkit_molecule with open('molecule.sdf', 'w') as f: writer = Chem.SDWriter(f) writer.write(rdkit_molecule) @@ -142,7 +152,7 @@ def compute_partial_charges_am1bcc(self, molecule): contents = infile.read() text_charges = contents.split() - charges = np.zeros([molecule.n_atoms], np.float64) + charges = np.zeros([off_molecule.n_atoms], np.float64) for index, token in enumerate(text_charges): charges[index] = float(token) @@ -174,3 +184,202 @@ def is_available(): return True except ImportError: return False + + def from_rdkit(self, molecule): + from openforcefield.topology.molecule import Molecule + + rdkit_molecule = molecule.rdkit_molecule + return Molecule.from_rdkit(rdkit_molecule) + + def get_parameters_from_forcefield(self, forcefield, molecule): + from openforcefield.typing.engines.smirnoff import ForceField + from openforcefield.topology import Topology + + off_molecule = molecule.off_molecule + topology = Topology.from_molecules([off_molecule]) + + if isinstance(forcefield, str): + forcefield = ForceField(forcefield) + elif isinstance(forcefield, ForceField): + pass + else: + raise Exception('Invalid forcefield type') + + molecule_parameters_list = forcefield.label_molecules(topology) + + assert len(molecule_parameters_list) == 1, 'A single molecule is ' \ + 'expected' + return self.OpenForceFieldParameters(molecule_parameters_list[0]) + + class OpenForceFieldParameters(dict): + def __init__(self, parameters_list): + for key, value in parameters_list.items(): + self[key] = value + + def __str__(self): + output = '' + for force_tag, force_dict in self.items(): + output += f"\n{force_tag}:\n" + for (atom_indices, parameter) in force_dict.items(): + atomstr = '' + for idx in atom_indices: + atomstr += '%3s' % idx + output += " - atoms: %s parameter_id: %s smirks %s\n" % \ + (atomstr, parameter.id, parameter.smirks) + return output + + def _build_list(self, parameters, attribute_name): + try: + return [(index, getattr(parameter, attribute_name)) + for index, parameter in parameters.items()] + except AttributeError: + pass + + # Van der Waals parameters + def get_vdW_parameters(self): + if 'vdW' in self: + return self['vdW'] + + def get_vdW_sigmas(self): + parameters = self.get_vdW_parameters() + return self._build_list(parameters, 'sigma') + + def get_vdW_epsilons(self): + parameters = self.get_vdW_parameters() + return self._build_list(parameters, 'epsilon') + + def get_vdW_rmin_halves(self): + parameters = self.get_vdW_parameters() + return self._build_list(parameters, 'rmin_half') + + # Bond parameters + def get_bond_parameters(self): + if 'Bonds' in self: + return self['Bonds'] + + def get_bond_lengths(self): + parameters = self.get_bond_parameters() + return self._build_list(parameters, 'length') + + def get_bond_ks(self): + parameters = self.get_bond_parameters() + return self._build_list(parameters, 'k') + + # Angle parameters + def get_angle_parameters(self): + if 'Angles' in self: + return self['Angles'] + + def get_angle_angles(self): + parameters = self.get_angle_parameters() + return self._build_list(parameters, 'angle') + + def get_angle_ks(self): + parameters = self.get_angle_parameters() + return self._build_list(parameters, 'k') + + # Dihedral parameters + def get_dihedral_parameters(self): + if 'ProperTorsions' in self: + return self['ProperTorsions'] + + def get_dihedral_periodicity1s(self): + parameters = self.get_dihedral_parameters() + return self._build_list(parameters, 'periodicity1') + + def get_dihedral_periodicity2s(self): + parameters = self.get_dihedral_parameters() + return self._build_list(parameters, 'periodicity2') + + def get_dihedral_periodicity3s(self): + parameters = self.get_dihedral_parameters() + return self._build_list(parameters, 'periodicity3') + + def get_dihedral_phase1s(self): + parameters = self.get_dihedral_parameters() + return self._build_list(parameters, 'phase1') + + def get_dihedral_phase2s(self): + parameters = self.get_dihedral_parameters() + return self._build_list(parameters, 'phase2') + + def get_dihedral_phase3s(self): + parameters = self.get_dihedral_parameters() + return self._build_list(parameters, 'phase3') + + def get_dihedral_k1s(self): + parameters = self.get_dihedral_parameters() + return self._build_list(parameters, 'k1') + + def get_dihedral_k2s(self): + parameters = self.get_dihedral_parameters() + return self._build_list(parameters, 'k2') + + def get_dihedral_k3s(self): + parameters = self.get_dihedral_parameters() + return self._build_list(parameters, 'k3') + + def get_dihedral_idiv1s(self): + parameters = self.get_dihedral_parameters() + return self._build_list(parameters, 'idiv1') + + def get_dihedral_idiv2s(self): + parameters = self.get_dihedral_parameters() + return self._build_list(parameters, 'idiv2') + + def get_dihedral_idiv3s(self): + parameters = self.get_dihedral_parameters() + return self._build_list(parameters, 'idiv3') + + # Improper parameters + def get_improper_parameters(self): + if 'ImproperTorsions' in self: + return self['ImproperTorsions'] + + def get_improper_periodicity1s(self): + parameters = self.get_improper_parameters() + return self._build_list(parameters, 'periodicity1') + + def get_improper_periodicity2s(self): + parameters = self.get_improper_parameters() + return self._build_list(parameters, 'periodicity2') + + def get_improper_periodicity3s(self): + parameters = self.get_improper_parameters() + return self._build_list(parameters, 'periodicity3') + + def get_improper_phase1s(self): + parameters = self.get_improper_parameters() + return self._build_list(parameters, 'phase1') + + def get_improper_phase2s(self): + parameters = self.get_improper_parameters() + return self._build_list(parameters, 'phase2') + + def get_improper_phase3s(self): + parameters = self.get_improper_parameters() + return self._build_list(parameters, 'phase3') + + def get_improper_k1s(self): + parameters = self.get_improper_parameters() + return self._build_list(parameters, 'k1') + + def get_improper_k2s(self): + parameters = self.get_improper_parameters() + return self._build_list(parameters, 'k2') + + def get_improper_k3s(self): + parameters = self.get_improper_parameters() + return self._build_list(parameters, 'k3') + + def get_improper_idiv1s(self): + parameters = self.get_improper_parameters() + return self._build_list(parameters, 'idiv1') + + def get_improper_idiv2s(self): + parameters = self.get_improper_parameters() + return self._build_list(parameters, 'idiv2') + + def get_improper_idiv3s(self): + parameters = self.get_improper_parameters() + return self._build_list(parameters, 'idiv3') From 24b4849ceb0adff64c4f70e65931849b7cb5e4b9 Mon Sep 17 00:00:00 2001 From: Marti Municoy Date: Mon, 22 Jun 2020 18:21:38 +0200 Subject: [PATCH 09/67] Minor bug fix --- offPELE/utils/toolkits.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/offPELE/utils/toolkits.py b/offPELE/utils/toolkits.py index 6f9c527b..6d177771 100644 --- a/offPELE/utils/toolkits.py +++ b/offPELE/utils/toolkits.py @@ -158,6 +158,8 @@ def compute_partial_charges_am1bcc(self, molecule): charges = unit.Quantity(charges, unit.elementary_charge) + return charges + class OpenForceFieldToolkitWrapper(ToolkitWrapper): _toolkit_name = 'OpenForceField Toolkit' From 4d0cfa917dfcd50f03e8eb1e3378fff352c83b6c Mon Sep 17 00:00:00 2001 From: Marti Municoy Date: Tue, 23 Jun 2020 12:51:10 +0200 Subject: [PATCH 10/67] Iterator over TopologyElement subclasses --- offPELE/topology/__init__.py | 1 + offPELE/topology/topology.py | 150 +++++++++++++++++++++++++++++++++++ 2 files changed, 151 insertions(+) create mode 100644 offPELE/topology/topology.py diff --git a/offPELE/topology/__init__.py b/offPELE/topology/__init__.py index 836146e1..10433126 100644 --- a/offPELE/topology/__init__.py +++ b/offPELE/topology/__init__.py @@ -1 +1,2 @@ +from .topology import * from .molecule import Molecule diff --git a/offPELE/topology/topology.py b/offPELE/topology/topology.py new file mode 100644 index 00000000..49c40fdd --- /dev/null +++ b/offPELE/topology/topology.py @@ -0,0 +1,150 @@ +# Global imports +from simtk import unit + + +class TopologyElement(object): + _name = None + _writable_attrs = [] + + class TopologyIterator(object): + def __init__(self, top_el): + self._index = int(0) + self._top_el = top_el + + def __next__(self): + if self._index == len(self._top_el._writable_attrs): + raise StopIteration + + attr_name = self._top_el._writable_attrs[self._index] + attr_value = getattr(self._top_el, attr_name) + self._index += 1 + + return attr_name, attr_value + + @property + def name(self): + return self._name + + @property + def n_writable_attrs(self): + return len(self._writable_attrs) + + def __iter__(self): + return self.TopologyIterator(self) + + def __repr__(self): + repr_string = '{}('.format(self._name) + attrs = [attr for attr in self] + for attr_name, value in attrs[:-1]: + repr_string += '{}={}, '.format(attr_name, value) + repr_string += '{}={})'.format(*attrs[-1]) + + return repr_string + + def __str__(self): + return self.__repr__() + + +class Bond(TopologyElement): + _name = 'Bond' + _writable_attrs = ['atom1_idx', 'atom2_idx', 'spring_constant', 'eq_dist'] + + def __init__(self, index=-1, atom1_idx=None, atom2_idx=None, + spring_constant=None, eq_dist=None): + self.index = index + self.atom1_idx = atom1_idx + self.atom2_idx = atom2_idx + self.spring_constant = spring_constant + self.eq_dist = eq_dist + + +class Angle(TopologyElement): + _name = 'Angle' + _writable_attrs = ['atom1_idx', 'atom2_idx', 'atom3_idx', + 'spring_constant', 'eq_angle'] + + def __init__(self, index=-1, atom1_idx=None, atom2_idx=None, + atom3_idx=None, spring_constant=None, eq_angle=None): + self.index = index + self.atom1_idx = atom1_idx + self.atom2_idx = atom2_idx + self.atom3_idx = atom3_idx + self.spring_constant = spring_constant + self.eq_angle = eq_angle + + +class Dihedral(TopologyElement): + _name = 'Dihedral' + _writable_attrs = ['atom1_idx', 'atom2_idx', 'atom3_idx', 'atom4_idx', + 'periodicity', 'prefactor', 'constant'] + + def __init__(self, index=-1, atom1_idx=None, atom2_idx=None, + atom3_idx=None, atom4_idx=None, periodicity=None, + prefactor=None, constant=None): + self.index = index + self.atom1_idx = atom1_idx + self.atom2_idx = atom2_idx + self.atom3_idx = atom3_idx + self.atom4_idx = atom4_idx + self.periodicity = periodicity + self.prefactor = prefactor + self.constant = constant + + +class Proper(Dihedral): + _name = 'Proper' + + +class Improper(Dihedral): + _name = 'Improper' + + +class OFFDihedral(object): + _to_PELE_class = Dihedral + + def __init__(self, index=-1, atom1_idx=None, atom2_idx=None, + atom3_idx=None, atom4_idx=None, periodicity=None, + phase=None, k=None, idivf=None): + self.index = index + self.atom1_idx = atom1_idx + self.atom2_idx = atom2_idx + self.atom3_idx = atom3_idx + self.atom4_idx = atom4_idx + self.periodicity = periodicity + self.phase = phase + self.k = k + self.idivf = idivf + + def to_PELE(self): + if (self.periodicity is None or self.phase is None + or self.k is None or self.idivf is None): + return None + + assert self.periodicity in (1, 2, 3, 4, 6), 'Expected values for ' \ + 'periodicity are 1, 2, 3, 4 or 6, obtained ' \ + '{}'.format(self.periodicity) + assert self.phase.value_in_unit(unit.degree) in (0, 180), \ + 'Expected values for phase are 0 or 180, obtained ' \ + '{}'.format(self.phase) + assert self.idivf == 1, 'Expected values for idivf is 1, ' \ + 'obtained {}'.format(self.divf) + + # TODO Convert OFF's dihedrals equation to PELE's + PELE_dihedral_kwargs = {'index': self.index, + 'atom1_idx': self.atom1_idx, + 'atom2_idx': self.atom2_idx, + 'atom3_idx': self.atom3_idx, + 'atom4_idx': self.atom4_idx, + 'periodicity': self.periodicity, + 'prefactor': 1, + 'constant': self.k} + + return self._to_PELE_class(**PELE_dihedral_kwargs) + + +class OFFProper(OFFDihedral): + _to_PELE_class = Proper + + +class OFFImproper(OFFDihedral): + _to_PELE_class = Improper From 4ce187375ce80f0fa7b08e71d50cfad401d9be0b Mon Sep 17 00:00:00 2001 From: Marti Municoy Date: Tue, 23 Jun 2020 12:51:49 +0200 Subject: [PATCH 11/67] Molecule parameter builders are implemented --- offPELE/topology/molecule.py | 248 ++++++++++++++++++++++++++++++----- 1 file changed, 216 insertions(+), 32 deletions(-) diff --git a/offPELE/topology/molecule.py b/offPELE/topology/molecule.py index 4952a060..b2369bee 100644 --- a/offPELE/topology/molecule.py +++ b/offPELE/topology/molecule.py @@ -5,9 +5,11 @@ from pathlib import Path from .rotamer import RotamerLibrary, Rotamer +from .topology import Bond, Angle, OFFProper, OFFImproper from offPELE.utils.toolkits import (AmberToolkitWrapper, RDKitToolkitWrapper, OpenForceFieldToolkitWrapper) +from offPELE.utils import rmin_halves_to_sigmas class Atom(object): @@ -39,16 +41,6 @@ def set_as_branch(self): self.core = False -class Bond(object): - def __init__(self, index=-1, atom1_idx=None, atom2_idx=None, - spring_constant=None, eq_dist=None): - self.index = index - self.atom1_idx = atom1_idx - self.atom2_idx = atom2_idx - self.spring_constant = spring_constant - self.eq_dist = eq_dist - - class Molecule(object): def __init__(self, path=None): if isinstance(path, str): @@ -69,7 +61,7 @@ def _initialize(self): self._atoms = list() self._bonds = list() self._angles = list() - self._dihedrals = list() + self._propers = list() self._impropers = list() self._rdkit_molecule = None self._off_molecule = None @@ -122,7 +114,7 @@ def parameterize(self, forcefield): self._build_angles() - self._build_dihedrals() + self._build_propers() self._build_impropers() @@ -360,44 +352,220 @@ def _assert_parameterized(self): raise Exception('Molecule not parameterized') def _calculate_am1bcc_charges(self): - ambertoolkit = AmberToolkitWrapper() + amber_toolkit = AmberToolkitWrapper() - charges = ambertoolkit.compute_partial_charges_am1bcc(self) + charges = amber_toolkit.compute_partial_charges_am1bcc(self) self.off_molecule.partial_charges = charges def _build_atoms(self): # PELE needs underscores instead of whitespaces - pdb_atom_names = [name.replace(' ', '_',) - for name in self.get_pdb_atom_names()] - - for index, atom in enumerate(self.off_molecule.atoms): + pdb_atom_names = {(i, ): name.replace(' ', '_',) + for i, name in enumerate(self.get_pdb_atom_names())} + + # TODO should we assign an OPLS type? How can we do this with OFF? + OPLS_types = {i: None + for i in self.parameters.get_vdW_parameters().keys()} + + # TODO Do we need to assign unknown value? Which is its purpose? + unknowns = {i: None + for i in self.parameters.get_vdW_parameters().keys()} + + # TODO Create z-matrix from 3D coordinates + z_matrix_xs, z_matrix_ys, z_matrix_zs = ( + {i: None for i in self.parameters.get_vdW_parameters().keys()}, + {i: None for i in self.parameters.get_vdW_parameters().keys()}, + {i: None for i in self.parameters.get_vdW_parameters().keys()}) + + sigmas = self.parameters.get_vdW_sigmas() + + if all([sigma is None for sigma in sigmas.values()]): + rmin_halves = self.parameters.get_vdW_rmin_halves() + sigmas = rmin_halves_to_sigmas(rmin_halves) + + epsilons = self.parameters.get_vdW_epsilons() + + # TODO Find a way to assign implicit solvent parameters to atoms with OFF + born_radii = {i: None + for i in self.parameters.get_vdW_parameters().keys()} + SASA_radii = {i: None + for i in self.parameters.get_vdW_parameters().keys()} + nonpolar_gammas = {i: None for i in + self.parameters.get_vdW_parameters().keys()} + nonpolar_alphas = {i: None for i in + self.parameters.get_vdW_parameters().keys()} + + for index in self.parameters.get_vdW_parameters().keys(): atom = Atom(index=index, PDB_name=pdb_atom_names[index], - OPLS_type=None, unknown=None, z_matrix_x=None, - z_matrix_y=None, z_matrix_z=None, - sigma=None, - epsilon=None, + OPLS_type=OPLS_types[index], + unknown=unknowns[index], + z_matrix_x=z_matrix_xs[index], + z_matrix_y=z_matrix_ys[index], + z_matrix_z=z_matrix_zs[index], + sigma=sigmas[index], + epsilon=epsilons[index], charge=self.off_molecule.partial_charges[index], - born_radius=None, - SASA_radius=None, - nonpolar_gamma=None, - nonpolar_alpha=None) + born_radius=born_radii[index], + SASA_radius=SASA_radii[index], + nonpolar_gamma=nonpolar_gammas[index], + nonpolar_alpha=nonpolar_alphas[index]) self._add_atom(atom) def _add_atom(self, atom): self._atoms.append(atom) def _build_bonds(self): - pass + lengths = self.parameters.get_bond_lengths() - def _build_angles(self): - pass + ks = self.parameters.get_bond_ks() - def _build_dihedrals(self): - pass + bond_indexes = self.parameters.get_bond_parameters().keys() + + for index, atom_indexes in enumerate(bond_indexes): + (atom1_idx, atom2_idx) = atom_indexes + bond = Bond(index=index, atom1_idx=atom1_idx, atom2_idx=atom2_idx, + spring_constant=ks[atom_indexes], + eq_dist=lengths[atom_indexes]) + self._add_bond(bond) + + def _add_bond(self, bond): + self._bonds.append(bond) + + def _build_angles(self): + angles = self.parameters.get_angle_angles() + + ks = self.parameters.get_angle_ks() + + angle_indexes = self.parameters.get_angle_parameters().keys() + + for index, atom_indexes in enumerate(angle_indexes): + atom1_idx, atom2_idx, atom3_idx = atom_indexes + angle = Angle(index=index, atom1_idx=atom1_idx, + atom2_idx=atom2_idx, atom3_idx=atom3_idx, + spring_constant=ks[atom_indexes], + eq_angle=angles[atom_indexes]) + self._add_angle(angle) + + def _add_angle(self, angle): + self._angles.append(angle) + + def _build_propers(self): + periodicity1s = self.parameters.get_dihedral_periodicity1s() + phase1s = self.parameters.get_dihedral_phase1s() + k1s = self.parameters.get_dihedral_k1s() + idivf1s = self.parameters.get_dihedral_idivf1s() + + periodicity2s = self.parameters.get_dihedral_periodicity2s() + phase2s = self.parameters.get_dihedral_phase2s() + k2s = self.parameters.get_dihedral_k2s() + idivf2s = self.parameters.get_dihedral_idivf2s() + + periodicity3s = self.parameters.get_dihedral_periodicity3s() + phase3s = self.parameters.get_dihedral_phase3s() + k3s = self.parameters.get_dihedral_k3s() + idivf3s = self.parameters.get_dihedral_idivf3s() + + dihedral_indexes = self.parameters.get_dihedral_parameters().keys() + + for index, atom_indexes in enumerate(dihedral_indexes): + atom1_idx, atom2_idx, atom3_idx, atom4_idx = atom_indexes + off_proper = OFFProper(index=index, atom1_idx=atom1_idx, + atom2_idx=atom2_idx, atom3_idx=atom3_idx, + atom4_idx=atom4_idx, + periodicity=periodicity1s[atom_indexes], + phase=phase1s[atom_indexes], + k=k1s[atom_indexes], + idivf=idivf1s[atom_indexes]) + + PELE_proper = off_proper.to_PELE() + if PELE_proper: + self._add_proper(PELE_proper) + + off_proper = OFFProper(index=index, atom1_idx=atom1_idx, + atom2_idx=atom2_idx, atom3_idx=atom3_idx, + atom4_idx=atom4_idx, + periodicity=periodicity2s[atom_indexes], + phase=phase2s[atom_indexes], + k=k2s[atom_indexes], + idivf=idivf2s[atom_indexes]) + + PELE_proper = off_proper.to_PELE() + if PELE_proper: + self._add_proper(PELE_proper) + + off_proper = OFFProper(index=index, atom1_idx=atom1_idx, + atom2_idx=atom2_idx, atom3_idx=atom3_idx, + atom4_idx=atom4_idx, + periodicity=periodicity3s[atom_indexes], + phase=phase3s[atom_indexes], + k=k3s[atom_indexes], + idivf=idivf3s[atom_indexes]) + + PELE_proper = off_proper.to_PELE() + if PELE_proper: + self._add_proper(PELE_proper) + + def _add_proper(self, proper): + self._propers.append(proper) def _build_impropers(self): - pass + periodicity1s = self.parameters.get_dihedral_periodicity1s() + phase1s = self.parameters.get_dihedral_phase1s() + k1s = self.parameters.get_dihedral_k1s() + idivf1s = self.parameters.get_dihedral_idivf1s() + + periodicity2s = self.parameters.get_dihedral_periodicity2s() + phase2s = self.parameters.get_dihedral_phase2s() + k2s = self.parameters.get_dihedral_k2s() + idivf2s = self.parameters.get_dihedral_idivf2s() + + periodicity3s = self.parameters.get_dihedral_periodicity3s() + phase3s = self.parameters.get_dihedral_phase3s() + k3s = self.parameters.get_dihedral_k3s() + idivf3s = self.parameters.get_dihedral_idivf3s() + + dihedral_indexes = self.parameters.get_dihedral_parameters().keys() + + for index, atom_indexes in enumerate(dihedral_indexes): + atom1_idx, atom2_idx, atom3_idx, atom4_idx = atom_indexes + off_improper = OFFImproper(index=index, atom1_idx=atom1_idx, + atom2_idx=atom2_idx, atom3_idx=atom3_idx, + atom4_idx=atom4_idx, + periodicity=periodicity1s[atom_indexes], + phase=phase1s[atom_indexes], + k=k1s[atom_indexes], + idivf=idivf1s[atom_indexes]) + + PELE_improper = off_improper.to_PELE() + if PELE_improper: + self._add_improper(PELE_improper) + + off_improper = OFFImproper(index=index, atom1_idx=atom1_idx, + atom2_idx=atom2_idx, atom3_idx=atom3_idx, + atom4_idx=atom4_idx, + periodicity=periodicity2s[atom_indexes], + phase=phase2s[atom_indexes], + k=k2s[atom_indexes], + idivf=idivf2s[atom_indexes]) + + PELE_improper = off_improper.to_PELE() + if PELE_improper: + self._add_improper(PELE_improper) + + off_improper = OFFImproper(index=index, atom1_idx=atom1_idx, + atom2_idx=atom2_idx, atom3_idx=atom3_idx, + atom4_idx=atom4_idx, + periodicity=periodicity3s[atom_indexes], + phase=phase3s[atom_indexes], + k=k3s[atom_indexes], + idivf=idivf3s[atom_indexes]) + + PELE_improper = off_improper.to_PELE() + if PELE_improper: + self._add_improper(PELE_improper) + + def _add_improper(self, improper): + self._impropers.append(improper) def get_pdb_atom_names(self): self._assert_parameterized() @@ -432,3 +600,19 @@ def name(self): @property def atoms(self): return self._atoms + + @property + def bonds(self): + return self._bonds + + @property + def angles(self): + return self._angles + + @property + def propers(self): + return self._propers + + @property + def impropers(self): + return self._impropers From 7eb45b5078ccc8afba9ba415e5ac6be0671c296b Mon Sep 17 00:00:00 2001 From: Marti Municoy Date: Tue, 23 Jun 2020 15:45:47 +0200 Subject: [PATCH 12/67] Implementation of parameter assignment to offPELE's molecule --- offPELE/topology/molecule.py | 8 ++++ offPELE/topology/topology.py | 42 ++++++++++++++++-- offPELE/utils/toolkits.py | 83 +++++++++++++++++++----------------- offPELE/utils/utils.py | 16 +++++++ 4 files changed, 105 insertions(+), 44 deletions(-) diff --git a/offPELE/topology/molecule.py b/offPELE/topology/molecule.py index b2369bee..94055f5d 100644 --- a/offPELE/topology/molecule.py +++ b/offPELE/topology/molecule.py @@ -62,7 +62,9 @@ def _initialize(self): self._bonds = list() self._angles = list() self._propers = list() + self._OFF_propers = list() self._impropers = list() + self._OFF_impropers = list() self._rdkit_molecule = None self._off_molecule = None self._rotamer_library = None @@ -480,6 +482,7 @@ def _build_propers(self): PELE_proper = off_proper.to_PELE() if PELE_proper: self._add_proper(PELE_proper) + self._add_OFF_proper(off_proper) off_proper = OFFProper(index=index, atom1_idx=atom1_idx, atom2_idx=atom2_idx, atom3_idx=atom3_idx, @@ -492,6 +495,7 @@ def _build_propers(self): PELE_proper = off_proper.to_PELE() if PELE_proper: self._add_proper(PELE_proper) + self._add_OFF_proper(off_proper) off_proper = OFFProper(index=index, atom1_idx=atom1_idx, atom2_idx=atom2_idx, atom3_idx=atom3_idx, @@ -504,10 +508,14 @@ def _build_propers(self): PELE_proper = off_proper.to_PELE() if PELE_proper: self._add_proper(PELE_proper) + self._add_OFF_proper(off_proper) def _add_proper(self, proper): self._propers.append(proper) + def _add_OFF_proper(self, proper): + self._OFF_propers.append(proper) + def _build_impropers(self): periodicity1s = self.parameters.get_dihedral_periodicity1s() phase1s = self.parameters.get_dihedral_phase1s() diff --git a/offPELE/topology/topology.py b/offPELE/topology/topology.py index 49c40fdd..c47e9029 100644 --- a/offPELE/topology/topology.py +++ b/offPELE/topology/topology.py @@ -90,6 +90,17 @@ def __init__(self, index=-1, atom1_idx=None, atom2_idx=None, self.prefactor = prefactor self.constant = constant + def plot(self): + from matplotlib import pyplot + import numpy as np + + x = unit.Quantity(np.arange(0, np.pi, 0.1), unit=unit.radians) + pyplot.plot(x, self.constant * (1 + self.prefactor + * np.cos(self.periodicity * x)), + 'r--') + + pyplot.show() + class Proper(Dihedral): _name = 'Proper' @@ -99,7 +110,10 @@ class Improper(Dihedral): _name = 'Improper' -class OFFDihedral(object): +class OFFDihedral(TopologyElement): + _name = 'OFFDihedral' + _writable_attrs = ['atom1_idx', 'atom2_idx', 'atom3_idx', 'atom4_idx', + 'periodicity', 'phase', 'k', 'idivf'] _to_PELE_class = Dihedral def __init__(self, index=-1, atom1_idx=None, atom2_idx=None, @@ -129,22 +143,42 @@ def to_PELE(self): assert self.idivf == 1, 'Expected values for idivf is 1, ' \ 'obtained {}'.format(self.divf) - # TODO Convert OFF's dihedrals equation to PELE's + if self.phase.value_in_unit(unit.degree) == 180: + PELE_prefactor = -1 + else: + PELE_prefactor = 1 + + # TODO doublecheck idivf term in OFF's torsion equation + PELE_constant = self.k / self.idivf + PELE_dihedral_kwargs = {'index': self.index, 'atom1_idx': self.atom1_idx, 'atom2_idx': self.atom2_idx, 'atom3_idx': self.atom3_idx, 'atom4_idx': self.atom4_idx, 'periodicity': self.periodicity, - 'prefactor': 1, - 'constant': self.k} + 'prefactor': PELE_prefactor, + 'constant': PELE_constant} return self._to_PELE_class(**PELE_dihedral_kwargs) + def plot(self): + from matplotlib import pyplot + import numpy as np + + x = unit.Quantity(np.arange(0, np.pi, 0.1), unit=unit.radians) + pyplot.plot(x, + self.k * (1 + np.cos(self.periodicity * x - self.phase)), + 'r--') + + pyplot.show() + class OFFProper(OFFDihedral): + _name = 'OFFProper' _to_PELE_class = Proper class OFFImproper(OFFDihedral): + _name = 'OFFImproper' _to_PELE_class = Improper diff --git a/offPELE/utils/toolkits.py b/offPELE/utils/toolkits.py index 6d177771..d4d2aa16 100644 --- a/offPELE/utils/toolkits.py +++ b/offPELE/utils/toolkits.py @@ -230,12 +230,15 @@ def __str__(self): (atomstr, parameter.id, parameter.smirks) return output - def _build_list(self, parameters, attribute_name): - try: - return [(index, getattr(parameter, attribute_name)) - for index, parameter in parameters.items()] - except AttributeError: - pass + def _build_dict(self, parameters, attribute_name): + output_dict = dict() + for index, parameter in parameters.items(): + try: + output_dict[index] = getattr(parameter, attribute_name) + except IndexError: + output_dict[index] = None + + return output_dict # Van der Waals parameters def get_vdW_parameters(self): @@ -244,15 +247,15 @@ def get_vdW_parameters(self): def get_vdW_sigmas(self): parameters = self.get_vdW_parameters() - return self._build_list(parameters, 'sigma') + return self._build_dict(parameters, 'sigma') def get_vdW_epsilons(self): parameters = self.get_vdW_parameters() - return self._build_list(parameters, 'epsilon') + return self._build_dict(parameters, 'epsilon') def get_vdW_rmin_halves(self): parameters = self.get_vdW_parameters() - return self._build_list(parameters, 'rmin_half') + return self._build_dict(parameters, 'rmin_half') # Bond parameters def get_bond_parameters(self): @@ -261,11 +264,11 @@ def get_bond_parameters(self): def get_bond_lengths(self): parameters = self.get_bond_parameters() - return self._build_list(parameters, 'length') + return self._build_dict(parameters, 'length') def get_bond_ks(self): parameters = self.get_bond_parameters() - return self._build_list(parameters, 'k') + return self._build_dict(parameters, 'k') # Angle parameters def get_angle_parameters(self): @@ -274,11 +277,11 @@ def get_angle_parameters(self): def get_angle_angles(self): parameters = self.get_angle_parameters() - return self._build_list(parameters, 'angle') + return self._build_dict(parameters, 'angle') def get_angle_ks(self): parameters = self.get_angle_parameters() - return self._build_list(parameters, 'k') + return self._build_dict(parameters, 'k') # Dihedral parameters def get_dihedral_parameters(self): @@ -287,51 +290,51 @@ def get_dihedral_parameters(self): def get_dihedral_periodicity1s(self): parameters = self.get_dihedral_parameters() - return self._build_list(parameters, 'periodicity1') + return self._build_dict(parameters, 'periodicity1') def get_dihedral_periodicity2s(self): parameters = self.get_dihedral_parameters() - return self._build_list(parameters, 'periodicity2') + return self._build_dict(parameters, 'periodicity2') def get_dihedral_periodicity3s(self): parameters = self.get_dihedral_parameters() - return self._build_list(parameters, 'periodicity3') + return self._build_dict(parameters, 'periodicity3') def get_dihedral_phase1s(self): parameters = self.get_dihedral_parameters() - return self._build_list(parameters, 'phase1') + return self._build_dict(parameters, 'phase1') def get_dihedral_phase2s(self): parameters = self.get_dihedral_parameters() - return self._build_list(parameters, 'phase2') + return self._build_dict(parameters, 'phase2') def get_dihedral_phase3s(self): parameters = self.get_dihedral_parameters() - return self._build_list(parameters, 'phase3') + return self._build_dict(parameters, 'phase3') def get_dihedral_k1s(self): parameters = self.get_dihedral_parameters() - return self._build_list(parameters, 'k1') + return self._build_dict(parameters, 'k1') def get_dihedral_k2s(self): parameters = self.get_dihedral_parameters() - return self._build_list(parameters, 'k2') + return self._build_dict(parameters, 'k2') def get_dihedral_k3s(self): parameters = self.get_dihedral_parameters() - return self._build_list(parameters, 'k3') + return self._build_dict(parameters, 'k3') - def get_dihedral_idiv1s(self): + def get_dihedral_idivf1s(self): parameters = self.get_dihedral_parameters() - return self._build_list(parameters, 'idiv1') + return self._build_dict(parameters, 'idivf1') - def get_dihedral_idiv2s(self): + def get_dihedral_idivf2s(self): parameters = self.get_dihedral_parameters() - return self._build_list(parameters, 'idiv2') + return self._build_dict(parameters, 'idivf2') - def get_dihedral_idiv3s(self): + def get_dihedral_idivf3s(self): parameters = self.get_dihedral_parameters() - return self._build_list(parameters, 'idiv3') + return self._build_dict(parameters, 'idivf3') # Improper parameters def get_improper_parameters(self): @@ -340,48 +343,48 @@ def get_improper_parameters(self): def get_improper_periodicity1s(self): parameters = self.get_improper_parameters() - return self._build_list(parameters, 'periodicity1') + return self._build_dict(parameters, 'periodicity1') def get_improper_periodicity2s(self): parameters = self.get_improper_parameters() - return self._build_list(parameters, 'periodicity2') + return self._build_dict(parameters, 'periodicity2') def get_improper_periodicity3s(self): parameters = self.get_improper_parameters() - return self._build_list(parameters, 'periodicity3') + return self._build_dict(parameters, 'periodicity3') def get_improper_phase1s(self): parameters = self.get_improper_parameters() - return self._build_list(parameters, 'phase1') + return self._build_dict(parameters, 'phase1') def get_improper_phase2s(self): parameters = self.get_improper_parameters() - return self._build_list(parameters, 'phase2') + return self._build_dict(parameters, 'phase2') def get_improper_phase3s(self): parameters = self.get_improper_parameters() - return self._build_list(parameters, 'phase3') + return self._build_dict(parameters, 'phase3') def get_improper_k1s(self): parameters = self.get_improper_parameters() - return self._build_list(parameters, 'k1') + return self._build_dict(parameters, 'k1') def get_improper_k2s(self): parameters = self.get_improper_parameters() - return self._build_list(parameters, 'k2') + return self._build_dict(parameters, 'k2') def get_improper_k3s(self): parameters = self.get_improper_parameters() - return self._build_list(parameters, 'k3') + return self._build_dict(parameters, 'k3') def get_improper_idiv1s(self): parameters = self.get_improper_parameters() - return self._build_list(parameters, 'idiv1') + return self._build_dict(parameters, 'idiv1') def get_improper_idiv2s(self): parameters = self.get_improper_parameters() - return self._build_list(parameters, 'idiv2') + return self._build_dict(parameters, 'idiv2') def get_improper_idiv3s(self): parameters = self.get_improper_parameters() - return self._build_list(parameters, 'idiv3') + return self._build_dict(parameters, 'idiv3') diff --git a/offPELE/utils/utils.py b/offPELE/utils/utils.py index 2bac787f..78827c5e 100644 --- a/offPELE/utils/utils.py +++ b/offPELE/utils/utils.py @@ -2,6 +2,8 @@ import os import contextlib +from simtk import unit + def get_data_file_path(relative_path): @@ -24,3 +26,17 @@ def temporary_cd(path): yield finally: os.chdir(old_path) + + +def rmin_halves_to_sigmas(rmin_halves): + """ + Convert rmin_half values to sigmas according to: http://ambermd.org/Questions/vdwequation.pdf + """ + FACTOR = 1.122462048309373 # The sixth root of 2 + + sigmas = dict() + for indexes, rmin_half in rmin_halves.items(): + sigma = FACTOR * rmin_half + sigmas[indexes] = sigma + + return sigmas From 3cdbaca34125b9c6c31ed324ee86d4a019452d8c Mon Sep 17 00:00:00 2001 From: Marti Municoy Date: Tue, 23 Jun 2020 15:47:35 +0200 Subject: [PATCH 13/67] rmin_half-sigma converter is moved to OFF toolkit --- offPELE/topology/molecule.py | 6 ++---- offPELE/utils/toolkits.py | 22 ++++++++++++++++++++++ offPELE/utils/utils.py | 16 ---------------- 3 files changed, 24 insertions(+), 20 deletions(-) diff --git a/offPELE/topology/molecule.py b/offPELE/topology/molecule.py index 94055f5d..87550f53 100644 --- a/offPELE/topology/molecule.py +++ b/offPELE/topology/molecule.py @@ -9,7 +9,6 @@ from offPELE.utils.toolkits import (AmberToolkitWrapper, RDKitToolkitWrapper, OpenForceFieldToolkitWrapper) -from offPELE.utils import rmin_halves_to_sigmas class Atom(object): @@ -369,7 +368,7 @@ def _build_atoms(self): OPLS_types = {i: None for i in self.parameters.get_vdW_parameters().keys()} - # TODO Do we need to assign unknown value? Which is its purpose? + # TODO Which is the purpose of unknown value? Is it important? unknowns = {i: None for i in self.parameters.get_vdW_parameters().keys()} @@ -382,8 +381,7 @@ def _build_atoms(self): sigmas = self.parameters.get_vdW_sigmas() if all([sigma is None for sigma in sigmas.values()]): - rmin_halves = self.parameters.get_vdW_rmin_halves() - sigmas = rmin_halves_to_sigmas(rmin_halves) + sigmas = self.parameters.get_vdW_sigmas_from_rmin_halves() epsilons = self.parameters.get_vdW_epsilons() diff --git a/offPELE/utils/toolkits.py b/offPELE/utils/toolkits.py index d4d2aa16..0329cab0 100644 --- a/offPELE/utils/toolkits.py +++ b/offPELE/utils/toolkits.py @@ -218,6 +218,24 @@ def __init__(self, parameters_list): for key, value in parameters_list.items(): self[key] = value + def sigmas_from_rmin_halves(func): + """ + Convert rmin_half values to sigmas according to: + http://ambermd.org/Questions/vdwequation.pdf + """ + FACTOR = 1.122462048309373 # The sixth root of 2 + + def function_wrapper(x): + rmin_halves = func(x) + + sigmas = dict() + for indexes, rmin_half in rmin_halves.items(): + sigma = FACTOR * rmin_half + sigmas[indexes] = sigma + + return sigmas + return function_wrapper + def __str__(self): output = '' for force_tag, force_dict in self.items(): @@ -257,6 +275,10 @@ def get_vdW_rmin_halves(self): parameters = self.get_vdW_parameters() return self._build_dict(parameters, 'rmin_half') + @sigmas_from_rmin_halves + def get_vdW_sigmas_from_rmin_halves(self): + return self.get_vdW_rmin_halves() + # Bond parameters def get_bond_parameters(self): if 'Bonds' in self: diff --git a/offPELE/utils/utils.py b/offPELE/utils/utils.py index 78827c5e..2bac787f 100644 --- a/offPELE/utils/utils.py +++ b/offPELE/utils/utils.py @@ -2,8 +2,6 @@ import os import contextlib -from simtk import unit - def get_data_file_path(relative_path): @@ -26,17 +24,3 @@ def temporary_cd(path): yield finally: os.chdir(old_path) - - -def rmin_halves_to_sigmas(rmin_halves): - """ - Convert rmin_half values to sigmas according to: http://ambermd.org/Questions/vdwequation.pdf - """ - FACTOR = 1.122462048309373 # The sixth root of 2 - - sigmas = dict() - for indexes, rmin_half in rmin_halves.items(): - sigma = FACTOR * rmin_half - sigmas[indexes] = sigma - - return sigmas From 1e03327ca54440b0700b9badebbae6e0ccc5e193 Mon Sep 17 00:00:00 2001 From: Marti Municoy Date: Tue, 23 Jun 2020 17:51:24 +0200 Subject: [PATCH 14/67] Dynamic assignment of dihedral parameters --- offPELE/topology/molecule.py | 206 ++++++++++++++++------------------- offPELE/utils/toolkits.py | 133 ++++++++-------------- 2 files changed, 142 insertions(+), 197 deletions(-) diff --git a/offPELE/topology/molecule.py b/offPELE/topology/molecule.py index 87550f53..179cd235 100644 --- a/offPELE/topology/molecule.py +++ b/offPELE/topology/molecule.py @@ -450,63 +450,52 @@ def _add_angle(self, angle): self._angles.append(angle) def _build_propers(self): - periodicity1s = self.parameters.get_dihedral_periodicity1s() - phase1s = self.parameters.get_dihedral_phase1s() - k1s = self.parameters.get_dihedral_k1s() - idivf1s = self.parameters.get_dihedral_idivf1s() - - periodicity2s = self.parameters.get_dihedral_periodicity2s() - phase2s = self.parameters.get_dihedral_phase2s() - k2s = self.parameters.get_dihedral_k2s() - idivf2s = self.parameters.get_dihedral_idivf2s() - - periodicity3s = self.parameters.get_dihedral_periodicity3s() - phase3s = self.parameters.get_dihedral_phase3s() - k3s = self.parameters.get_dihedral_k3s() - idivf3s = self.parameters.get_dihedral_idivf3s() - - dihedral_indexes = self.parameters.get_dihedral_parameters().keys() - - for index, atom_indexes in enumerate(dihedral_indexes): - atom1_idx, atom2_idx, atom3_idx, atom4_idx = atom_indexes - off_proper = OFFProper(index=index, atom1_idx=atom1_idx, - atom2_idx=atom2_idx, atom3_idx=atom3_idx, - atom4_idx=atom4_idx, - periodicity=periodicity1s[atom_indexes], - phase=phase1s[atom_indexes], - k=k1s[atom_indexes], - idivf=idivf1s[atom_indexes]) - - PELE_proper = off_proper.to_PELE() - if PELE_proper: - self._add_proper(PELE_proper) - self._add_OFF_proper(off_proper) - - off_proper = OFFProper(index=index, atom1_idx=atom1_idx, - atom2_idx=atom2_idx, atom3_idx=atom3_idx, - atom4_idx=atom4_idx, - periodicity=periodicity2s[atom_indexes], - phase=phase2s[atom_indexes], - k=k2s[atom_indexes], - idivf=idivf2s[atom_indexes]) - - PELE_proper = off_proper.to_PELE() - if PELE_proper: - self._add_proper(PELE_proper) - self._add_OFF_proper(off_proper) - - off_proper = OFFProper(index=index, atom1_idx=atom1_idx, - atom2_idx=atom2_idx, atom3_idx=atom3_idx, - atom4_idx=atom4_idx, - periodicity=periodicity3s[atom_indexes], - phase=phase3s[atom_indexes], - k=k3s[atom_indexes], - idivf=idivf3s[atom_indexes]) - - PELE_proper = off_proper.to_PELE() - if PELE_proper: - self._add_proper(PELE_proper) - self._add_OFF_proper(off_proper) + periodicities = self.parameters.get_dihedral_periodicities() + phases = self.parameters.get_dihedral_phases() + ks = self.parameters.get_dihedral_ks() + idivfs = self.parameters.get_dihedral_idivfs() + + # idivf is a optional parameter in OpenForceField + if len(idivfs) == 0: + for period_by_index in periodicities: + idivfs.append(dict(zip(period_by_index.keys(), + [1, ] * len(period_by_index.keys())))) + + assert len(periodicities) == len(phases) and \ + len(periodicities) == len(ks) and \ + len(periodicities) == len(idivfs), 'Unconsistent set of ' \ + 'OpenForceField\'s torsional parameters. They all should have ' \ + 'equal lengths' + + for period_by_index, phase_by_index, k_by_index, idivf_by_index in \ + zip(periodicities, phases, ks, idivfs): + + assert period_by_index.keys() == phase_by_index.keys() and \ + period_by_index.keys() == k_by_index.keys() and \ + period_by_index.keys() == idivf_by_index.keys(), 'Unconsistent ' \ + 'torsional parameter indexes. Keys should match.' + + for index in period_by_index.keys(): + atom1_idx, atom2_idx, atom3_idx, atom4_idx = index + + period = period_by_index[index] + phase = phase_by_index[index] + k = k_by_index[index] + idivf = idivf_by_index[index] + + if period and phase and k and idivf: + off_proper = OFFProper(atom1_idx=atom1_idx, + atom2_idx=atom2_idx, + atom3_idx=atom3_idx, + atom4_idx=atom4_idx, + periodicity=period, + phase=phase, + k=k, + idivf=idivf) + + PELE_proper = off_proper.to_PELE() + self._add_proper(PELE_proper) + self._add_OFF_proper(off_proper) def _add_proper(self, proper): self._propers.append(proper) @@ -515,64 +504,59 @@ def _add_OFF_proper(self, proper): self._OFF_propers.append(proper) def _build_impropers(self): - periodicity1s = self.parameters.get_dihedral_periodicity1s() - phase1s = self.parameters.get_dihedral_phase1s() - k1s = self.parameters.get_dihedral_k1s() - idivf1s = self.parameters.get_dihedral_idivf1s() - - periodicity2s = self.parameters.get_dihedral_periodicity2s() - phase2s = self.parameters.get_dihedral_phase2s() - k2s = self.parameters.get_dihedral_k2s() - idivf2s = self.parameters.get_dihedral_idivf2s() - - periodicity3s = self.parameters.get_dihedral_periodicity3s() - phase3s = self.parameters.get_dihedral_phase3s() - k3s = self.parameters.get_dihedral_k3s() - idivf3s = self.parameters.get_dihedral_idivf3s() - - dihedral_indexes = self.parameters.get_dihedral_parameters().keys() - - for index, atom_indexes in enumerate(dihedral_indexes): - atom1_idx, atom2_idx, atom3_idx, atom4_idx = atom_indexes - off_improper = OFFImproper(index=index, atom1_idx=atom1_idx, - atom2_idx=atom2_idx, atom3_idx=atom3_idx, - atom4_idx=atom4_idx, - periodicity=periodicity1s[atom_indexes], - phase=phase1s[atom_indexes], - k=k1s[atom_indexes], - idivf=idivf1s[atom_indexes]) - - PELE_improper = off_improper.to_PELE() - if PELE_improper: - self._add_improper(PELE_improper) - - off_improper = OFFImproper(index=index, atom1_idx=atom1_idx, - atom2_idx=atom2_idx, atom3_idx=atom3_idx, - atom4_idx=atom4_idx, - periodicity=periodicity2s[atom_indexes], - phase=phase2s[atom_indexes], - k=k2s[atom_indexes], - idivf=idivf2s[atom_indexes]) - - PELE_improper = off_improper.to_PELE() - if PELE_improper: - self._add_improper(PELE_improper) - - off_improper = OFFImproper(index=index, atom1_idx=atom1_idx, - atom2_idx=atom2_idx, atom3_idx=atom3_idx, - atom4_idx=atom4_idx, - periodicity=periodicity3s[atom_indexes], - phase=phase3s[atom_indexes], - k=k3s[atom_indexes], - idivf=idivf3s[atom_indexes]) - - PELE_improper = off_improper.to_PELE() - if PELE_improper: - self._add_improper(PELE_improper) + periodicities = self.parameters.get_improper_periodicities() + phases = self.parameters.get_improper_phases() + ks = self.parameters.get_improper_ks() + idivfs = self.parameters.get_improper_idivfs() + + # idivf is a optional parameter in OpenForceField + if len(idivfs) == 0: + for period_by_index in periodicities: + idivfs.append(dict(zip(period_by_index.keys(), + [1, ] * len(period_by_index.keys())))) + + assert len(periodicities) == len(phases) and \ + len(periodicities) == len(ks) and \ + len(periodicities) == len(idivfs), 'Unconsistent set of ' \ + 'OpenForceField\'s improper parameters. They all should have ' \ + 'equal lengths' + + for period_by_index, phase_by_index, k_by_index, idivf_by_index in \ + zip(periodicities, phases, ks, idivfs): + + assert period_by_index.keys() == phase_by_index.keys() and \ + period_by_index.keys() == k_by_index.keys() and \ + period_by_index.keys() == idivf_by_index.keys(), 'Unconsistent ' \ + 'torsional parameter indexes. Keys should match.' + + for index in period_by_index.keys(): + atom1_idx, atom2_idx, atom3_idx, atom4_idx = index + + period = period_by_index[index] + phase = phase_by_index[index] + k = k_by_index[index] + idivf = idivf_by_index[index] + + if period and phase and k and idivf: + off_improper = OFFImproper(atom1_idx=atom1_idx, + atom2_idx=atom2_idx, + atom3_idx=atom3_idx, + atom4_idx=atom4_idx, + periodicity=period, + phase=phase, + k=k, + idivf=idivf) + + PELE_improper = off_improper.to_PELE() + self._add_improper(PELE_improper) + self._add_OFF_improper(off_improper) def _add_improper(self, improper): self._impropers.append(improper) + def _add_OFF_improper(self, improper): + self._OFF_impropers.append(improper) + def get_pdb_atom_names(self): self._assert_parameterized() diff --git a/offPELE/utils/toolkits.py b/offPELE/utils/toolkits.py index 0329cab0..a03ebd68 100644 --- a/offPELE/utils/toolkits.py +++ b/offPELE/utils/toolkits.py @@ -3,6 +3,7 @@ import tempfile import os import subprocess +from collections import defaultdict import numpy as np from simtk import unit @@ -249,14 +250,38 @@ def __str__(self): return output def _build_dict(self, parameters, attribute_name): - output_dict = dict() + value_by_index = dict() for index, parameter in parameters.items(): - try: - output_dict[index] = getattr(parameter, attribute_name) - except IndexError: - output_dict[index] = None + value_by_index[index] = getattr(parameter, attribute_name) - return output_dict + return value_by_index + + def _build_dynamic_dicts(self, parameters, attr_core_name): + parameters_by_index = defaultdict(dict) + all_attr_ids_found = set() + for index, parameter in parameters.items(): + counter = int(1) + attr_name = attr_core_name + str(counter) + while(attr_name in parameter.to_dict()): + all_attr_ids_found.add(counter) + attr_value = getattr(parameter, attr_name) + parameters_by_index[index][counter] = attr_value + counter += 1 + attr_name = attr_core_name + str(counter) + + output_list = list() + for attr_id in sorted(all_attr_ids_found): + value_by_index = dict() + for index in parameters.keys(): + if attr_id in parameters_by_index[index]: + value_by_index[index] = \ + parameters_by_index[index][attr_id] + else: + value_by_index[index] = None + + output_list.append(value_by_index) + + return output_list # Van der Waals parameters def get_vdW_parameters(self): @@ -310,103 +335,39 @@ def get_dihedral_parameters(self): if 'ProperTorsions' in self: return self['ProperTorsions'] - def get_dihedral_periodicity1s(self): - parameters = self.get_dihedral_parameters() - return self._build_dict(parameters, 'periodicity1') - - def get_dihedral_periodicity2s(self): - parameters = self.get_dihedral_parameters() - return self._build_dict(parameters, 'periodicity2') - - def get_dihedral_periodicity3s(self): - parameters = self.get_dihedral_parameters() - return self._build_dict(parameters, 'periodicity3') - - def get_dihedral_phase1s(self): - parameters = self.get_dihedral_parameters() - return self._build_dict(parameters, 'phase1') - - def get_dihedral_phase2s(self): - parameters = self.get_dihedral_parameters() - return self._build_dict(parameters, 'phase2') - - def get_dihedral_phase3s(self): - parameters = self.get_dihedral_parameters() - return self._build_dict(parameters, 'phase3') - - def get_dihedral_k1s(self): - parameters = self.get_dihedral_parameters() - return self._build_dict(parameters, 'k1') - - def get_dihedral_k2s(self): - parameters = self.get_dihedral_parameters() - return self._build_dict(parameters, 'k2') - - def get_dihedral_k3s(self): + def get_dihedral_periodicities(self): parameters = self.get_dihedral_parameters() - return self._build_dict(parameters, 'k3') + return self._build_dynamic_dicts(parameters, 'periodicity') - def get_dihedral_idivf1s(self): + def get_dihedral_phases(self): parameters = self.get_dihedral_parameters() - return self._build_dict(parameters, 'idivf1') + return self._build_dynamic_dicts(parameters, 'phase') - def get_dihedral_idivf2s(self): + def get_dihedral_ks(self): parameters = self.get_dihedral_parameters() - return self._build_dict(parameters, 'idivf2') + return self._build_dynamic_dicts(parameters, 'k') - def get_dihedral_idivf3s(self): + def get_dihedral_idivfs(self): parameters = self.get_dihedral_parameters() - return self._build_dict(parameters, 'idivf3') + return self._build_dynamic_dicts(parameters, 'idivf') # Improper parameters def get_improper_parameters(self): if 'ImproperTorsions' in self: return self['ImproperTorsions'] - def get_improper_periodicity1s(self): - parameters = self.get_improper_parameters() - return self._build_dict(parameters, 'periodicity1') - - def get_improper_periodicity2s(self): - parameters = self.get_improper_parameters() - return self._build_dict(parameters, 'periodicity2') - - def get_improper_periodicity3s(self): - parameters = self.get_improper_parameters() - return self._build_dict(parameters, 'periodicity3') - - def get_improper_phase1s(self): - parameters = self.get_improper_parameters() - return self._build_dict(parameters, 'phase1') - - def get_improper_phase2s(self): - parameters = self.get_improper_parameters() - return self._build_dict(parameters, 'phase2') - - def get_improper_phase3s(self): - parameters = self.get_improper_parameters() - return self._build_dict(parameters, 'phase3') - - def get_improper_k1s(self): - parameters = self.get_improper_parameters() - return self._build_dict(parameters, 'k1') - - def get_improper_k2s(self): - parameters = self.get_improper_parameters() - return self._build_dict(parameters, 'k2') - - def get_improper_k3s(self): + def get_improper_periodicities(self): parameters = self.get_improper_parameters() - return self._build_dict(parameters, 'k3') + return self._build_dynamic_dicts(parameters, 'periodicity') - def get_improper_idiv1s(self): + def get_improper_phases(self): parameters = self.get_improper_parameters() - return self._build_dict(parameters, 'idiv1') + return self._build_dynamic_dicts(parameters, 'phase') - def get_improper_idiv2s(self): + def get_improper_ks(self): parameters = self.get_improper_parameters() - return self._build_dict(parameters, 'idiv2') + return self._build_dynamic_dicts(parameters, 'k') - def get_improper_idiv3s(self): + def get_improper_idivfs(self): parameters = self.get_improper_parameters() - return self._build_dict(parameters, 'idiv3') + return self._build_dynamic_dicts(parameters, 'idivf') From 3b38e8acd4456bebcde44da00f0752562dafab7d Mon Sep 17 00:00:00 2001 From: Marti Municoy Date: Tue, 23 Jun 2020 18:34:20 +0200 Subject: [PATCH 15/67] Dihedral conversion test is added --- offPELE/data/ligands/BIA.pdb | 115 ++++++++++++++++++++++++++++++ offPELE/data/ligands/LG1.pdb | 79 +++++++++++++++++++++ offPELE/data/ligands/MDB.pdb | 77 ++++++++++++++++++++ offPELE/data/ligands/OLC.pdb | 117 +++++++++++++++++++++++++++++++ offPELE/data/ligands/SBN.pdb | 113 +++++++++++++++++++++++++++++ offPELE/data/ligands/TOL.pdb | 59 ++++++++++++++++ offPELE/tests/__init__.py | 0 offPELE/tests/test_parameters.py | 31 ++++++++ offPELE/tests/utils.py | 14 ++++ 9 files changed, 605 insertions(+) create mode 100644 offPELE/data/ligands/BIA.pdb create mode 100644 offPELE/data/ligands/LG1.pdb create mode 100644 offPELE/data/ligands/MDB.pdb create mode 100644 offPELE/data/ligands/OLC.pdb create mode 100644 offPELE/data/ligands/SBN.pdb create mode 100644 offPELE/data/ligands/TOL.pdb create mode 100644 offPELE/tests/__init__.py create mode 100644 offPELE/tests/test_parameters.py create mode 100644 offPELE/tests/utils.py diff --git a/offPELE/data/ligands/BIA.pdb b/offPELE/data/ligands/BIA.pdb new file mode 100644 index 00000000..bccd685a --- /dev/null +++ b/offPELE/data/ligands/BIA.pdb @@ -0,0 +1,115 @@ +HEADER HYDROLASE 16-AUG-14 4W52 +REMARK 4 4W52 COMPLIES WITH FORMAT V. 3.30, +REMARK 888 +REMARK 888 WRITTEN BY MAESTRO (A PRODUCT OF SCHRODINGER, LLC) +TITLE T4 LYSOZYME L99A WITH BENZENE BOUND +EXPDTA X-RAY DIFFRACTION +REMARK 2 RESOLUTION. 1.50 ANGSTROMS +REMARK 3 R VALUE : 0.165000 +REMARK 3 FREE R VALUE : 0.182000 +REMARK 200 TEMPERATURE (KELVIN) : 100.00 +REMARK 200 PH : 7.50 +REMARK 350 BIOMOLECULE: 1 +REMARK 350 APPLY THE FOLLOWING TO CHAINS: A +REMARK 350 BIOMT1 1 1.000000 0.000000 0.000000 0.000000 +REMARK 350 BIOMT2 1 0.000000 1.000000 0.000000 0.000000 +REMARK 350 BIOMT3 1 0.000000 0.000000 1.000000 0.000000 +CRYST1 60.350 60.350 96.610 90.00 90.00 120.00 P 32 2 1 6 +HET BNZ L 1 40 +HETNAM BNZ BENZENE +FORMUL 1 BNZ C6 H6 +MODEL 1 +HETATM 1 C1 BNZ L 1 -32.969 6.196 2.877 0.70 15.06 C +HETATM 2 C2 BNZ L 1 -32.945 7.046 3.973 0.70 12.84 C +HETATM 3 C3 BNZ L 1 -33.719 6.798 5.113 0.70 12.24 C +HETATM 4 C4 BNZ L 1 -34.540 5.680 5.143 0.70 13.09 C +HETATM 5 C5 BNZ L 1 -34.545 4.825 4.044 0.70 12.54 C +HETATM 6 C6 BNZ L 1 -33.787 5.069 2.915 0.70 14.23 C +HETATM 7 C7 BNZ L 1 -33.652 7.760 6.313 1.00 0.00 C +HETATM 8 C8 BNZ L 1 -35.417 3.555 4.060 1.00 0.00 C +HETATM 9 C9 BNZ L 1 -34.087 9.169 5.868 1.00 0.00 C +HETATM 10 C10 BNZ L 1 -35.239 2.794 2.733 1.00 0.00 C +HETATM 11 C11 BNZ L 1 -33.899 11.875 9.244 1.00 0.00 C +HETATM 12 C12 BNZ L 1 -34.313 12.347 7.988 1.00 0.00 C +HETATM 13 C13 BNZ L 1 -34.374 11.470 6.893 1.00 0.00 C +HETATM 14 C14 BNZ L 1 -34.021 10.120 7.054 1.00 0.00 C +HETATM 15 C15 BNZ L 1 -33.607 9.648 8.311 1.00 0.00 C +HETATM 16 C16 BNZ L 1 -33.546 10.525 9.406 1.00 0.00 C +HETATM 17 C17 BNZ L 1 -34.699 13.828 7.811 1.00 0.00 C +HETATM 18 C18 BNZ L 1 -33.495 14.720 8.164 1.00 0.00 C +HETATM 19 H1 BNZ L 1 -32.360 6.413 2.012 1.00 0.00 H +HETATM 20 H2 BNZ L 1 -32.318 7.925 3.961 1.00 0.00 H +HETATM 21 H3 BNZ L 1 -35.158 5.487 6.007 1.00 0.00 H +HETATM 22 H4 BNZ L 1 -33.823 4.399 2.069 1.00 0.00 H +HETATM 23 H5 BNZ L 1 -34.318 7.407 7.101 1.00 0.00 H +HETATM 24 H6 BNZ L 1 -32.631 7.799 6.692 1.00 0.00 H +HETATM 25 H7 BNZ L 1 -33.421 9.523 5.081 1.00 0.00 H +HETATM 26 H8 BNZ L 1 -35.109 9.131 5.490 1.00 0.00 H +HETATM 27 H9 BNZ L 1 -35.113 2.916 4.889 1.00 0.00 H +HETATM 28 H10 BNZ L 1 -36.463 3.834 4.181 1.00 0.00 H +HETATM 29 H11 BNZ L 1 -35.856 1.895 2.744 1.00 0.00 H +HETATM 30 H12 BNZ L 1 -35.543 3.432 1.903 1.00 0.00 H +HETATM 31 H13 BNZ L 1 -34.193 2.514 2.612 1.00 0.00 H +HETATM 32 H14 BNZ L 1 -33.851 12.565 10.104 1.00 0.00 H +HETATM 33 H15 BNZ L 1 -34.699 11.841 5.906 1.00 0.00 H +HETATM 34 H16 BNZ L 1 -33.330 8.587 8.438 1.00 0.00 H +HETATM 35 H17 BNZ L 1 -33.221 10.154 10.393 1.00 0.00 H +HETATM 36 H18 BNZ L 1 -34.991 14.006 6.776 1.00 0.00 H +HETATM 37 H19 BNZ L 1 -35.534 14.067 8.470 1.00 0.00 H +HETATM 38 H20 BNZ L 1 -33.769 15.767 8.039 1.00 0.00 H +HETATM 39 H21 BNZ L 1 -33.202 14.542 9.199 1.00 0.00 H +HETATM 40 H22 BNZ L 1 -32.660 14.481 7.506 1.00 0.00 H +CONECT 1 2 6 19 +CONECT 1 2 +CONECT 2 1 3 20 +CONECT 2 1 +CONECT 3 2 4 7 +CONECT 3 4 +CONECT 4 3 5 21 +CONECT 4 3 +CONECT 5 4 6 8 +CONECT 5 6 +CONECT 6 1 5 22 +CONECT 6 5 +CONECT 19 1 +CONECT 20 2 +CONECT 7 3 23 24 9 +CONECT 21 4 +CONECT 8 5 10 27 28 +CONECT 22 6 +CONECT 23 7 +CONECT 24 7 +CONECT 9 7 25 26 14 +CONECT 25 9 +CONECT 26 9 +CONECT 10 8 29 30 31 +CONECT 27 8 +CONECT 28 8 +CONECT 29 10 +CONECT 30 10 +CONECT 31 10 +CONECT 11 12 16 32 +CONECT 11 12 +CONECT 12 11 13 17 +CONECT 12 11 +CONECT 13 12 14 33 +CONECT 13 14 +CONECT 14 9 13 15 +CONECT 14 13 +CONECT 15 14 16 34 +CONECT 15 16 +CONECT 16 11 15 35 +CONECT 16 15 +CONECT 32 11 +CONECT 17 12 36 37 18 +CONECT 33 13 +CONECT 34 15 +CONECT 35 16 +CONECT 36 17 +CONECT 37 17 +CONECT 18 17 38 39 40 +CONECT 38 18 +CONECT 39 18 +CONECT 40 18 +ENDMDL +END diff --git a/offPELE/data/ligands/LG1.pdb b/offPELE/data/ligands/LG1.pdb new file mode 100644 index 00000000..d017323c --- /dev/null +++ b/offPELE/data/ligands/LG1.pdb @@ -0,0 +1,79 @@ +REMARK 4 COMPLIES WITH FORMAT V. 3.0, 1-DEC-2006 +REMARK 888 +REMARK 888 WRITTEN BY MAESTRO (A PRODUCT OF SCHRODINGER, LLC) +TITLE Structure1 +MODEL 1 +HETATM 1 C1 1 1.343 -0.053 0.228 1.00 0.00 C +HETATM 2 C2 1 0.653 1.179 0.246 1.00 0.00 C +HETATM 3 C3 1 -0.754 1.209 0.262 1.00 0.00 C +HETATM 4 C4 1 -1.487 0.006 0.269 1.00 0.00 C +HETATM 5 C5 1 -0.805 -1.228 0.249 1.00 0.00 C +HETATM 6 C6 1 0.602 -1.259 0.228 1.00 0.00 C +HETATM 7 C7 1 2.865 -0.033 0.216 1.00 0.00 C +HETATM 8 C8 1 -3.000 0.036 0.300 1.00 0.00 C +HETATM 9 C9 1 3.542 -1.414 0.188 1.00 0.00 C +HETATM 10 C10 1 7.890 -1.484 0.245 1.00 0.00 C +HETATM 11 C11 1 7.150 -2.677 0.177 1.00 0.00 C +HETATM 12 C12 1 5.741 -2.636 0.155 1.00 0.00 C +HETATM 13 C13 1 5.063 -1.399 0.196 1.00 0.00 C +HETATM 14 C14 1 5.812 -0.201 0.261 1.00 0.00 C +HETATM 15 C15 1 7.222 -0.244 0.286 1.00 0.00 C +HETATM 16 H1 1 1.209 2.107 0.242 1.00 0.00 H +HETATM 17 H2 1 -1.268 2.159 0.273 1.00 0.00 H +HETATM 18 H3 1 -1.359 -2.155 0.256 1.00 0.00 H +HETATM 19 H4 1 1.092 -2.220 0.205 1.00 0.00 H +HETATM 20 H5 1 8.969 -1.515 0.260 1.00 0.00 H +HETATM 21 H6 1 7.660 -3.628 0.143 1.00 0.00 H +HETATM 22 H7 1 5.181 -3.563 0.116 1.00 0.00 H +HETATM 23 H8 1 5.329 0.766 0.290 1.00 0.00 H +HETATM 24 H9 1 7.791 0.671 0.352 1.00 0.00 H +HETATM 25 H10 1 -3.414 -0.971 0.370 1.00 0.00 H +HETATM 26 H11 1 -3.345 0.594 1.173 1.00 0.00 H +HETATM 27 H12 1 -3.399 0.515 -0.594 1.00 0.00 H +HETATM 28 H13 1 2.940 -2.310 0.164 1.00 0.00 H +HETATM 29 H14 1 3.393 0.909 0.226 1.00 0.00 H +CONECT 1 2 6 7 +CONECT 1 2 +CONECT 2 1 3 16 +CONECT 2 1 +CONECT 3 2 4 17 +CONECT 3 4 +CONECT 4 3 5 8 +CONECT 4 3 +CONECT 5 4 6 18 +CONECT 5 6 +CONECT 6 1 5 19 +CONECT 6 5 +CONECT 7 1 9 29 +CONECT 7 9 +CONECT 16 2 +CONECT 17 3 +CONECT 8 4 25 26 27 +CONECT 18 5 +CONECT 19 6 +CONECT 9 7 13 28 +CONECT 9 7 +CONECT 10 11 15 20 +CONECT 10 11 +CONECT 11 10 12 21 +CONECT 11 10 +CONECT 12 11 13 22 +CONECT 12 13 +CONECT 13 9 12 14 +CONECT 13 12 +CONECT 14 13 15 23 +CONECT 14 15 +CONECT 15 10 14 24 +CONECT 15 14 +CONECT 20 10 +CONECT 21 11 +CONECT 22 12 +CONECT 23 14 +CONECT 24 15 +CONECT 25 8 +CONECT 26 8 +CONECT 27 8 +CONECT 28 9 +CONECT 29 7 +ENDMDL +END diff --git a/offPELE/data/ligands/MDB.pdb b/offPELE/data/ligands/MDB.pdb new file mode 100644 index 00000000..d09364a8 --- /dev/null +++ b/offPELE/data/ligands/MDB.pdb @@ -0,0 +1,77 @@ +HEADER HYDROLASE 16-AUG-14 4W52 +REMARK 4 4W52 COMPLIES WITH FORMAT V. 3.30, +REMARK 888 +REMARK 888 WRITTEN BY MAESTRO (A PRODUCT OF SCHRODINGER, LLC) +TITLE T4 LYSOZYME L99A WITH BENZENE BOUND +EXPDTA X-RAY DIFFRACTION +REMARK 2 RESOLUTION. 1.50 ANGSTROMS +REMARK 3 R VALUE : 0.165000 +REMARK 3 FREE R VALUE : 0.182000 +REMARK 200 TEMPERATURE (KELVIN) : 100.00 +REMARK 200 PH : 7.50 +REMARK 350 BIOMOLECULE: 1 +REMARK 350 APPLY THE FOLLOWING TO CHAINS: A +REMARK 350 BIOMT1 1 1.000000 0.000000 0.000000 0.000000 +REMARK 350 BIOMT2 1 0.000000 1.000000 0.000000 0.000000 +REMARK 350 BIOMT3 1 0.000000 0.000000 1.000000 0.000000 +CRYST1 60.350 60.350 96.610 90.00 90.00 120.00 P 32 2 1 6 +HET BNZ L 1 24 +HETNAM BNZ BENZENE +FORMUL 1 BNZ C6 H6 +MODEL 1 +HETATM 1 C1 BNZ L 1 -32.969 6.196 2.877 0.70 15.06 C +HETATM 2 C2 BNZ L 1 -32.945 7.046 3.973 0.70 12.84 C +HETATM 3 C3 BNZ L 1 -33.719 6.798 5.113 0.70 12.24 C +HETATM 4 C4 BNZ L 1 -34.540 5.680 5.143 0.70 13.09 C +HETATM 5 C5 BNZ L 1 -34.545 4.825 4.044 0.70 12.54 C +HETATM 6 C6 BNZ L 1 -33.787 5.069 2.915 0.70 14.23 C +HETATM 7 C7 BNZ L 1 -33.652 7.760 6.313 1.00 0.00 C +HETATM 8 C8 BNZ L 1 -35.417 3.555 4.060 1.00 0.00 C +HETATM 9 C9 BNZ L 1 -34.087 9.169 5.868 1.00 0.00 C +HETATM 10 C10 BNZ L 1 -35.239 2.794 2.733 1.00 0.00 C +HETATM 11 H1 BNZ L 1 -32.360 6.413 2.012 1.00 0.00 H +HETATM 12 H2 BNZ L 1 -32.318 7.925 3.961 1.00 0.00 H +HETATM 13 H3 BNZ L 1 -35.158 5.487 6.007 1.00 0.00 H +HETATM 14 H4 BNZ L 1 -33.823 4.399 2.069 1.00 0.00 H +HETATM 15 H5 BNZ L 1 -34.318 7.407 7.101 1.00 0.00 H +HETATM 16 H6 BNZ L 1 -32.631 7.799 6.692 1.00 0.00 H +HETATM 17 H7 BNZ L 1 -34.040 9.850 6.718 1.00 0.00 H +HETATM 18 H8 BNZ L 1 -33.421 9.523 5.081 1.00 0.00 H +HETATM 19 H9 BNZ L 1 -35.109 9.131 5.490 1.00 0.00 H +HETATM 20 H10 BNZ L 1 -35.113 2.916 4.889 1.00 0.00 H +HETATM 21 H11 BNZ L 1 -36.463 3.834 4.181 1.00 0.00 H +HETATM 22 H12 BNZ L 1 -35.856 1.895 2.744 1.00 0.00 H +HETATM 23 H13 BNZ L 1 -35.543 3.432 1.903 1.00 0.00 H +HETATM 24 H14 BNZ L 1 -34.193 2.514 2.612 1.00 0.00 H +CONECT 1 2 6 11 +CONECT 1 2 +CONECT 2 1 3 12 +CONECT 2 1 +CONECT 3 2 4 7 +CONECT 3 4 +CONECT 4 3 5 13 +CONECT 4 3 +CONECT 5 4 6 8 +CONECT 5 6 +CONECT 6 1 5 14 +CONECT 6 5 +CONECT 11 1 +CONECT 12 2 +CONECT 7 3 15 16 9 +CONECT 13 4 +CONECT 8 5 10 20 21 +CONECT 14 6 +CONECT 15 7 +CONECT 16 7 +CONECT 9 7 17 18 19 +CONECT 17 9 +CONECT 18 9 +CONECT 19 9 +CONECT 10 8 22 23 24 +CONECT 20 8 +CONECT 21 8 +CONECT 22 10 +CONECT 23 10 +CONECT 24 10 +ENDMDL +END diff --git a/offPELE/data/ligands/OLC.pdb b/offPELE/data/ligands/OLC.pdb new file mode 100644 index 00000000..f6b63382 --- /dev/null +++ b/offPELE/data/ligands/OLC.pdb @@ -0,0 +1,117 @@ +REMARK 4 COMPLIES WITH FORMAT V. 3.0, 1-DEC-2006 +REMARK 888 +REMARK 888 WRITTEN BY MAESTRO (A PRODUCT OF SCHRODINGER, LLC) +TITLE MRO_oleic - preprocessed +MODEL 1 +HETATM 1 C2 OLC L 1 4.148 7.353 -18.237 1.00 0.00 C +HETATM 2 C1 OLC L 1 2.819 7.913 -18.760 1.00 0.00 C +HETATM 3 C3 OLC L 1 4.336 5.840 -18.529 1.00 0.00 C +HETATM 4 O1 OLC L 1 1.997 8.332 -17.914 1.00 0.00 O +HETATM 5 O2 OLC L 1 2.619 7.886 -19.995 1.00 0.00 O1- +HETATM 6 C4 OLC L 1 3.226 4.913 -17.967 1.00 0.00 C +HETATM 7 C5 OLC L 1 3.428 3.426 -18.324 1.00 0.00 C +HETATM 8 C6 OLC L 1 2.293 2.492 -17.836 1.00 0.00 C +HETATM 9 C7 OLC L 1 2.536 1.015 -18.229 1.00 0.00 C +HETATM 10 C8 OLC L 1 1.783 -0.056 -17.392 1.00 0.00 C +HETATM 11 C9 OLC L 1 2.501 -1.407 -17.407 1.00 0.00 C +HETATM 12 C10 OLC L 1 2.074 -2.659 -17.133 1.00 0.00 C +HETATM 13 C11 OLC L 1 0.708 -3.141 -16.670 1.00 0.00 C +HETATM 14 C12 OLC L 1 -0.251 -3.573 -17.803 1.00 0.00 C +HETATM 15 C13 OLC L 1 -0.435 -2.432 -18.806 1.00 0.00 C +HETATM 16 C14 OLC L 1 -1.522 -2.562 -19.874 1.00 0.00 C +HETATM 17 C15 OLC L 1 -1.587 -1.234 -20.659 1.00 0.00 C +HETATM 18 C16 OLC L 1 -2.964 -0.881 -21.233 1.00 0.00 C +HETATM 19 C17 OLC L 1 -2.994 0.581 -21.715 1.00 0.00 C +HETATM 20 C18 OLC L 1 -4.370 1.021 -22.222 1.00 0.00 C +HETATM 21 H1 OLC L 1 4.953 7.921 -18.708 1.00 0.00 H +HETATM 22 H2 OLC L 1 4.242 7.560 -17.172 1.00 0.00 H +HETATM 23 H3 OLC L 1 4.417 5.705 -19.610 1.00 0.00 H +HETATM 24 H4 OLC L 1 5.305 5.541 -18.122 1.00 0.00 H +HETATM 25 H5 OLC L 1 3.168 5.041 -16.885 1.00 0.00 H +HETATM 26 H6 OLC L 1 2.260 5.241 -18.354 1.00 0.00 H +HETATM 27 H7 OLC L 1 3.528 3.341 -19.407 1.00 0.00 H +HETATM 28 H8 OLC L 1 4.382 3.100 -17.908 1.00 0.00 H +HETATM 29 H9 OLC L 1 2.207 2.594 -16.755 1.00 0.00 H +HETATM 30 H10 OLC L 1 1.338 2.828 -18.243 1.00 0.00 H +HETATM 31 H11 OLC L 1 2.303 0.878 -19.287 1.00 0.00 H +HETATM 32 H12 OLC L 1 3.609 0.837 -18.162 1.00 0.00 H +HETATM 33 H13 OLC L 1 1.694 0.260 -16.354 1.00 0.00 H +HETATM 34 H14 OLC L 1 0.765 -0.137 -17.754 1.00 0.00 H +HETATM 35 H15 OLC L 1 3.532 -1.332 -17.691 1.00 0.00 H +HETATM 36 H16 OLC L 1 2.801 -3.444 -17.245 1.00 0.00 H +HETATM 37 H17 OLC L 1 0.860 -3.979 -15.988 1.00 0.00 H +HETATM 38 H18 OLC L 1 0.249 -2.379 -16.052 1.00 0.00 H +HETATM 39 H19 OLC L 1 0.119 -4.466 -18.306 1.00 0.00 H +HETATM 40 H20 OLC L 1 -0.682 -1.556 -18.213 1.00 0.00 H +HETATM 41 H21 OLC L 1 -1.314 -3.400 -20.542 1.00 0.00 H +HETATM 42 H22 OLC L 1 -2.477 -2.781 -19.397 1.00 0.00 H +HETATM 43 H23 OLC L 1 -1.295 -0.409 -20.004 1.00 0.00 H +HETATM 44 H24 OLC L 1 -0.835 -1.239 -21.451 1.00 0.00 H +HETATM 45 H25 OLC L 1 -3.211 -1.562 -22.049 1.00 0.00 H +HETATM 46 H26 OLC L 1 -3.725 -1.022 -20.464 1.00 0.00 H +HETATM 47 H27 OLC L 1 -2.697 1.242 -20.897 1.00 0.00 H +HETATM 48 H28 OLC L 1 -2.249 0.727 -22.499 1.00 0.00 H +HETATM 49 H29 OLC L 1 -4.348 2.068 -22.528 1.00 0.00 H +HETATM 50 H30 OLC L 1 -4.680 0.430 -23.084 1.00 0.00 H +HETATM 51 H31 OLC L 1 -5.129 0.919 -21.446 1.00 0.00 H +HETATM 52 H32 OLC L 1 -1.213 -3.839 -17.365 1.00 0.00 H +HETATM 53 H33 OLC L 1 0.515 -2.220 -19.298 1.00 0.00 H +CONECT 1 2 3 21 22 +CONECT 2 1 4 5 +CONECT 2 4 +CONECT 3 1 6 23 24 +CONECT 4 2 +CONECT 4 2 +CONECT 5 2 +CONECT 6 3 7 25 26 +CONECT 7 6 8 27 28 +CONECT 8 7 9 29 30 +CONECT 9 8 10 31 32 +CONECT 10 9 11 33 34 +CONECT 11 10 12 35 +CONECT 11 12 +CONECT 12 11 13 36 +CONECT 12 11 +CONECT 13 12 14 37 38 +CONECT 14 13 15 39 52 +CONECT 15 14 16 40 53 +CONECT 16 15 17 41 42 +CONECT 17 16 18 43 44 +CONECT 18 17 19 45 46 +CONECT 19 18 20 47 48 +CONECT 20 19 49 50 51 +CONECT 21 1 +CONECT 22 1 +CONECT 23 3 +CONECT 24 3 +CONECT 25 6 +CONECT 26 6 +CONECT 27 7 +CONECT 28 7 +CONECT 29 8 +CONECT 30 8 +CONECT 31 9 +CONECT 32 9 +CONECT 33 10 +CONECT 34 10 +CONECT 35 11 +CONECT 36 12 +CONECT 37 13 +CONECT 38 13 +CONECT 39 14 +CONECT 40 15 +CONECT 41 16 +CONECT 42 16 +CONECT 43 17 +CONECT 44 17 +CONECT 45 18 +CONECT 46 18 +CONECT 47 19 +CONECT 48 19 +CONECT 49 20 +CONECT 50 20 +CONECT 51 20 +CONECT 52 14 +CONECT 53 15 +ENDMDL +END diff --git a/offPELE/data/ligands/SBN.pdb b/offPELE/data/ligands/SBN.pdb new file mode 100644 index 00000000..2e5993ee --- /dev/null +++ b/offPELE/data/ligands/SBN.pdb @@ -0,0 +1,113 @@ +HEADER HYDROLASE 16-AUG-14 4W52 +REMARK 4 4W52 COMPLIES WITH FORMAT V. 3.30, +REMARK 888 +REMARK 888 WRITTEN BY MAESTRO (A PRODUCT OF SCHRODINGER, LLC) +TITLE T4 LYSOZYME L99A WITH BENZENE BOUND +EXPDTA X-RAY DIFFRACTION +REMARK 2 RESOLUTION. 1.50 ANGSTROMS +REMARK 3 R VALUE : 0.165000 +REMARK 3 FREE R VALUE : 0.182000 +REMARK 200 TEMPERATURE (KELVIN) : 100.00 +REMARK 200 PH : 7.50 +REMARK 350 BIOMOLECULE: 1 +REMARK 350 APPLY THE FOLLOWING TO CHAINS: A +REMARK 350 BIOMT1 1 1.000000 0.000000 0.000000 0.000000 +REMARK 350 BIOMT2 1 0.000000 1.000000 0.000000 0.000000 +REMARK 350 BIOMT3 1 0.000000 0.000000 1.000000 0.000000 +CRYST1 60.350 60.350 96.610 90.00 90.00 120.00 P 32 2 1 6 +HET BNZ L 1 38 +HETNAM BNZ BENZENE +FORMUL 1 BNZ C6 H6 +MODEL 1 +HETATM 1 C1 BNZ L 1 -33.582 6.460 2.611 0.70 15.06 C +HETATM 2 C2 BNZ L 1 -33.631 7.357 3.696 0.70 12.84 C +HETATM 3 C3 BNZ L 1 -33.786 6.873 5.012 0.70 12.24 C +HETATM 4 C4 BNZ L 1 -33.919 5.485 5.223 0.70 13.09 C +HETATM 5 C5 BNZ L 1 -33.896 4.576 4.142 0.70 12.54 C +HETATM 6 C6 BNZ L 1 -33.714 5.075 2.831 0.70 14.23 C +HETATM 7 C7 BNZ L 1 -33.872 7.783 6.160 1.00 0.00 C +HETATM 8 C8 BNZ L 1 -34.085 3.091 4.441 1.00 0.00 C +HETATM 9 C9 BNZ L 1 -33.822 9.127 6.080 1.00 0.00 C +HETATM 10 C10 BNZ L 1 -34.100 2.160 3.217 1.00 0.00 C +HETATM 11 C11 BNZ L 1 -33.933 11.924 9.346 1.00 0.00 C +HETATM 12 C12 BNZ L 1 -33.831 12.383 8.017 1.00 0.00 C +HETATM 13 C13 BNZ L 1 -33.789 11.448 6.961 1.00 0.00 C +HETATM 14 C14 BNZ L 1 -33.846 10.061 7.218 1.00 0.00 C +HETATM 15 C15 BNZ L 1 -33.964 9.616 8.554 1.00 0.00 C +HETATM 16 C16 BNZ L 1 -33.997 10.544 9.614 1.00 0.00 C +HETATM 17 C17 BNZ L 1 -33.776 13.874 7.729 1.00 0.00 C +HETATM 18 C18 BNZ L 1 -32.492 14.526 8.257 1.00 0.00 C +HETATM 19 H1 BNZ L 1 -33.446 6.838 1.609 1.00 0.00 H +HETATM 20 H2 BNZ L 1 -33.524 8.414 3.510 1.00 0.00 H +HETATM 21 H3 BNZ L 1 -34.060 5.113 6.226 1.00 0.00 H +HETATM 22 H4 BNZ L 1 -33.681 4.413 1.977 1.00 0.00 H +HETATM 23 H5 BNZ L 1 -33.298 2.771 5.124 1.00 0.00 H +HETATM 24 H6 BNZ L 1 -35.024 2.973 4.985 1.00 0.00 H +HETATM 25 H7 BNZ L 1 -34.259 1.123 3.515 1.00 0.00 H +HETATM 26 H8 BNZ L 1 -34.902 2.426 2.527 1.00 0.00 H +HETATM 27 H9 BNZ L 1 -33.154 2.202 2.677 1.00 0.00 H +HETATM 28 H10 BNZ L 1 -33.962 12.631 10.164 1.00 0.00 H +HETATM 29 H11 BNZ L 1 -33.717 11.794 5.940 1.00 0.00 H +HETATM 30 H12 BNZ L 1 -34.006 8.563 8.787 1.00 0.00 H +HETATM 31 H13 BNZ L 1 -34.070 10.196 10.634 1.00 0.00 H +HETATM 32 H14 BNZ L 1 -33.858 14.046 6.656 1.00 0.00 H +HETATM 33 H15 BNZ L 1 -34.649 14.347 8.181 1.00 0.00 H +HETATM 34 H16 BNZ L 1 -32.467 15.590 8.021 1.00 0.00 H +HETATM 35 H17 BNZ L 1 -32.408 14.428 9.339 1.00 0.00 H +HETATM 36 H18 BNZ L 1 -31.610 14.066 7.812 1.00 0.00 H +HETATM 37 H19 BNZ L 1 -33.748 9.587 5.105 1.00 0.00 H +HETATM 38 H20 BNZ L 1 -33.961 7.304 7.125 1.00 0.00 H +CONECT 1 2 6 19 +CONECT 1 2 +CONECT 2 1 3 20 +CONECT 2 1 +CONECT 3 2 4 7 +CONECT 3 4 +CONECT 4 3 5 21 +CONECT 4 3 +CONECT 5 4 6 8 +CONECT 5 6 +CONECT 6 1 5 22 +CONECT 6 5 +CONECT 19 1 +CONECT 20 2 +CONECT 7 3 9 38 +CONECT 7 9 +CONECT 21 4 +CONECT 8 5 10 23 24 +CONECT 22 6 +CONECT 9 7 14 37 +CONECT 9 7 +CONECT 10 8 25 26 27 +CONECT 23 8 +CONECT 24 8 +CONECT 25 10 +CONECT 26 10 +CONECT 27 10 +CONECT 11 12 16 28 +CONECT 11 12 +CONECT 12 11 13 17 +CONECT 12 11 +CONECT 13 12 14 29 +CONECT 13 14 +CONECT 14 9 13 15 +CONECT 14 13 +CONECT 15 14 16 30 +CONECT 15 16 +CONECT 16 11 15 31 +CONECT 16 15 +CONECT 28 11 +CONECT 17 12 32 33 18 +CONECT 29 13 +CONECT 30 15 +CONECT 31 16 +CONECT 32 17 +CONECT 33 17 +CONECT 18 17 34 35 36 +CONECT 34 18 +CONECT 35 18 +CONECT 36 18 +CONECT 37 9 +CONECT 38 7 +ENDMDL +END diff --git a/offPELE/data/ligands/TOL.pdb b/offPELE/data/ligands/TOL.pdb new file mode 100644 index 00000000..a02000d6 --- /dev/null +++ b/offPELE/data/ligands/TOL.pdb @@ -0,0 +1,59 @@ +HEADER HYDROLASE 16-AUG-14 4W52 +REMARK 4 4W52 COMPLIES WITH FORMAT V. 3.30, +REMARK 888 +REMARK 888 WRITTEN BY MAESTRO (A PRODUCT OF SCHRODINGER, LLC) +TITLE T4 LYSOZYME L99A WITH BENZENE BOUND +EXPDTA X-RAY DIFFRACTION +REMARK 2 RESOLUTION. 1.50 ANGSTROMS +REMARK 3 R VALUE : 0.165000 +REMARK 3 FREE R VALUE : 0.182000 +REMARK 200 TEMPERATURE (KELVIN) : 100.00 +REMARK 200 PH : 7.50 +REMARK 350 BIOMOLECULE: 1 +REMARK 350 APPLY THE FOLLOWING TO CHAINS: A +REMARK 350 BIOMT1 1 1.000000 0.000000 0.000000 0.000000 +REMARK 350 BIOMT2 1 0.000000 1.000000 0.000000 0.000000 +REMARK 350 BIOMT3 1 0.000000 0.000000 1.000000 0.000000 +CRYST1 60.350 60.350 96.610 90.00 90.00 120.00 P 32 2 1 6 +HET BNZ L 1 15 +HETNAM BNZ BENZENE +FORMUL 1 BNZ C6 H6 +MODEL 1 +HETATM 1 C1 BNZ L 1 -32.969 6.196 2.877 0.70 15.06 C +HETATM 2 C2 BNZ L 1 -32.945 7.046 3.973 0.70 12.84 C +HETATM 3 C3 BNZ L 1 -33.719 6.798 5.113 0.70 12.24 C +HETATM 4 C4 BNZ L 1 -34.540 5.680 5.143 0.70 13.09 C +HETATM 5 C5 BNZ L 1 -34.545 4.825 4.044 0.70 12.54 C +HETATM 6 C6 BNZ L 1 -33.787 5.069 2.915 0.70 14.23 C +HETATM 7 C7 BNZ L 1 -33.652 7.760 6.313 1.00 0.00 C +HETATM 8 H1 BNZ L 1 -32.360 6.413 2.012 1.00 0.00 H +HETATM 9 H2 BNZ L 1 -32.318 7.925 3.961 1.00 0.00 H +HETATM 10 H4 BNZ L 1 -35.158 5.487 6.007 1.00 0.00 H +HETATM 11 H5 BNZ L 1 -35.156 3.935 4.055 1.00 0.00 H +HETATM 12 H6 BNZ L 1 -33.823 4.399 2.069 1.00 0.00 H +HETATM 13 H7 BNZ L 1 -34.318 7.407 7.101 1.00 0.00 H +HETATM 14 H8 BNZ L 1 -32.631 7.799 6.692 1.00 0.00 H +HETATM 15 H9 BNZ L 1 -33.960 8.757 5.998 1.00 0.00 H +CONECT 1 2 6 8 +CONECT 1 2 +CONECT 2 1 3 9 +CONECT 2 1 +CONECT 3 2 4 7 +CONECT 3 4 +CONECT 4 3 5 10 +CONECT 4 3 +CONECT 5 4 6 11 +CONECT 5 6 +CONECT 6 1 5 12 +CONECT 6 5 +CONECT 8 1 +CONECT 9 2 +CONECT 7 3 13 14 15 +CONECT 10 4 +CONECT 11 5 +CONECT 12 6 +CONECT 13 7 +CONECT 14 7 +CONECT 15 7 +ENDMDL +END diff --git a/offPELE/tests/__init__.py b/offPELE/tests/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/offPELE/tests/test_parameters.py b/offPELE/tests/test_parameters.py new file mode 100644 index 00000000..b8a6329c --- /dev/null +++ b/offPELE/tests/test_parameters.py @@ -0,0 +1,31 @@ +import pytest + +from simtk import unit +import numpy as np + +from offPELE.utils import get_data_file_path +from .utils import (SET_OF_LIGAND_PATHS, apply_PELE_dihedral_equation, + apply_OFF_dihedral_equation) +from offPELE.topology import Molecule + + +class TestDihedrals(object): + def test_OFF_to_PELE_conversion(self): + MAX_THRESHOLD = 1e-10 + FORCEFIELD_NAME = 'openff_unconstrained-1.1.1.offxml' + + for ligand_path in SET_OF_LIGAND_PATHS: + ligand_path = get_data_file_path(ligand_path) + molecule = Molecule(ligand_path) + molecule.parameterize(FORCEFIELD_NAME) + + x = unit.Quantity(np.arange(0, np.pi, 0.1), unit=unit.radians) + + for PELE_proper, OFF_proper in zip(molecule.propers, + molecule._OFF_propers): + PELE_y = apply_PELE_dihedral_equation(PELE_proper, x) + OFF_y = apply_OFF_dihedral_equation(OFF_proper, x) + + y_diff = PELE_y - OFF_y + + assert np.linalg.norm(y_diff) < MAX_THRESHOLD diff --git a/offPELE/tests/utils.py b/offPELE/tests/utils.py new file mode 100644 index 00000000..9b0c1106 --- /dev/null +++ b/offPELE/tests/utils.py @@ -0,0 +1,14 @@ +import numpy as np + + +SET_OF_LIGAND_PATHS = ['ligands/BNZ.pdb', 'ligands/TOL.pdb', 'ligands/MDB.pdb', + 'ligands/BIA.pdb', 'ligands/SBN.pdb', 'ligands/OLC.pdb'] + + +def apply_PELE_dihedral_equation(proper, x): + return proper.constant * (1 + proper.prefactor + * np.cos(proper.periodicity * x)) + + +def apply_OFF_dihedral_equation(proper, x): + return proper.k * (1 + np.cos(proper.periodicity * x - proper.phase)) From 9cdc87bbe95d234177d9406bafef65b60f298b04 Mon Sep 17 00:00:00 2001 From: Marti Municoy Date: Thu, 25 Jun 2020 10:55:51 +0200 Subject: [PATCH 16/67] Save forcefield name to molecule object --- offPELE/template/impact.py | 36 ++++++++++++++++++++++++++++++------ offPELE/topology/molecule.py | 9 ++++++++- offPELE/utils/toolkits.py | 10 ++++++++++ 3 files changed, 48 insertions(+), 7 deletions(-) diff --git a/offPELE/template/impact.py b/offPELE/template/impact.py index cd7770a3..3eedf595 100644 --- a/offPELE/template/impact.py +++ b/offPELE/template/impact.py @@ -5,7 +5,8 @@ class Impact(object): def __init__(self, molecule): - if isinstance(molecule, offPELE.topology.Molecule): + if (isinstance(molecule, offPELE.topology.Molecule) + or isinstance(molecule, offPELE.topology.molecule.Molecule)): self._initialize_from_molecule(molecule) else: raise Exception('Invalid input molecule for Impact template') @@ -14,7 +15,7 @@ def _initialize_from_molecule(self, molecule): self._molecule = molecule def write(self, path): - with open(path) as file: + with open(path, 'w') as file: self._write_header(file) self._write_resx(file) self._write_nbon(file) @@ -25,16 +26,35 @@ def write(self, path): self._write_end(file) def _write_header(self, file): - file.write('* LIGAND DATABASE FILE ({})\n'.format( - self.molecule.forcefield)) + file.write('* LIGAND DATABASE FILE') + if self.molecule.forcefield: + file.write(' ({})'.format(self.molecule.forcefield)) + file.write('\n') file.write('* File generated with offPELE {}\n'.format( offPELE.__version__)) def _write_resx(self, file): - pass + # template name + file.write('{:5}'.format(self.molecule.name)) + # number of non bonding parameters + file.write('{:6d}'.format(len(self.molecule.atoms))) + # number of bond parameters + file.write('{:6d}'.format(len(self.molecule.bonds))) + # number of angle parameters + file.write('{:7d}'.format(len(self.molecule.angles))) + # number of dihedral parameters + # TODO doublecheck that it is indeed the sum of propers and impropers + file.write('{:7d}'.format(len(self.molecule.propers) + + len(self.molecule.impropers))) + # # number of non-null elements in the interactions matrix + # TODO It might not be always 0 + file.write('{:8d}'.format(0)) + file.write('\n') def _write_nbon(self, file): - pass + for atom in self.molecule.atoms: + # atom id number + file.write('{:5d}'.format(atom.index)) def _write_bond(self, file): pass @@ -50,3 +70,7 @@ def _write_iphi(self, file): def _write_end(self, file): file.write('END\n') + + @property + def molecule(self): + return self._molecule diff --git a/offPELE/topology/molecule.py b/offPELE/topology/molecule.py index 179cd235..be8f3a0e 100644 --- a/offPELE/topology/molecule.py +++ b/offPELE/topology/molecule.py @@ -56,7 +56,7 @@ def __init__(self, path=None): def _initialize(self): self._name = '' - self._forcefield = '' + self._forcefield = None self._atoms = list() self._bonds = list() self._angles = list() @@ -105,6 +105,9 @@ def parameterize(self, forcefield): forcefield, self) self.parameters = parameters + # TODO Is there a way to retrieve the name of the OFF's ForceField object? + if isinstance(forcefield, str): + self._forcefield = Path(forcefield).stem print(' - Computing partial charges with am1bcc') self._calculate_am1bcc_charges() @@ -587,6 +590,10 @@ def rotamer_library(self): def name(self): return self._name + @property + def forcefield(self): + return self._forcefield + @property def atoms(self): return self._atoms diff --git a/offPELE/utils/toolkits.py b/offPELE/utils/toolkits.py index a03ebd68..873f8de4 100644 --- a/offPELE/utils/toolkits.py +++ b/offPELE/utils/toolkits.py @@ -194,6 +194,16 @@ def from_rdkit(self, molecule): rdkit_molecule = molecule.rdkit_molecule return Molecule.from_rdkit(rdkit_molecule) + def get_forcefield(self, forcefield_name): + from openforcefield.typing.engines.smirnoff import ForceField + + if isinstance(forcefield_name, str): + forcefield = ForceField(forcefield_name) + else: + raise Exception('Invalid forcefield type') + + return forcefield + def get_parameters_from_forcefield(self, forcefield, molecule): from openforcefield.typing.engines.smirnoff import ForceField from openforcefield.topology import Topology From 10461392195818839273c77cfa4c92c072a7185f Mon Sep 17 00:00:00 2001 From: Marti Municoy Date: Thu, 25 Jun 2020 10:59:51 +0200 Subject: [PATCH 17/67] Index is now an int rather than a tupple to 1 int --- offPELE/topology/molecule.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/offPELE/topology/molecule.py b/offPELE/topology/molecule.py index be8f3a0e..b7891342 100644 --- a/offPELE/topology/molecule.py +++ b/offPELE/topology/molecule.py @@ -399,7 +399,9 @@ def _build_atoms(self): self.parameters.get_vdW_parameters().keys()} for index in self.parameters.get_vdW_parameters().keys(): - atom = Atom(index=index, PDB_name=pdb_atom_names[index], + assert len(index) == 1, 'Index should be a tupple of length 1' + atom = Atom(index=int(index[0]), + PDB_name=pdb_atom_names[index], OPLS_type=OPLS_types[index], unknown=unknowns[index], z_matrix_x=z_matrix_xs[index], From ef20a97c168c27f8f1a3a354d928e763b3d5feb8 Mon Sep 17 00:00:00 2001 From: Marti Municoy Date: Thu, 25 Jun 2020 17:49:30 +0200 Subject: [PATCH 18/67] Parent setter in MolecularGraph --- offPELE/topology/molecule.py | 315 ++++++++++++++++++++--------------- 1 file changed, 185 insertions(+), 130 deletions(-) diff --git a/offPELE/topology/molecule.py b/offPELE/topology/molecule.py index b7891342..f3dd0f6c 100644 --- a/offPELE/topology/molecule.py +++ b/offPELE/topology/molecule.py @@ -4,6 +4,8 @@ from copy import deepcopy from pathlib import Path +import networkx as nx + from .rotamer import RotamerLibrary, Rotamer from .topology import Bond, Angle, OFFProper, OFFImproper from offPELE.utils.toolkits import (AmberToolkitWrapper, @@ -16,7 +18,7 @@ def __init__(self, index=-1, core=None, OPLS_type=None, PDB_name=None, unknown=None, z_matrix_x=None, z_matrix_y=None, z_matrix_z=None, sigma=None, epsilon=None, charge=None, born_radius=None, SASA_radius=None, nonpolar_gamma=None, - nonpolar_alpha=None): + nonpolar_alpha=None, parent=None): self.index = index self.core = core self.OPLS_type = OPLS_type @@ -32,6 +34,7 @@ def __init__(self, index=-1, core=None, OPLS_type=None, PDB_name=None, self.SASA_radius = SASA_radius # Rad. Non Polar Type self.nonpolar_gamma = nonpolar_gamma # SGB Non Polar gamma self.nonpolar_alpha = nonpolar_alpha # SGB Non Polar type + self.parent = parent def set_as_core(self): self.core = True @@ -39,99 +42,29 @@ def set_as_core(self): def set_as_branch(self): self.core = False + def set_parent(self, parent): + self.parent = parent -class Molecule(object): - def __init__(self, path=None): - if isinstance(path, str): - from pathlib import Path - extension = Path(path).suffix - extension = extension.strip('.') - if extension == 'pdb': - self._initialize_from_pdb(path) - else: - raise ValueError( - '{} is not a valid extension'.format(extension)) - else: - self._initialize() - def _initialize(self): - self._name = '' - self._forcefield = None - self._atoms = list() - self._bonds = list() - self._angles = list() - self._propers = list() - self._OFF_propers = list() - self._impropers = list() - self._OFF_impropers = list() - self._rdkit_molecule = None - self._off_molecule = None - self._rotamer_library = None - - def _initialize_from_pdb(self, path): - self._initialize() - print(' - Loading molecule from RDKit') +class MolecularGraph(nx.Graph): + def __init__(self, molecule): + super().__init__(self) + self._molecule = molecule + self._compute_rotamer_graph(molecule) + def _compute_rotamer_graph(self, molecule): rdkit_toolkit = RDKitToolkitWrapper() - self._rdkit_molecule = rdkit_toolkit.from_pdb(path) - - # RDKit must generate stereochemistry specifically from 3D coords - rdkit_toolkit.assign_stereochemistry_from_3D(self) - - openforcefield_toolkit = OpenForceFieldToolkitWrapper() + rot_bonds_atom_ids = \ + rdkit_toolkit.get_atom_ids_with_rotatable_bonds(molecule) - self._off_molecule = openforcefield_toolkit.from_rdkit(self) - - name = Path(path).stem - if len(name) > 2: - self.set_name(name) - - def set_name(self, name): - if isinstance(name, str) and len(name) > 2: - name = name[0:3].upper() - self._name = name + rdkit_molecule = molecule.rdkit_molecule - if self.off_molecule: - self.off_molecule.name = name - - def parameterize(self, forcefield): - if not self.off_molecule and not self.rdkit_molecule: - raise Exception('OpenForceField molecule was not initialized ' - + 'correctly') - - print(' - Loading forcefield') - openforcefield_toolkit = OpenForceFieldToolkitWrapper() - parameters = openforcefield_toolkit.get_parameters_from_forcefield( - forcefield, self) - - self.parameters = parameters - # TODO Is there a way to retrieve the name of the OFF's ForceField object? - if isinstance(forcefield, str): - self._forcefield = Path(forcefield).stem - - print(' - Computing partial charges with am1bcc') - self._calculate_am1bcc_charges() - - self._build_atoms() - - self._build_bonds() - - self._build_angles() - - self._build_propers() - - self._build_impropers() - - def _compute_rotamer_graph(self, rot_bonds_atom_ids): - import networkx as nx - graph = nx.Graph() - - for atom in self.rdkit_molecule.GetAtoms(): + for atom in rdkit_molecule.GetAtoms(): pdb_info = atom.GetPDBResidueInfo() - graph.add_node(atom.GetIdx(), pdb_name=pdb_info.GetName(), - nrot_neighbors=list()) + self.add_node(atom.GetIdx(), pdb_name=pdb_info.GetName(), + nrot_neighbors=list()) - for bond in self.rdkit_molecule.GetBonds(): + for bond in rdkit_molecule.GetBonds(): atom1 = bond.GetBeginAtomIdx() atom2 = bond.GetEndAtomIdx() if ((atom1, atom2) in rot_bonds_atom_ids @@ -139,29 +72,27 @@ def _compute_rotamer_graph(self, rot_bonds_atom_ids): rotatable = True else: rotatable = False - graph.nodes[atom1]['nrot_neighbors'].append(atom2) - graph.nodes[atom2]['nrot_neighbors'].append(atom1) + self.nodes[atom1]['nrot_neighbors'].append(atom2) + self.nodes[atom2]['nrot_neighbors'].append(atom1) - graph.add_edge(bond.GetBeginAtomIdx(), - bond.GetEndAtomIdx(), - weight=int(rotatable)) + self.add_edge(bond.GetBeginAtomIdx(), + bond.GetEndAtomIdx(), + weight=int(rotatable)) for i, j in rot_bonds_atom_ids: - graph[i][j]['weight'] = 1 - graph.nodes[i]['rotatable'] = True - graph.nodes[j]['rotatable'] = True - - return graph + self[i][j]['weight'] = 1 + self.nodes[i]['rotatable'] = True + self.nodes[j]['rotatable'] = True - def _set_core(self, graph, rot_bonds_atom_ids): - def get_all_nrot_neighbors(atom_id, visited_neighbors): + def set_core(self): + def get_all_nrot_neighbors(self, atom_id, visited_neighbors): if atom_id in visited_neighbors: return visited_neighbors visited_neighbors.add(atom_id) - nrot_neighbors = graph.nodes[atom_id]['nrot_neighbors'] + nrot_neighbors = self.nodes[atom_id]['nrot_neighbors'] for nrot_neighbor in nrot_neighbors: visited_neighbors = get_all_nrot_neighbors( - nrot_neighbor, visited_neighbors) + self, nrot_neighbor, visited_neighbors) return visited_neighbors from networkx.algorithms.shortest_paths.generic import \ @@ -169,10 +100,10 @@ def get_all_nrot_neighbors(atom_id, visited_neighbors): from networkx.algorithms.distance_measures import eccentricity # Calculate graph distances according to weight values - weighted_distances = dict(shortest_path_length(graph, weight="weight")) + weighted_distances = dict(shortest_path_length(self, weight="weight")) # Calculate eccentricites using weighted distances - eccentricities = eccentricity(graph, sp=weighted_distances) + eccentricities = eccentricity(self, sp=weighted_distances) # Group nodes by eccentricity nodes_by_eccentricities = defaultdict(list) @@ -188,28 +119,69 @@ def get_all_nrot_neighbors(atom_id, visited_neighbors): for node in centered_nodes: if node in already_visited: continue - centered_node_groups.append(get_all_nrot_neighbors(node, set())) + centered_node_groups.append(get_all_nrot_neighbors(self, node, + set())) # In case of more than one group, core will be the largest node_group = sorted(centered_node_groups, key=len, reverse=True)[0] - for atom in self.atoms: + for atom in self.molecule.atoms: if atom.index in node_group: atom.set_as_core() else: atom.set_as_branch() - def _get_rot_bonds_per_group(self, graph, branch_groups): + def set_parents(self): + def recursive_child_visitor(parent, already_visited=set()): + if parent in already_visited: + return already_visited + + already_visited.add(parent) + + childs = [self.molecule.atoms[n] for n in self.neighbors(parent.index)] + + for child in childs: + if child in already_visited: + continue + child.set_parent(parent) + already_visited = recursive_child_visitor(child, + already_visited) + + return already_visited + + # Start from an atom from the core + parent = None + for atom in self.molecule.atoms: + if atom.core: + parent = atom + break + + # Assert a parent was found + assert parent is not None, 'No core atom found in molecule ' \ + '{}'.format(self.molecule.name) + + already_visited = recursive_child_visitor(parent) + + # Assert all nodes were explored + assert len(already_visited) == len(self.molecule.atoms), 'Not all ' \ + 'nodes were explored' + + # Assert absolut parent is the only with None parent value + assert parent.parent is None and \ + sum([int(a.parent is not None) for a in self.molecule.atoms]) \ + == len(self.molecule.atoms) - 1, 'Found descendant without parent' + + def _get_rot_bonds_per_group(self, branch_groups): rot_bonds_per_group = list() for group in branch_groups: rot_bonds = list() visited_bonds = set() for node in group: - bonds = graph.edges(node) + bonds = self.edges(node) for bond in bonds: if bond in visited_bonds: continue - if graph[bond[0]][bond[1]]['weight'] == 1: + if self[bond[0]][bond[1]]['weight'] == 1: rot_bonds.append(bond) visited_bonds.add(bond) visited_bonds.add((bond[1], bond[0])) @@ -249,68 +221,147 @@ def _get_sorted_bonds_per_group(self, core_atom_per_group, return sorted_rot_bonds_per_group - def _build_rotamer_library(self, graph, resolution): - import networkx as nx - + def build_rotamer_library(self, resolution): core_atoms = set() - for atom in self.atoms: + for atom in self.molecule.atoms: if atom.core: core_atoms.add(atom) core_indexes = [atom.index for atom in core_atoms] assert len(core_atoms) > 0, 'No core atoms were found' - branch_graph = deepcopy(graph) + branch_graph = deepcopy(self) for core_atom in core_atoms: branch_graph.remove_node(core_atom.index) branch_groups = list(nx.connected_components(branch_graph)) - rot_bonds_per_group = self._get_rot_bonds_per_group( - graph, branch_groups) + rot_bonds_per_group = self._get_rot_bonds_per_group(branch_groups) core_atom_per_group = self._get_core_atom_per_group( rot_bonds_per_group, core_indexes) - distances = dict(nx.shortest_path_length(graph)) + distances = dict(nx.shortest_path_length(self)) sorted_rot_bonds_per_group = self._get_sorted_bonds_per_group( core_atom_per_group, rot_bonds_per_group, distances) - self._rotamer_library = RotamerLibrary(self.name) + rotamer_library = RotamerLibrary(self.molecule.name) # PELE needs underscores instead of whitespaces pdb_atom_names = [name.replace(' ', '_',) - for name in self.get_pdb_atom_names()] + for name in self.molecule.get_pdb_atom_names()] for group_id, rot_bonds in enumerate(sorted_rot_bonds_per_group): for (atom1_index, atom2_index) in rot_bonds: atom1_name = pdb_atom_names[atom1_index] atom2_name = pdb_atom_names[atom2_index] rotamer = Rotamer(atom1_name, atom2_name, resolution) - self.rotamer_library.add_rotamer(rotamer, group_id) + rotamer_library.add_rotamer(rotamer, group_id) + + return rotamer_library + + @property + def molecule(self): + return self._molecule + + +class Molecule(object): + def __init__(self, path=None): + if isinstance(path, str): + from pathlib import Path + extension = Path(path).suffix + extension = extension.strip('.') + if extension == 'pdb': + self._initialize_from_pdb(path) + else: + raise ValueError( + '{} is not a valid extension'.format(extension)) + else: + self._initialize() + + def _initialize(self): + self._name = '' + self._forcefield = None + self._atoms = list() + self._bonds = list() + self._angles = list() + self._propers = list() + self._OFF_propers = list() + self._impropers = list() + self._OFF_impropers = list() + self._rdkit_molecule = None + self._off_molecule = None + self._rotamer_library = None + self._graph = None + + def _initialize_from_pdb(self, path): + self._initialize() + print(' - Loading molecule from RDKit') + + rdkit_toolkit = RDKitToolkitWrapper() + self._rdkit_molecule = rdkit_toolkit.from_pdb(path) + + # RDKit must generate stereochemistry specifically from 3D coords + rdkit_toolkit.assign_stereochemistry_from_3D(self) + + openforcefield_toolkit = OpenForceFieldToolkitWrapper() + + self._off_molecule = openforcefield_toolkit.from_rdkit(self) + + name = Path(path).stem + if len(name) > 2: + self.set_name(name) + + def set_name(self, name): + if isinstance(name, str) and len(name) > 2: + name = name[0:3].upper() + self._name = name + + if self.off_molecule: + self.off_molecule.name = name + + def parameterize(self, forcefield): + if not self.off_molecule and not self.rdkit_molecule: + raise Exception('OpenForceField molecule was not initialized ' + + 'correctly') + + print(' - Loading forcefield') + openforcefield_toolkit = OpenForceFieldToolkitWrapper() + parameters = openforcefield_toolkit.get_parameters_from_forcefield( + forcefield, self) + + self.parameters = parameters + # TODO Is there a way to retrieve the name of the OFF's ForceField object? + if isinstance(forcefield, str): + self._forcefield = Path(forcefield).stem + + print(' - Computing partial charges with am1bcc') + self._calculate_am1bcc_charges() + + self._build_atoms() + + self._build_bonds() + + self._build_angles() + + self._build_propers() + + self._build_impropers() def build_rotamer_library(self, resolution): self._assert_parameterized() - try: - from rdkit import Chem - except ImportError: - raise Exception('RDKit Python API not found') - print(' - Generating rotamer library') - # Fins rotatable bond ids as in Lipinski module in RDKit - # https://github.com/rdkit/rdkit/blob/1bf6ef3d65f5c7b06b56862b3fb9116a3839b229/rdkit/Chem/Lipinski.py#L47 - rot_bonds_atom_ids = self._rdkit_molecule.GetSubstructMatches( - Chem.MolFromSmarts('[!$(*#*)&!D1]-&!@[!$(*#*)&!D1]')) + self._graph = MolecularGraph(self) - graph = self._compute_rotamer_graph(rot_bonds_atom_ids) + self.graph.set_core() - self._set_core(graph, rot_bonds_atom_ids) + self.graph.set_parents() - self._build_rotamer_library(graph, resolution) + self._rotamer_library = self.graph.build_rotamer_library(resolution) def plot_rotamer_graph(self): self._assert_parameterized() @@ -615,3 +666,7 @@ def propers(self): @property def impropers(self): return self._impropers + + @property + def graph(self): + return self._graph From 1ada5b8fffc18e9b5cb04adb5cad254b745f55de Mon Sep 17 00:00:00 2001 From: Marti Municoy Date: Fri, 26 Jun 2020 01:13:15 +0200 Subject: [PATCH 19/67] New ZMatrix class --- offPELE/template/impact.py | 100 ++++++++++++++++++++++- offPELE/topology/__init__.py | 1 + offPELE/topology/molecule.py | 134 ++++++++++++++++++++++++------- offPELE/topology/zmatrix.py | 150 +++++++++++++++++++++++++++++++++++ offPELE/utils/toolkits.py | 33 +++++++- 5 files changed, 382 insertions(+), 36 deletions(-) create mode 100644 offPELE/topology/zmatrix.py diff --git a/offPELE/template/impact.py b/offPELE/template/impact.py index 3eedf595..a76fc15e 100644 --- a/offPELE/template/impact.py +++ b/offPELE/template/impact.py @@ -1,6 +1,9 @@ # Global imports +from copy import deepcopy + import offPELE +from offPELE.topology import ZMatrix class Impact(object): @@ -41,10 +44,10 @@ def _write_resx(self, file): # number of bond parameters file.write('{:6d}'.format(len(self.molecule.bonds))) # number of angle parameters - file.write('{:7d}'.format(len(self.molecule.angles))) + file.write('{:6d}'.format(len(self.molecule.angles))) # number of dihedral parameters # TODO doublecheck that it is indeed the sum of propers and impropers - file.write('{:7d}'.format(len(self.molecule.propers) + file.write('{:8d}'.format(len(self.molecule.propers) + len(self.molecule.impropers))) # # number of non-null elements in the interactions matrix # TODO It might not be always 0 @@ -52,9 +55,30 @@ def _write_resx(self, file): file.write('\n') def _write_nbon(self, file): - for atom in self.molecule.atoms: + zmatrix = ZMatrix(self.molecule) + + for i, atom in enumerate(self.molecule.atoms): + w_atom = WritableAtom(atom) # atom id number - file.write('{:5d}'.format(atom.index)) + file.write('{:5d}'.format(w_atom.index)) + file.write(' ') + file.write('{:5d}'.format(w_atom.parent.index)) + file.write(' ') + file.write('{:1}'.format(w_atom.core)) + file.write(' ') + file.write('{:4}'.format(w_atom.OPLS_type)) + file.write(' ') + file.write('{:4}'.format(w_atom.PDB_name)) + file.write(' ') + file.write('{:5}'.format(w_atom.unknown)) + file.write(' ') + file.write('{: 11.6f}'.format(zmatrix[i][0])) + file.write(' ') + file.write('{: 11.6f}'.format(zmatrix[i][1])) + file.write(' ') + file.write('{: 11.6f}'.format(zmatrix[i][2])) + file.write(' ') + file.write('\n') def _write_bond(self, file): pass @@ -74,3 +98,71 @@ def _write_end(self, file): @property def molecule(self): return self._molecule + + +class WritableAtom(offPELE.topology.molecule.Atom): + def __init__(self, atom): + # We do not want to modify the original object + atom = deepcopy(atom) + + assert isinstance(atom, (offPELE.topology.molecule.Atom, + offPELE.topology.molecule.DummyAtom)), \ + 'Wrong type: {}'.format(type(atom)) + + super().__init__(atom.index, atom.core, atom.OPLS_type, atom.PDB_name, + atom.unknown, atom.x, atom.y, atom.z, atom.sigma, + atom.epsilon, atom.charge, atom.born_radius, + atom.SASA_radius, atom.nonpolar_gamma, + atom.nonpolar_alpha, atom.parent) + + def none_to_zero(f): + def function_wrapper(*args, **kwargs): + out = f(*args, **kwargs) + if out is None: + out = int(0) + return out + return function_wrapper + + def dummy_to_writable(f): + def function_wrapper(*args, **kwargs): + out = f(*args, **kwargs) + out = WritableAtom(out) + return out + return function_wrapper + + def none_to_dummy(f): + def function_wrapper(*args, **kwargs): + out = f(*args, **kwargs) + if out is None: + out = offPELE.topology.molecule.DummyAtom(index=-1) + return out + return function_wrapper + + @property + @dummy_to_writable + @none_to_dummy + def parent(self): + return super().parent + + @property + def index(self): + return int(self._index) + 1 + + @property + def core(self): + if self._core: + return 'M' + else: + return 'S' + + # TODO Consider removing any reference to OPLS, if possible + # Otherwise, use SMIRks to find the best match + @property + def OPLS_type(self): + return 'OFFT' # stands for OpenForceField type + + # TODO Review the actual purpose of this attribute in PELE + @property + @none_to_zero + def unknown(self): + return super().unknown diff --git a/offPELE/topology/__init__.py b/offPELE/topology/__init__.py index 10433126..fcb0e2e0 100644 --- a/offPELE/topology/__init__.py +++ b/offPELE/topology/__init__.py @@ -1,2 +1,3 @@ from .topology import * from .molecule import Molecule +from .zmatrix import ZMatrix diff --git a/offPELE/topology/molecule.py b/offPELE/topology/molecule.py index f3dd0f6c..40ec9dd0 100644 --- a/offPELE/topology/molecule.py +++ b/offPELE/topology/molecule.py @@ -15,35 +15,111 @@ class Atom(object): def __init__(self, index=-1, core=None, OPLS_type=None, PDB_name=None, - unknown=None, z_matrix_x=None, z_matrix_y=None, - z_matrix_z=None, sigma=None, epsilon=None, charge=None, - born_radius=None, SASA_radius=None, nonpolar_gamma=None, - nonpolar_alpha=None, parent=None): - self.index = index - self.core = core - self.OPLS_type = OPLS_type - self.PDB_name = PDB_name - self.unknown = unknown - self.z_matrix_x = z_matrix_x - self.z_matrix_y = z_matrix_y - self.z_matrix_z = z_matrix_z - self.sigma = sigma - self.epsilon = epsilon - self.charge = charge - self.born_radius = born_radius # Rad. Non Polar SGB - self.SASA_radius = SASA_radius # Rad. Non Polar Type - self.nonpolar_gamma = nonpolar_gamma # SGB Non Polar gamma - self.nonpolar_alpha = nonpolar_alpha # SGB Non Polar type - self.parent = parent + unknown=None, x=None, y=None, z=None, sigma=None, + epsilon=None, charge=None, born_radius=None, SASA_radius=None, + nonpolar_gamma=None, nonpolar_alpha=None, parent=None): + self._index = index + self._core = core + self._OPLS_type = OPLS_type + self._PDB_name = PDB_name + self._unknown = unknown + self._x = x + self._y = y + self._z = z + self._sigma = sigma + self._epsilon = epsilon + self._charge = charge + self._born_radius = born_radius # Rad. Non Polar SGB + self._SASA_radius = SASA_radius # Rad. Non Polar Type + self._nonpolar_gamma = nonpolar_gamma # SGB Non Polar gamma + self._nonpolar_alpha = nonpolar_alpha # SGB Non Polar type + self._parent = parent def set_as_core(self): - self.core = True + self._core = True def set_as_branch(self): - self.core = False + self._core = False def set_parent(self, parent): - self.parent = parent + self._parent = parent + + def set_coords(self, coords): + assert len(coords) == 3, '3D array is expected' + + self._x, self._y, self._z = coords + + @property + def index(self): + return self._index + + @property + def core(self): + return self._core + + @property + def OPLS_type(self): + return self._OPLS_type + + @property + def PDB_name(self): + return self._PDB_name + + @property + def unknown(self): + return self._unknown + + @property + def x(self): + return self._x + + @property + def y(self): + return self._y + + @property + def z(self): + return self._z + + @property + def sigma(self): + return self._sigma + + @property + def epsilon(self): + return self._epsilon + + @property + def charge(self): + return self._charge + + @property + def born_radius(self): + return self._born_radius + + @property + def SASA_radius(self): + return self._SASA_radius + + @property + def nonpolar_gamma(self): + return self._nonpolar_gamma + + @property + def nonpolar_alpha(self): + return self._nonpolar_alpha + + @property + def parent(self): + return self._parent + + +class DummyAtom(Atom): + def __init__(self, index=-1, PDB_name='DUMM', parent=None): + if parent is None: + parent = self + super().__init__(index, False, None, PDB_name, None, None, None, None, + None, None, None, None, None, None, None, parent) class MolecularGraph(nx.Graph): @@ -427,10 +503,8 @@ def _build_atoms(self): for i in self.parameters.get_vdW_parameters().keys()} # TODO Create z-matrix from 3D coordinates - z_matrix_xs, z_matrix_ys, z_matrix_zs = ( - {i: None for i in self.parameters.get_vdW_parameters().keys()}, - {i: None for i in self.parameters.get_vdW_parameters().keys()}, - {i: None for i in self.parameters.get_vdW_parameters().keys()}) + + coords = RDKitToolkitWrapper().get_coordinates(self) sigmas = self.parameters.get_vdW_sigmas() @@ -455,9 +529,9 @@ def _build_atoms(self): PDB_name=pdb_atom_names[index], OPLS_type=OPLS_types[index], unknown=unknowns[index], - z_matrix_x=z_matrix_xs[index], - z_matrix_y=z_matrix_ys[index], - z_matrix_z=z_matrix_zs[index], + x=coords[index][0], + y=coords[index][1], + z=coords[index][2], sigma=sigmas[index], epsilon=epsilons[index], charge=self.off_molecule.partial_charges[index], diff --git a/offPELE/topology/zmatrix.py b/offPELE/topology/zmatrix.py new file mode 100644 index 00000000..0b146a98 --- /dev/null +++ b/offPELE/topology/zmatrix.py @@ -0,0 +1,150 @@ +from copy import deepcopy + +import numpy as np + +from offPELE.topology.molecule import Atom, DummyAtom + + +class ZMatrix(np.ndarray): + """ + Inspired by the PlopRotTemp algorithm + """ + + def __init__(self, molecule): + # We will work on a copy of the molecule's object to modify it freely + self._molecule = deepcopy(molecule) + + def __new__(cls, molecule): + molecule = deepcopy(molecule) + obj = np.zeros((len(molecule.atoms), 3)).view(cls) + coords = cls._extract_coords(molecule) + obj = cls._build_zmatrix(cls, obj, coords, molecule) + + return obj + + def _extract_coords(molecule): + coords = list() + for atom in molecule.atoms: + coords.append((atom.x, atom.y, atom.z)) + + return coords + + def _get_absolute_parent(molecule): + absolute_parent = list() + for atom in molecule.atoms: + if atom.parent is None: + absolute_parent.append(atom) + + assert len(absolute_parent) == 1, 'Only 1 absolute parent is expected' + + return absolute_parent[0] + + def _calculate_bond(x1, y1, z1, x2, y2, z2): + dx = x1 - x2 + dy = y1 - y2 + dz = z1 - z2 + + return np.sqrt(dx * dx + dy * dy + dz * dz) + + def _calculate_angle(x1, y1, z1, x2, y2, z2, x3, y3, z3): + dx_12 = x1 - x2 + dy_12 = y1 - y2 + dz_12 = z1 - z2 + + dx_31 = x3 - x1 + dy_31 = y3 - y1 + dz_31 = z3 - z1 + + vdot = dx_12 * dx_31 + dy_12 * dy_31 + dz_12 * dz_31 + + assert np.fabs(vdot) > 0, 'A non-zero angle is expected' + + d12 = np.sqrt(dx_12 * dx_12 + dy_12 * dy_12 + dz_12 * dz_12) + d31 = np.sqrt(dx_31 * dx_31 + dy_31 * dy_31 + dz_31 * dz_31) + + xang = vdot / (d12 * d31) + + if xang - 1.0 > -0.0000000001: + return 0.0 + elif xang + 1.0 < 0.0000000001: + return np.pi + + return np.arccos(xang) * 180.0 / np.pi + + def _calculate_dihedral(x1, y1, z1, x2, y2, z2, x3, y3, z3, x4, y4, z4): + dx_12 = x1 - x2 + dy_12 = y1 - y2 + dz_12 = z1 - z2 + + dx_32 = x3 - x2 + dy_32 = y3 - y2 + dz_32 = z3 - z2 + + dx_34 = x3 - x4 + dy_34 = y3 - y4 + dz_34 = z3 - z4 + + ax = dy_12 * dz_32 - dz_12 * dy_32 + ay = dz_12 * dx_32 - dx_12 * dz_32 + az = dx_12 * dy_32 - dy_12 * dx_32 + cx = dy_32 * dz_34 - dz_32 * dy_34 + cy = dz_32 * dx_34 - dx_32 * dz_34 + cz = dx_32 * dy_34 - dy_32 * dx_34 + + rac = ax * cx + ay * cy + az * cz + ra = ax * ax + ay * ay + az * az + rc = cx * cx + cy * cy + cz * cz + + cosang = rac / np.sqrt(ra * rc) + + if cosang - 1.0 > -0.00000000001: + phi = 0.0 + elif cosang + 1.0 < 0.00000000001: + phi = np.pi + else: + phi = np.arccos(cosang) + + s = dx_12 * cx + dy_12 * cy + dz_12 * cz + if (s < 0): + phi = -phi # to account for phi between pi and 2pi + + return phi * 180.0 / np.pi + + def _build_zmatrix(cls, obj, coords, molecule): + + dummy1 = DummyAtom(index=-3, PDB_name='DUM1', parent=None) + dummy2 = DummyAtom(index=-2, PDB_name='DUM2', parent=dummy1) + dummy3 = DummyAtom(index=-1, PDB_name='DUM3', parent=dummy2) + absolute_parent = cls._get_absolute_parent(molecule) + absolute_parent.set_parent(dummy3) + + dummy1.set_coords([0.0, 0.0, 0.0]) # at origin + dummy2.set_coords([0.0, 0.0, 1.0]) # at z axis + dummy3.set_coords([1.0, 0.0, 0.0]) # at x axis + + for i, atom in enumerate(molecule.atoms): + atom1 = atom + atom2 = atom1.parent + atom3 = atom2.parent + atom4 = atom3.parent + + assert atom1 is not None and atom2 is not None \ + and atom3 is not None and atom4 is not None, \ + 'None parent is not expected' + + x1, y1, z1 = (atom1.x, atom1.y, atom1.z) + x2, y2, z2 = (atom2.x, atom2.y, atom2.z) + x3, y3, z3 = (atom3.x, atom3.y, atom3.z) + x4, y4, z4 = (atom4.x, atom4.y, atom4.z) + + obj[i][0] = cls._calculate_bond(x1, y1, z1, + x2, y2, z2) + obj[i][1] = cls._calculate_angle(x1, y1, z1, + x2, y2, z2, + x3, y3, z3) + obj[i][2] = cls._calculate_dihedral(x1, y1, z1, + x2, y2, z2, + x3, y3, z3, + x4, y4, z4) + + return obj diff --git a/offPELE/utils/toolkits.py b/offPELE/utils/toolkits.py index 873f8de4..aebef016 100644 --- a/offPELE/utils/toolkits.py +++ b/offPELE/utils/toolkits.py @@ -4,6 +4,7 @@ import os import subprocess from collections import defaultdict +from pathlib import Path import numpy as np from simtk import unit @@ -85,12 +86,39 @@ def assign_stereochemistry_from_3D(self, molecule): def to_sfd_file(self, molecule, path): from rdkit import Chem + assert Path(path).suffix == '.sdf', 'Wrong extension' + rdkit_molecule = molecule.rdkit_molecule - with open('molecule.sdf', 'w') as f: + with open(path, 'w') as f: writer = Chem.SDWriter(f) writer.write(rdkit_molecule) writer.close() + def to_xyz_file(self, molecule, path): + from rdkit import Chem + + assert Path(path).suffix == '.xyz', 'Wrong extension' + + rdkit_molecule = molecule.rdkit_molecule + Chem.MolToXYZFile(rdkit_molecule, path) + + def get_atom_ids_with_rotatable_bonds(self, molecule): + from rdkit import Chem + + rdkit_molecule = molecule.rdkit_molecule + # Fins rotatable bond ids as in Lipinski module in RDKit + # https://github.com/rdkit/rdkit/blob/1bf6ef3d65f5c7b06b56862b3fb9116a3839b229/rdkit/Chem/Lipinski.py#L47 + rot_bonds_atom_ids = rdkit_molecule.GetSubstructMatches( + Chem.MolFromSmarts('[!$(*#*)&!D1]-&!@[!$(*#*)&!D1]')) + + return rot_bonds_atom_ids + + def get_coordinates(self, molecule): + rdkit_molecule = molecule.rdkit_molecule + + conformer = rdkit_molecule.GetConformer() + return conformer.GetPositions() + class AmberToolkitWrapper(ToolkitWrapper): _toolkit_name = 'Amber Toolkit' @@ -129,7 +157,8 @@ def compute_partial_charges_am1bcc(self, molecule): net_charge = off_molecule.total_charge / \ unit.elementary_charge - self._rdkit_toolkit_wrapper.to_sfd_file(molecule, tmpdir) + self._rdkit_toolkit_wrapper.to_sfd_file( + molecule, tmpdir + '/molecule.sdf') subprocess.check_output([ "antechamber", "-i", "molecule.sdf", "-fi", "sdf", From 19d1cf13b1e74331109ff5ef889349f0d5e3edba Mon Sep 17 00:00:00 2001 From: Marti Municoy Date: Fri, 26 Jun 2020 11:14:55 +0200 Subject: [PATCH 20/67] Impact template writer is fully implemented --- offPELE/template/impact.py | 365 ++++++++++++++++++++++++++++++++--- offPELE/topology/__init__.py | 2 +- offPELE/topology/topology.py | 116 +++++++++-- 3 files changed, 438 insertions(+), 45 deletions(-) diff --git a/offPELE/template/impact.py b/offPELE/template/impact.py index a76fc15e..e159fb9d 100644 --- a/offPELE/template/impact.py +++ b/offPELE/template/impact.py @@ -2,6 +2,8 @@ # Global imports from copy import deepcopy +from simtk import unit + import offPELE from offPELE.topology import ZMatrix @@ -35,6 +37,7 @@ def _write_header(self, file): file.write('\n') file.write('* File generated with offPELE {}\n'.format( offPELE.__version__)) + file.write('*\n') def _write_resx(self, file): # template name @@ -54,7 +57,6 @@ def _write_resx(self, file): file.write('{:8d}'.format(0)) file.write('\n') - def _write_nbon(self, file): zmatrix = ZMatrix(self.molecule) for i, atom in enumerate(self.molecule.atoms): @@ -77,44 +79,157 @@ def _write_nbon(self, file): file.write('{: 11.6f}'.format(zmatrix[i][1])) file.write(' ') file.write('{: 11.6f}'.format(zmatrix[i][2])) + file.write('\n') + # TODO Should we add the interactions matrix here? + + def _write_nbon(self, file): + file.write('NBON\n') + for atom in self.molecule.atoms: + w_atom = WritableAtom(atom) + # TODO an extra space is found in the IMPACT file generated by + # PlopRotTemp, consider removing it + file.write(' ') + # Atom id + file.write('{:5d}'.format(w_atom.index)) + file.write(' ') + # Sigma + file.write('{: 8.4f}'.format(w_atom.sigma)) file.write(' ') + # Epsilon + file.write('{: 8.4f}'.format(w_atom.epsilon)) + file.write(' ') + # Charge + file.write('{: 10.6f}'.format(w_atom.charge)) + file.write(' ') + # Rad. Non Polar SGB + file.write('{: 8.4f}'.format(w_atom.born_radius)) + file.write(' ') + # Rad. Non Polar Type + file.write('{: 8.4f}'.format(w_atom.SASA_radius)) + file.write(' ') + # SGB Non Polar gamma + file.write('{: 13.9f}'.format(w_atom.nonpolar_gamma)) + file.write(' ') + # SGB Non Polar type + file.write('{: 13.9f}'.format(w_atom.nonpolar_alpha)) file.write('\n') def _write_bond(self, file): - pass + file.write('BOND\n') + for bond in self.molecule.bonds: + w_bond = WritableBond(bond) + idx1, idx2, spring, eq_dist = [attr[1] for attr in list(w_bond)] + # TODO an extra space is found in the IMPACT file generated by + # PlopRotTemp, consider removing it + file.write(' ') + # Atom 1 id + file.write('{:5d}'.format(idx1)) + file.write(' ') + # Atom 2 id + file.write('{:5d}'.format(idx2)) + file.write(' ') + # Spring constant + file.write('{: 9.3f}'.format(spring.value_in_unit( + unit.kilocalorie / (unit.angstrom**2 * unit.mole)))) + file.write(' ') + # Equilibrium distance + file.write('{: 6.3f}\n'.format(eq_dist.value_in_unit( + unit.angstrom))) def _write_thet(self, file): - pass + file.write('THET\n') + for angle in self.molecule.angles: + w_angle = WritableAngle(angle) + idx1, idx2, idx3, spring, eq_angl = [attr[1] for attr in + list(w_angle)] + # TODO an extra space is found in the IMPACT file generated by + # PlopRotTemp, consider removing it + file.write(' ') + # Atom 1 id + file.write('{:5d}'.format(idx1)) + file.write(' ') + # Atom 2 id + file.write('{:5d}'.format(idx2)) + file.write(' ') + # Atom 3 id + file.write('{:5d}'.format(idx3)) + file.write(' ') + # Spring constant + file.write('{: 11.5f}'.format(spring.value_in_unit( + unit.kilocalorie / (unit.degree**2 * unit.mole)))) + # Equilibrium angle + file.write('{: 11.5f}\n'.format(eq_angl.value_in_unit( + unit.degree))) def _write_phi(self, file): - pass + file.write('PHI\n') + for proper in self.molecule.propers: + w_proper = WritableProper(proper) + idx1, idx2, idx3, idx4, constant, prefactor, term = \ + [attr[1] for attr in list(w_proper)] + # Atom 1 id + file.write('{:5d}'.format(idx1)) + file.write(' ') + # Atom 2 id + file.write('{:5d}'.format(idx2)) + file.write(' ') + # Atom 3 id + file.write('{:5d}'.format(idx3)) + file.write(' ') + # Atom 4 id + file.write('{:5d}'.format(idx4)) + file.write(' ') + # Constant + file.write('{: 9.5f}'.format(constant)) + file.write(' ') + # Prefactor + file.write('{: 4.1f}'.format(prefactor)) + file.write(' ') + # Number of term + file.write('{:3.1f}'.format(term)) + file.write('\n') def _write_iphi(self, file): - pass + file.write('IPHI\n') + for improper in self.molecule.impropers: + w_improper = WritableImproper(improper) + idx1, idx2, idx3, idx4, constant, prefactor, term = \ + [attr[1] for attr in list(w_improper)] + # TODO an extra space is found in the IMPACT file generated by + # PlopRotTemp, consider removing it + file.write(' ') + # Atom 1 id + file.write('{:5d}'.format(idx1)) + file.write(' ') + # Atom 2 id + file.write('{:5d}'.format(idx2)) + file.write(' ') + # Atom 3 id + file.write('{:5d}'.format(idx3)) + file.write(' ') + # Atom 4 id + file.write('{:5d}'.format(idx4)) + file.write(' ') + # Constant + file.write('{: 9.5f}'.format(constant)) + file.write(' ') + # Prefactor + file.write('{: 4.1f}'.format(prefactor)) + file.write(' ') + # Number of term + file.write('{:3.1f}'.format(term)) + file.write('\n') def _write_end(self, file): file.write('END\n') - @property + @ property def molecule(self): return self._molecule -class WritableAtom(offPELE.topology.molecule.Atom): - def __init__(self, atom): - # We do not want to modify the original object - atom = deepcopy(atom) - - assert isinstance(atom, (offPELE.topology.molecule.Atom, - offPELE.topology.molecule.DummyAtom)), \ - 'Wrong type: {}'.format(type(atom)) - - super().__init__(atom.index, atom.core, atom.OPLS_type, atom.PDB_name, - atom.unknown, atom.x, atom.y, atom.z, atom.sigma, - atom.epsilon, atom.charge, atom.born_radius, - atom.SASA_radius, atom.nonpolar_gamma, - atom.nonpolar_alpha, atom.parent) - +class WritableWrapper(object): + @staticmethod def none_to_zero(f): def function_wrapper(*args, **kwargs): out = f(*args, **kwargs) @@ -123,6 +238,7 @@ def function_wrapper(*args, **kwargs): return out return function_wrapper + @staticmethod def dummy_to_writable(f): def function_wrapper(*args, **kwargs): out = f(*args, **kwargs) @@ -130,6 +246,7 @@ def function_wrapper(*args, **kwargs): return out return function_wrapper + @staticmethod def none_to_dummy(f): def function_wrapper(*args, **kwargs): out = f(*args, **kwargs) @@ -138,9 +255,46 @@ def function_wrapper(*args, **kwargs): return out return function_wrapper + @staticmethod + def in_angstrom(f): + def function_wrapper(*args, **kwargs): + out = f(*args, **kwargs) + return out.value_in_unit(unit.angstrom) + return function_wrapper + + @staticmethod + def in_kcalmol(f): + def function_wrapper(*args, **kwargs): + out = f(*args, **kwargs) + return out.value_in_unit(unit.kilocalorie / unit.mole) + return function_wrapper + + @staticmethod + def in_elementarycharge(f): + def function_wrapper(*args, **kwargs): + out = f(*args, **kwargs) + return out.value_in_unit(unit.elementary_charge) + return function_wrapper + + +class WritableAtom(offPELE.topology.molecule.Atom, WritableWrapper): + def __init__(self, atom): + # We do not want to modify the original object + atom = deepcopy(atom) + + assert isinstance(atom, (offPELE.topology.molecule.Atom, + offPELE.topology.molecule.DummyAtom)), \ + 'Wrong type: {}'.format(type(atom)) + + super().__init__(atom.index, atom.core, atom.OPLS_type, atom.PDB_name, + atom.unknown, atom.x, atom.y, atom.z, atom.sigma, + atom.epsilon, atom.charge, atom.born_radius, + atom.SASA_radius, atom.nonpolar_gamma, + atom.nonpolar_alpha, atom.parent) + @property - @dummy_to_writable - @none_to_dummy + @WritableWrapper.dummy_to_writable + @WritableWrapper.none_to_dummy def parent(self): return super().parent @@ -163,6 +317,169 @@ def OPLS_type(self): # TODO Review the actual purpose of this attribute in PELE @property - @none_to_zero + @WritableWrapper.none_to_zero def unknown(self): return super().unknown + + @property + @WritableWrapper.in_angstrom + def sigma(self): + return super().sigma + + @property + @WritableWrapper.in_kcalmol + def epsilon(self): + return super().epsilon + + @property + @WritableWrapper.in_elementarycharge + def charge(self): + return super().charge + + @property + @WritableWrapper.none_to_zero + def born_radius(self): + return super().born_radius + + @property + @WritableWrapper.none_to_zero + def SASA_radius(self): + return super().SASA_radius + + @property + @WritableWrapper.none_to_zero + def nonpolar_gamma(self): + return super().nonpolar_gamma + + @property + @WritableWrapper.none_to_zero + def nonpolar_alpha(self): + return super().nonpolar_alpha + + +class WritableBond(offPELE.topology.Bond, WritableWrapper): + def __init__(self, bond): + # We do not want to modify the original object + bond = deepcopy(bond) + + assert isinstance(bond, (offPELE.topology.Bond, + offPELE.topology.topology.Bond)), \ + 'Wrong type: {}'.format(type(bond)) + + super().__init__(index=bond.index, atom1_idx=bond.atom1_idx, + atom2_idx=bond.atom2_idx, + spring_constant=bond.spring_constant, + eq_dist=bond.eq_dist) + + @property + def atom1_idx(self): + return super().atom1_idx + 1 + + @property + def atom2_idx(self): + return super().atom2_idx + 1 + + +class WritableAngle(offPELE.topology.Angle, WritableWrapper): + def __init__(self, angle): + # We do not want to modify the original object + angle = deepcopy(angle) + + assert isinstance(angle, (offPELE.topology.Angle, + offPELE.topology.topology.Angle)), \ + 'Wrong type: {}'.format(type(angle)) + + super().__init__(index=angle.index, atom1_idx=angle.atom1_idx, + atom2_idx=angle.atom2_idx, atom3_idx=angle.atom3_idx, + spring_constant=angle.spring_constant, + eq_angle=angle.eq_angle) + + @property + def atom1_idx(self): + return super().atom1_idx + 1 + + @property + def atom2_idx(self): + return super().atom2_idx + 1 + + @property + def atom3_idx(self): + return super().atom3_idx + 1 + + +class WritableProper(offPELE.topology.Proper, WritableWrapper): + def __init__(self, proper): + # We do not want to modify the original object + proper = deepcopy(proper) + + assert isinstance(proper, (offPELE.topology.Proper, + offPELE.topology.topology.Proper)), \ + 'Wrong type: {}'.format(type(proper)) + + super().__init__(index=proper.index, atom1_idx=proper.atom1_idx, + atom2_idx=proper.atom2_idx, + atom3_idx=proper.atom3_idx, + atom4_idx=proper.atom4_idx, + periodicity=proper.periodicity, + prefactor=proper.prefactor, + constant=proper.constant) + + @property + def atom1_idx(self): + return super().atom1_idx + 1 + + @property + def atom2_idx(self): + return super().atom2_idx + 1 + + @property + def atom3_idx(self): + return super().atom3_idx + 1 + + @property + def atom4_idx(self): + return super().atom4_idx + 1 + + @property + @WritableWrapper.in_kcalmol + def constant(self): + return super().constant + + +class WritableImproper(offPELE.topology.Improper, WritableWrapper): + def __init__(self, improper): + # We do not want to modify the original object + improper = deepcopy(improper) + + assert isinstance(improper, (offPELE.topology.Improper, + offPELE.topology.topology.Improper)), \ + 'Wrong type: {}'.format(type(improper)) + + super().__init__(index=improper.index, atom1_idx=improper.atom1_idx, + atom2_idx=improper.atom2_idx, + atom3_idx=improper.atom3_idx, + atom4_idx=improper.atom4_idx, + periodicity=improper.periodicity, + prefactor=improper.prefactor, + constant=improper.constant) + + @property + def atom1_idx(self): + return super().atom1_idx + 1 + + @property + def atom2_idx(self): + return super().atom2_idx + 1 + + @property + def atom3_idx(self): + return super().atom3_idx + 1 + + @property + def atom4_idx(self): + return super().atom4_idx + 1 + + @property + @WritableWrapper.in_kcalmol + def constant(self): + return super().constant diff --git a/offPELE/topology/__init__.py b/offPELE/topology/__init__.py index fcb0e2e0..f6e06276 100644 --- a/offPELE/topology/__init__.py +++ b/offPELE/topology/__init__.py @@ -1,3 +1,3 @@ -from .topology import * +from .topology import Bond, Angle, Proper, Improper from .molecule import Molecule from .zmatrix import ZMatrix diff --git a/offPELE/topology/topology.py b/offPELE/topology/topology.py index c47e9029..a01a25e8 100644 --- a/offPELE/topology/topology.py +++ b/offPELE/topology/topology.py @@ -51,11 +51,31 @@ class Bond(TopologyElement): def __init__(self, index=-1, atom1_idx=None, atom2_idx=None, spring_constant=None, eq_dist=None): - self.index = index - self.atom1_idx = atom1_idx - self.atom2_idx = atom2_idx - self.spring_constant = spring_constant - self.eq_dist = eq_dist + self._index = index + self._atom1_idx = atom1_idx + self._atom2_idx = atom2_idx + self._spring_constant = spring_constant + self._eq_dist = eq_dist + + @property + def index(self): + return self._index + + @property + def atom1_idx(self): + return self._atom1_idx + + @property + def atom2_idx(self): + return self._atom2_idx + + @property + def spring_constant(self): + return self._spring_constant + + @property + def eq_dist(self): + return self._eq_dist class Angle(TopologyElement): @@ -65,30 +85,54 @@ class Angle(TopologyElement): def __init__(self, index=-1, atom1_idx=None, atom2_idx=None, atom3_idx=None, spring_constant=None, eq_angle=None): - self.index = index - self.atom1_idx = atom1_idx - self.atom2_idx = atom2_idx - self.atom3_idx = atom3_idx - self.spring_constant = spring_constant - self.eq_angle = eq_angle + self._index = index + self._atom1_idx = atom1_idx + self._atom2_idx = atom2_idx + self._atom3_idx = atom3_idx + self._spring_constant = spring_constant + self._eq_angle = eq_angle + + @property + def index(self): + return self._index + + @property + def atom1_idx(self): + return self._atom1_idx + + @property + def atom2_idx(self): + return self._atom2_idx + + @property + def atom3_idx(self): + return self._atom3_idx + + @property + def spring_constant(self): + return self._spring_constant + + @property + def eq_angle(self): + return self._eq_angle class Dihedral(TopologyElement): _name = 'Dihedral' _writable_attrs = ['atom1_idx', 'atom2_idx', 'atom3_idx', 'atom4_idx', - 'periodicity', 'prefactor', 'constant'] + 'constant', 'prefactor', 'periodicity'] def __init__(self, index=-1, atom1_idx=None, atom2_idx=None, atom3_idx=None, atom4_idx=None, periodicity=None, prefactor=None, constant=None): - self.index = index - self.atom1_idx = atom1_idx - self.atom2_idx = atom2_idx - self.atom3_idx = atom3_idx - self.atom4_idx = atom4_idx - self.periodicity = periodicity - self.prefactor = prefactor - self.constant = constant + self._index = index + self._atom1_idx = atom1_idx + self._atom2_idx = atom2_idx + self._atom3_idx = atom3_idx + self._atom4_idx = atom4_idx + self._periodicity = periodicity + self._prefactor = prefactor + self._constant = constant def plot(self): from matplotlib import pyplot @@ -101,6 +145,38 @@ def plot(self): pyplot.show() + @property + def index(self): + return self._index + + @property + def atom1_idx(self): + return self._atom1_idx + + @property + def atom2_idx(self): + return self._atom2_idx + + @property + def atom3_idx(self): + return self._atom3_idx + + @property + def atom4_idx(self): + return self._atom4_idx + + @property + def periodicity(self): + return self._periodicity + + @property + def prefactor(self): + return self._prefactor + + @property + def constant(self): + return self._constant + class Proper(Dihedral): _name = 'Proper' From 89f77da0b8c4e2ab8bb85f759f11c39ec68ac89f Mon Sep 17 00:00:00 2001 From: Marti Municoy Date: Fri, 26 Jun 2020 16:36:01 +0200 Subject: [PATCH 21/67] Sort atoms according to core and parent.index attributes --- offPELE/template/impact.py | 100 +++++++++++++++++++++++++++++++---- offPELE/topology/molecule.py | 3 ++ offPELE/topology/topology.py | 27 ++++++++++ 3 files changed, 120 insertions(+), 10 deletions(-) diff --git a/offPELE/template/impact.py b/offPELE/template/impact.py index e159fb9d..c103db4a 100644 --- a/offPELE/template/impact.py +++ b/offPELE/template/impact.py @@ -17,7 +17,48 @@ def __init__(self, molecule): raise Exception('Invalid input molecule for Impact template') def _initialize_from_molecule(self, molecule): - self._molecule = molecule + # We will work with a copy to prevent the modification of the original + # object + self._molecule = deepcopy(molecule) + self._sort() + + def _sort(self): + sorted_atoms = list() + + # Sort by core attribute and parent index + for atom in sorted(self.molecule.atoms, + key=lambda a: (WritableAtom(a).core, + WritableAtom(a).parent.index)): + sorted_atoms.append(atom) + + # Define reindexer and reindex atoms + reindexer = dict() + for new_index, atom in enumerate(sorted_atoms): + old_index = atom._index + reindexer[old_index] = new_index + atom.set_index(new_index) + + # Replace old atom list by the sorted one + self.molecule._atoms = sorted_atoms + + # Reindex bonds, angles, propers and impropers + for bond in self.molecule.bonds: + bond.set_atom1_idx(reindexer[bond.atom1_idx]) + bond.set_atom2_idx(reindexer[bond.atom2_idx]) + for angle in self.molecule.angles: + angle.set_atom1_idx(reindexer[angle.atom1_idx]) + angle.set_atom2_idx(reindexer[angle.atom2_idx]) + angle.set_atom3_idx(reindexer[angle.atom3_idx]) + for proper in self.molecule.propers: + proper.set_atom1_idx(reindexer[proper.atom1_idx]) + proper.set_atom2_idx(reindexer[proper.atom2_idx]) + proper.set_atom3_idx(reindexer[proper.atom3_idx]) + proper.set_atom4_idx(reindexer[proper.atom4_idx]) + for improper in self.molecule.impropers: + improper.set_atom1_idx(reindexer[improper.atom1_idx]) + improper.set_atom2_idx(reindexer[improper.atom2_idx]) + improper.set_atom3_idx(reindexer[improper.atom3_idx]) + improper.set_atom4_idx(reindexer[improper.atom4_idx]) def write(self, path): with open(path, 'w') as file: @@ -129,12 +170,10 @@ def _write_bond(self, file): file.write('{:5d}'.format(idx2)) file.write(' ') # Spring constant - file.write('{: 9.3f}'.format(spring.value_in_unit( - unit.kilocalorie / (unit.angstrom**2 * unit.mole)))) + file.write('{: 9.3f}'.format(spring)) file.write(' ') # Equilibrium distance - file.write('{: 6.3f}\n'.format(eq_dist.value_in_unit( - unit.angstrom))) + file.write('{: 6.3f}\n'.format(eq_dist)) def _write_thet(self, file): file.write('THET\n') @@ -155,11 +194,9 @@ def _write_thet(self, file): file.write('{:5d}'.format(idx3)) file.write(' ') # Spring constant - file.write('{: 11.5f}'.format(spring.value_in_unit( - unit.kilocalorie / (unit.degree**2 * unit.mole)))) + file.write('{: 11.5f}'.format(spring)) # Equilibrium angle - file.write('{: 11.5f}\n'.format(eq_angl.value_in_unit( - unit.degree))) + file.write('{: 11.5f}\n'.format(eq_angl)) def _write_phi(self, file): file.write('PHI\n') @@ -223,7 +260,7 @@ def _write_iphi(self, file): def _write_end(self, file): file.write('END\n') - @ property + @property def molecule(self): return self._molecule @@ -276,6 +313,29 @@ def function_wrapper(*args, **kwargs): return out.value_in_unit(unit.elementary_charge) return function_wrapper + @staticmethod + def in_kcal_deg2mol(f): + def function_wrapper(*args, **kwargs): + out = f(*args, **kwargs) + return out.value_in_unit(unit.kilocalorie + / (unit.degree**2 * unit.mole)) + return function_wrapper + + @staticmethod + def in_deg(f): + def function_wrapper(*args, **kwargs): + out = f(*args, **kwargs) + return out.value_in_unit(unit.degree) + return function_wrapper + + @staticmethod + def in_kcal_angstrom2mol(f): + def function_wrapper(*args, **kwargs): + out = f(*args, **kwargs) + return out.value_in_unit(unit.kilocalorie + / (unit.angstrom**2 * unit.mole)) + return function_wrapper + class WritableAtom(offPELE.topology.molecule.Atom, WritableWrapper): def __init__(self, atom): @@ -379,6 +439,16 @@ def atom1_idx(self): def atom2_idx(self): return super().atom2_idx + 1 + @property + @WritableWrapper.in_kcal_angstrom2mol + def spring_constant(self): + return super().spring_constant + + @property + @WritableWrapper.in_angstrom + def eq_dist(self): + return super().eq_dist + class WritableAngle(offPELE.topology.Angle, WritableWrapper): def __init__(self, angle): @@ -406,6 +476,16 @@ def atom2_idx(self): def atom3_idx(self): return super().atom3_idx + 1 + @property + @WritableWrapper.in_kcal_deg2mol + def spring_constant(self): + return super().spring_constant + + @property + @WritableWrapper.in_deg + def eq_angle(self): + return super().eq_angle + class WritableProper(offPELE.topology.Proper, WritableWrapper): def __init__(self, proper): diff --git a/offPELE/topology/molecule.py b/offPELE/topology/molecule.py index 40ec9dd0..3b4ee694 100644 --- a/offPELE/topology/molecule.py +++ b/offPELE/topology/molecule.py @@ -35,6 +35,9 @@ def __init__(self, index=-1, core=None, OPLS_type=None, PDB_name=None, self._nonpolar_alpha = nonpolar_alpha # SGB Non Polar type self._parent = parent + def set_index(self, index): + self._index = index + def set_as_core(self): self._core = True diff --git a/offPELE/topology/topology.py b/offPELE/topology/topology.py index a01a25e8..610d6a0c 100644 --- a/offPELE/topology/topology.py +++ b/offPELE/topology/topology.py @@ -57,6 +57,12 @@ def __init__(self, index=-1, atom1_idx=None, atom2_idx=None, self._spring_constant = spring_constant self._eq_dist = eq_dist + def set_atom1_idx(self, index): + self._atom1_idx = index + + def set_atom2_idx(self, index): + self._atom2_idx = index + @property def index(self): return self._index @@ -92,6 +98,15 @@ def __init__(self, index=-1, atom1_idx=None, atom2_idx=None, self._spring_constant = spring_constant self._eq_angle = eq_angle + def set_atom1_idx(self, index): + self._atom1_idx = index + + def set_atom2_idx(self, index): + self._atom2_idx = index + + def set_atom3_idx(self, index): + self._atom3_idx = index + @property def index(self): return self._index @@ -134,6 +149,18 @@ def __init__(self, index=-1, atom1_idx=None, atom2_idx=None, self._prefactor = prefactor self._constant = constant + def set_atom1_idx(self, index): + self._atom1_idx = index + + def set_atom2_idx(self, index): + self._atom2_idx = index + + def set_atom3_idx(self, index): + self._atom3_idx = index + + def set_atom4_idx(self, index): + self._atom4_idx = index + def plot(self): from matplotlib import pyplot import numpy as np From e6f4342b741619569635fc35fed16728735d0b96 Mon Sep 17 00:00:00 2001 From: Marti Municoy Date: Fri, 26 Jun 2020 17:14:05 +0200 Subject: [PATCH 22/67] Sigma conversion is fixed and SASA radius is defined from sigma --- offPELE/template/impact.py | 2 +- offPELE/topology/molecule.py | 7 +++++-- offPELE/utils/toolkits.py | 4 ++-- 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/offPELE/template/impact.py b/offPELE/template/impact.py index c103db4a..9e9f1885 100644 --- a/offPELE/template/impact.py +++ b/offPELE/template/impact.py @@ -402,7 +402,7 @@ def born_radius(self): return super().born_radius @property - @WritableWrapper.none_to_zero + @WritableWrapper.in_angstrom def SASA_radius(self): return super().SASA_radius diff --git a/offPELE/topology/molecule.py b/offPELE/topology/molecule.py index 3b4ee694..0cb8902f 100644 --- a/offPELE/topology/molecule.py +++ b/offPELE/topology/molecule.py @@ -519,8 +519,11 @@ def _build_atoms(self): # TODO Find a way to assign implicit solvent parameters to atoms with OFF born_radii = {i: None for i in self.parameters.get_vdW_parameters().keys()} - SASA_radii = {i: None - for i in self.parameters.get_vdW_parameters().keys()} + + # TODO Doublecheck this relation + SASA_radii = {i: j / 2.0 for i, j in sigmas.items()} + + # TODO Find a way to assign implicit solvent parameters to atoms with OFF nonpolar_gammas = {i: None for i in self.parameters.get_vdW_parameters().keys()} nonpolar_alphas = {i: None for i in diff --git a/offPELE/utils/toolkits.py b/offPELE/utils/toolkits.py index aebef016..c0475a5f 100644 --- a/offPELE/utils/toolkits.py +++ b/offPELE/utils/toolkits.py @@ -263,14 +263,14 @@ def sigmas_from_rmin_halves(func): Convert rmin_half values to sigmas according to: http://ambermd.org/Questions/vdwequation.pdf """ - FACTOR = 1.122462048309373 # The sixth root of 2 + FACTOR = 0.8908987181403393 # The inverse of the sixth root of 2 def function_wrapper(x): rmin_halves = func(x) sigmas = dict() for indexes, rmin_half in rmin_halves.items(): - sigma = FACTOR * rmin_half + sigma = FACTOR * 2 * rmin_half sigmas[indexes] = sigma return sigmas From fb65a24725b175616cadc12e71b9e2ea5047cc13 Mon Sep 17 00:00:00 2001 From: Marti Municoy Date: Fri, 26 Jun 2020 17:45:59 +0200 Subject: [PATCH 23/67] Add Parameterize notebook to repo --- offPELE/examples/Parameterize.ipynb | 253 ++++++++++++++++++++++++++++ 1 file changed, 253 insertions(+) create mode 100644 offPELE/examples/Parameterize.ipynb diff --git a/offPELE/examples/Parameterize.ipynb b/offPELE/examples/Parameterize.ipynb new file mode 100644 index 00000000..acf4a6ce --- /dev/null +++ b/offPELE/examples/Parameterize.ipynb @@ -0,0 +1,253 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [], + "source": [ + "import offPELE.topology.molecule as mol\n", + "from offPELE.template import Impact" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + " - Loading molecule from RDKit\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "Warning: Unable to load toolkit 'OpenEye Toolkit'. The Open Force Field Toolkit does not require the OpenEye Toolkits, and can use RDKit/AmberTools instead. However, if you have a valid license for the OpenEye Toolkits, consider installing them for faster performance and additional file format support: https://docs.eyesopen.com/toolkits/python/quickstart-python/linuxosx.html OpenEye offers free Toolkit licenses for academics: https://www.eyesopen.com/academic-licensing\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + " - Loading forcefield\n", + " - Computing partial charges with am1bcc\n", + " - Generating rotamer library\n" + ] + } + ], + "source": [ + "NAME = 'BNZ'\n", + "EXTENSION = '.pdb'\n", + "FORCEFIELD = 'openff_unconstrained-1.1.1.offxml' \n", + "\n", + "molecule = mol.Molecule('../data/ligands/' + NAME.upper() + EXTENSION)\n", + "molecule.parameterize(FORCEFIELD)\n", + "molecule.build_rotamer_library(resolution=30)\n", + "molecule.rotamer_library.to_file('../data/templates/' + NAME.upper() + '.rot.assign')\n", + "impact = Impact(molecule)\n", + "impact.write('../data/templates/' + NAME.lower() + 'z')" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": { + "scrolled": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + " - Loading molecule from RDKit\n", + " - Loading forcefield\n", + " - Computing partial charges with am1bcc\n", + " - Generating rotamer library\n" + ] + } + ], + "source": [ + "NAME = 'TOL'\n", + "EXTENSION = '.pdb'\n", + "FORCEFIELD = 'openff_unconstrained-1.1.1.offxml' \n", + "\n", + "molecule = mol.Molecule('../data/ligands/' + NAME.upper() + EXTENSION)\n", + "molecule.parameterize(FORCEFIELD)\n", + "molecule.build_rotamer_library(resolution=30)\n", + "molecule.rotamer_library.to_file('../data/templates/' + NAME.upper() + '.rot.assign')\n", + "impact = Impact(molecule)\n", + "impact.write('../data/templates/' + NAME.lower() + 'z')" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + " - Loading molecule from RDKit\n", + " - Loading forcefield\n", + " - Computing partial charges with am1bcc\n", + " - Generating rotamer library\n" + ] + } + ], + "source": [ + "NAME = 'OLC'\n", + "EXTENSION = '.pdb'\n", + "FORCEFIELD = 'openff_unconstrained-1.1.1.offxml' \n", + "\n", + "molecule = mol.Molecule('../data/ligands/' + NAME.upper() + EXTENSION)\n", + "molecule.parameterize(FORCEFIELD)\n", + "molecule.build_rotamer_library(resolution=30)\n", + "molecule.rotamer_library.to_file('../data/templates/' + NAME.upper() + '.rot.assign')\n", + "impact = Impact(molecule)\n", + "impact.write('../data/templates/' + NAME.lower() + 'z')" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + " - Loading molecule from RDKit\n", + " - Loading forcefield\n", + " - Computing partial charges with am1bcc\n", + " - Generating rotamer library\n" + ] + } + ], + "source": [ + "NAME = 'BIA'\n", + "EXTENSION = '.pdb'\n", + "FORCEFIELD = 'openff_unconstrained-1.1.1.offxml' \n", + "\n", + "molecule = mol.Molecule('../data/ligands/' + NAME.upper() + EXTENSION)\n", + "molecule.parameterize(FORCEFIELD)\n", + "molecule.build_rotamer_library(resolution=30)\n", + "molecule.rotamer_library.to_file('../data/templates/' + NAME.upper() + '.rot.assign')\n", + "impact = Impact(molecule)\n", + "impact.write('../data/templates/' + NAME.lower() + 'z')" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + " - Loading molecule from RDKit\n", + " - Loading forcefield\n", + " - Computing partial charges with am1bcc\n", + " - Generating rotamer library\n" + ] + } + ], + "source": [ + "NAME = 'LG1'\n", + "EXTENSION = '.pdb'\n", + "FORCEFIELD = 'openff_unconstrained-1.1.1.offxml' \n", + "\n", + "molecule = mol.Molecule('../data/ligands/' + NAME.upper() + EXTENSION)\n", + "molecule.parameterize(FORCEFIELD)\n", + "molecule.build_rotamer_library(resolution=30)\n", + "molecule.rotamer_library.to_file('../data/templates/' + NAME.upper() + '.rot.assign')\n", + "impact = Impact(molecule)\n", + "impact.write('../data/templates/' + NAME.lower() + 'z')" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + " - Loading molecule from RDKit\n", + " - Loading forcefield\n", + " - Computing partial charges with am1bcc\n", + " - Generating rotamer library\n" + ] + } + ], + "source": [ + "NAME = 'MDB'\n", + "EXTENSION = '.pdb'\n", + "FORCEFIELD = 'openff_unconstrained-1.1.1.offxml' \n", + "\n", + "molecule = mol.Molecule('../data/ligands/' + NAME.upper() + EXTENSION)\n", + "molecule.parameterize(FORCEFIELD)\n", + "molecule.build_rotamer_library(resolution=30)\n", + "molecule.rotamer_library.to_file('../data/templates/' + NAME.upper() + '.rot.assign')\n", + "impact = Impact(molecule)\n", + "impact.write('../data/templates/' + NAME.lower() + 'z')" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + " - Loading molecule from RDKit\n", + " - Loading forcefield\n", + " - Computing partial charges with am1bcc\n", + " - Generating rotamer library\n" + ] + } + ], + "source": [ + "NAME = 'SBN'\n", + "EXTENSION = '.pdb'\n", + "FORCEFIELD = 'openff_unconstrained-1.1.1.offxml' \n", + "\n", + "molecule = mol.Molecule('../data/ligands/' + NAME.upper() + EXTENSION)\n", + "molecule.parameterize(FORCEFIELD)\n", + "molecule.build_rotamer_library(resolution=30)\n", + "molecule.rotamer_library.to_file('../data/templates/' + NAME.upper() + '.rot.assign')\n", + "impact = Impact(molecule)\n", + "impact.write('../data/templates/' + NAME.lower() + 'z')" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.7.4" + } + }, + "nbformat": 4, + "nbformat_minor": 4 +} From 06b504c7d6efb3434a2384989dda67986b6e618a Mon Sep 17 00:00:00 2001 From: Marti Municoy Date: Fri, 26 Jun 2020 17:55:58 +0200 Subject: [PATCH 24/67] Wrong OFF-PELE parameter-conversions are fixed --- offPELE/template/impact.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/offPELE/template/impact.py b/offPELE/template/impact.py index 9e9f1885..68619567 100644 --- a/offPELE/template/impact.py +++ b/offPELE/template/impact.py @@ -169,8 +169,8 @@ def _write_bond(self, file): # Atom 2 id file.write('{:5d}'.format(idx2)) file.write(' ') - # Spring constant - file.write('{: 9.3f}'.format(spring)) + # Spring constant (PELE works with half of the OFF's spring) + file.write('{: 9.3f}'.format(spring / 2.0)) file.write(' ') # Equilibrium distance file.write('{: 6.3f}\n'.format(eq_dist)) @@ -193,8 +193,8 @@ def _write_thet(self, file): # Atom 3 id file.write('{:5d}'.format(idx3)) file.write(' ') - # Spring constant - file.write('{: 11.5f}'.format(spring)) + # Spring constant (PELE works with half of the OFF's spring) + file.write('{: 11.5f}'.format(spring / 2.0)) # Equilibrium angle file.write('{: 11.5f}\n'.format(eq_angl)) @@ -314,11 +314,11 @@ def function_wrapper(*args, **kwargs): return function_wrapper @staticmethod - def in_kcal_deg2mol(f): + def in_kcal_rad2mol(f): def function_wrapper(*args, **kwargs): out = f(*args, **kwargs) return out.value_in_unit(unit.kilocalorie - / (unit.degree**2 * unit.mole)) + / (unit.radian**2 * unit.mole)) return function_wrapper @staticmethod @@ -477,7 +477,7 @@ def atom3_idx(self): return super().atom3_idx + 1 @property - @WritableWrapper.in_kcal_deg2mol + @WritableWrapper.in_kcal_rad2mol def spring_constant(self): return super().spring_constant From 8c1b72d141dc175d7ce6087e472489312e5991d0 Mon Sep 17 00:00:00 2001 From: Marti Municoy Date: Mon, 29 Jun 2020 18:10:06 +0200 Subject: [PATCH 25/67] New solvent class to parameterize implicit solvent --- offPELE/solvent/__init__.py | 1 + offPELE/solvent/solvent.py | 122 +++++++++++++++++++++++++++++++++++ offPELE/topology/molecule.py | 2 +- offPELE/utils/toolkits.py | 84 ++++++++++++++++-------- 4 files changed, 180 insertions(+), 29 deletions(-) create mode 100644 offPELE/solvent/__init__.py create mode 100644 offPELE/solvent/solvent.py diff --git a/offPELE/solvent/__init__.py b/offPELE/solvent/__init__.py new file mode 100644 index 00000000..c5ba5def --- /dev/null +++ b/offPELE/solvent/__init__.py @@ -0,0 +1 @@ +from .solvent import * diff --git a/offPELE/solvent/solvent.py b/offPELE/solvent/solvent.py new file mode 100644 index 00000000..7d17575e --- /dev/null +++ b/offPELE/solvent/solvent.py @@ -0,0 +1,122 @@ +import numpy as np +from simtk import unit + +from offPELE.utils import get_data_file_path +from offPELE.utils.toolkits import OpenForceFieldToolkitWrapper + + +class _SolventWrapper(object): + _ff_file = None + _name = None + + def __init__(self, molecule): + self._molecule = molecule + self._radii = np.zeros(len(self.molecule.atoms)) + self._scales = np.zeros(len(self.molecule.atoms)) + self._solvent_dielectric = float(0) + self._solute_dielectric = float(0) + self._surface_area_penalty = float(0) + self._solvent_radius = float(0) + self._initialize_from_molecule() + + def _initialize_from_molecule(self): + off_toolkit = OpenForceFieldToolkitWrapper() + + GBSA_handler = off_toolkit.get_parameter_handler_from_forcefield( + 'GBSA', self._ff_file) + + self._solvent_dielectric = GBSA_handler.solvent_dielectric + self._solute_dielectric = GBSA_handler.solute_dielectric + self._surface_area_penalty = GBSA_handler.surface_area_penalty + self._solvent_radius = GBSA_handler.solvent_radius + + parameters = off_toolkit.get_parameters_from_forcefield( + self._ff_file, self.molecule) + + self._radii = parameters.get_GBSA_radii() + self._scales = parameters.get_GBSA_scales() + + def to_dict(self): + data = dict() + data['SolventParameters'] = dict() + data['SolventParameters']['Name'] = self.name + data['SolventParameters']['General'] = dict() + data['SolventParameters']['General']['solvent_dielectric'] = \ + round(self.solvent_dielectric, 5) + data['SolventParameters']['General']['solute_dielectric'] = \ + round(self.solute_dielectric, 5) + data['SolventParameters']['General']['solvent_radius'] = \ + round(self.solvent_radius.value_in_unit(unit.angstrom), 5) + data['SolventParameters']['General']['surface_area_penalty'] = \ + round(self.surface_area_penalty.value_in_unit( + unit.kilocalorie / (unit.angstrom**2 * unit.mole)), 8) + data['SolventParameters'][self.molecule.name] = dict() + for atom in self.molecule.rdkit_molecule.GetAtoms(): + pdb_info = atom.GetPDBResidueInfo() + name = pdb_info.GetName().replace(' ', '_') + index = atom.GetIdx() + data['SolventParameters'][self.molecule.name][name] = \ + {'radius': round(self.radii[tuple((index, ))].value_in_unit( + unit.angstrom), 5), + 'scale': round(self.scales[tuple((index, ))], 5)} + + return data + + def to_json_file(self, path): + import json + with open(path, 'w') as file: + json.dump(self.to_dict(), file, indent=4) + + @property + def name(self): + return self._name + + @property + def molecule(self): + return self._molecule + + @property + def radii(self): + return self._radii + + @property + def scales(self): + return self._scales + + @property + def solvent_dielectric(self): + return self._solvent_dielectric + + @property + def solute_dielectric(self): + return self._solute_dielectric + + @property + def surface_area_penalty(self): + return self._surface_area_penalty + + @property + def solvent_radius(self): + return self._solvent_radius + + +class OBC1(_SolventWrapper): + _ff_file = get_data_file_path('forcefields/GBSA_OBC1-1.0.offxml') + _name = 'OBC1' + + def __init__(self, molecule): + super().__init__(molecule) + + def _initialize_from_molecule(self): + super()._initialize_from_molecule() + + +class OBC2(_SolventWrapper): + _ff_file = get_data_file_path('forcefields/GBSA_OBC1-1.0.offxml') + _name = 'OBC2' + + def __init__(self, molecule): + super().__init__(molecule) + + def _initialize_from_molecule(self): + super()._initialize_from_molecule() diff --git a/offPELE/topology/molecule.py b/offPELE/topology/molecule.py index 0cb8902f..45ace912 100644 --- a/offPELE/topology/molecule.py +++ b/offPELE/topology/molecule.py @@ -520,7 +520,7 @@ def _build_atoms(self): born_radii = {i: None for i in self.parameters.get_vdW_parameters().keys()} - # TODO Doublecheck this relation + # TODO Doublecheck later this relation SASA_radii = {i: j / 2.0 for i, j in sigmas.items()} # TODO Find a way to assign implicit solvent parameters to atoms with OFF diff --git a/offPELE/utils/toolkits.py b/offPELE/utils/toolkits.py index c0475a5f..fa518b74 100644 --- a/offPELE/utils/toolkits.py +++ b/offPELE/utils/toolkits.py @@ -253,6 +253,19 @@ def get_parameters_from_forcefield(self, forcefield, molecule): 'expected' return self.OpenForceFieldParameters(molecule_parameters_list[0]) + def get_parameter_handler_from_forcefield(self, parameter_handler_name, + forcefield): + from openforcefield.typing.engines.smirnoff import ForceField + + if isinstance(forcefield, str): + forcefield = ForceField(forcefield) + elif isinstance(forcefield, ForceField): + pass + else: + raise Exception('Invalid forcefield type') + + return forcefield.get_parameter_handler(parameter_handler_name) + class OpenForceFieldParameters(dict): def __init__(self, parameters_list): for key, value in parameters_list.items(): @@ -289,38 +302,40 @@ def __str__(self): return output def _build_dict(self, parameters, attribute_name): - value_by_index = dict() - for index, parameter in parameters.items(): - value_by_index[index] = getattr(parameter, attribute_name) + if parameters: + value_by_index = dict() + for index, parameter in parameters.items(): + value_by_index[index] = getattr(parameter, attribute_name) - return value_by_index + return value_by_index def _build_dynamic_dicts(self, parameters, attr_core_name): - parameters_by_index = defaultdict(dict) - all_attr_ids_found = set() - for index, parameter in parameters.items(): - counter = int(1) - attr_name = attr_core_name + str(counter) - while(attr_name in parameter.to_dict()): - all_attr_ids_found.add(counter) - attr_value = getattr(parameter, attr_name) - parameters_by_index[index][counter] = attr_value - counter += 1 + if parameters: + parameters_by_index = defaultdict(dict) + all_attr_ids_found = set() + for index, parameter in parameters.items(): + counter = int(1) attr_name = attr_core_name + str(counter) - - output_list = list() - for attr_id in sorted(all_attr_ids_found): - value_by_index = dict() - for index in parameters.keys(): - if attr_id in parameters_by_index[index]: - value_by_index[index] = \ - parameters_by_index[index][attr_id] - else: - value_by_index[index] = None - - output_list.append(value_by_index) - - return output_list + while(attr_name in parameter.to_dict()): + all_attr_ids_found.add(counter) + attr_value = getattr(parameter, attr_name) + parameters_by_index[index][counter] = attr_value + counter += 1 + attr_name = attr_core_name + str(counter) + + output_list = list() + for attr_id in sorted(all_attr_ids_found): + value_by_index = dict() + for index in parameters.keys(): + if attr_id in parameters_by_index[index]: + value_by_index[index] = \ + parameters_by_index[index][attr_id] + else: + value_by_index[index] = None + + output_list.append(value_by_index) + + return output_list # Van der Waals parameters def get_vdW_parameters(self): @@ -410,3 +425,16 @@ def get_improper_ks(self): def get_improper_idivfs(self): parameters = self.get_improper_parameters() return self._build_dynamic_dicts(parameters, 'idivf') + + # GBSA solvent parameters + def get_GBSA_parameters(self): + if 'GBSA' in self: + return self['GBSA'] + + def get_GBSA_radii(self): + parameters = self.get_GBSA_parameters() + return self._build_dict(parameters, 'radius') + + def get_GBSA_scales(self): + parameters = self.get_GBSA_parameters() + return self._build_dict(parameters, 'scale') From c2081a3472a5cb21b74c29306cc017520fb956d9 Mon Sep 17 00:00:00 2001 From: Marti Municoy Date: Mon, 29 Jun 2020 19:24:05 +0200 Subject: [PATCH 26/67] Warning on one line --- offPELE/utils/utils.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/offPELE/utils/utils.py b/offPELE/utils/utils.py index 2bac787f..f8ee6b0f 100644 --- a/offPELE/utils/utils.py +++ b/offPELE/utils/utils.py @@ -24,3 +24,7 @@ def temporary_cd(path): yield finally: os.chdir(old_path) + + +def warning_on_one_line(message, category, filename, lineno, file=None, line=None): + return ' %s:%s: %s:%s' % (filename, lineno, category.__name__, message) From 84f7b87c60ab51424888f787a62f2c251892a3c0 Mon Sep 17 00:00:00 2001 From: Marti Municoy Date: Mon, 29 Jun 2020 19:24:23 +0200 Subject: [PATCH 27/67] OBC1 warning --- offPELE/solvent/solvent.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/offPELE/solvent/solvent.py b/offPELE/solvent/solvent.py index 7d17575e..c9d899b9 100644 --- a/offPELE/solvent/solvent.py +++ b/offPELE/solvent/solvent.py @@ -1,7 +1,7 @@ import numpy as np from simtk import unit -from offPELE.utils import get_data_file_path +from offPELE.utils import get_data_file_path, warning_on_one_line from offPELE.utils.toolkits import OpenForceFieldToolkitWrapper @@ -105,6 +105,11 @@ class OBC1(_SolventWrapper): _name = 'OBC1' def __init__(self, molecule): + # Not implemented in PELE + import warnings + warnings.formatwarning = warning_on_one_line + warnings.warn("OBC1 is not implemented in PELE", Warning) + super().__init__(molecule) def _initialize_from_molecule(self): From 09ae973199e0b5feb8731acc76c9457af1f5d9cf Mon Sep 17 00:00:00 2001 From: Marti Municoy Date: Mon, 29 Jun 2020 22:50:19 +0200 Subject: [PATCH 28/67] Wrong atom type identation is fixed --- offPELE/template/impact.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/offPELE/template/impact.py b/offPELE/template/impact.py index 68619567..781778cd 100644 --- a/offPELE/template/impact.py +++ b/offPELE/template/impact.py @@ -108,9 +108,9 @@ def _write_resx(self, file): file.write('{:5d}'.format(w_atom.parent.index)) file.write(' ') file.write('{:1}'.format(w_atom.core)) - file.write(' ') + file.write(' ') file.write('{:4}'.format(w_atom.OPLS_type)) - file.write(' ') + file.write(' ') file.write('{:4}'.format(w_atom.PDB_name)) file.write(' ') file.write('{:5}'.format(w_atom.unknown)) From 4643e498a082e39b5d3c79c0dfb6695d2bb906eb Mon Sep 17 00:00:00 2001 From: Marti Municoy Date: Fri, 3 Jul 2020 09:10:38 +0200 Subject: [PATCH 29/67] Solvent forcefields are included to repo --- offPELE/data/forcefields/GBSA_OBC1-1.0.offxml | 18 ++++++++++++++++++ offPELE/data/forcefields/GBSA_OBC2-1.0.offxml | 18 ++++++++++++++++++ 2 files changed, 36 insertions(+) create mode 100644 offPELE/data/forcefields/GBSA_OBC1-1.0.offxml create mode 100644 offPELE/data/forcefields/GBSA_OBC2-1.0.offxml diff --git a/offPELE/data/forcefields/GBSA_OBC1-1.0.offxml b/offPELE/data/forcefields/GBSA_OBC1-1.0.offxml new file mode 100644 index 00000000..d896d560 --- /dev/null +++ b/offPELE/data/forcefields/GBSA_OBC1-1.0.offxml @@ -0,0 +1,18 @@ + + 2019-08-08 + J. Chodera, (MSKCC); J. Wagner (Open Force Field) + + + + + + + + + + + + + + + diff --git a/offPELE/data/forcefields/GBSA_OBC2-1.0.offxml b/offPELE/data/forcefields/GBSA_OBC2-1.0.offxml new file mode 100644 index 00000000..dadecc20 --- /dev/null +++ b/offPELE/data/forcefields/GBSA_OBC2-1.0.offxml @@ -0,0 +1,18 @@ + + 2019-08-08 + J. Chodera, (MSKCC); J. Wagner (Open Force Field) + + + + + + + + + + + + + + + From 5d728ef942d7d8550ad18d940b42021d9239f234 Mon Sep 17 00:00:00 2001 From: Marti Municoy Date: Mon, 6 Jul 2020 11:20:09 +0200 Subject: [PATCH 30/67] Molecule name extracted from PDB's residue name --- .../extract_parameters_from_SMIRNOFF.ipynb | 911 ------------------ offPELE/topology/molecule.py | 8 +- offPELE/utils/toolkits.py | 6 + 3 files changed, 10 insertions(+), 915 deletions(-) delete mode 100644 offPELE/examples/extract_parameters_from_SMIRNOFF.ipynb diff --git a/offPELE/examples/extract_parameters_from_SMIRNOFF.ipynb b/offPELE/examples/extract_parameters_from_SMIRNOFF.ipynb deleted file mode 100644 index 07bbd120..00000000 --- a/offPELE/examples/extract_parameters_from_SMIRNOFF.ipynb +++ /dev/null @@ -1,911 +0,0 @@ -{ - "cells": [ - { - "cell_type": "code", - "execution_count": 41, - "metadata": {}, - "outputs": [], - "source": [ - "from rdkit import Chem\n", - "from rdkit.Chem.Draw import IPythonConsole\n", - "from rdkit.Chem.Draw.MolDrawing import MolDrawing, DrawingOptions\n", - "\n", - "DrawingOptions.bondLineWidth=1.8\n", - "\n", - "from openforcefield.topology import Molecule\n", - "from offPELE.utils import get_data_file_path" - ] - }, - { - "cell_type": "code", - "execution_count": 46, - "metadata": {}, - "outputs": [], - "source": [ - "file_path = get_data_file_path('ligands/BNZ.pdb')\n", - "ligand_rdkit_molecule = Chem.rdmolfiles.MolFromPDBFile(file_path, removeHs=False)\n", - "ligand_molecule = Molecule.from_rdkit(ligand_rdkit_molecule)" - ] - }, - { - "cell_type": "code", - "execution_count": 47, - "metadata": {}, - "outputs": [ - { - "data": { - "image/png": "iVBORw0KGgoAAAANSUhEUgAAASwAAAEsCAIAAAD2HxkiAAAF5ElEQVR4nO3dUW7bVhRF0brojJVhhGNWPwikRdo6tSC+fUmu9ZcgQUhLW4cy7fjj+Xz+BnR+rw8A7k6EEBMhxEQIMRFCTIQQEyHERAgxEUJMhBATIcRECDERQkyEEBMhxEQIMRFCTIQQEyHERAgxEUJMhBATIcRECDERQkyEEBMhxEQIMRFCTIQQEyHERAgxEUJMhBATIcRECDERQkyEEBMhxEQIMRFCTIQQEyHERAgxEUJMhBATIcRECDERQkyEEBMhxEQIMRFCTIQQEyHERAgxEUJMhBATIcRECDERQkyEEBMhxEQIMRFCTIQQEyHERAgxEUJMhBATIcRECDERQkyEEBMhxEQIMRFCTIQQEyHERAgxEb7Btm2//J2zu8M5VkQIMRFCTIQQ+6M+gIu4wxukO5xjQoTv8Xg8/v7LSz5f73COCZejEBMhxEQIsY/n81kfA9yaJYSYCCEmwmNd4PP4FziF4UR4rMfjceon8bZtP90e5O1ECDERHu68Y2gG1xAhxES4whnH0AwuI0KIiXCRc42hGVxJhOucpUMFLiZCiIlwqfljaAbXEyHERLja5DE0gwnfT9j4+Bj3kR94SDdhCSEmwsbz+fz4+KiP4i9mMCRCiIkwM2cMzWBLhBATYWnCGJrBnAghJsJYO4ZmcAIRQswL4QjVGHr0J/Cj0XrhNaHL0QlcjkJMhLF2iybcI0GEEBNhacJbMmOYEyHERJiZMIM7Y9hyi2Kco3sYUj4/THkxvps5M/jDwEO6CZejgZlPdxelFRFCTISrzZzBnTFMiBBiIlxq8gzujOF6IoSYCNeZP4M7Y7iYCCEmwkXOMoM7Y7iSCFc4V4E7HS4jQoiJ8HBnnMGdMVxDhBAT4bHOO4M7Y7iACCEmwgOdfQZ3xvBoIjzKNQrc6fBQIoSYCA9xpRncGcPjiBBiIny/683gzhgeRIQQu2CE27b98neOc9UZ3C0ew/ahXOaCEc50ugu50x3wed3uf+B+4aX027dv//8P/9cM7htylpH85FC/Oobfv3//6r/+eDy++ldO7XYRvvAAf+mvnKi011z+BNe7ZoQz3zmcZQxHHeTMh/K9rhnhT9u18oE8S2mvWX9q4UO5jE/MLDX/VtuFX0HGEuH7zS/tNfo8iAhXm5yozBI+6Ef55Ak99rl+xmO+AEt4lE8Wb+YYKrAiwsa0DmUWEuGBppX2Gn0eTYSZOYnKrCXCY80p7TX6XECEpQmJyiwnwsNNKO01+lxDhCuMvV3htsQEIoSYCBcZOIZmcAgRjrC+Q5nNIcJ1zvIZGn0uJsKlhlyUuhAdRYQQE+Fq+RiawWlECDERBsIxNIMDiRBiImwkY2gGZ/KhLw156g85jNuyhBATYWnC19CYwZwIISbC2NjvJ2QZEULMC+EI1Rh69Ce45o9GO5fwmtDl6AQuRyEmwli7RRPukSBCiImwNOEtmTHMiRBiIsxMmMGdMWyJEGIibMyZwZ0xDIkQYiIMbNs2agZ3z+dz27b6KO5IhKtt2/Z4POqj+HePx0OH64kQYiJcavIM7ozheiKEmAjXmT+DO2O4mAgXOUuBOx2uJEKIiXCFc83gzhguI0KIifBwZ5zBnTFcQ4QQE+GxzjuDO2O4wKxvqIEbsoQQEyHERAgxEUJMhBATIcRE+Ab/vJN2vXtrdzjHigghJkKIiRBiflLve9zhDdIdzjEhwvf46au0L/l8vcM5JlyOQkyEEBMhxHw/IcQsIcRECDERQkyEEBMhxEQIMRFCTIQQEyHERAgxEUJMhBATIcRECDERQkyEEBMhxEQIMRFCTIQQEyHERAgxEUJMhBATIcRECDERQkyEEBMhxEQIMRFCTIQQEyHERAgxEUJMhBATIcRECDERQkyEEBMhxEQIMRFCTIQQEyHERAgxEUJMhBATIcRECDERQkyEEBMhxEQIMRFCTIQQEyHERAgxEUJMhBATIcRECDERQkyEEBMhxEQIMRFCTIQQEyHERAgxEUJMhBATIcRECDERQkyEEPsT+gxFZQGbML0AAAAASUVORK5CYII=\n", - "text/plain": [ - "" - ] - }, - "execution_count": 47, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "ligand_rdkit_molecule.Compute2DCoords()\n", - "Chem.Draw.MolToImage(ligand_rdkit_molecule)" - ] - }, - { - "cell_type": "code", - "execution_count": 48, - "metadata": {}, - "outputs": [], - "source": [ - "from openforcefield.typing.engines.smirnoff import ForceField\n", - "#from openforcefields import get_forcefield_dirs_paths\n", - "forcefield = ForceField('openff-1.1.1.offxml')" - ] - }, - { - "cell_type": "code", - "execution_count": 49, - "metadata": {}, - "outputs": [], - "source": [ - "system = forcefield.create_openmm_system(ligand_molecule.to_topology())" - ] - }, - { - "cell_type": "code", - "execution_count": 6, - "metadata": {}, - "outputs": [], - "source": [ - "forces = system.getForces()" - ] - }, - { - "cell_type": "code", - "execution_count": 19, - "metadata": {}, - "outputs": [], - "source": [ - "force = forces[1]" - ] - }, - { - "cell_type": "code", - "execution_count": 21, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "[1,\n", - " 3,\n", - " 6,\n", - " 0,\n", - " 2,\n", - " Quantity(value=3.141592653589793, unit=radian),\n", - " Quantity(value=1.5341333333333336, unit=kilojoule/mole)]" - ] - }, - "execution_count": 21, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "force.getTorsionParameters(1)" - ] - }, - { - "cell_type": "code", - "execution_count": 23, - "metadata": {}, - "outputs": [], - "source": [ - "from simtk.openmm import XmlSerializer\n", - "with open('complex.xml', 'w') as f:\n", - " f.write(XmlSerializer.serialize(system))" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Get atomic mass" - ] - }, - { - "cell_type": "code", - "execution_count": 50, - "metadata": { - "scrolled": true - }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "TopologyAtom 0 with reference atom and parent TopologyMolecule \n", - "TopologyAtom 1 with reference atom and parent TopologyMolecule \n", - "TopologyAtom 2 with reference atom and parent TopologyMolecule \n", - "TopologyAtom 3 with reference atom and parent TopologyMolecule \n", - "TopologyAtom 4 with reference atom and parent TopologyMolecule \n", - "TopologyAtom 5 with reference atom and parent TopologyMolecule \n", - "TopologyAtom 6 with reference atom and parent TopologyMolecule \n", - "TopologyAtom 7 with reference atom and parent TopologyMolecule \n", - "TopologyAtom 8 with reference atom and parent TopologyMolecule \n", - "TopologyAtom 9 with reference atom and parent TopologyMolecule \n", - "TopologyAtom 10 with reference atom and parent TopologyMolecule \n", - "TopologyAtom 11 with reference atom and parent TopologyMolecule \n" - ] - } - ], - "source": [ - "for atom in ligand_molecule.to_topology().topology_particles:\n", - " print(atom)\n", - " " - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Forcefield parameter handlers" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Parameter handler dependencies" - ] - }, - { - "cell_type": "code", - "execution_count": 58, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Constraints:\n", - "Bonds:\n", - " - Constraints\n", - "Angles:\n", - " - Constraints\n", - "ProperTorsions:\n", - "ImproperTorsions:\n", - "vdW:\n", - "Electrostatics:\n", - " - vdW\n", - "LibraryCharges:\n", - " - vdW\n", - " - Electrostatics\n", - "ToolkitAM1BCC:\n", - " - vdW\n", - " - Electrostatics\n", - " - LibraryCharges\n" - ] - } - ], - "source": [ - "for tagname, handler in forcefield._parameter_handlers.items():\n", - " print('{}:'.format(tagname))\n", - " if handler._DEPENDENCIES is not None:\n", - " for dep in handler._DEPENDENCIES:\n", - " print(' -', dep._TAGNAME)" - ] - }, - { - "cell_type": "code", - "execution_count": 59, - "metadata": {}, - "outputs": [], - "source": [ - "ordered_parameter_handlers = forcefield._resolve_parameter_handler_order()" - ] - }, - { - "cell_type": "code", - "execution_count": 63, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "vdW\n", - "Electrostatics\n", - "LibraryCharges\n", - "ToolkitAM1BCC\n", - "ImproperTorsions\n", - "ProperTorsions\n", - "Constraints\n", - "Angles\n", - "Bonds\n" - ] - } - ], - "source": [ - "for handler in ordered_parameter_handlers:\n", - " print(handler._TAGNAME)" - ] - }, - { - "cell_type": "code", - "execution_count": 154, - "metadata": {}, - "outputs": [], - "source": [ - "ligand_topology = ligand_molecule.to_topology()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Extract vdW parameters" - ] - }, - { - "cell_type": "code", - "execution_count": 155, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "vdW\n" - ] - } - ], - "source": [ - "from openforcefield.typing.engines.smirnoff.parameters import vdWHandler\n", - "\n", - "for handler in ordered_parameter_handlers:\n", - " if isinstance(handler, vdWHandler):\n", - " break\n", - "\n", - "vdW_handler = handler\n", - "print(vdW_handler._TAGNAME)" - ] - }, - { - "cell_type": "code", - "execution_count": 156, - "metadata": {}, - "outputs": [], - "source": [ - "vdW_matches = vdW_handler.find_matches(ligand_topology)" - ] - }, - { - "cell_type": "code", - "execution_count": 157, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "(0,) 0.086 kcal/mol None 1.908 A\n", - "(1,) 0.086 kcal/mol None 1.908 A\n", - "(2,) 0.086 kcal/mol None 1.908 A\n", - "(3,) 0.086 kcal/mol None 1.908 A\n", - "(4,) 0.086 kcal/mol None 1.908 A\n", - "(5,) 0.086 kcal/mol None 1.908 A\n", - "(6,) 0.015 kcal/mol None 1.459 A\n", - "(7,) 0.015 kcal/mol None 1.459 A\n", - "(8,) 0.015 kcal/mol None 1.459 A\n", - "(9,) 0.015 kcal/mol None 1.459 A\n", - "(10,) 0.015 kcal/mol None 1.459 A\n", - "(11,) 0.015 kcal/mol None 1.459 A\n" - ] - } - ], - "source": [ - "for topology_atom_indices, vdW_match in vdW_matches.items():\n", - " print(topology_atom_indices, vdW_match.parameter_type.epsilon, vdW_match.parameter_type.sigma,\n", - " vdW_match.parameter_type.rmin_half)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Extract electrostatic parameters" - ] - }, - { - "cell_type": "code", - "execution_count": 183, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Electrostatics\n" - ] - } - ], - "source": [ - "from openforcefield.typing.engines.smirnoff.parameters import ElectrostaticsHandler\n", - "\n", - "for handler in ordered_parameter_handlers:\n", - " if isinstance(handler, ElectrostaticsHandler):\n", - " break\n", - "\n", - "electrostatics_handler = handler\n", - "print(electrostatics_handler._TAGNAME)" - ] - }, - { - "cell_type": "code", - "execution_count": 184, - "metadata": {}, - "outputs": [], - "source": [ - "electrostatics_matches = electrostatics_handler.find_matches(ligand_topology)" - ] - }, - { - "cell_type": "code", - "execution_count": 185, - "metadata": {}, - "outputs": [], - "source": [ - "for topology_atom_indices, electrostatics_match in electrostatics_matches.items():\n", - " print(topology_atom_indices, electrostatics_match.parameter_type.epsilon, electrostatics_match.parameter_type.sigma,\n", - " electrostatics_match.parameter_type.rmin_half)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Extract library charge parameters" - ] - }, - { - "cell_type": "code", - "execution_count": 186, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "LibraryCharges\n" - ] - } - ], - "source": [ - "from openforcefield.typing.engines.smirnoff.parameters import LibraryChargeHandler\n", - "\n", - "for handler in ordered_parameter_handlers:\n", - " if isinstance(handler, LibraryChargeHandler):\n", - " break\n", - "\n", - "library_charge_handler = handler\n", - "print(library_charge_handler._TAGNAME)" - ] - }, - { - "cell_type": "code", - "execution_count": 187, - "metadata": {}, - "outputs": [], - "source": [ - "library_charge_matches = library_charge_handler.find_matches(ligand_topology)" - ] - }, - { - "cell_type": "code", - "execution_count": 188, - "metadata": {}, - "outputs": [], - "source": [ - "for topology_atom_indices, library_charge_match in library_charge_matches.items():\n", - " print(topology_atom_indices, library_charge_match.parameter_type.epsilon, library_charge_match.parameter_type.sigma,\n", - " library_charge_match.parameter_type.rmin_half)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Extract ToolkitAM1BCC parameters" - ] - }, - { - "cell_type": "code", - "execution_count": 189, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "ToolkitAM1BCC\n" - ] - } - ], - "source": [ - "from openforcefield.typing.engines.smirnoff.parameters import ToolkitAM1BCCHandler\n", - "\n", - "for handler in ordered_parameter_handlers:\n", - " if isinstance(handler, ToolkitAM1BCCHandler):\n", - " break\n", - "\n", - "toolkit_AM1BCC_handler = handler\n", - "print(toolkit_AM1BCC_handler._TAGNAME)" - ] - }, - { - "cell_type": "code", - "execution_count": 190, - "metadata": {}, - "outputs": [], - "source": [ - "toolkit_AM1BCC_matches = toolkit_AM1BCC_handler.find_matches(ligand_topology)" - ] - }, - { - "cell_type": "code", - "execution_count": 191, - "metadata": {}, - "outputs": [], - "source": [ - "for topology_atom_indices, toolkit_AM1BCC_match in toolkit_AM1BCC_matches.items():\n", - " print(topology_atom_indices, library_charge_match.parameter_type.epsilon, library_charge_match.parameter_type.sigma,\n", - " library_charge_match.parameter_type.rmin_half)" - ] - }, - { - "cell_type": "code", - "execution_count": 192, - "metadata": {}, - "outputs": [ - { - "ename": "SyntaxError", - "evalue": "invalid syntax (, line 1)", - "output_type": "error", - "traceback": [ - "\u001b[0;36m File \u001b[0;32m\"\"\u001b[0;36m, line \u001b[0;32m1\u001b[0m\n\u001b[0;31m toolkit_AM1BCC_match.\u001b[0m\n\u001b[0m ^\u001b[0m\n\u001b[0;31mSyntaxError\u001b[0m\u001b[0;31m:\u001b[0m invalid syntax\n" - ] - } - ], - "source": [ - "toolkit_AM1BCC_match." - ] - }, - { - "cell_type": "code", - "execution_count": 169, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "" - ] - }, - "execution_count": 169, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "ligand_topology" - ] - }, - { - "cell_type": "code", - "execution_count": 177, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Molecule with name 'HYDROLASE' and SMILES '[H][c]1[c]([H])[c]([H])[c]([H])[c]([H])[c]1[H]'\n" - ] - } - ], - "source": [ - "for molecule in ligand_topology.reference_molecules:\n", - " print(molecule)" - ] - }, - { - "cell_type": "code", - "execution_count": 180, - "metadata": {}, - "outputs": [], - "source": [ - "molecule.compute_partial_charges_am1bcc()" - ] - }, - { - "cell_type": "code", - "execution_count": 182, - "metadata": {}, - "outputs": [ - { - "ename": "NotImplementedError", - "evalue": "", - "output_type": "error", - "traceback": [ - "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", - "\u001b[0;31mNotImplementedError\u001b[0m Traceback (most recent call last)", - "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0mmolecule\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mcompute_partial_charges\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", - "\u001b[0;32m~/environments/boost_1_68_0/lib/python3.7/site-packages/openforcefield-0.6.0+422.gd36894a-py3.7.egg/openforcefield/topology/molecule.py\u001b[0m in \u001b[0;36mcompute_partial_charges\u001b[0;34m(self, toolkit_registry)\u001b[0m\n\u001b[1;32m 2355\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 2356\u001b[0m \"\"\"\n\u001b[0;32m-> 2357\u001b[0;31m \u001b[0;32mraise\u001b[0m \u001b[0mNotImplementedError\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 2358\u001b[0m \u001b[0;31m# TODO: Implement this in a way that's compliant with SMIRNOFF's tag when the spec gets finalized\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 2359\u001b[0m \u001b[0;31m# if isinstance(toolkit_registry, ToolkitRegistry):\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", - "\u001b[0;31mNotImplementedError\u001b[0m: " - ] - } - ], - "source": [ - "molecule.compute_partial_charges()" - ] - }, - { - "cell_type": "code", - "execution_count": 181, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "Quantity(value=array([-0.13, -0.13, -0.13, -0.13, -0.13, -0.13, 0.13, 0.13, 0.13,\n", - " 0.13, 0.13, 0.13]), unit=elementary charge)" - ] - }, - "execution_count": 181, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "molecule.partial_charges" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Extract bond parameters" - ] - }, - { - "cell_type": "code", - "execution_count": 90, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Bonds\n" - ] - } - ], - "source": [ - "from openforcefield.typing.engines.smirnoff.parameters import BondHandler\n", - "\n", - "for handler in ordered_parameter_handlers:\n", - " if isinstance(handler, BondHandler):\n", - " break\n", - "\n", - "bond_handler = handler\n", - "print(bond_handler._TAGNAME)" - ] - }, - { - "cell_type": "code", - "execution_count": 91, - "metadata": {}, - "outputs": [], - "source": [ - "bond_matches = bond_handler.find_matches(ligand_topology)" - ] - }, - { - "cell_type": "code", - "execution_count": 92, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "(0, 1) 1.388684811982 A 703.7861640732 kcal/(A**2 mol)\n", - "(0, 5) 1.388684811982 A 703.7861640732 kcal/(A**2 mol)\n", - "(0, 6) 1.085028902395 A 808.0585583296 kcal/(A**2 mol)\n", - "(1, 2) 1.388684811982 A 703.7861640732 kcal/(A**2 mol)\n", - "(1, 7) 1.085028902395 A 808.0585583296 kcal/(A**2 mol)\n", - "(2, 3) 1.388684811982 A 703.7861640732 kcal/(A**2 mol)\n", - "(2, 8) 1.085028902395 A 808.0585583296 kcal/(A**2 mol)\n", - "(3, 4) 1.388684811982 A 703.7861640732 kcal/(A**2 mol)\n", - "(3, 9) 1.085028902395 A 808.0585583296 kcal/(A**2 mol)\n", - "(4, 5) 1.388684811982 A 703.7861640732 kcal/(A**2 mol)\n", - "(4, 10) 1.085028902395 A 808.0585583296 kcal/(A**2 mol)\n", - "(5, 11) 1.085028902395 A 808.0585583296 kcal/(A**2 mol)\n" - ] - } - ], - "source": [ - "for topology_atom_indices, bond_match in bond_matches.items():\n", - " print(topology_atom_indices, bond_match.parameter_type.length, bond_match.parameter_type.k)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Extract angle parameters" - ] - }, - { - "cell_type": "code", - "execution_count": 93, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Angles\n" - ] - } - ], - "source": [ - "from openforcefield.typing.engines.smirnoff.parameters import AngleHandler\n", - "\n", - "for handler in ordered_parameter_handlers:\n", - " if isinstance(handler, AngleHandler):\n", - " break\n", - "\n", - "angle_handler = handler\n", - "print(angle_handler._TAGNAME)" - ] - }, - { - "cell_type": "code", - "execution_count": 98, - "metadata": {}, - "outputs": [], - "source": [ - "angle_matches = angle_handler.find_matches(ligand_topology)" - ] - }, - { - "cell_type": "code", - "execution_count": 100, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "(0, 1, 2) 132.0554838002 deg 153.7825131248 kcal/(mol rad**2)\n", - "(0, 1, 7) 137.9694119749 deg 66.76856405714 kcal/(mol rad**2)\n", - "(0, 5, 4) 132.0554838002 deg 153.7825131248 kcal/(mol rad**2)\n", - "(0, 5, 11) 137.9694119749 deg 66.76856405714 kcal/(mol rad**2)\n", - "(1, 0, 5) 132.0554838002 deg 153.7825131248 kcal/(mol rad**2)\n", - "(1, 0, 6) 137.9694119749 deg 66.76856405714 kcal/(mol rad**2)\n", - "(1, 2, 3) 132.0554838002 deg 153.7825131248 kcal/(mol rad**2)\n", - "(1, 2, 8) 137.9694119749 deg 66.76856405714 kcal/(mol rad**2)\n", - "(2, 1, 7) 137.9694119749 deg 66.76856405714 kcal/(mol rad**2)\n", - "(2, 3, 4) 132.0554838002 deg 153.7825131248 kcal/(mol rad**2)\n", - "(2, 3, 9) 137.9694119749 deg 66.76856405714 kcal/(mol rad**2)\n", - "(3, 2, 8) 137.9694119749 deg 66.76856405714 kcal/(mol rad**2)\n", - "(3, 4, 5) 132.0554838002 deg 153.7825131248 kcal/(mol rad**2)\n", - "(3, 4, 10) 137.9694119749 deg 66.76856405714 kcal/(mol rad**2)\n", - "(4, 3, 9) 137.9694119749 deg 66.76856405714 kcal/(mol rad**2)\n", - "(4, 5, 11) 137.9694119749 deg 66.76856405714 kcal/(mol rad**2)\n", - "(5, 0, 6) 137.9694119749 deg 66.76856405714 kcal/(mol rad**2)\n", - "(5, 4, 10) 137.9694119749 deg 66.76856405714 kcal/(mol rad**2)\n" - ] - } - ], - "source": [ - "for topology_atom_indices, angle_match in angle_matches.items():\n", - " print(topology_atom_indices, angle_match.parameter_type.angle, angle_match.parameter_type.k)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Extract proper torsion parameters" - ] - }, - { - "cell_type": "code", - "execution_count": 104, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "ProperTorsions\n" - ] - } - ], - "source": [ - "from openforcefield.typing.engines.smirnoff.parameters import ProperTorsionHandler\n", - "\n", - "for handler in ordered_parameter_handlers:\n", - " if isinstance(handler, ProperTorsionHandler):\n", - " break\n", - "\n", - "proper_torsion_handler = handler\n", - "print(proper_torsion_handler._TAGNAME)" - ] - }, - { - "cell_type": "code", - "execution_count": 105, - "metadata": {}, - "outputs": [], - "source": [ - "proper_torsion_matches = proper_torsion_handler.find_matches(ligand_topology)" - ] - }, - { - "cell_type": "code", - "execution_count": 110, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "(0, 1, 2, 3) [2] [Quantity(value=180.0, unit=degree)] [Quantity(value=2.639861699998, unit=kilocalorie/mole)]\n", - "(0, 1, 2, 8) [2] [Quantity(value=180.0, unit=degree)] [Quantity(value=2.639861699998, unit=kilocalorie/mole)]\n", - "(0, 5, 4, 3) [2] [Quantity(value=180.0, unit=degree)] [Quantity(value=2.639861699998, unit=kilocalorie/mole)]\n", - "(0, 5, 4, 10) [2] [Quantity(value=180.0, unit=degree)] [Quantity(value=2.639861699998, unit=kilocalorie/mole)]\n", - "(1, 0, 5, 4) [2] [Quantity(value=180.0, unit=degree)] [Quantity(value=2.639861699998, unit=kilocalorie/mole)]\n", - "(1, 0, 5, 11) [2] [Quantity(value=180.0, unit=degree)] [Quantity(value=2.639861699998, unit=kilocalorie/mole)]\n", - "(1, 2, 3, 4) [2] [Quantity(value=180.0, unit=degree)] [Quantity(value=2.639861699998, unit=kilocalorie/mole)]\n", - "(1, 2, 3, 9) [2] [Quantity(value=180.0, unit=degree)] [Quantity(value=2.639861699998, unit=kilocalorie/mole)]\n", - "(2, 1, 0, 5) [2] [Quantity(value=180.0, unit=degree)] [Quantity(value=2.639861699998, unit=kilocalorie/mole)]\n", - "(2, 1, 0, 6) [2] [Quantity(value=180.0, unit=degree)] [Quantity(value=2.639861699998, unit=kilocalorie/mole)]\n", - "(2, 3, 4, 5) [2] [Quantity(value=180.0, unit=degree)] [Quantity(value=2.639861699998, unit=kilocalorie/mole)]\n", - "(2, 3, 4, 10) [2] [Quantity(value=180.0, unit=degree)] [Quantity(value=2.639861699998, unit=kilocalorie/mole)]\n", - "(3, 2, 1, 7) [2] [Quantity(value=180.0, unit=degree)] [Quantity(value=2.639861699998, unit=kilocalorie/mole)]\n", - "(3, 4, 5, 11) [2] [Quantity(value=180.0, unit=degree)] [Quantity(value=2.639861699998, unit=kilocalorie/mole)]\n", - "(4, 3, 2, 8) [2] [Quantity(value=180.0, unit=degree)] [Quantity(value=2.639861699998, unit=kilocalorie/mole)]\n", - "(4, 5, 0, 6) [2] [Quantity(value=180.0, unit=degree)] [Quantity(value=2.639861699998, unit=kilocalorie/mole)]\n", - "(5, 0, 1, 7) [2] [Quantity(value=180.0, unit=degree)] [Quantity(value=2.639861699998, unit=kilocalorie/mole)]\n", - "(5, 4, 3, 9) [2] [Quantity(value=180.0, unit=degree)] [Quantity(value=2.639861699998, unit=kilocalorie/mole)]\n", - "(6, 0, 1, 7) [2] [Quantity(value=180.0, unit=degree)] [Quantity(value=2.639861699998, unit=kilocalorie/mole)]\n", - "(6, 0, 5, 11) [2] [Quantity(value=180.0, unit=degree)] [Quantity(value=2.639861699998, unit=kilocalorie/mole)]\n", - "(7, 1, 2, 8) [2] [Quantity(value=180.0, unit=degree)] [Quantity(value=2.639861699998, unit=kilocalorie/mole)]\n", - "(8, 2, 3, 9) [2] [Quantity(value=180.0, unit=degree)] [Quantity(value=2.639861699998, unit=kilocalorie/mole)]\n", - "(9, 3, 4, 10) [2] [Quantity(value=180.0, unit=degree)] [Quantity(value=2.639861699998, unit=kilocalorie/mole)]\n", - "(10, 4, 5, 11) [2] [Quantity(value=180.0, unit=degree)] [Quantity(value=2.639861699998, unit=kilocalorie/mole)]\n" - ] - } - ], - "source": [ - "for topology_atom_indices, proper_torsion_match in proper_torsion_matches.items():\n", - " print(topology_atom_indices, proper_torsion_match.parameter_type.periodicity,\n", - " proper_torsion_match.parameter_type.phase, proper_torsion_match.parameter_type.k)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Extract improper torsion parameters" - ] - }, - { - "cell_type": "code", - "execution_count": 111, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "ImproperTorsions\n" - ] - } - ], - "source": [ - "from openforcefield.typing.engines.smirnoff.parameters import ImproperTorsionHandler\n", - "\n", - "for handler in ordered_parameter_handlers:\n", - " if isinstance(handler, ImproperTorsionHandler):\n", - " break\n", - "\n", - "improper_torsion_handler = handler\n", - "print(improper_torsion_handler._TAGNAME)" - ] - }, - { - "cell_type": "code", - "execution_count": 112, - "metadata": {}, - "outputs": [], - "source": [ - "improper_torsion_matches = improper_torsion_handler.find_matches(ligand_topology)" - ] - }, - { - "cell_type": "code", - "execution_count": 113, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "(0, 1, 2, 7) [2] [Quantity(value=180.0, unit=degree)] [Quantity(value=1.1, unit=kilocalorie/mole)]\n", - "(0, 5, 4, 11) [2] [Quantity(value=180.0, unit=degree)] [Quantity(value=1.1, unit=kilocalorie/mole)]\n", - "(1, 0, 5, 6) [2] [Quantity(value=180.0, unit=degree)] [Quantity(value=1.1, unit=kilocalorie/mole)]\n", - "(1, 2, 3, 8) [2] [Quantity(value=180.0, unit=degree)] [Quantity(value=1.1, unit=kilocalorie/mole)]\n", - "(2, 3, 4, 9) [2] [Quantity(value=180.0, unit=degree)] [Quantity(value=1.1, unit=kilocalorie/mole)]\n", - "(3, 4, 5, 10) [2] [Quantity(value=180.0, unit=degree)] [Quantity(value=1.1, unit=kilocalorie/mole)]\n" - ] - } - ], - "source": [ - "for topology_atom_indices, improper_torsion_match in improper_torsion_matches.items():\n", - " print(topology_atom_indices, improper_torsion_match.parameter_type.periodicity,\n", - " improper_torsion_match.parameter_type.phase, improper_torsion_match.parameter_type.k)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.7.4" - } - }, - "nbformat": 4, - "nbformat_minor": 4 -} diff --git a/offPELE/topology/molecule.py b/offPELE/topology/molecule.py index 45ace912..29c43843 100644 --- a/offPELE/topology/molecule.py +++ b/offPELE/topology/molecule.py @@ -385,14 +385,14 @@ def _initialize_from_pdb(self, path): # RDKit must generate stereochemistry specifically from 3D coords rdkit_toolkit.assign_stereochemistry_from_3D(self) + # Set molecule name according to PDB's residue name + name = rdkit_toolkit.get_residue_name(self) + self.set_name(name) + openforcefield_toolkit = OpenForceFieldToolkitWrapper() self._off_molecule = openforcefield_toolkit.from_rdkit(self) - name = Path(path).stem - if len(name) > 2: - self.set_name(name) - def set_name(self, name): if isinstance(name, str) and len(name) > 2: name = name[0:3].upper() diff --git a/offPELE/utils/toolkits.py b/offPELE/utils/toolkits.py index fa518b74..0084bf83 100644 --- a/offPELE/utils/toolkits.py +++ b/offPELE/utils/toolkits.py @@ -83,6 +83,12 @@ def assign_stereochemistry_from_3D(self, molecule): rdkit_molecule = molecule.rdkit_molecule Chem.rdmolops.AssignStereochemistryFrom3D(rdkit_molecule) + def get_residue_name(self, molecule): + rdkit_molecule = molecule.rdkit_molecule + + first_atom = list(rdkit_molecule.GetAtoms())[0] + return first_atom.GetPDBResidueInfo().GetResidueName() + def to_sfd_file(self, molecule, path): from rdkit import Chem From c3239d5953b7769641e28c7ba162593383d1ed7a Mon Sep 17 00:00:00 2001 From: Marti Municoy Date: Mon, 6 Jul 2020 11:31:55 +0200 Subject: [PATCH 31/67] Minor change in Impact header format --- offPELE/template/impact.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/offPELE/template/impact.py b/offPELE/template/impact.py index 781778cd..d0ac4c2c 100644 --- a/offPELE/template/impact.py +++ b/offPELE/template/impact.py @@ -76,7 +76,7 @@ def _write_header(self, file): if self.molecule.forcefield: file.write(' ({})'.format(self.molecule.forcefield)) file.write('\n') - file.write('* File generated with offPELE {}\n'.format( + file.write('* File generated with offPELE-{}\n'.format( offPELE.__version__)) file.write('*\n') From edcea265ade1d5e96ebbe486691acb9022e48ce0 Mon Sep 17 00:00:00 2001 From: Marti Municoy Date: Mon, 6 Jul 2020 11:38:15 +0200 Subject: [PATCH 32/67] MolecularGraph moved to rotamer --- offPELE/topology/molecule.py | 227 +---------------------------------- offPELE/topology/rotamer.py | 225 ++++++++++++++++++++++++++++++++++ 2 files changed, 226 insertions(+), 226 deletions(-) diff --git a/offPELE/topology/molecule.py b/offPELE/topology/molecule.py index 29c43843..a7a20c99 100644 --- a/offPELE/topology/molecule.py +++ b/offPELE/topology/molecule.py @@ -1,16 +1,12 @@ # Global imports -from collections import defaultdict -from copy import deepcopy from pathlib import Path -import networkx as nx - -from .rotamer import RotamerLibrary, Rotamer from .topology import Bond, Angle, OFFProper, OFFImproper from offPELE.utils.toolkits import (AmberToolkitWrapper, RDKitToolkitWrapper, OpenForceFieldToolkitWrapper) +from .rotamer import MolecularGraph class Atom(object): @@ -125,227 +121,6 @@ def __init__(self, index=-1, PDB_name='DUMM', parent=None): None, None, None, None, None, None, None, parent) -class MolecularGraph(nx.Graph): - def __init__(self, molecule): - super().__init__(self) - self._molecule = molecule - self._compute_rotamer_graph(molecule) - - def _compute_rotamer_graph(self, molecule): - rdkit_toolkit = RDKitToolkitWrapper() - rot_bonds_atom_ids = \ - rdkit_toolkit.get_atom_ids_with_rotatable_bonds(molecule) - - rdkit_molecule = molecule.rdkit_molecule - - for atom in rdkit_molecule.GetAtoms(): - pdb_info = atom.GetPDBResidueInfo() - self.add_node(atom.GetIdx(), pdb_name=pdb_info.GetName(), - nrot_neighbors=list()) - - for bond in rdkit_molecule.GetBonds(): - atom1 = bond.GetBeginAtomIdx() - atom2 = bond.GetEndAtomIdx() - if ((atom1, atom2) in rot_bonds_atom_ids - or (atom2, atom2) in rot_bonds_atom_ids): - rotatable = True - else: - rotatable = False - self.nodes[atom1]['nrot_neighbors'].append(atom2) - self.nodes[atom2]['nrot_neighbors'].append(atom1) - - self.add_edge(bond.GetBeginAtomIdx(), - bond.GetEndAtomIdx(), - weight=int(rotatable)) - - for i, j in rot_bonds_atom_ids: - self[i][j]['weight'] = 1 - self.nodes[i]['rotatable'] = True - self.nodes[j]['rotatable'] = True - - def set_core(self): - def get_all_nrot_neighbors(self, atom_id, visited_neighbors): - if atom_id in visited_neighbors: - return visited_neighbors - visited_neighbors.add(atom_id) - nrot_neighbors = self.nodes[atom_id]['nrot_neighbors'] - for nrot_neighbor in nrot_neighbors: - visited_neighbors = get_all_nrot_neighbors( - self, nrot_neighbor, visited_neighbors) - return visited_neighbors - - from networkx.algorithms.shortest_paths.generic import \ - shortest_path_length - from networkx.algorithms.distance_measures import eccentricity - - # Calculate graph distances according to weight values - weighted_distances = dict(shortest_path_length(self, weight="weight")) - - # Calculate eccentricites using weighted distances - eccentricities = eccentricity(self, sp=weighted_distances) - - # Group nodes by eccentricity - nodes_by_eccentricities = defaultdict(list) - for node, ecc in eccentricities.items(): - nodes_by_eccentricities[ecc].append(node) - - # Core atoms must have the minimum eccentricity - _, centered_nodes = sorted(nodes_by_eccentricities.items())[0] - - # Construct nrot groups with centered nodes - already_visited = set() - centered_node_groups = list() - for node in centered_nodes: - if node in already_visited: - continue - centered_node_groups.append(get_all_nrot_neighbors(self, node, - set())) - - # In case of more than one group, core will be the largest - node_group = sorted(centered_node_groups, key=len, reverse=True)[0] - - for atom in self.molecule.atoms: - if atom.index in node_group: - atom.set_as_core() - else: - atom.set_as_branch() - - def set_parents(self): - def recursive_child_visitor(parent, already_visited=set()): - if parent in already_visited: - return already_visited - - already_visited.add(parent) - - childs = [self.molecule.atoms[n] for n in self.neighbors(parent.index)] - - for child in childs: - if child in already_visited: - continue - child.set_parent(parent) - already_visited = recursive_child_visitor(child, - already_visited) - - return already_visited - - # Start from an atom from the core - parent = None - for atom in self.molecule.atoms: - if atom.core: - parent = atom - break - - # Assert a parent was found - assert parent is not None, 'No core atom found in molecule ' \ - '{}'.format(self.molecule.name) - - already_visited = recursive_child_visitor(parent) - - # Assert all nodes were explored - assert len(already_visited) == len(self.molecule.atoms), 'Not all ' \ - 'nodes were explored' - - # Assert absolut parent is the only with None parent value - assert parent.parent is None and \ - sum([int(a.parent is not None) for a in self.molecule.atoms]) \ - == len(self.molecule.atoms) - 1, 'Found descendant without parent' - - def _get_rot_bonds_per_group(self, branch_groups): - rot_bonds_per_group = list() - for group in branch_groups: - rot_bonds = list() - visited_bonds = set() - for node in group: - bonds = self.edges(node) - for bond in bonds: - if bond in visited_bonds: - continue - if self[bond[0]][bond[1]]['weight'] == 1: - rot_bonds.append(bond) - visited_bonds.add(bond) - visited_bonds.add((bond[1], bond[0])) - rot_bonds_per_group.append(rot_bonds) - - return rot_bonds_per_group - - def _get_core_atom_per_group(self, rot_bonds_per_group, core_indexes): - core_atom_per_group = list() - for rot_bonds in rot_bonds_per_group: - for (a1, a2) in rot_bonds: - if a1 in core_indexes: - core_atom_per_group.append(a1) - break - elif a2 in core_indexes: - core_atom_per_group.append(a2) - break - else: - core_atom_per_group.append(None) - - return core_atom_per_group - - def _get_sorted_bonds_per_group(self, core_atom_per_group, - rot_bonds_per_group, distances): - sorted_rot_bonds_per_group = list() - for core_atom, rot_bonds in zip(core_atom_per_group, - rot_bonds_per_group): - sorting_dict = dict() - for bond in rot_bonds: - min_d = min([distances[core_atom][bond[0]], - distances[core_atom][bond[1]]]) - sorting_dict[bond] = min_d - - sorted_rot_bonds_per_group.append( - [i[0] for i in - sorted(sorting_dict.items(), key=lambda item: item[1])]) - - return sorted_rot_bonds_per_group - - def build_rotamer_library(self, resolution): - core_atoms = set() - for atom in self.molecule.atoms: - if atom.core: - core_atoms.add(atom) - core_indexes = [atom.index for atom in core_atoms] - - assert len(core_atoms) > 0, 'No core atoms were found' - - branch_graph = deepcopy(self) - - for core_atom in core_atoms: - branch_graph.remove_node(core_atom.index) - - branch_groups = list(nx.connected_components(branch_graph)) - - rot_bonds_per_group = self._get_rot_bonds_per_group(branch_groups) - - core_atom_per_group = self._get_core_atom_per_group( - rot_bonds_per_group, core_indexes) - - distances = dict(nx.shortest_path_length(self)) - - sorted_rot_bonds_per_group = self._get_sorted_bonds_per_group( - core_atom_per_group, rot_bonds_per_group, distances) - - rotamer_library = RotamerLibrary(self.molecule.name) - - # PELE needs underscores instead of whitespaces - pdb_atom_names = [name.replace(' ', '_',) - for name in self.molecule.get_pdb_atom_names()] - - for group_id, rot_bonds in enumerate(sorted_rot_bonds_per_group): - for (atom1_index, atom2_index) in rot_bonds: - atom1_name = pdb_atom_names[atom1_index] - atom2_name = pdb_atom_names[atom2_index] - rotamer = Rotamer(atom1_name, atom2_name, resolution) - rotamer_library.add_rotamer(rotamer, group_id) - - return rotamer_library - - @property - def molecule(self): - return self._molecule - - class Molecule(object): def __init__(self, path=None): if isinstance(path, str): diff --git a/offPELE/topology/rotamer.py b/offPELE/topology/rotamer.py index bb35c70e..2cdd185e 100644 --- a/offPELE/topology/rotamer.py +++ b/offPELE/topology/rotamer.py @@ -1,5 +1,9 @@ # Global imports from collections import defaultdict +import networkx as nx +from copy import deepcopy + +from offPELE.utils.toolkits import RDKitToolkitWrapper class Rotamer(object): @@ -46,3 +50,224 @@ def residue_name(self): @property def rotamers(self): return self._rotamers + + +class MolecularGraph(nx.Graph): + def __init__(self, molecule): + super().__init__(self) + self._molecule = molecule + self._compute_rotamer_graph(molecule) + + def _compute_rotamer_graph(self, molecule): + rdkit_toolkit = RDKitToolkitWrapper() + rot_bonds_atom_ids = \ + rdkit_toolkit.get_atom_ids_with_rotatable_bonds(molecule) + + rdkit_molecule = molecule.rdkit_molecule + + for atom in rdkit_molecule.GetAtoms(): + pdb_info = atom.GetPDBResidueInfo() + self.add_node(atom.GetIdx(), pdb_name=pdb_info.GetName(), + nrot_neighbors=list()) + + for bond in rdkit_molecule.GetBonds(): + atom1 = bond.GetBeginAtomIdx() + atom2 = bond.GetEndAtomIdx() + if ((atom1, atom2) in rot_bonds_atom_ids + or (atom2, atom2) in rot_bonds_atom_ids): + rotatable = True + else: + rotatable = False + self.nodes[atom1]['nrot_neighbors'].append(atom2) + self.nodes[atom2]['nrot_neighbors'].append(atom1) + + self.add_edge(bond.GetBeginAtomIdx(), + bond.GetEndAtomIdx(), + weight=int(rotatable)) + + for i, j in rot_bonds_atom_ids: + self[i][j]['weight'] = 1 + self.nodes[i]['rotatable'] = True + self.nodes[j]['rotatable'] = True + + def set_core(self): + def get_all_nrot_neighbors(self, atom_id, visited_neighbors): + if atom_id in visited_neighbors: + return visited_neighbors + visited_neighbors.add(atom_id) + nrot_neighbors = self.nodes[atom_id]['nrot_neighbors'] + for nrot_neighbor in nrot_neighbors: + visited_neighbors = get_all_nrot_neighbors( + self, nrot_neighbor, visited_neighbors) + return visited_neighbors + + from networkx.algorithms.shortest_paths.generic import \ + shortest_path_length + from networkx.algorithms.distance_measures import eccentricity + + # Calculate graph distances according to weight values + weighted_distances = dict(shortest_path_length(self, weight="weight")) + + # Calculate eccentricites using weighted distances + eccentricities = eccentricity(self, sp=weighted_distances) + + # Group nodes by eccentricity + nodes_by_eccentricities = defaultdict(list) + for node, ecc in eccentricities.items(): + nodes_by_eccentricities[ecc].append(node) + + # Core atoms must have the minimum eccentricity + _, centered_nodes = sorted(nodes_by_eccentricities.items())[0] + + # Construct nrot groups with centered nodes + already_visited = set() + centered_node_groups = list() + for node in centered_nodes: + if node in already_visited: + continue + centered_node_groups.append(get_all_nrot_neighbors(self, node, + set())) + + # In case of more than one group, core will be the largest + node_group = sorted(centered_node_groups, key=len, reverse=True)[0] + + for atom in self.molecule.atoms: + if atom.index in node_group: + atom.set_as_core() + else: + atom.set_as_branch() + + def set_parents(self): + def recursive_child_visitor(parent, already_visited=set()): + if parent in already_visited: + return already_visited + + already_visited.add(parent) + + childs = [self.molecule.atoms[n] for n in self.neighbors(parent.index)] + + for child in childs: + if child in already_visited: + continue + child.set_parent(parent) + already_visited = recursive_child_visitor(child, + already_visited) + + return already_visited + + # Start from an atom from the core + parent = None + for atom in self.molecule.atoms: + if atom.core: + parent = atom + break + + # Assert a parent was found + assert parent is not None, 'No core atom found in molecule ' \ + '{}'.format(self.molecule.name) + + already_visited = recursive_child_visitor(parent) + + # Assert all nodes were explored + assert len(already_visited) == len(self.molecule.atoms), 'Not all ' \ + 'nodes were explored' + + # Assert absolut parent is the only with None parent value + assert parent.parent is None and \ + sum([int(a.parent is not None) for a in self.molecule.atoms]) \ + == len(self.molecule.atoms) - 1, 'Found descendant without parent' + + def _get_rot_bonds_per_group(self, branch_groups): + rot_bonds_per_group = list() + for group in branch_groups: + rot_bonds = list() + visited_bonds = set() + for node in group: + bonds = self.edges(node) + for bond in bonds: + if bond in visited_bonds: + continue + if self[bond[0]][bond[1]]['weight'] == 1: + rot_bonds.append(bond) + visited_bonds.add(bond) + visited_bonds.add((bond[1], bond[0])) + rot_bonds_per_group.append(rot_bonds) + + return rot_bonds_per_group + + def _get_core_atom_per_group(self, rot_bonds_per_group, core_indexes): + core_atom_per_group = list() + for rot_bonds in rot_bonds_per_group: + for (a1, a2) in rot_bonds: + if a1 in core_indexes: + core_atom_per_group.append(a1) + break + elif a2 in core_indexes: + core_atom_per_group.append(a2) + break + else: + core_atom_per_group.append(None) + + return core_atom_per_group + + def _get_sorted_bonds_per_group(self, core_atom_per_group, + rot_bonds_per_group, distances): + sorted_rot_bonds_per_group = list() + for core_atom, rot_bonds in zip(core_atom_per_group, + rot_bonds_per_group): + sorting_dict = dict() + for bond in rot_bonds: + min_d = min([distances[core_atom][bond[0]], + distances[core_atom][bond[1]]]) + sorting_dict[bond] = min_d + + sorted_rot_bonds_per_group.append( + [i[0] for i in + sorted(sorting_dict.items(), key=lambda item: item[1])]) + + return sorted_rot_bonds_per_group + + def build_rotamer_library(self, resolution): + core_atoms = set() + for atom in self.molecule.atoms: + if atom.core: + core_atoms.add(atom) + core_indexes = [atom.index for atom in core_atoms] + + assert len(core_atoms) > 0, 'No core atoms were found' + + branch_graph = deepcopy(self) + + for core_atom in core_atoms: + branch_graph.remove_node(core_atom.index) + + branch_groups = list(nx.connected_components(branch_graph)) + + rot_bonds_per_group = self._get_rot_bonds_per_group(branch_groups) + + core_atom_per_group = self._get_core_atom_per_group( + rot_bonds_per_group, core_indexes) + + distances = dict(nx.shortest_path_length(self)) + + sorted_rot_bonds_per_group = self._get_sorted_bonds_per_group( + core_atom_per_group, rot_bonds_per_group, distances) + + rotamer_library = RotamerLibrary(self.molecule.name) + + # PELE needs underscores instead of whitespaces + pdb_atom_names = [name.replace(' ', '_',) + for name in self.molecule.get_pdb_atom_names()] + + for group_id, rot_bonds in enumerate(sorted_rot_bonds_per_group): + for (atom1_index, atom2_index) in rot_bonds: + atom1_name = pdb_atom_names[atom1_index] + atom2_name = pdb_atom_names[atom2_index] + rotamer = Rotamer(atom1_name, atom2_name, resolution) + rotamer_library.add_rotamer(rotamer, group_id) + + return rotamer_library + + @property + def molecule(self): + return self._molecule From 3fb83429a1031cbf64e5c0ea6455ce6f203757ef Mon Sep 17 00:00:00 2001 From: Marti Municoy Date: Mon, 6 Jul 2020 15:51:24 +0200 Subject: [PATCH 33/67] Main module is added --- offPELE/__init__.py | 2 ++ offPELE/main.py | 29 +++++++++++++++++++++++++++++ 2 files changed, 31 insertions(+) create mode 100644 offPELE/main.py diff --git a/offPELE/__init__.py b/offPELE/__init__.py index e44e9d15..4ad4b77d 100644 --- a/offPELE/__init__.py +++ b/offPELE/__init__.py @@ -1,3 +1,5 @@ from ._version import get_versions __version__ = get_versions()['version'] del get_versions + +from main import main diff --git a/offPELE/main.py b/offPELE/main.py new file mode 100644 index 00000000..90982a4f --- /dev/null +++ b/offPELE/main.py @@ -0,0 +1,29 @@ +# -*- coding: utf-8 -*- + + +# Global imports +import argparse as ap + + +# Script information +__author__ = "Marti Municoy" +__license__ = "GPL" +__maintainer__ = "Marti Municoy" +__email__ = "marti.municoy@bsc.es" + + +def parse_args(): + parser = ap.ArgumentParser() + parser.add_argument("pdb_file", metavar="FILE", type=str, + help="Path PDB file to parameterize") + args = parser.parse_args() + + return args.pdb_file + + +def main(): + pass + + +if __name__ == '__main__': + main() From c69643f94333753a59f22b3f2aae13498bf6d7fa Mon Sep 17 00:00:00 2001 From: Daniel Date: Mon, 6 Jul 2020 16:06:51 +0200 Subject: [PATCH 34/67] Main function development --- offPELE/__init__.py | 2 -- offPELE/main.py | 8 +++++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/offPELE/__init__.py b/offPELE/__init__.py index 4ad4b77d..e44e9d15 100644 --- a/offPELE/__init__.py +++ b/offPELE/__init__.py @@ -1,5 +1,3 @@ from ._version import get_versions __version__ = get_versions()['version'] del get_versions - -from main import main diff --git a/offPELE/main.py b/offPELE/main.py index 90982a4f..345846a2 100644 --- a/offPELE/main.py +++ b/offPELE/main.py @@ -14,15 +14,17 @@ def parse_args(): parser = ap.ArgumentParser() - parser.add_argument("pdb_file", metavar="FILE", type=str, + parser.add_argument("pdb_file", metavar="PDB FILE", type=str, help="Path PDB file to parameterize") args = parser.parse_args() - return args.pdb_file + return args def main(): - pass + args = parse_args() + print('hey') + print(args.pdb_file) if __name__ == '__main__': From 17aa547565f8f0faeebcca78453490ccf8c057e6 Mon Sep 17 00:00:00 2001 From: Marti Municoy Date: Mon, 6 Jul 2020 17:51:09 +0200 Subject: [PATCH 35/67] Main function fully implemented --- offPELE/main.py | 101 ++++++++++++++++++++++++++++++++++++++++- offPELE/utils/utils.py | 15 ++++++ 2 files changed, 114 insertions(+), 2 deletions(-) diff --git a/offPELE/main.py b/offPELE/main.py index 345846a2..cf8e2dd1 100644 --- a/offPELE/main.py +++ b/offPELE/main.py @@ -2,8 +2,13 @@ # Global imports +import os +import warnings import argparse as ap +import offPELE +from offPELE.utils import check_if_path_exists, create_path + # Script information __author__ = "Marti Municoy" @@ -12,19 +17,111 @@ __email__ = "marti.municoy@bsc.es" +# Constants +DEFAULT_OFF_FORCEFIELD = 'openff_unconstrained-1.1.1.offxml' +DEFAULT_RESOLUTION = int(30) +IMPACT_TEMPLATE_PATH = 'DataLocal/Templates/OFF/Parsley/HeteroAtoms/' +ROTAMER_LIBRARY_PATH = 'DataLocal/LigandRotamerLibs/' +SOLVENT_TEMPLATE_PATH = 'DataLocal/OBC/' + + +# Functions def parse_args(): parser = ap.ArgumentParser() parser.add_argument("pdb_file", metavar="PDB FILE", type=str, help="Path PDB file to parameterize") + parser.add_argument("-f", "--forcefield", metavar="OFF FORCEFIELD", + type=str, help="OFF forcefield name. Default is " + + str(DEFAULT_OFF_FORCEFIELD), + default=DEFAULT_OFF_FORCEFIELD) + parser.add_argument("-r", "--resolution", metavar="INT", + help="Rotamer library resolution. Default is " + + str(DEFAULT_RESOLUTION), + default=DEFAULT_RESOLUTION) + parser.add_argument("-o", "--output", metavar="PATH", + help="Output path. Default is the current working " + + "directory") + parser.add_argument('--with_solvent', dest='with_solvent', + help="Generate OBC solvent parameters", + action='store_true') + parser.add_argument('--as_DataLocal', dest='as_datalocal', + help="Output will be saved following PELE's DataLocal " + + "hierarchy", action='store_true') + + parser.set_defaults(as_datalocal=False) + parser.set_defaults(with_solvent=False) + args = parser.parse_args() + if args.output is None: + args.output = os.getcwd() + return args +def handle_output_paths(molecule, args): + from pathlib import Path + name = molecule.name + output_path = Path(args.output) + check_if_path_exists(output_path) + + rotlib_path = output_path + impact_path = output_path + solvent_path = output_path + + rotlib_name = name.upper() + '.rot.assign' + impact_name = name.lower() + 'z' + solvent_name = name.lower() + '_solv.json' + + if args.as_datalocal: + rotlib_path = rotlib_path.joinpath(ROTAMER_LIBRARY_PATH) + impact_path = impact_path.joinpath(IMPACT_TEMPLATE_PATH) + solvent_path = solvent_path.joinpath(SOLVENT_TEMPLATE_PATH) + + create_path(rotlib_path) + create_path(impact_path) + create_path(solvent_path) + + return rotlib_path.joinpath(rotlib_name), \ + impact_path.joinpath(impact_name), \ + solvent_path.joinpath(solvent_name) + + def main(): args = parse_args() - print('hey') - print(args.pdb_file) + print('Open Force Field parameterizer for PELE v' + '{}'.format(offPELE.__version__)) + print('-' * 60) + print(' - PDB to parameterize: {}'.format(args.pdb_file)) + print(' - Force field: {}'.format(args.forcefield)) + print(' - Rotamer library resolution: {}'.format(args.resolution)) + print(' - Output path: {}'.format(args.output)) + print(' - DataLocal-like output: {}'.format(args.as_datalocal)) + print('-' * 60 + '\n') + + # Supress OpenForceField toolkit warnings + import logging + logging.getLogger().setLevel(logging.ERROR) + + from offPELE.topology import Molecule + from offPELE.template import Impact + from offPELE.solvent import OBC2 + + molecule = Molecule(args.pdb_file) + molecule.parameterize(args.forcefield) + + rotlib_out, impact_out, solvent_out = handle_output_paths(molecule, args) + + molecule.build_rotamer_library(resolution=args.resolution) + molecule.rotamer_library.to_file(rotlib_out) + impact = Impact(molecule) + impact.write(impact_out) + + if args.with_solvent: + solvent = OBC2(molecule) + solvent.to_json_file(solvent_out) + + print(' - All files were generated with successfully') if __name__ == '__main__': diff --git a/offPELE/utils/utils.py b/offPELE/utils/utils.py index f8ee6b0f..c9534f28 100644 --- a/offPELE/utils/utils.py +++ b/offPELE/utils/utils.py @@ -28,3 +28,18 @@ def temporary_cd(path): def warning_on_one_line(message, category, filename, lineno, file=None, line=None): return ' %s:%s: %s:%s' % (filename, lineno, category.__name__, message) + + +def check_if_path_exists(path): + from pathlib import Path + + if not isinstance(path, Path): + path = Path(path) + + if not path.is_dir(): + raise ValueError('Invalid path to {}'.format(path)) + + +def create_path(path): + import os + os.makedirs(str(path), exist_ok=True) From d1f5f3d57d7f18e3cf0676aa30544cb813f6a167 Mon Sep 17 00:00:00 2001 From: Marti Municoy Date: Mon, 6 Jul 2020 17:59:29 +0200 Subject: [PATCH 36/67] Minor fixes --- offPELE/utils/toolkits.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/offPELE/utils/toolkits.py b/offPELE/utils/toolkits.py index 0084bf83..5abfe13d 100644 --- a/offPELE/utils/toolkits.py +++ b/offPELE/utils/toolkits.py @@ -54,8 +54,8 @@ def __init__(self): if not self.is_available(): raise ToolkitUnavailableException( - 'The required toolkit {self.toolkit_name} is not ' - 'available.') + 'The required toolkit {} is not '.format(self.toolkit_name) + + 'available.') @staticmethod def is_available(): From 97cf6e2827ca5b02cbf798a2a77c626c5f86aab2 Mon Sep 17 00:00:00 2001 From: Marti Municoy Date: Mon, 6 Jul 2020 18:19:31 +0200 Subject: [PATCH 37/67] Minor changes --- offPELE/main.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/offPELE/main.py b/offPELE/main.py index cf8e2dd1..54b20912 100644 --- a/offPELE/main.py +++ b/offPELE/main.py @@ -35,8 +35,8 @@ def parse_args(): + str(DEFAULT_OFF_FORCEFIELD), default=DEFAULT_OFF_FORCEFIELD) parser.add_argument("-r", "--resolution", metavar="INT", - help="Rotamer library resolution. Default is " - + str(DEFAULT_RESOLUTION), + help="Rotamer library resolution in degrees. " + + "Default is " + str(DEFAULT_RESOLUTION), default=DEFAULT_RESOLUTION) parser.add_argument("-o", "--output", metavar="PATH", help="Output path. Default is the current working " From f78740cd3b12016973fb7148187072cae1e17914 Mon Sep 17 00:00:00 2001 From: Marti Municoy Date: Mon, 6 Jul 2020 18:21:37 +0200 Subject: [PATCH 38/67] Minor changes --- offPELE/main.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/offPELE/main.py b/offPELE/main.py index 54b20912..2771bbb2 100644 --- a/offPELE/main.py +++ b/offPELE/main.py @@ -42,7 +42,7 @@ def parse_args(): help="Output path. Default is the current working " + "directory") parser.add_argument('--with_solvent', dest='with_solvent', - help="Generate OBC solvent parameters", + help="Generate solvent parameters for OBC", action='store_true') parser.add_argument('--as_DataLocal', dest='as_datalocal', help="Output will be saved following PELE's DataLocal " From fa477da730811ab627221b25722fe0b4a431dc0c Mon Sep 17 00:00:00 2001 From: Marti Municoy Date: Mon, 6 Jul 2020 18:23:34 +0200 Subject: [PATCH 39/67] Minor changes --- offPELE/main.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/offPELE/main.py b/offPELE/main.py index 2771bbb2..f51e2d16 100644 --- a/offPELE/main.py +++ b/offPELE/main.py @@ -30,9 +30,9 @@ def parse_args(): parser = ap.ArgumentParser() parser.add_argument("pdb_file", metavar="PDB FILE", type=str, help="Path PDB file to parameterize") - parser.add_argument("-f", "--forcefield", metavar="OFF FORCEFIELD", - type=str, help="OFF forcefield name. Default is " - + str(DEFAULT_OFF_FORCEFIELD), + parser.add_argument("-f", "--forcefield", metavar="NAME", + type=str, help="OpenForceField's forcefield name. " + + "Default is " + str(DEFAULT_OFF_FORCEFIELD), default=DEFAULT_OFF_FORCEFIELD) parser.add_argument("-r", "--resolution", metavar="INT", help="Rotamer library resolution in degrees. " From c3e1b43a43c2ada32e550a51f90d2b0e7a1ac9c8 Mon Sep 17 00:00:00 2001 From: Marti Municoy Date: Mon, 6 Jul 2020 18:43:34 +0200 Subject: [PATCH 40/67] Minor changes --- offPELE/main.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/offPELE/main.py b/offPELE/main.py index f51e2d16..af21c6e6 100644 --- a/offPELE/main.py +++ b/offPELE/main.py @@ -89,6 +89,7 @@ def handle_output_paths(molecule, args): def main(): args = parse_args() + print('-' * 60) print('Open Force Field parameterizer for PELE v' '{}'.format(offPELE.__version__)) print('-' * 60) @@ -97,7 +98,7 @@ def main(): print(' - Rotamer library resolution: {}'.format(args.resolution)) print(' - Output path: {}'.format(args.output)) print(' - DataLocal-like output: {}'.format(args.as_datalocal)) - print('-' * 60 + '\n') + print('-' * 60) # Supress OpenForceField toolkit warnings import logging @@ -122,6 +123,7 @@ def main(): solvent.to_json_file(solvent_out) print(' - All files were generated with successfully') + print('-' * 60) if __name__ == '__main__': From ffd8c529464552c3bcd60971d4f0a9a2b19fb179 Mon Sep 17 00:00:00 2001 From: Marti Municoy Date: Mon, 6 Jul 2020 18:46:40 +0200 Subject: [PATCH 41/67] Minor changes --- offPELE/main.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/offPELE/main.py b/offPELE/main.py index af21c6e6..2e6bfb7c 100644 --- a/offPELE/main.py +++ b/offPELE/main.py @@ -122,7 +122,7 @@ def main(): solvent = OBC2(molecule) solvent.to_json_file(solvent_out) - print(' - All files were generated with successfully') + print(' - All files were generated successfully') print('-' * 60) From 98ab989ecf258f0ef0fc5417a845c3654291160f Mon Sep 17 00:00:00 2001 From: Marti Municoy Date: Tue, 7 Jul 2020 07:44:01 +0200 Subject: [PATCH 42/67] Default forcefield changed to Parsley-1.2.0 --- offPELE/main.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/offPELE/main.py b/offPELE/main.py index 2e6bfb7c..44623c0e 100644 --- a/offPELE/main.py +++ b/offPELE/main.py @@ -18,7 +18,7 @@ # Constants -DEFAULT_OFF_FORCEFIELD = 'openff_unconstrained-1.1.1.offxml' +DEFAULT_OFF_FORCEFIELD = 'openff_unconstrained-1.2.0.offxml' DEFAULT_RESOLUTION = int(30) IMPACT_TEMPLATE_PATH = 'DataLocal/Templates/OFF/Parsley/HeteroAtoms/' ROTAMER_LIBRARY_PATH = 'DataLocal/LigandRotamerLibs/' From 4b3ab3d35bc9a4c2256773992ec820e8438bcb17 Mon Sep 17 00:00:00 2001 From: Marti Municoy Date: Wed, 8 Jul 2020 08:46:45 +0200 Subject: [PATCH 43/67] Benchmarks README initialized --- offPELE/data/benchmarks/README.md | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 offPELE/data/benchmarks/README.md diff --git a/offPELE/data/benchmarks/README.md b/offPELE/data/benchmarks/README.md new file mode 100644 index 00000000..6c3710e1 --- /dev/null +++ b/offPELE/data/benchmarks/README.md @@ -0,0 +1,17 @@ +# Benchmarks +Datasets to be used in benchmarking studies for offPELE. + +## Content +_Content under construction_ +- GPCRs +- PPI (Protein-protein inhibitors) +- Small molecule set +- Small molecule set with experimental hydration free energies + +## Analysis features +_Content under construction_ +- Rotamer library comparison between offPELE and PlopRotTemp +- Experimental hydration free energies comparison _(inside the PELE-platform)_ +- Comparison of parameters between offPELE and PlopRotTemp (bonds, angles, dihedrals, nonbonding and OBC) +- Structural comparison between PELE's OPLS and OFF implementations +- Energetic profile comparison in gold-standard systems (previously published) From 99027b735bf4cb68cf7f96f2eb15a6a25c05aa3d Mon Sep 17 00:00:00 2001 From: Marti Municoy Date: Tue, 14 Jul 2020 00:38:46 +0200 Subject: [PATCH 44/67] Docstrings are added --- offPELE/template/impact.py | 563 ++++++++++++++++++++++++++++++++++++- 1 file changed, 559 insertions(+), 4 deletions(-) diff --git a/offPELE/template/impact.py b/offPELE/template/impact.py index d0ac4c2c..0eba22ca 100644 --- a/offPELE/template/impact.py +++ b/offPELE/template/impact.py @@ -1,5 +1,8 @@ +""" +This module contains any class or function related with PELE's Impact +template. +""" -# Global imports from copy import deepcopy from simtk import unit @@ -9,7 +12,34 @@ class Impact(object): + """ + It is in charge of writing a Molecule object as a PELE's Impact + template. + """ + def __init__(self, molecule): + """ + Initiate and Impact object. + + Parameters + ---------- + molecule : An offPELE.topology.Molecule + A Molecule object to be written as an Impact file + + Examples + -------- + + Write the Impact template of a offPELE's molecule + + >>> from offPELE.topology import Molecule + >>> from offPELE.template import Impact + + >>> molecule = Molecule('molecule.pdb') + >>> molecule.parameterize('openff_unconstrained-1.1.1.offxml') + >>> impact = Impact(molecule) + >>> impact.write('molz') + + """ if (isinstance(molecule, offPELE.topology.Molecule) or isinstance(molecule, offPELE.topology.molecule.Molecule)): self._initialize_from_molecule(molecule) @@ -17,12 +47,21 @@ def __init__(self, molecule): raise Exception('Invalid input molecule for Impact template') def _initialize_from_molecule(self, molecule): + """ + Initializes an Impact object from an offPELE.topology.Molecule. + + Parameters + ---------- + molecule : An offPELE.topology.Molecule + A Molecule object to be written as an Impact file + """ # We will work with a copy to prevent the modification of the original # object self._molecule = deepcopy(molecule) self._sort() def _sort(self): + """ Sort and reindex atoms in a Molecule.""" sorted_atoms = list() # Sort by core attribute and parent index @@ -61,6 +100,14 @@ def _sort(self): improper.set_atom4_idx(reindexer[improper.atom4_idx]) def write(self, path): + """ + It writes the Impact template to a file. + + Parameters + ---------- + path : str + Path to write to + """ with open(path, 'w') as file: self._write_header(file) self._write_resx(file) @@ -72,6 +119,14 @@ def write(self, path): self._write_end(file) def _write_header(self, file): + """ + It writes the header of the Impact file. + + Parameters + ---------- + file : file object + File to write to + """ file.write('* LIGAND DATABASE FILE') if self.molecule.forcefield: file.write(' ({})'.format(self.molecule.forcefield)) @@ -81,6 +136,14 @@ def _write_header(self, file): file.write('*\n') def _write_resx(self, file): + """ + It writes the resx section of the Impact file. + + Parameters + ---------- + file : file object + File to write to + """ # template name file.write('{:5}'.format(self.molecule.name)) # number of non bonding parameters @@ -124,6 +187,14 @@ def _write_resx(self, file): # TODO Should we add the interactions matrix here? def _write_nbon(self, file): + """ + It writes the nbon section of the Impact file. + + Parameters + ---------- + file : file object + File to write to + """ file.write('NBON\n') for atom in self.molecule.atoms: w_atom = WritableAtom(atom) @@ -156,6 +227,14 @@ def _write_nbon(self, file): file.write('\n') def _write_bond(self, file): + """ + It writes the bond section of the Impact file. + + Parameters + ---------- + file : file object + File to write to + """ file.write('BOND\n') for bond in self.molecule.bonds: w_bond = WritableBond(bond) @@ -176,6 +255,14 @@ def _write_bond(self, file): file.write('{: 6.3f}\n'.format(eq_dist)) def _write_thet(self, file): + """ + It writes the thet section of the Impact file. + + Parameters + ---------- + file : file object + File to write to + """ file.write('THET\n') for angle in self.molecule.angles: w_angle = WritableAngle(angle) @@ -199,6 +286,14 @@ def _write_thet(self, file): file.write('{: 11.5f}\n'.format(eq_angl)) def _write_phi(self, file): + """ + It writes the phi section of the Impact file. + + Parameters + ---------- + file : file object + File to write to + """ file.write('PHI\n') for proper in self.molecule.propers: w_proper = WritableProper(proper) @@ -227,6 +322,14 @@ def _write_phi(self, file): file.write('\n') def _write_iphi(self, file): + """ + It writes the iphi section of the Impact file. + + Parameters + ---------- + file : file object + File to write to + """ file.write('IPHI\n') for improper in self.molecule.impropers: w_improper = WritableImproper(improper) @@ -258,16 +361,49 @@ def _write_iphi(self, file): file.write('\n') def _write_end(self, file): + """ + It writes the ending line of the Impact file. + + Parameters + ---------- + file : file object + File to write to + """ file.write('END\n') @property def molecule(self): + """ + The offPELE's Molecule. + + Returns + ------- + molecule : an offPELE.topology.Molecule + The offPELE's Molecule object + """ return self._molecule class WritableWrapper(object): + """ + Wrapper class for writable parameters. + """ + @staticmethod def none_to_zero(f): + """ + It converts a returned None to zero. + + Parameters + ---------- + f : function + The function to apply the decorator to + + Returns + ------- + out : function's output + It is set to zero in case that it is None + """ def function_wrapper(*args, **kwargs): out = f(*args, **kwargs) if out is None: @@ -277,6 +413,19 @@ def function_wrapper(*args, **kwargs): @staticmethod def dummy_to_writable(f): + """ + It converts a returned DummyAtom to a WritableAtom. + + Parameters + ---------- + f : function + The function to apply the decorator to + + Returns + ------- + out : WritableAtom + A WritableAtom object + """ def function_wrapper(*args, **kwargs): out = f(*args, **kwargs) out = WritableAtom(out) @@ -285,6 +434,19 @@ def function_wrapper(*args, **kwargs): @staticmethod def none_to_dummy(f): + """ + It converts a returned None to a DummyAtom. + + Parameters + ---------- + f : function + The function to apply the decorator to + + Returns + ------- + out : DummyAtom + A DummyAtom object + """ def function_wrapper(*args, **kwargs): out = f(*args, **kwargs) if out is None: @@ -294,6 +456,19 @@ def function_wrapper(*args, **kwargs): @staticmethod def in_angstrom(f): + """ + It expresses a simtk.unit.Quantity in angstroms. + + Parameters + ---------- + f : function + The function to apply the decorator to + + Returns + ------- + out : float + simtk.unit.Quantity expressed in angstroms + """ def function_wrapper(*args, **kwargs): out = f(*args, **kwargs) return out.value_in_unit(unit.angstrom) @@ -301,6 +476,19 @@ def function_wrapper(*args, **kwargs): @staticmethod def in_kcalmol(f): + """ + It expresses a simtk.unit.Quantity in kcal/mol. + + Parameters + ---------- + f : function + The function to apply the decorator to + + Returns + ------- + out : float + simtk.unit.Quantity expressed in kcal/mol + """ def function_wrapper(*args, **kwargs): out = f(*args, **kwargs) return out.value_in_unit(unit.kilocalorie / unit.mole) @@ -308,6 +496,19 @@ def function_wrapper(*args, **kwargs): @staticmethod def in_elementarycharge(f): + """ + It expresses a simtk.unit.Quantity in elementary charges. + + Parameters + ---------- + f : function + The function to apply the decorator to + + Returns + ------- + out : float + simtk.unit.Quantity expressed in elementary charges + """ def function_wrapper(*args, **kwargs): out = f(*args, **kwargs) return out.value_in_unit(unit.elementary_charge) @@ -315,6 +516,19 @@ def function_wrapper(*args, **kwargs): @staticmethod def in_kcal_rad2mol(f): + """ + It expresses a simtk.unit.Quantity in kcal/rad2mol. + + Parameters + ---------- + f : function + The function to apply the decorator to + + Returns + ------- + out : float + simtk.unit.Quantity expressed in kcal/rad2mol + """ def function_wrapper(*args, **kwargs): out = f(*args, **kwargs) return out.value_in_unit(unit.kilocalorie @@ -323,6 +537,19 @@ def function_wrapper(*args, **kwargs): @staticmethod def in_deg(f): + """ + It expresses a simtk.unit.Quantity in degrees. + + Parameters + ---------- + f : function + The function to apply the decorator to + + Returns + ------- + out : float + simtk.unit.Quantity expressed in degrees + """ def function_wrapper(*args, **kwargs): out = f(*args, **kwargs) return out.value_in_unit(unit.degree) @@ -330,6 +557,19 @@ def function_wrapper(*args, **kwargs): @staticmethod def in_kcal_angstrom2mol(f): + """ + It expresses a simtk.unit.Quantity in kcal/angstrom2mol. + + Parameters + ---------- + f : function + The function to apply the decorator to + + Returns + ------- + out : float + simtk.unit.Quantity expressed in kcal/angstrom2mol + """ def function_wrapper(*args, **kwargs): out = f(*args, **kwargs) return out.value_in_unit(unit.kilocalorie @@ -338,7 +578,19 @@ def function_wrapper(*args, **kwargs): class WritableAtom(offPELE.topology.molecule.Atom, WritableWrapper): + """ + Writable offPELE's Atom class + """ + def __init__(self, atom): + """ + It initializes a WritableAtom object. + + Parameters + ---------- + atom : an offPELE.topology.molecule.Atom + The Atom to create the WritableAtom with + """ # We do not want to modify the original object atom = deepcopy(atom) @@ -356,69 +608,184 @@ def __init__(self, atom): @WritableWrapper.dummy_to_writable @WritableWrapper.none_to_dummy def parent(self): + """ + Atom's parent. + + Returns + ------- + parent : an offPELE.topology.molecule.Atom + The parent of this Atom object + """ return super().parent @property def index(self): + """ + Atom's index. + + Returns + ------- + index : int + The index of this Atom object + """ return int(self._index) + 1 @property def core(self): + """ + Atom's core char. + + Returns + ------- + index : str + The core type of this Atom object + """ if self._core: return 'M' else: return 'S' - # TODO Consider removing any reference to OPLS, if possible - # Otherwise, use SMIRks to find the best match @property def OPLS_type(self): + """ + Atom's OPLS type. + + .. todo :: + + * Consider removing any reference to OPLS, if possible + Otherwise, use SMIRks to find the best match + + Returns + ------- + index : str + The OLPS type of this Atom object + """ return 'OFFT' # stands for OpenForceField type - # TODO Review the actual purpose of this attribute in PELE + # TODO @property @WritableWrapper.none_to_zero def unknown(self): + """ + Atom's unknown int. + + .. todo :: + + * Review the actual purpose of this attribute in PELE + + Returns + ------- + unknown : int + The unknown int of this Atom object + """ return super().unknown @property @WritableWrapper.in_angstrom def sigma(self): + """ + Atom's sigma. + + Returns + ------- + sigma : float + The sigma of this Atom object, expressed in angstroms + """ return super().sigma @property @WritableWrapper.in_kcalmol def epsilon(self): + """ + Atom's epsilon. + + Returns + ------- + epsilon : float + The epsilon of this Atom object, expressed in kcal/mol + """ return super().epsilon @property @WritableWrapper.in_elementarycharge def charge(self): + """ + Atom's charge. + + Returns + ------- + charge : float + The charge of this Atom object, expressed in elementary units + """ return super().charge @property @WritableWrapper.none_to_zero def born_radius(self): + """ + Atom's Born radius. + + Returns + ------- + born_radius : float + The Born radius of this Atom object + """ return super().born_radius @property @WritableWrapper.in_angstrom def SASA_radius(self): + """ + Atom's SASA radius. + + Returns + ------- + SASA_radius : float + The SASA radius of this Atom object, expressed in angstroms + """ return super().SASA_radius @property @WritableWrapper.none_to_zero def nonpolar_gamma(self): + """ + Atom's nonpolar gamma. + + Returns + ------- + nonpolar_gamma : float + The nonpolar gamma of this Atom object + """ return super().nonpolar_gamma @property @WritableWrapper.none_to_zero def nonpolar_alpha(self): + """ + Atom's nonpolar alpha. + + Returns + ------- + nonpolar_alpha : float + The nonpolar alpha of this Atom object + """ return super().nonpolar_alpha class WritableBond(offPELE.topology.Bond, WritableWrapper): + """ + Writable offPELE's Bond class + """ + def __init__(self, bond): + """ + It initializes a WritableBond object. + + Parameters + ---------- + bond : an offPELE.topology.Bond + The Bond to create the WritableBond with + """ # We do not want to modify the original object bond = deepcopy(bond) @@ -433,25 +800,69 @@ def __init__(self, bond): @property def atom1_idx(self): + """ + Bond's atom1 index. + + Returns + ------- + atom1_idx : int + The index of the first atom involved in this Bond object + """ return super().atom1_idx + 1 @property def atom2_idx(self): + """ + Bond's atom2 index. + + Returns + ------- + atom2_idx : int + The index of the second atom involved in this Bond object + """ return super().atom2_idx + 1 @property @WritableWrapper.in_kcal_angstrom2mol def spring_constant(self): + """ + Bond's spring constant. + + Returns + ------- + spring_constant : float + The spring constant of this Bond object + """ return super().spring_constant @property @WritableWrapper.in_angstrom def eq_dist(self): + """ + Bond's equilibrium distance. + + Returns + ------- + eq_dist : float + The equilibrium distance of this Bond object + """ return super().eq_dist class WritableAngle(offPELE.topology.Angle, WritableWrapper): + """ + Writable offPELE's Angle class + """ + def __init__(self, angle): + """ + It initializes a WritableAngle object. + + Parameters + ---------- + angle : an offPELE.topology.Angle + The Angle to create the WritableAngle with + """ # We do not want to modify the original object angle = deepcopy(angle) @@ -466,29 +877,81 @@ def __init__(self, angle): @property def atom1_idx(self): + """ + Angle's atom1 index. + + Returns + ------- + atom1_idx : int + The index of the first atom involved in this Angle object + """ return super().atom1_idx + 1 @property def atom2_idx(self): + """ + Angle's atom2 index. + + Returns + ------- + atom2_idx : int + The index of the second atom involved in this Angle object + """ return super().atom2_idx + 1 @property def atom3_idx(self): + """ + Angle's atom3 index. + + Returns + ------- + atom3_idx : int + The index of the third atom involved in this Angle object + """ return super().atom3_idx + 1 @property @WritableWrapper.in_kcal_rad2mol def spring_constant(self): + """ + Angle's spring constant. + + Returns + ------- + spring_constant : float + The spring constant of this Angle object + """ return super().spring_constant @property @WritableWrapper.in_deg def eq_angle(self): + """ + Angle's equilibrium distance. + + Returns + ------- + eq_angle : float + The equilibrium angle of this Angle object + """ return super().eq_angle class WritableProper(offPELE.topology.Proper, WritableWrapper): + """ + Writable offPELE's Proper class + """ + def __init__(self, proper): + """ + It initializes a WritableProper object. + + Parameters + ---------- + proper : an offPELE.topology.Proper + The Proper to create the WritableProper with + """ # We do not want to modify the original object proper = deepcopy(proper) @@ -506,28 +969,80 @@ def __init__(self, proper): @property def atom1_idx(self): + """ + Proper's atom1 index. + + Returns + ------- + atom1_idx : int + The index of the first atom involved in this Proper object + """ return super().atom1_idx + 1 @property def atom2_idx(self): + """ + Proper's atom2 index. + + Returns + ------- + atom2_idx : int + The index of the second atom involved in this Proper object + """ return super().atom2_idx + 1 @property def atom3_idx(self): + """ + Proper's atom3 index. + + Returns + ------- + atom3_idx : int + The index of the third atom involved in this Proper object + """ return super().atom3_idx + 1 @property def atom4_idx(self): + """ + Proper's atom4 index. + + Returns + ------- + atom4_idx : int + The index of the fourth atom involved in this Proper object + """ return super().atom4_idx + 1 @property @WritableWrapper.in_kcalmol def constant(self): + """ + Proper's constant. + + Returns + ------- + constant : float + The constant of this Proper object, expressed in kcal/mol + """ return super().constant class WritableImproper(offPELE.topology.Improper, WritableWrapper): + """ + Writable offPELE's Improper class + """ + def __init__(self, improper): + """ + It initializes a WritableImproper object. + + Parameters + ---------- + improper : an offPELE.topology.Improper + The Improper to create the WritableImproper with + """ # We do not want to modify the original object improper = deepcopy(improper) @@ -545,21 +1060,61 @@ def __init__(self, improper): @property def atom1_idx(self): + """ + Improper's atom1 index. + + Returns + ------- + atom1_idx : int + The index of the first atom involved in this Improper object + """ return super().atom1_idx + 1 @property def atom2_idx(self): + """ + Improper's atom2 index. + + Returns + ------- + atom2_idx : int + The index of the second atom involved in this Improper object + """ return super().atom2_idx + 1 @property def atom3_idx(self): + """ + Improper's atom3 index. + + Returns + ------- + atom3_idx : int + The index of the third atom involved in this Improper object + """ return super().atom3_idx + 1 @property def atom4_idx(self): + """ + Improper's atom4 index. + + Returns + ------- + atom4_idx : int + The index of the fourth atom involved in this Improper object + """ return super().atom4_idx + 1 @property @WritableWrapper.in_kcalmol def constant(self): + """ + Improper's constant. + + Returns + ------- + constant : float + The constant of this Improper object, expressed in kcal/mol + """ return super().constant From 08240453b9df1f0f33a2959bc0174d8f1bf28b6f Mon Sep 17 00:00:00 2001 From: danielSoler93 Date: Tue, 14 Jul 2020 03:20:48 +0200 Subject: [PATCH 45/67] Generate main to run as external module --- offPELE/main.py | 41 +++++++++++++++++++++++++---------------- 1 file changed, 25 insertions(+), 16 deletions(-) diff --git a/offPELE/main.py b/offPELE/main.py index 44623c0e..aef7c1e2 100644 --- a/offPELE/main.py +++ b/offPELE/main.py @@ -23,6 +23,9 @@ IMPACT_TEMPLATE_PATH = 'DataLocal/Templates/OFF/Parsley/HeteroAtoms/' ROTAMER_LIBRARY_PATH = 'DataLocal/LigandRotamerLibs/' SOLVENT_TEMPLATE_PATH = 'DataLocal/OBC/' +DEFAULT_OUTPUT = False +DEFAULT_DATA_LOCAL = False +DEFAULT_SOLVENT = True # Functions @@ -59,10 +62,10 @@ def parse_args(): return args -def handle_output_paths(molecule, args): +def handle_output_paths(molecule, output, as_datalocal): from pathlib import Path name = molecule.name - output_path = Path(args.output) + output_path = Path(output) check_if_path_exists(output_path) rotlib_path = output_path @@ -73,7 +76,7 @@ def handle_output_paths(molecule, args): impact_name = name.lower() + 'z' solvent_name = name.lower() + '_solv.json' - if args.as_datalocal: + if as_datalocal: rotlib_path = rotlib_path.joinpath(ROTAMER_LIBRARY_PATH) impact_path = impact_path.joinpath(IMPACT_TEMPLATE_PATH) solvent_path = solvent_path.joinpath(SOLVENT_TEMPLATE_PATH) @@ -87,17 +90,18 @@ def handle_output_paths(molecule, args): solvent_path.joinpath(solvent_name) -def main(): - args = parse_args() +def main(pdb_file, forcefield=DEFAULT_OFF_FORCEFIELD, resolution=DEFAULT_RESOLUTION, + output=DEFAULT_OUTPUT, as_datalocal=DEFAULT_DATA_LOCAL, + with_solvent=DEFAULT_SOLVENT): print('-' * 60) print('Open Force Field parameterizer for PELE v' '{}'.format(offPELE.__version__)) print('-' * 60) - print(' - PDB to parameterize: {}'.format(args.pdb_file)) - print(' - Force field: {}'.format(args.forcefield)) - print(' - Rotamer library resolution: {}'.format(args.resolution)) - print(' - Output path: {}'.format(args.output)) - print(' - DataLocal-like output: {}'.format(args.as_datalocal)) + print(' - PDB to parameterize: {}'.format(pdb_file)) + print(' - Force field: {}'.format(forcefield)) + print(' - Rotamer library resolution: {}'.format(resolution)) + print(' - Output path: {}'.format(output)) + print(' - DataLocal-like output: {}'.format(as_datalocal)) print('-' * 60) # Supress OpenForceField toolkit warnings @@ -108,17 +112,20 @@ def main(): from offPELE.template import Impact from offPELE.solvent import OBC2 - molecule = Molecule(args.pdb_file) - molecule.parameterize(args.forcefield) + if not output: + output = os.getcwd() + + molecule = Molecule(pdb_file) + molecule.parameterize(forcefield) - rotlib_out, impact_out, solvent_out = handle_output_paths(molecule, args) + rotlib_out, impact_out, solvent_out = handle_output_paths(molecule, output, as_datalocal) - molecule.build_rotamer_library(resolution=args.resolution) + molecule.build_rotamer_library(resolution=resolution) molecule.rotamer_library.to_file(rotlib_out) impact = Impact(molecule) impact.write(impact_out) - if args.with_solvent: + if with_solvent: solvent = OBC2(molecule) solvent.to_json_file(solvent_out) @@ -127,4 +134,6 @@ def main(): if __name__ == '__main__': - main() + args = parse_args() + main(args.pdb_file, args.forcefield, args.resolution, + args.output, args.as_datalocal) From 09908a4fb1a7a40739e6e657fae9e7b6b3081c0d Mon Sep 17 00:00:00 2001 From: Marti Municoy Date: Tue, 14 Jul 2020 08:58:19 +0200 Subject: [PATCH 46/67] Add docstrings to tests --- offPELE/tests/test_parameters.py | 12 ++++++++++++ offPELE/tests/utils.py | 25 +++++++++++++++++++++++++ 2 files changed, 37 insertions(+) diff --git a/offPELE/tests/test_parameters.py b/offPELE/tests/test_parameters.py index b8a6329c..7e261ed0 100644 --- a/offPELE/tests/test_parameters.py +++ b/offPELE/tests/test_parameters.py @@ -1,3 +1,7 @@ +""" +This module contains the tests to check offPELE's parameters. +""" + import pytest from simtk import unit @@ -10,7 +14,15 @@ class TestDihedrals(object): + """ + It wraps all tests that involve the dihedral parameters. + """ + def test_OFF_to_PELE_conversion(self): + """ + It checks the difference between dihedral equations from PELE and + Open Force Field. Their values should match throughout all the domain. + """ MAX_THRESHOLD = 1e-10 FORCEFIELD_NAME = 'openff_unconstrained-1.1.1.offxml' diff --git a/offPELE/tests/utils.py b/offPELE/tests/utils.py index 9b0c1106..0db8576a 100644 --- a/offPELE/tests/utils.py +++ b/offPELE/tests/utils.py @@ -1,3 +1,7 @@ +""" +This module contains a variety of helpful tools for tests. +""" + import numpy as np @@ -6,9 +10,30 @@ def apply_PELE_dihedral_equation(proper, x): + """ + Given an x, it applies the PELE's dihedral equation to obtain a y. + + Parameters + ---------- + proper : an offPELE.topology.Proper + The proper whose parameters will be applied to equation + x : float + Equation's x value + """ return proper.constant * (1 + proper.prefactor * np.cos(proper.periodicity * x)) def apply_OFF_dihedral_equation(proper, x): + """ + Given an x, it applies the Open Force Field's dihedral equation to obtain + a y. + + Parameters + ---------- + proper : an offPELE.topology.Proper + The proper whose parameters will be applied to equation + x : float + Equation's x value + """ return proper.k * (1 + np.cos(proper.periodicity * x - proper.phase)) From 64d0216c24f18eb21dc5d5a368fe7f03888c4615 Mon Sep 17 00:00:00 2001 From: Marti Municoy Date: Tue, 14 Jul 2020 17:28:24 +0200 Subject: [PATCH 47/67] Add docstrings and split run_offPELE() from main() --- offPELE/main.py | 103 +++++++++++++++++++++++++++++++++++++----------- 1 file changed, 80 insertions(+), 23 deletions(-) diff --git a/offPELE/main.py b/offPELE/main.py index aef7c1e2..13c1b3dd 100644 --- a/offPELE/main.py +++ b/offPELE/main.py @@ -1,35 +1,37 @@ # -*- coding: utf-8 -*- +""" +This module is designed to run offPELE through the command-line. +""" + +__author__ = "Marti Municoy" +__license__ = "GPL" +__maintainer__ = "Marti Municoy" +__email__ = "marti.municoy@bsc.es" -# Global imports import os -import warnings import argparse as ap import offPELE from offPELE.utils import check_if_path_exists, create_path -# Script information -__author__ = "Marti Municoy" -__license__ = "GPL" -__maintainer__ = "Marti Municoy" -__email__ = "marti.municoy@bsc.es" - - -# Constants DEFAULT_OFF_FORCEFIELD = 'openff_unconstrained-1.2.0.offxml' DEFAULT_RESOLUTION = int(30) IMPACT_TEMPLATE_PATH = 'DataLocal/Templates/OFF/Parsley/HeteroAtoms/' ROTAMER_LIBRARY_PATH = 'DataLocal/LigandRotamerLibs/' SOLVENT_TEMPLATE_PATH = 'DataLocal/OBC/' -DEFAULT_OUTPUT = False -DEFAULT_DATA_LOCAL = False -DEFAULT_SOLVENT = True -# Functions def parse_args(): + """ + It parses the command-line arguments. + + Returns + ------- + args : argparse.Namespace + It contains the command-line arguments that are supplied by the user + """ parser = ap.ArgumentParser() parser.add_argument("pdb_file", metavar="PDB FILE", type=str, help="Path PDB file to parameterize") @@ -56,13 +58,32 @@ def parse_args(): args = parser.parse_args() - if args.output is None: - args.output = os.getcwd() - return args def handle_output_paths(molecule, output, as_datalocal): + """ + It handles the output paths where offPELE's output files will be saved. + + Parameters + ---------- + molecule : offPELE.topology.Molecule + A Molecule object + output : str + The output path supplied by the user + as_datalocal : bool + Whether to save output files following PELE's DataLocal hierarchy or + not + + Returns + ------- + rotlib_path : pathlib.Path + The output path for the rotamer library + impact_path : pathlib.Path + The output path for the Impact template + solvent_path : pathlib.Path + The output path for the solvent template + """ from pathlib import Path name = molecule.name output_path = Path(output) @@ -90,9 +111,29 @@ def handle_output_paths(molecule, output, as_datalocal): solvent_path.joinpath(solvent_name) -def main(pdb_file, forcefield=DEFAULT_OFF_FORCEFIELD, resolution=DEFAULT_RESOLUTION, - output=DEFAULT_OUTPUT, as_datalocal=DEFAULT_DATA_LOCAL, - with_solvent=DEFAULT_SOLVENT): +def run_offPELE(pdb_file, forcefield=DEFAULT_OFF_FORCEFIELD, + resolution=DEFAULT_RESOLUTION, output=None, + with_solvent=False, as_datalocal=False,): + """ + It runs offPELE. + + Parameters + ---------- + pdb_file : str + The path to the pdb_file to parameterize with offPELE + forcefield : str + The name of an OpenForceField's forcefield + resolution : float + The resolution in degrees for the rotamer library + output : str + Path where output files will be saved + with_solvent : bool + Whether to generate and save the solvent parameters for the input + molecule or not + as_datalocal : bool + Whether to save output files following PELE's DataLocal hierarchy or + not + """ print('-' * 60) print('Open Force Field parameterizer for PELE v' '{}'.format(offPELE.__version__)) @@ -133,7 +174,23 @@ def main(pdb_file, forcefield=DEFAULT_OFF_FORCEFIELD, resolution=DEFAULT_RESOLUT print('-' * 60) -if __name__ == '__main__': +def main(): + """ + It reads the command-line arguments and calls offPELE. + + Examples + -------- + + From the command-line: + + >>> python main.py molecule.pdb -f openff_unconstrained-1.1.1.offxml -r 30 + -o output_path/ --with_solvent --as_DataLocal + + """ args = parse_args() - main(args.pdb_file, args.forcefield, args.resolution, - args.output, args.as_datalocal) + run_offPELE(args.pdb_file, args.forcefield, args.resolution, args.output, + args.as_datalocal) + + +if __name__ == '__main__': + main() From f603f066bbdef05253e24eb5c161012af06482a3 Mon Sep 17 00:00:00 2001 From: Marti Municoy Date: Tue, 14 Jul 2020 17:41:08 +0200 Subject: [PATCH 48/67] Fix minor bugs --- offPELE/main.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/offPELE/main.py b/offPELE/main.py index 13c1b3dd..2f259fd5 100644 --- a/offPELE/main.py +++ b/offPELE/main.py @@ -142,6 +142,7 @@ def run_offPELE(pdb_file, forcefield=DEFAULT_OFF_FORCEFIELD, print(' - Force field: {}'.format(forcefield)) print(' - Rotamer library resolution: {}'.format(resolution)) print(' - Output path: {}'.format(output)) + print(' - Write solvent parameters: {}'.format(with_solvent)) print(' - DataLocal-like output: {}'.format(as_datalocal)) print('-' * 60) @@ -189,7 +190,7 @@ def main(): """ args = parse_args() run_offPELE(args.pdb_file, args.forcefield, args.resolution, args.output, - args.as_datalocal) + args.with_solvent, args.as_datalocal) if __name__ == '__main__': From 59f5329de8b75dfd3b2f655199d9d2dca6686bd8 Mon Sep 17 00:00:00 2001 From: Marti Municoy Date: Wed, 15 Jul 2020 18:03:14 +0200 Subject: [PATCH 49/67] Change package name --- MANIFEST.in | 2 +- README.md | 4 +- offPELE/_version.py | 4 +- offPELE/data/benchmarks/README.md | 6 +- offPELE/examples/Parameterize.ipynb | 25 ++++++--- offPELE/main.py | 34 ++++++------ offPELE/solvent/solvent.py | 66 +++++++++++++++++++++- offPELE/template/impact.py | 86 ++++++++++++++--------------- offPELE/tests/test_parameters.py | 6 +- offPELE/tests/utils.py | 4 +- offPELE/topology/molecule.py | 2 +- offPELE/topology/rotamer.py | 2 +- offPELE/topology/zmatrix.py | 4 +- offPELE/utils/toolkits.py | 2 +- offPELE/utils/utils.py | 2 +- setup.cfg | 6 +- setup.py | 12 ++-- 17 files changed, 169 insertions(+), 98 deletions(-) diff --git a/MANIFEST.in b/MANIFEST.in index a206e51f..f3d03376 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -1,2 +1,2 @@ include versioneer.py -include offPELE/_version.py +include offpele/_version.py diff --git a/README.md b/README.md index b2203b28..5668dbea 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,2 @@ -# Open Force Field toolkit for PELE -The Open Force Field toolkit for PELE is a Python package that builds PELE-compatible force field templates using the Open Force Field toolkit. +# Open Force Field to PELE +The Open Force Field to PELE (offpele for short) is a Python package that builds PELE-compatible force field templates using the Open Force Field toolkit. diff --git a/offPELE/_version.py b/offPELE/_version.py index 4dd4f71f..c74e69ef 100644 --- a/offPELE/_version.py +++ b/offPELE/_version.py @@ -42,8 +42,8 @@ def get_config(): cfg.VCS = "git" cfg.style = "pep440" cfg.tag_prefix = "" - cfg.parentdir_prefix = "offPELE-" - cfg.versionfile_source = "offPELE/_version.py" + cfg.parentdir_prefix = "offpele-" + cfg.versionfile_source = "offpele/_version.py" cfg.verbose = False return cfg diff --git a/offPELE/data/benchmarks/README.md b/offPELE/data/benchmarks/README.md index 6c3710e1..ca3be857 100644 --- a/offPELE/data/benchmarks/README.md +++ b/offPELE/data/benchmarks/README.md @@ -1,5 +1,5 @@ # Benchmarks -Datasets to be used in benchmarking studies for offPELE. +Datasets to be used in benchmarking studies for offpele. ## Content _Content under construction_ @@ -10,8 +10,8 @@ _Content under construction_ ## Analysis features _Content under construction_ -- Rotamer library comparison between offPELE and PlopRotTemp +- Rotamer library comparison between offpele and PlopRotTemp - Experimental hydration free energies comparison _(inside the PELE-platform)_ -- Comparison of parameters between offPELE and PlopRotTemp (bonds, angles, dihedrals, nonbonding and OBC) +- Comparison of parameters between offpele and PlopRotTemp (bonds, angles, dihedrals, nonbonding and OBC) - Structural comparison between PELE's OPLS and OFF implementations - Energetic profile comparison in gold-standard systems (previously published) diff --git a/offPELE/examples/Parameterize.ipynb b/offPELE/examples/Parameterize.ipynb index acf4a6ce..5148fcf5 100644 --- a/offPELE/examples/Parameterize.ipynb +++ b/offPELE/examples/Parameterize.ipynb @@ -6,8 +6,17 @@ "metadata": {}, "outputs": [], "source": [ - "import offPELE.topology.molecule as mol\n", - "from offPELE.template import Impact" + "import offpele.topology.molecule as mol\n", + "from offpele.template import Impact" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [], + "source": [ + "from offpele.topology import Molecule" ] }, { @@ -54,7 +63,7 @@ }, { "cell_type": "code", - "execution_count": 6, + "execution_count": 3, "metadata": { "scrolled": false }, @@ -85,7 +94,7 @@ }, { "cell_type": "code", - "execution_count": 7, + "execution_count": 4, "metadata": {}, "outputs": [ { @@ -114,7 +123,7 @@ }, { "cell_type": "code", - "execution_count": 8, + "execution_count": 5, "metadata": {}, "outputs": [ { @@ -143,7 +152,7 @@ }, { "cell_type": "code", - "execution_count": 9, + "execution_count": 6, "metadata": {}, "outputs": [ { @@ -172,7 +181,7 @@ }, { "cell_type": "code", - "execution_count": 10, + "execution_count": 7, "metadata": {}, "outputs": [ { @@ -201,7 +210,7 @@ }, { "cell_type": "code", - "execution_count": 11, + "execution_count": 8, "metadata": {}, "outputs": [ { diff --git a/offPELE/main.py b/offPELE/main.py index 2f259fd5..d22824c0 100644 --- a/offPELE/main.py +++ b/offPELE/main.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- """ -This module is designed to run offPELE through the command-line. +This module is designed to run offpele through the command-line. """ __author__ = "Marti Municoy" @@ -12,8 +12,8 @@ import os import argparse as ap -import offPELE -from offPELE.utils import check_if_path_exists, create_path +import offpele +from offpele.utils import check_if_path_exists, create_path DEFAULT_OFF_FORCEFIELD = 'openff_unconstrained-1.2.0.offxml' @@ -63,11 +63,11 @@ def parse_args(): def handle_output_paths(molecule, output, as_datalocal): """ - It handles the output paths where offPELE's output files will be saved. + It handles the output paths where offpele's output files will be saved. Parameters ---------- - molecule : offPELE.topology.Molecule + molecule : offpele.topology.Molecule A Molecule object output : str The output path supplied by the user @@ -111,16 +111,16 @@ def handle_output_paths(molecule, output, as_datalocal): solvent_path.joinpath(solvent_name) -def run_offPELE(pdb_file, forcefield=DEFAULT_OFF_FORCEFIELD, - resolution=DEFAULT_RESOLUTION, output=None, - with_solvent=False, as_datalocal=False,): +def run_offpele(pdb_file, forcefield=DEFAULT_OFF_FORCEFIELD, + resolution=DEFAULT_RESOLUTION, output=None, + with_solvent=False, as_datalocal=False,): """ - It runs offPELE. + It runs offpele. Parameters ---------- pdb_file : str - The path to the pdb_file to parameterize with offPELE + The path to the pdb_file to parameterize with offpele forcefield : str The name of an OpenForceField's forcefield resolution : float @@ -136,7 +136,7 @@ def run_offPELE(pdb_file, forcefield=DEFAULT_OFF_FORCEFIELD, """ print('-' * 60) print('Open Force Field parameterizer for PELE v' - '{}'.format(offPELE.__version__)) + '{}'.format(offpele.__version__)) print('-' * 60) print(' - PDB to parameterize: {}'.format(pdb_file)) print(' - Force field: {}'.format(forcefield)) @@ -150,9 +150,9 @@ def run_offPELE(pdb_file, forcefield=DEFAULT_OFF_FORCEFIELD, import logging logging.getLogger().setLevel(logging.ERROR) - from offPELE.topology import Molecule - from offPELE.template import Impact - from offPELE.solvent import OBC2 + from offpele.topology import Molecule + from offpele.template import Impact + from offpele.solvent import OBC2 if not output: output = os.getcwd() @@ -177,7 +177,7 @@ def run_offPELE(pdb_file, forcefield=DEFAULT_OFF_FORCEFIELD, def main(): """ - It reads the command-line arguments and calls offPELE. + It reads the command-line arguments and calls offpele. Examples -------- @@ -189,8 +189,8 @@ def main(): """ args = parse_args() - run_offPELE(args.pdb_file, args.forcefield, args.resolution, args.output, - args.with_solvent, args.as_datalocal) + run_offpele(args.pdb_file, args.forcefield, args.resolution, args.output, + args.with_solvent, args.as_datalocal) if __name__ == '__main__': diff --git a/offPELE/solvent/solvent.py b/offPELE/solvent/solvent.py index c9d899b9..e50651cb 100644 --- a/offPELE/solvent/solvent.py +++ b/offPELE/solvent/solvent.py @@ -1,15 +1,31 @@ +""" +This module contains classes and functions involved in the manipulation of +PELE's solvent templates. +""" + import numpy as np from simtk import unit -from offPELE.utils import get_data_file_path, warning_on_one_line -from offPELE.utils.toolkits import OpenForceFieldToolkitWrapper +from offpele.utils import get_data_file_path, warning_on_one_line +from offpele.utils.toolkits import OpenForceFieldToolkitWrapper class _SolventWrapper(object): + """ + A wrapper for any solvent-like class. + """ _ff_file = None _name = None def __init__(self, molecule): + """ + Initializes a SolventWrapper object. + + Parameters + ---------- + molecule : An offpele.topology.Molecule + A Molecule object to be written as an Impact file + """ self._molecule = molecule self._radii = np.zeros(len(self.molecule.atoms)) self._scales = np.zeros(len(self.molecule.atoms)) @@ -20,6 +36,11 @@ def __init__(self, molecule): self._initialize_from_molecule() def _initialize_from_molecule(self): + """ + Initializes a SolventWrapper object using an offpele's Molecule. + """ + print(' - Loading solvent parameters') + off_toolkit = OpenForceFieldToolkitWrapper() GBSA_handler = off_toolkit.get_parameter_handler_from_forcefield( @@ -37,6 +58,14 @@ def _initialize_from_molecule(self): self._scales = parameters.get_GBSA_scales() def to_dict(self): + """ + Returns this SolventWrapper object as a dictionary. + + Returns + ------- + data : dict + A dictionary containing the data of this SolventWrapper object + """ data = dict() data['SolventParameters'] = dict() data['SolventParameters']['Name'] = self.name @@ -63,20 +92,53 @@ def to_dict(self): return data def to_json_file(self, path): + """ + Writes this SolventWrapper object to a json file. + + Parameters + ---------- + path : str + Path to save the json file to + """ import json with open(path, 'w') as file: json.dump(self.to_dict(), file, indent=4) @property def name(self): + """ + The name of the solvent. + + Returns + ------- + name : str + The name of this solvent object. + """ return self._name @property def molecule(self): + """ + The offpele's Molecule to parameterize. + + Returns + ------- + molecule : an offpele.topology.Molecule + The offpele's Molecule object + """ return self._molecule @property def radii(self): + """ + The list of radii of the parameterized molecule. + + Returns + ------- + radii : numpy.array + List of radii + """ + # TODO assert is a numpy array return self._radii @property diff --git a/offPELE/template/impact.py b/offPELE/template/impact.py index 0eba22ca..50e5d9f8 100644 --- a/offPELE/template/impact.py +++ b/offPELE/template/impact.py @@ -7,8 +7,8 @@ from simtk import unit -import offPELE -from offPELE.topology import ZMatrix +import offpele +from offpele.topology import ZMatrix class Impact(object): @@ -19,20 +19,20 @@ class Impact(object): def __init__(self, molecule): """ - Initiate and Impact object. + Initializes an Impact object. Parameters ---------- - molecule : An offPELE.topology.Molecule + molecule : An offpele.topology.Molecule A Molecule object to be written as an Impact file Examples -------- - Write the Impact template of a offPELE's molecule + Write the Impact template of a offpele's molecule - >>> from offPELE.topology import Molecule - >>> from offPELE.template import Impact + >>> from offpele.topology import Molecule + >>> from offpele.template import Impact >>> molecule = Molecule('molecule.pdb') >>> molecule.parameterize('openff_unconstrained-1.1.1.offxml') @@ -40,19 +40,19 @@ def __init__(self, molecule): >>> impact.write('molz') """ - if (isinstance(molecule, offPELE.topology.Molecule) - or isinstance(molecule, offPELE.topology.molecule.Molecule)): + if (isinstance(molecule, offpele.topology.Molecule) + or isinstance(molecule, offpele.topology.molecule.Molecule)): self._initialize_from_molecule(molecule) else: raise Exception('Invalid input molecule for Impact template') def _initialize_from_molecule(self, molecule): """ - Initializes an Impact object from an offPELE.topology.Molecule. + Initializes an Impact object from an offpele.topology.Molecule. Parameters ---------- - molecule : An offPELE.topology.Molecule + molecule : An offpele.topology.Molecule A Molecule object to be written as an Impact file """ # We will work with a copy to prevent the modification of the original @@ -131,8 +131,8 @@ def _write_header(self, file): if self.molecule.forcefield: file.write(' ({})'.format(self.molecule.forcefield)) file.write('\n') - file.write('* File generated with offPELE-{}\n'.format( - offPELE.__version__)) + file.write('* File generated with offpele-{}\n'.format( + offpele.__version__)) file.write('*\n') def _write_resx(self, file): @@ -374,12 +374,12 @@ def _write_end(self, file): @property def molecule(self): """ - The offPELE's Molecule. + The offpele's Molecule. Returns ------- - molecule : an offPELE.topology.Molecule - The offPELE's Molecule object + molecule : an offpele.topology.Molecule + The offpele's Molecule object """ return self._molecule @@ -450,7 +450,7 @@ def none_to_dummy(f): def function_wrapper(*args, **kwargs): out = f(*args, **kwargs) if out is None: - out = offPELE.topology.molecule.DummyAtom(index=-1) + out = offpele.topology.molecule.DummyAtom(index=-1) return out return function_wrapper @@ -577,9 +577,9 @@ def function_wrapper(*args, **kwargs): return function_wrapper -class WritableAtom(offPELE.topology.molecule.Atom, WritableWrapper): +class WritableAtom(offpele.topology.molecule.Atom, WritableWrapper): """ - Writable offPELE's Atom class + Writable offpele's Atom class """ def __init__(self, atom): @@ -588,14 +588,14 @@ def __init__(self, atom): Parameters ---------- - atom : an offPELE.topology.molecule.Atom + atom : an offpele.topology.molecule.Atom The Atom to create the WritableAtom with """ # We do not want to modify the original object atom = deepcopy(atom) - assert isinstance(atom, (offPELE.topology.molecule.Atom, - offPELE.topology.molecule.DummyAtom)), \ + assert isinstance(atom, (offpele.topology.molecule.Atom, + offpele.topology.molecule.DummyAtom)), \ 'Wrong type: {}'.format(type(atom)) super().__init__(atom.index, atom.core, atom.OPLS_type, atom.PDB_name, @@ -613,7 +613,7 @@ def parent(self): Returns ------- - parent : an offPELE.topology.molecule.Atom + parent : an offpele.topology.molecule.Atom The parent of this Atom object """ return super().parent @@ -772,9 +772,9 @@ def nonpolar_alpha(self): return super().nonpolar_alpha -class WritableBond(offPELE.topology.Bond, WritableWrapper): +class WritableBond(offpele.topology.Bond, WritableWrapper): """ - Writable offPELE's Bond class + Writable offpele's Bond class """ def __init__(self, bond): @@ -783,14 +783,14 @@ def __init__(self, bond): Parameters ---------- - bond : an offPELE.topology.Bond + bond : an offpele.topology.Bond The Bond to create the WritableBond with """ # We do not want to modify the original object bond = deepcopy(bond) - assert isinstance(bond, (offPELE.topology.Bond, - offPELE.topology.topology.Bond)), \ + assert isinstance(bond, (offpele.topology.Bond, + offpele.topology.topology.Bond)), \ 'Wrong type: {}'.format(type(bond)) super().__init__(index=bond.index, atom1_idx=bond.atom1_idx, @@ -849,9 +849,9 @@ def eq_dist(self): return super().eq_dist -class WritableAngle(offPELE.topology.Angle, WritableWrapper): +class WritableAngle(offpele.topology.Angle, WritableWrapper): """ - Writable offPELE's Angle class + Writable offpele's Angle class """ def __init__(self, angle): @@ -860,14 +860,14 @@ def __init__(self, angle): Parameters ---------- - angle : an offPELE.topology.Angle + angle : an offpele.topology.Angle The Angle to create the WritableAngle with """ # We do not want to modify the original object angle = deepcopy(angle) - assert isinstance(angle, (offPELE.topology.Angle, - offPELE.topology.topology.Angle)), \ + assert isinstance(angle, (offpele.topology.Angle, + offpele.topology.topology.Angle)), \ 'Wrong type: {}'.format(type(angle)) super().__init__(index=angle.index, atom1_idx=angle.atom1_idx, @@ -938,9 +938,9 @@ def eq_angle(self): return super().eq_angle -class WritableProper(offPELE.topology.Proper, WritableWrapper): +class WritableProper(offpele.topology.Proper, WritableWrapper): """ - Writable offPELE's Proper class + Writable offpele's Proper class """ def __init__(self, proper): @@ -949,14 +949,14 @@ def __init__(self, proper): Parameters ---------- - proper : an offPELE.topology.Proper + proper : an offpele.topology.Proper The Proper to create the WritableProper with """ # We do not want to modify the original object proper = deepcopy(proper) - assert isinstance(proper, (offPELE.topology.Proper, - offPELE.topology.topology.Proper)), \ + assert isinstance(proper, (offpele.topology.Proper, + offpele.topology.topology.Proper)), \ 'Wrong type: {}'.format(type(proper)) super().__init__(index=proper.index, atom1_idx=proper.atom1_idx, @@ -1029,9 +1029,9 @@ def constant(self): return super().constant -class WritableImproper(offPELE.topology.Improper, WritableWrapper): +class WritableImproper(offpele.topology.Improper, WritableWrapper): """ - Writable offPELE's Improper class + Writable offpele's Improper class """ def __init__(self, improper): @@ -1040,14 +1040,14 @@ def __init__(self, improper): Parameters ---------- - improper : an offPELE.topology.Improper + improper : an offpele.topology.Improper The Improper to create the WritableImproper with """ # We do not want to modify the original object improper = deepcopy(improper) - assert isinstance(improper, (offPELE.topology.Improper, - offPELE.topology.topology.Improper)), \ + assert isinstance(improper, (offpele.topology.Improper, + offpele.topology.topology.Improper)), \ 'Wrong type: {}'.format(type(improper)) super().__init__(index=improper.index, atom1_idx=improper.atom1_idx, diff --git a/offPELE/tests/test_parameters.py b/offPELE/tests/test_parameters.py index 7e261ed0..721da5a8 100644 --- a/offPELE/tests/test_parameters.py +++ b/offPELE/tests/test_parameters.py @@ -1,5 +1,5 @@ """ -This module contains the tests to check offPELE's parameters. +This module contains the tests to check offpele's parameters. """ import pytest @@ -7,10 +7,10 @@ from simtk import unit import numpy as np -from offPELE.utils import get_data_file_path +from offpele.utils import get_data_file_path from .utils import (SET_OF_LIGAND_PATHS, apply_PELE_dihedral_equation, apply_OFF_dihedral_equation) -from offPELE.topology import Molecule +from offpele.topology import Molecule class TestDihedrals(object): diff --git a/offPELE/tests/utils.py b/offPELE/tests/utils.py index 0db8576a..91b3fd21 100644 --- a/offPELE/tests/utils.py +++ b/offPELE/tests/utils.py @@ -15,7 +15,7 @@ def apply_PELE_dihedral_equation(proper, x): Parameters ---------- - proper : an offPELE.topology.Proper + proper : an offpele.topology.Proper The proper whose parameters will be applied to equation x : float Equation's x value @@ -31,7 +31,7 @@ def apply_OFF_dihedral_equation(proper, x): Parameters ---------- - proper : an offPELE.topology.Proper + proper : an offpele.topology.Proper The proper whose parameters will be applied to equation x : float Equation's x value diff --git a/offPELE/topology/molecule.py b/offPELE/topology/molecule.py index a7a20c99..b8562b0c 100644 --- a/offPELE/topology/molecule.py +++ b/offPELE/topology/molecule.py @@ -3,7 +3,7 @@ from pathlib import Path from .topology import Bond, Angle, OFFProper, OFFImproper -from offPELE.utils.toolkits import (AmberToolkitWrapper, +from offpele.utils.toolkits import (AmberToolkitWrapper, RDKitToolkitWrapper, OpenForceFieldToolkitWrapper) from .rotamer import MolecularGraph diff --git a/offPELE/topology/rotamer.py b/offPELE/topology/rotamer.py index 2cdd185e..369f90d9 100644 --- a/offPELE/topology/rotamer.py +++ b/offPELE/topology/rotamer.py @@ -3,7 +3,7 @@ import networkx as nx from copy import deepcopy -from offPELE.utils.toolkits import RDKitToolkitWrapper +from offpele.utils.toolkits import RDKitToolkitWrapper class Rotamer(object): diff --git a/offPELE/topology/zmatrix.py b/offPELE/topology/zmatrix.py index 0b146a98..f741827c 100644 --- a/offPELE/topology/zmatrix.py +++ b/offPELE/topology/zmatrix.py @@ -2,7 +2,7 @@ import numpy as np -from offPELE.topology.molecule import Atom, DummyAtom +from offpele.topology.molecule import Atom, DummyAtom class ZMatrix(np.ndarray): @@ -130,7 +130,7 @@ def _build_zmatrix(cls, obj, coords, molecule): assert atom1 is not None and atom2 is not None \ and atom3 is not None and atom4 is not None, \ - 'None parent is not expected' + 'A None as parent is not expected' x1, y1, z1 = (atom1.x, atom1.y, atom1.z) x2, y2, z2 = (atom2.x, atom2.y, atom2.z) diff --git a/offPELE/utils/toolkits.py b/offPELE/utils/toolkits.py index 5abfe13d..4e00bb8f 100644 --- a/offPELE/utils/toolkits.py +++ b/offPELE/utils/toolkits.py @@ -9,7 +9,7 @@ import numpy as np from simtk import unit -from offPELE.utils import temporary_cd +from offpele.utils import temporary_cd # Exceptions diff --git a/offPELE/utils/utils.py b/offPELE/utils/utils.py index c9534f28..5f6cce33 100644 --- a/offPELE/utils/utils.py +++ b/offPELE/utils/utils.py @@ -5,7 +5,7 @@ def get_data_file_path(relative_path): - fn = resource_filename('offPELE', os.path.join( + fn = resource_filename('offpele', os.path.join( 'data', relative_path)) if not os.path.exists(fn): diff --git a/setup.cfg b/setup.cfg index 24805542..7d19cf47 100644 --- a/setup.cfg +++ b/setup.cfg @@ -1,7 +1,7 @@ [versioneer] VCS = git style = pep440 -versionfile_source = offPELE/_version.py -versionfile_build = offPELE/_version.py +versionfile_source = offpele/_version.py +versionfile_build = offpele/_version.py tag_prefix = '' -parentdir_prefix = offPELE- +parentdir_prefix = offpele- diff --git a/setup.py b/setup.py index d1614a76..6e13b2a7 100644 --- a/setup.py +++ b/setup.py @@ -17,14 +17,14 @@ def find_package_data(data_root, package_root): setup( - name="offPELE", + name="offpele", author="Martí Municoy", author_email="martimunicoy@gmail.com", - description=("Open Forcield Open Energy Project"), + description=("Open Force Field to PELE"), license="MIT", keywords="molecular mechanics, forcefield, potential energy", - url="http://github.com/martimunicoy/offPELE", - packages=['offPELE'], + url="http://github.com/martimunicoy/offpele", + packages=['offpele'], long_description=read('README.md'), classifiers=[ "Development Status :: 1 - Planning", @@ -38,6 +38,6 @@ def find_package_data(data_root, package_root): ], version=versioneer.get_version(), cmdclass=versioneer.get_cmdclass(), - package_data={'offPELE': find_package_data( - 'offPELE/data', 'offPELE')}, + package_data={'offpele': find_package_data( + 'offpele/data', 'offpele')}, ) From fe0a4fd46f2ad0002cbc44af50ba61fe4970f4d3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mart=C3=AD=20Municoy?= Date: Wed, 15 Jul 2020 18:04:08 +0200 Subject: [PATCH 50/67] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 5668dbea..38d2cf76 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,2 @@ # Open Force Field to PELE -The Open Force Field to PELE (offpele for short) is a Python package that builds PELE-compatible force field templates using the Open Force Field toolkit. +The Open Force Field to PELE is a Python package that builds PELE-compatible force field templates using the Open Force Field toolkit. From 5eb1af49fc9909ae9df95beb87f1e0a98c226887 Mon Sep 17 00:00:00 2001 From: Marti Municoy Date: Wed, 15 Jul 2020 18:09:21 +0200 Subject: [PATCH 51/67] Change module name --- {offPELE => offpele}/__init__.py | 0 {offPELE => offpele}/_version.py | 0 {offPELE => offpele}/data/benchmarks/README.md | 0 {offPELE => offpele}/data/complexes/LYS_BNZ.pdb | 0 {offPELE => offpele}/data/forcefields/GBSA_OBC1-1.0.offxml | 0 {offPELE => offpele}/data/forcefields/GBSA_OBC2-1.0.offxml | 0 {offPELE => offpele}/data/ligands/BIA.pdb | 0 {offPELE => offpele}/data/ligands/BNZ.mae | 0 {offPELE => offpele}/data/ligands/BNZ.pdb | 0 {offPELE => offpele}/data/ligands/LG1.pdb | 0 {offPELE => offpele}/data/ligands/MDB.pdb | 0 {offPELE => offpele}/data/ligands/OLC.pdb | 0 {offPELE => offpele}/data/ligands/SBN.pdb | 0 {offPELE => offpele}/data/ligands/TOL.mae | 0 {offPELE => offpele}/data/ligands/TOL.pdb | 0 {offPELE => offpele}/data/ligands/ligand.pdb | 0 {offPELE => offpele}/examples/Parameterize.ipynb | 0 {offPELE => offpele}/main.py | 0 {offPELE => offpele}/solvent/__init__.py | 0 {offPELE => offpele}/solvent/solvent.py | 0 {offPELE => offpele}/template/__init__.py | 0 {offPELE => offpele}/template/impact.py | 0 {offPELE => offpele}/tests/__init__.py | 0 {offPELE => offpele}/tests/test_parameters.py | 0 {offPELE => offpele}/tests/utils.py | 0 {offPELE => offpele}/topology/__init__.py | 0 {offPELE => offpele}/topology/molecule.py | 0 {offPELE => offpele}/topology/rotamer.py | 0 {offPELE => offpele}/topology/topology.py | 0 {offPELE => offpele}/topology/zmatrix.py | 0 {offPELE => offpele}/utils/__init__.py | 0 {offPELE => offpele}/utils/toolkits.py | 0 {offPELE => offpele}/utils/utils.py | 0 33 files changed, 0 insertions(+), 0 deletions(-) rename {offPELE => offpele}/__init__.py (100%) rename {offPELE => offpele}/_version.py (100%) rename {offPELE => offpele}/data/benchmarks/README.md (100%) rename {offPELE => offpele}/data/complexes/LYS_BNZ.pdb (100%) rename {offPELE => offpele}/data/forcefields/GBSA_OBC1-1.0.offxml (100%) rename {offPELE => offpele}/data/forcefields/GBSA_OBC2-1.0.offxml (100%) rename {offPELE => offpele}/data/ligands/BIA.pdb (100%) rename {offPELE => offpele}/data/ligands/BNZ.mae (100%) rename {offPELE => offpele}/data/ligands/BNZ.pdb (100%) rename {offPELE => offpele}/data/ligands/LG1.pdb (100%) rename {offPELE => offpele}/data/ligands/MDB.pdb (100%) rename {offPELE => offpele}/data/ligands/OLC.pdb (100%) rename {offPELE => offpele}/data/ligands/SBN.pdb (100%) rename {offPELE => offpele}/data/ligands/TOL.mae (100%) rename {offPELE => offpele}/data/ligands/TOL.pdb (100%) rename {offPELE => offpele}/data/ligands/ligand.pdb (100%) rename {offPELE => offpele}/examples/Parameterize.ipynb (100%) rename {offPELE => offpele}/main.py (100%) rename {offPELE => offpele}/solvent/__init__.py (100%) rename {offPELE => offpele}/solvent/solvent.py (100%) rename {offPELE => offpele}/template/__init__.py (100%) rename {offPELE => offpele}/template/impact.py (100%) rename {offPELE => offpele}/tests/__init__.py (100%) rename {offPELE => offpele}/tests/test_parameters.py (100%) rename {offPELE => offpele}/tests/utils.py (100%) rename {offPELE => offpele}/topology/__init__.py (100%) rename {offPELE => offpele}/topology/molecule.py (100%) rename {offPELE => offpele}/topology/rotamer.py (100%) rename {offPELE => offpele}/topology/topology.py (100%) rename {offPELE => offpele}/topology/zmatrix.py (100%) rename {offPELE => offpele}/utils/__init__.py (100%) rename {offPELE => offpele}/utils/toolkits.py (100%) rename {offPELE => offpele}/utils/utils.py (100%) diff --git a/offPELE/__init__.py b/offpele/__init__.py similarity index 100% rename from offPELE/__init__.py rename to offpele/__init__.py diff --git a/offPELE/_version.py b/offpele/_version.py similarity index 100% rename from offPELE/_version.py rename to offpele/_version.py diff --git a/offPELE/data/benchmarks/README.md b/offpele/data/benchmarks/README.md similarity index 100% rename from offPELE/data/benchmarks/README.md rename to offpele/data/benchmarks/README.md diff --git a/offPELE/data/complexes/LYS_BNZ.pdb b/offpele/data/complexes/LYS_BNZ.pdb similarity index 100% rename from offPELE/data/complexes/LYS_BNZ.pdb rename to offpele/data/complexes/LYS_BNZ.pdb diff --git a/offPELE/data/forcefields/GBSA_OBC1-1.0.offxml b/offpele/data/forcefields/GBSA_OBC1-1.0.offxml similarity index 100% rename from offPELE/data/forcefields/GBSA_OBC1-1.0.offxml rename to offpele/data/forcefields/GBSA_OBC1-1.0.offxml diff --git a/offPELE/data/forcefields/GBSA_OBC2-1.0.offxml b/offpele/data/forcefields/GBSA_OBC2-1.0.offxml similarity index 100% rename from offPELE/data/forcefields/GBSA_OBC2-1.0.offxml rename to offpele/data/forcefields/GBSA_OBC2-1.0.offxml diff --git a/offPELE/data/ligands/BIA.pdb b/offpele/data/ligands/BIA.pdb similarity index 100% rename from offPELE/data/ligands/BIA.pdb rename to offpele/data/ligands/BIA.pdb diff --git a/offPELE/data/ligands/BNZ.mae b/offpele/data/ligands/BNZ.mae similarity index 100% rename from offPELE/data/ligands/BNZ.mae rename to offpele/data/ligands/BNZ.mae diff --git a/offPELE/data/ligands/BNZ.pdb b/offpele/data/ligands/BNZ.pdb similarity index 100% rename from offPELE/data/ligands/BNZ.pdb rename to offpele/data/ligands/BNZ.pdb diff --git a/offPELE/data/ligands/LG1.pdb b/offpele/data/ligands/LG1.pdb similarity index 100% rename from offPELE/data/ligands/LG1.pdb rename to offpele/data/ligands/LG1.pdb diff --git a/offPELE/data/ligands/MDB.pdb b/offpele/data/ligands/MDB.pdb similarity index 100% rename from offPELE/data/ligands/MDB.pdb rename to offpele/data/ligands/MDB.pdb diff --git a/offPELE/data/ligands/OLC.pdb b/offpele/data/ligands/OLC.pdb similarity index 100% rename from offPELE/data/ligands/OLC.pdb rename to offpele/data/ligands/OLC.pdb diff --git a/offPELE/data/ligands/SBN.pdb b/offpele/data/ligands/SBN.pdb similarity index 100% rename from offPELE/data/ligands/SBN.pdb rename to offpele/data/ligands/SBN.pdb diff --git a/offPELE/data/ligands/TOL.mae b/offpele/data/ligands/TOL.mae similarity index 100% rename from offPELE/data/ligands/TOL.mae rename to offpele/data/ligands/TOL.mae diff --git a/offPELE/data/ligands/TOL.pdb b/offpele/data/ligands/TOL.pdb similarity index 100% rename from offPELE/data/ligands/TOL.pdb rename to offpele/data/ligands/TOL.pdb diff --git a/offPELE/data/ligands/ligand.pdb b/offpele/data/ligands/ligand.pdb similarity index 100% rename from offPELE/data/ligands/ligand.pdb rename to offpele/data/ligands/ligand.pdb diff --git a/offPELE/examples/Parameterize.ipynb b/offpele/examples/Parameterize.ipynb similarity index 100% rename from offPELE/examples/Parameterize.ipynb rename to offpele/examples/Parameterize.ipynb diff --git a/offPELE/main.py b/offpele/main.py similarity index 100% rename from offPELE/main.py rename to offpele/main.py diff --git a/offPELE/solvent/__init__.py b/offpele/solvent/__init__.py similarity index 100% rename from offPELE/solvent/__init__.py rename to offpele/solvent/__init__.py diff --git a/offPELE/solvent/solvent.py b/offpele/solvent/solvent.py similarity index 100% rename from offPELE/solvent/solvent.py rename to offpele/solvent/solvent.py diff --git a/offPELE/template/__init__.py b/offpele/template/__init__.py similarity index 100% rename from offPELE/template/__init__.py rename to offpele/template/__init__.py diff --git a/offPELE/template/impact.py b/offpele/template/impact.py similarity index 100% rename from offPELE/template/impact.py rename to offpele/template/impact.py diff --git a/offPELE/tests/__init__.py b/offpele/tests/__init__.py similarity index 100% rename from offPELE/tests/__init__.py rename to offpele/tests/__init__.py diff --git a/offPELE/tests/test_parameters.py b/offpele/tests/test_parameters.py similarity index 100% rename from offPELE/tests/test_parameters.py rename to offpele/tests/test_parameters.py diff --git a/offPELE/tests/utils.py b/offpele/tests/utils.py similarity index 100% rename from offPELE/tests/utils.py rename to offpele/tests/utils.py diff --git a/offPELE/topology/__init__.py b/offpele/topology/__init__.py similarity index 100% rename from offPELE/topology/__init__.py rename to offpele/topology/__init__.py diff --git a/offPELE/topology/molecule.py b/offpele/topology/molecule.py similarity index 100% rename from offPELE/topology/molecule.py rename to offpele/topology/molecule.py diff --git a/offPELE/topology/rotamer.py b/offpele/topology/rotamer.py similarity index 100% rename from offPELE/topology/rotamer.py rename to offpele/topology/rotamer.py diff --git a/offPELE/topology/topology.py b/offpele/topology/topology.py similarity index 100% rename from offPELE/topology/topology.py rename to offpele/topology/topology.py diff --git a/offPELE/topology/zmatrix.py b/offpele/topology/zmatrix.py similarity index 100% rename from offPELE/topology/zmatrix.py rename to offpele/topology/zmatrix.py diff --git a/offPELE/utils/__init__.py b/offpele/utils/__init__.py similarity index 100% rename from offPELE/utils/__init__.py rename to offpele/utils/__init__.py diff --git a/offPELE/utils/toolkits.py b/offpele/utils/toolkits.py similarity index 100% rename from offPELE/utils/toolkits.py rename to offpele/utils/toolkits.py diff --git a/offPELE/utils/utils.py b/offpele/utils/utils.py similarity index 100% rename from offPELE/utils/utils.py rename to offpele/utils/utils.py From 9f14b81a72b56bf72c2c8e3195c810135e01b9ee Mon Sep 17 00:00:00 2001 From: Marti Municoy Date: Wed, 15 Jul 2020 20:11:38 +0200 Subject: [PATCH 52/67] Add docstrings to solvent classes --- offpele/solvent/solvent.py | 99 +++++++++++++++++++++++++++++++++++--- 1 file changed, 92 insertions(+), 7 deletions(-) diff --git a/offpele/solvent/solvent.py b/offpele/solvent/solvent.py index e50651cb..5028f599 100644 --- a/offpele/solvent/solvent.py +++ b/offpele/solvent/solvent.py @@ -3,7 +3,6 @@ PELE's solvent templates. """ -import numpy as np from simtk import unit from offpele.utils import get_data_file_path, warning_on_one_line @@ -27,8 +26,12 @@ def __init__(self, molecule): A Molecule object to be written as an Impact file """ self._molecule = molecule - self._radii = np.zeros(len(self.molecule.atoms)) - self._scales = np.zeros(len(self.molecule.atoms)) + self._radii = dict.fromkeys([tuple((idx, )) + for idx in range(0, len(molecule.atoms))], + unit.Quantity()) + self._scales = dict.fromkeys([tuple((idx, )) + for idx in range(0, len(molecule.atoms))], + unit.Quantity()) self._solvent_dielectric = float(0) self._solute_dielectric = float(0) self._surface_area_penalty = float(0) @@ -131,42 +134,93 @@ def molecule(self): @property def radii(self): """ - The list of radii of the parameterized molecule. + The dict of radii of the parameterized molecule. Returns ------- - radii : numpy.array - List of radii + radii : dict[atom indexes: simtk.unit.Quantity] + The radius assigned to each atom of the molecule """ - # TODO assert is a numpy array return self._radii @property def scales(self): + """ + The dict of scales of the parameterized molecule. + + Returns + ------- + scales : dict[atom indexes: simtk.unit.Quantity] + The scale assigned to each atom of the molecule + """ return self._scales @property def solvent_dielectric(self): + """ + The solvent dielectric value of this solvent object. + + Returns + ------- + solvent_dielectric : float + The solvent dielectric value + """ return self._solvent_dielectric @property def solute_dielectric(self): + """ + The solute dielectric value of this solvent object. + + Returns + ------- + solute_dielectric : float + The solute dielectric value + """ return self._solute_dielectric @property def surface_area_penalty(self): + """ + The surface area penalty value of this solvent object. + + Returns + ------- + surface_area_penalty : float + The surface area penalty value + """ return self._surface_area_penalty @property def solvent_radius(self): + """ + The solvent radius value of this solvent object. + + Returns + ------- + solvent_radius : float + The solvent radius value + """ return self._solvent_radius class OBC1(_SolventWrapper): + """ + Implementation of the OBC1 solvent. + """ + _ff_file = get_data_file_path('forcefields/GBSA_OBC1-1.0.offxml') _name = 'OBC1' def __init__(self, molecule): + """ + Initializes an OBC1 object. + + Parameters + ---------- + molecule : An offpele.topology.Molecule + A Molecule object to be written as an Impact file + """ # Not implemented in PELE import warnings warnings.formatwarning = warning_on_one_line @@ -175,15 +229,46 @@ def __init__(self, molecule): super().__init__(molecule) def _initialize_from_molecule(self): + """ + Initializes the OBC1 solvent using an offpele's Molecule. + """ super()._initialize_from_molecule() class OBC2(_SolventWrapper): + """ + Implementation of the OBC1 solvent. + """ + _ff_file = get_data_file_path('forcefields/GBSA_OBC1-1.0.offxml') _name = 'OBC2' def __init__(self, molecule): + """ + Initializes an OBC2 object. + + Parameters + ---------- + molecule : An offpele.topology.Molecule + A Molecule object to be written as an Impact file + + Examples + -------- + + Generate the solvent parameters of a molecule + + >>> from offpele.topology import Molecule + >>> from offpele.solvent import OBC2 + + >>> molecule = Molecule('molecule.pdb') + >>> solvent = OBC2(molecule) + >>> solvent.to_json_file('molecule_solv.json') + + """ super().__init__(molecule) def _initialize_from_molecule(self): + """ + Initializes the OBC2 solvent using an offpele's Molecule. + """ super()._initialize_from_molecule() From 3fb19e2f3476a495e80c4d3e6d18fd7e751d78e7 Mon Sep 17 00:00:00 2001 From: Marti Municoy Date: Wed, 15 Jul 2020 20:32:20 +0200 Subject: [PATCH 53/67] Add docstrings to the zmatrix module --- offpele/topology/zmatrix.py | 159 +++++++++++++++++++++++++++++++++++- 1 file changed, 157 insertions(+), 2 deletions(-) diff --git a/offpele/topology/zmatrix.py b/offpele/topology/zmatrix.py index f741827c..037076e8 100644 --- a/offpele/topology/zmatrix.py +++ b/offpele/topology/zmatrix.py @@ -1,3 +1,8 @@ +""" +This module contains the classes and functions to generate the zmatrix of +a molecule. +""" + from copy import deepcopy import numpy as np @@ -7,14 +12,32 @@ class ZMatrix(np.ndarray): """ - Inspired by the PlopRotTemp algorithm + It generates the zmatrix of a molecule as a numpy.array. + + Inspired by the PlopRotTemp algorithm. """ def __init__(self, molecule): + """ + It initializes a ZMatrix object. + + Parameters + ---------- + molecule : An offpele.topology.Molecule + A Molecule object to be written as an Impact file + """ # We will work on a copy of the molecule's object to modify it freely self._molecule = deepcopy(molecule) def __new__(cls, molecule): + """ + It customizes the creation of the numpy.array. + + Parameters + ---------- + molecule : An offpele.topology.Molecule + A Molecule object to be written as an Impact file + """ molecule = deepcopy(molecule) obj = np.zeros((len(molecule.atoms), 3)).view(cls) coords = cls._extract_coords(molecule) @@ -23,6 +46,19 @@ def __new__(cls, molecule): return obj def _extract_coords(molecule): + """ + It extracts the coordinates of the molecule's atoms. + + Parameters + ---------- + molecule : An offpele.topology.Molecule + A Molecule object to be written as an Impact file + + Returns + ------- + coords : list[tuple[float]] + The coordinates of the molecule + """ coords = list() for atom in molecule.atoms: coords.append((atom.x, atom.y, atom.z)) @@ -30,6 +66,19 @@ def _extract_coords(molecule): return coords def _get_absolute_parent(molecule): + """ + It returns the absolute parent in the topology of the molecule. + + Parameters + ---------- + molecule : An offpele.topology.Molecule + A Molecule object to be written as an Impact file + + Returns + ------- + absolute_parent : offpele.topology.molecule.Atom + The absolute parent of the molecule + """ absolute_parent = list() for atom in molecule.atoms: if atom.parent is None: @@ -40,6 +89,29 @@ def _get_absolute_parent(molecule): return absolute_parent[0] def _calculate_bond(x1, y1, z1, x2, y2, z2): + """ + It calculates the bond distance between two sets of coordinates. + + Parameters + ---------- + x1 : float + The x1 coordinate + y1 : float + The y1 coordinate + z1 : float + The z1 coordinate + x2 : float + The x2 coordinate + y2 : float + The y2 coordinate + z2 : float + The z2 coordinate + + Returns + ------- + distance : float + The bond distance between the two sets of coordinates + """ dx = x1 - x2 dy = y1 - y2 dz = z1 - z2 @@ -47,6 +119,35 @@ def _calculate_bond(x1, y1, z1, x2, y2, z2): return np.sqrt(dx * dx + dy * dy + dz * dz) def _calculate_angle(x1, y1, z1, x2, y2, z2, x3, y3, z3): + """ + It calculates the angle between three sets of coordinates. + + Parameters + ---------- + x1 : float + The x1 coordinate + y1 : float + The y1 coordinate + z1 : float + The z1 coordinate + x2 : float + The x2 coordinate + y2 : float + The y2 coordinate + z2 : float + The z2 coordinate + x3 : float + The x3 coordinate + y3 : float + The y3 coordinate + z3 : float + The z3 coordinate + + Returns + ------- + angle : float + The angle between the three sets of coordinates + """ dx_12 = x1 - x2 dy_12 = y1 - y2 dz_12 = z1 - z2 @@ -72,6 +173,41 @@ def _calculate_angle(x1, y1, z1, x2, y2, z2, x3, y3, z3): return np.arccos(xang) * 180.0 / np.pi def _calculate_dihedral(x1, y1, z1, x2, y2, z2, x3, y3, z3, x4, y4, z4): + """ + It calculates the dihedral between four sets of coordinates. + + Parameters + ---------- + x1 : float + The x1 coordinate + y1 : float + The y1 coordinate + z1 : float + The z1 coordinate + x2 : float + The x2 coordinate + y2 : float + The y2 coordinate + z2 : float + The z2 coordinate + x3 : float + The x3 coordinate + y3 : float + The y3 coordinate + z3 : float + The z3 coordinate + x4 : float + The x4 coordinate + y4 : float + The y4 coordinate + z4 : float + The z4 coordinate + + Returns + ------- + dihedral : float + The dihedral between the four sets of coordinates + """ dx_12 = x1 - x2 dy_12 = y1 - y2 dz_12 = z1 - z2 @@ -111,7 +247,26 @@ def _calculate_dihedral(x1, y1, z1, x2, y2, z2, x3, y3, z3, x4, y4, z4): return phi * 180.0 / np.pi def _build_zmatrix(cls, obj, coords, molecule): - + """ + It buils the zmatrix. + + Parameters + ---------- + cls : ZMatrix class + The ZMatrix class + obj : ZMatrix object + The ZMatrix object + coords : list[tuple[float]] + The coordinates of the molecule + molecule : An offpele.topology.Molecule + A Molecule object to be written as an Impact file + + Returns + ------- + obj : ZMatrix object + The ZMatrix object which is a numpy.array with the corresponding + zmatrix initialized. + """ dummy1 = DummyAtom(index=-3, PDB_name='DUM1', parent=None) dummy2 = DummyAtom(index=-2, PDB_name='DUM2', parent=dummy1) dummy3 = DummyAtom(index=-1, PDB_name='DUM3', parent=dummy2) From 6d8c8cf4b92f6b96abacc871dd73512af7540a7b Mon Sep 17 00:00:00 2001 From: Marti Municoy Date: Wed, 15 Jul 2020 20:33:09 +0200 Subject: [PATCH 54/67] Remove unused Atom import --- offpele/topology/zmatrix.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/offpele/topology/zmatrix.py b/offpele/topology/zmatrix.py index 037076e8..cfde67d1 100644 --- a/offpele/topology/zmatrix.py +++ b/offpele/topology/zmatrix.py @@ -7,7 +7,7 @@ import numpy as np -from offpele.topology.molecule import Atom, DummyAtom +from offpele.topology.molecule import DummyAtom class ZMatrix(np.ndarray): From 583c2f8c3adfcaa99cec20e0a03ba02c571b3aa2 Mon Sep 17 00:00:00 2001 From: Marti Municoy Date: Thu, 16 Jul 2020 11:42:35 +0200 Subject: [PATCH 55/67] Add docstrings to topology module --- offpele/topology/topology.py | 430 ++++++++++++++++++++++++++++++++++- 1 file changed, 428 insertions(+), 2 deletions(-) diff --git a/offpele/topology/topology.py b/offpele/topology/topology.py index 610d6a0c..8ce4a535 100644 --- a/offpele/topology/topology.py +++ b/offpele/topology/topology.py @@ -1,17 +1,49 @@ -# Global imports +""" +This module handles the topological elements of force fields. +""" + from simtk import unit class TopologyElement(object): + """ + A wrapper for any topological element. + """ + _name = None _writable_attrs = [] class TopologyIterator(object): + """ + An iterator for topological elements that iterates over their + attributes in an ordered way. + + It is useful when writing topological elements to file. + """ + def __init__(self, top_el): + """ + It initiates a TopologyIterator object. + + Parameters + ---------- + top_el : a TopologyElement object + The topology element to iterate on. + """ self._index = int(0) self._top_el = top_el def __next__(self): + """ + It returns the next item for the iteration. + + Returns + ------- + attr_name : str + The name of the attribute + attr_value : float + The value of the attribute + """ if self._index == len(self._top_el._writable_attrs): raise StopIteration @@ -23,16 +55,48 @@ def __next__(self): @property def name(self): + """ + The name that this topological element has. + + Returns + ------- + name : str + The name of the topological element + """ return self._name @property def n_writable_attrs(self): + """ + The number of writable attributes this topological element has. + + Returns + ------- + n_writable_attrs : int + The number of writable attributes + """ return len(self._writable_attrs) def __iter__(self): + """ + It returns an instance of the TopologyIterator. + + Returns + ------- + iterator : a TopologyIterator + The TopologyIterator object + """ return self.TopologyIterator(self) def __repr__(self): + """ + It returns the representation string of this topological element. + + Returns + ------- + repr_string : str + The representation string + """ repr_string = '{}('.format(self._name) attrs = [attr for attr in self] for attr_name, value in attrs[:-1]: @@ -42,15 +106,44 @@ def __repr__(self): return repr_string def __str__(self): + """ + It returns the readable representation string of this topological + element. + + Returns + ------- + str_string : str + The readable representation string + """ return self.__repr__() class Bond(TopologyElement): + """ + It represents a bond in the topology. + """ + _name = 'Bond' _writable_attrs = ['atom1_idx', 'atom2_idx', 'spring_constant', 'eq_dist'] def __init__(self, index=-1, atom1_idx=None, atom2_idx=None, spring_constant=None, eq_dist=None): + """ + It initiates a Bond object. + + Parameters + ---------- + index : int + The index of this Bond object + atom1_idx : int + The index of the first atom involved in this Bond + atom2_idx : int + The index of the second atom involved in this Bond + spring_constant : simtk.unit.Quantity + The spring constant of this Bond + eq_dist : simtk.unit.Quantity + The equilibrium distance of this Bond + """ self._index = index self._atom1_idx = atom1_idx self._atom2_idx = atom2_idx @@ -58,39 +151,117 @@ def __init__(self, index=-1, atom1_idx=None, atom2_idx=None, self._eq_dist = eq_dist def set_atom1_idx(self, index): + """ + It sets atom1's index. + + Parameters + ---------- + index : int + The index of the first atom involved in this Bond + """ self._atom1_idx = index def set_atom2_idx(self, index): + """ + It sets atom2's index. + + Parameters + ---------- + index : int + The index of the second atom involved in this Bond + """ self._atom2_idx = index @property def index(self): + """ + Bond's index. + + Returns + ------- + index : int + The index of this Bond object + """ return self._index @property def atom1_idx(self): + """ + Bond's atom1 index. + + Returns + ------- + atom1_idx : int + The index of the first atom involved in this Bond object + """ return self._atom1_idx @property def atom2_idx(self): + """ + Bond's atom2 index. + + Returns + ------- + atom2_idx : int + The index of the second atom involved in this Bond object + """ return self._atom2_idx @property def spring_constant(self): + """ + Bond's spring constant. + + Returns + ------- + spring_constant : simtk.unit.Quantity + The spring constant of this Bond object + """ return self._spring_constant @property def eq_dist(self): + """ + Bond's equilibrium distance. + + Returns + ------- + eq_dist : simtk.unit.Quantity + The equilibrium distance of this Bond object + """ return self._eq_dist class Angle(TopologyElement): + """ + It represents an angle in the topology. + """ + _name = 'Angle' _writable_attrs = ['atom1_idx', 'atom2_idx', 'atom3_idx', 'spring_constant', 'eq_angle'] def __init__(self, index=-1, atom1_idx=None, atom2_idx=None, atom3_idx=None, spring_constant=None, eq_angle=None): + """ + It initiates an Angle object. + + Parameters + ---------- + index : int + The index of this Angle object + atom1_idx : int + The index of the first atom involved in this Angle + atom2_idx : int + The index of the second atom involved in this Angle + atom3_idx : int + The index of the third atom involved in this Angle + spring_constant : simtk.unit.Quantity + The spring constant of this Angle + eq_angle : simtk.unit.Quantity + The equilibrium angle of this Angle + """ self._index = index self._atom1_idx = atom1_idx self._atom2_idx = atom2_idx @@ -99,40 +270,118 @@ def __init__(self, index=-1, atom1_idx=None, atom2_idx=None, self._eq_angle = eq_angle def set_atom1_idx(self, index): + """ + It sets atom1's index. + + Parameters + ---------- + index : int + The index of the first atom involved in this Angle + """ self._atom1_idx = index def set_atom2_idx(self, index): + """ + It sets atom2's index. + + Parameters + ---------- + index : int + The index of the second atom involved in this Angle + """ self._atom2_idx = index def set_atom3_idx(self, index): + """ + It sets atom3's index. + + Parameters + ---------- + index : int + The index of the third atom involved in this Angle + """ self._atom3_idx = index @property def index(self): + """ + Angle's index. + + Returns + ------- + index : int + The index of this Angle object + """ return self._index @property def atom1_idx(self): + """ + Angle's atom1 index. + + Returns + ------- + atom1_idx : int + The index of the first atom involved in this Angle object + """ return self._atom1_idx @property def atom2_idx(self): + """ + Angle's atom2 index. + + Returns + ------- + atom1_idx : int + The index of the second atom involved in this Angle object + """ return self._atom2_idx @property def atom3_idx(self): + """ + Angle's atom3 index. + + Returns + ------- + atom1_idx : int + The index of the third atom involved in this Angle object + """ return self._atom3_idx @property def spring_constant(self): + """ + Angle's spring constant. + + Returns + ------- + spring_constant : simtk.unit.Quantity + The spring constant of this Angle object + """ return self._spring_constant @property def eq_angle(self): + """ + Angle's equilibrium angle. + + Returns + ------- + eq_angle : simtk.unit.Quantity + The equilibrium angle of this Angle object + """ return self._eq_angle class Dihedral(TopologyElement): + """ + It represents a dihedral in the topology. + + It can be a proper or an improper dihedral. + """ + _name = 'Dihedral' _writable_attrs = ['atom1_idx', 'atom2_idx', 'atom3_idx', 'atom4_idx', 'constant', 'prefactor', 'periodicity'] @@ -140,6 +389,28 @@ class Dihedral(TopologyElement): def __init__(self, index=-1, atom1_idx=None, atom2_idx=None, atom3_idx=None, atom4_idx=None, periodicity=None, prefactor=None, constant=None): + """ + It initiates an Dihedral object. + + Parameters + ---------- + index : int + The index of this Dihedral object + atom1_idx : int + The index of the first atom involved in this Dihedral + atom2_idx : int + The index of the second atom involved in this Dihedral + atom3_idx : int + The index of the third atom involved in this Dihedral + atom4_idx : int + The index of the fourth atom involved in this Dihedral + periodicity : int + The periodicity of this Dihedral + prefactor : int + The prefactor of this Dihedral + constant : simtk.unit.Quantity + The constant of this Dihedral + """ self._index = index self._atom1_idx = atom1_idx self._atom2_idx = atom2_idx @@ -150,18 +421,53 @@ def __init__(self, index=-1, atom1_idx=None, atom2_idx=None, self._constant = constant def set_atom1_idx(self, index): + """ + It sets atom1's index. + + Parameters + ---------- + index : int + The index of the first atom involved in this Dihedral + """ self._atom1_idx = index def set_atom2_idx(self, index): + """ + It sets atom2's index. + + Parameters + ---------- + index : int + The index of the second atom involved in this Dihedral + """ self._atom2_idx = index def set_atom3_idx(self, index): + """ + It sets atom3's index. + + Parameters + ---------- + index : int + The index of the third atom involved in this Dihedral + """ self._atom3_idx = index def set_atom4_idx(self, index): + """ + It sets atom4's index. + + Parameters + ---------- + index : int + The index of the fourth atom involved in this Dihedral + """ self._atom4_idx = index def plot(self): + """ + It plots this Dihedral as a function of phi angle. + """ from matplotlib import pyplot import numpy as np @@ -174,46 +480,122 @@ def plot(self): @property def index(self): + """ + Dihedral's index. + + Returns + ------- + index : int + The index of this Dihedral object + """ return self._index @property def atom1_idx(self): + """ + Dihedral's atom1 index. + + Returns + ------- + atom1_idx : int + The index of the first atom involved in this Dihedral object + """ return self._atom1_idx @property def atom2_idx(self): + """ + Dihedral's atom2 index. + + Returns + ------- + atom1_idx : int + The index of the second atom involved in this Dihedral object + """ return self._atom2_idx @property def atom3_idx(self): + """ + Dihedral's atom3 index. + + Returns + ------- + atom1_idx : int + The index of the third atom involved in this Dihedral object + """ return self._atom3_idx @property def atom4_idx(self): + """ + Dihedral's atom4 index. + + Returns + ------- + atom1_idx : int + The index of the fourth atom involved in this Dihedral object + """ return self._atom4_idx @property def periodicity(self): + """ + Dihedral's periodicity. + + Returns + ------- + periodicity : int + The periodicity this Dihedral object + """ return self._periodicity @property def prefactor(self): + """ + Dihedral's prefactor. + + Returns + ------- + prefactor : int + The prefactor this Dihedral object + """ return self._prefactor @property def constant(self): + """ + Dihedral's constant. + + Returns + ------- + constant : int + The constant this Dihedral object + """ return self._constant class Proper(Dihedral): + """ + It represents a proper dihedral in the topology. + """ + _name = 'Proper' class Improper(Dihedral): + """ + It represents an improper dihedral in the topology. + """ + _name = 'Improper' class OFFDihedral(TopologyElement): + """ + It represents a dihedral in the Open Force Field's topology. + """ + _name = 'OFFDihedral' _writable_attrs = ['atom1_idx', 'atom2_idx', 'atom3_idx', 'atom4_idx', 'periodicity', 'phase', 'k', 'idivf'] @@ -222,6 +604,30 @@ class OFFDihedral(TopologyElement): def __init__(self, index=-1, atom1_idx=None, atom2_idx=None, atom3_idx=None, atom4_idx=None, periodicity=None, phase=None, k=None, idivf=None): + """ + It initiates an Dihedral object. + + Parameters + ---------- + index : int + The index of this Dihedral object + atom1_idx : int + The index of the first atom involved in this Dihedral + atom2_idx : int + The index of the second atom involved in this Dihedral + atom3_idx : int + The index of the third atom involved in this Dihedral + atom4_idx : int + The index of the fourth atom involved in this Dihedral + periodicity : int + The periodicity of this Dihedral + phase : simtk.unit.Quantity + The phase of this Dihedral + k : simtk.unit.Quantity + The constant of this Dihedral + idivf : int + The idivf of this Dihedral + """ self.index = index self.atom1_idx = atom1_idx self.atom2_idx = atom2_idx @@ -233,6 +639,15 @@ def __init__(self, index=-1, atom1_idx=None, atom2_idx=None, self.idivf = idivf def to_PELE(self): + """ + It converts this Open Force Field Dihedral object into a + PELE-compatible one. + + Returns + ------- + PELE_dihedral : a Dihedral + The PELE-compatible Dihedral object + """ if (self.periodicity is None or self.phase is None or self.k is None or self.idivf is None): return None @@ -243,7 +658,7 @@ def to_PELE(self): assert self.phase.value_in_unit(unit.degree) in (0, 180), \ 'Expected values for phase are 0 or 180, obtained ' \ '{}'.format(self.phase) - assert self.idivf == 1, 'Expected values for idivf is 1, ' \ + assert self.idivf == 1, 'The expected value for idivf is 1, ' \ 'obtained {}'.format(self.divf) if self.phase.value_in_unit(unit.degree) == 180: @@ -266,6 +681,9 @@ def to_PELE(self): return self._to_PELE_class(**PELE_dihedral_kwargs) def plot(self): + """ + It plots this Dihedral as a function of phi angle. + """ from matplotlib import pyplot import numpy as np @@ -278,10 +696,18 @@ def plot(self): class OFFProper(OFFDihedral): + """ + It represents a proper dihedral in the Open Force Field's topology. + """ + _name = 'OFFProper' _to_PELE_class = Proper class OFFImproper(OFFDihedral): + """ + It represents an improper dihedral in the Open Force Field's topology. + """ + _name = 'OFFImproper' _to_PELE_class = Improper From 2f68e14951c643da669a2f068cef15537ccec685 Mon Sep 17 00:00:00 2001 From: Marti Municoy Date: Thu, 16 Jul 2020 20:53:59 +0200 Subject: [PATCH 56/67] Add docstrings to rotamer module --- offpele/topology/rotamer.py | 230 +++++++++++++++++++++++++++++++++++- 1 file changed, 228 insertions(+), 2 deletions(-) diff --git a/offpele/topology/rotamer.py b/offpele/topology/rotamer.py index 369f90d9..01e561fb 100644 --- a/offpele/topology/rotamer.py +++ b/offpele/topology/rotamer.py @@ -1,4 +1,7 @@ -# Global imports +""" +This module handles all classes and functions related with rotamers. +""" + from collections import defaultdict import networkx as nx from copy import deepcopy @@ -7,33 +10,104 @@ class Rotamer(object): + """ + It represents the conformational space of a rotatable bond, discretized + with a certain resolution. + """ + def __init__(self, atom1, atom2, resolution=30): + """ + It initiates an Rotamer object. + + Parameters + ---------- + atom1 : str + The name of the first atom involved in the rotamer + atom2 : str + The name of the second atom involved in the rotamer + resolution : float + The resolution to discretize the rotamer's conformational space + """ self._atom1 = atom1 self._atom2 = atom2 self._resolution = resolution @property def atom1(self): + """ + Rotamer's atom1 name. + + Returns + ------- + atom1 : str + The name of the first atom involved in this Rotamer object + """ return self._atom1 @property def atom2(self): + """ + Rotamer's atom2 name. + + Returns + ------- + atom2 : str + The name of the second atom involved in this Rotamer object + """ return self._atom2 @property def resolution(self): + """ + Rotamer's resolution. + + Returns + ------- + resolution : float + The resolution of this Rotamer object + """ return self._resolution class RotamerLibrary(object): + """ + It represents a set of rotamers found in the same molecule. + """ + def __init__(self, residue_name='LIG'): + """ + It initiates a RotamerLibrary object. + + Parameters + ---------- + residue_name : str + The name of the residue this RotamerLibrary belongs to + """ self._residue_name = residue_name self._rotamers = defaultdict(list) def add_rotamer(self, rotamer, group_id): + """ + It adds a rotamer to this RotamerLibrary. + + Parameters + ---------- + rotamer : a Rotamer + The Rotamer object to add to this RotamerLibrary + group_id : int + The index of the group where the rotamer belongs to + """ self._rotamers[group_id].append(rotamer) def to_file(self, path): + """ + It writes this RotamerLibrary to a file. + + Parameters + ---------- + path : str + Path to save the RotamerLibrary to + """ with open(path, 'w') as file: file.write('rot assign res {} &\n'.format(self.residue_name)) for i, group in enumerate(self.rotamers.keys()): @@ -45,20 +119,57 @@ def to_file(self, path): @property def residue_name(self): + """ + The name of the RotamerLibrary's residue. + + Returns + ------- + residue_name : str + The name of the residue of this RotamberLibrary object. + """ return self._residue_name @property def rotamers(self): + """ + RotamerLibrary's rotamers. + + Returns + ------- + rotamers : dict[int, Rotamer] + The rotamers of this RotamerLibrary object, grouped by the + group they belong to + """ return self._rotamers class MolecularGraph(nx.Graph): + """ + It represents the structure of a Molecule as a networkx.Graph. + """ + def __init__(self, molecule): + """ + It initializes a MolecularGraph object. + + Parameters + ---------- + molecule : An offpele.topology.Molecule + A Molecule object to be written as an Impact file + """ super().__init__(self) self._molecule = molecule self._compute_rotamer_graph(molecule) def _compute_rotamer_graph(self, molecule): + """ + It initializes the netwrokx.Graph with a Molecule object. + + Parameters + ---------- + molecule : An offpele.topology.Molecule + A Molecule object to be written as an Impact file + """ rdkit_toolkit = RDKitToolkitWrapper() rot_bonds_atom_ids = \ rdkit_toolkit.get_atom_ids_with_rotatable_bonds(molecule) @@ -91,7 +202,30 @@ def _compute_rotamer_graph(self, molecule): self.nodes[j]['rotatable'] = True def set_core(self): + """ + It sets the core of the molecule to minimize the amount of consecutive + rotamers as much as possible. + """ + def get_all_nrot_neighbors(self, atom_id, visited_neighbors): + """ + A recursive function that hierarchically visits all atom neighbors + in the graph. + + Parameters + ---------- + atom_id : int + Is is both the id of the graph's node and index of the + corresponding atom + visited_neighbors : set[int] + The ids of the nodes that have already been visited + + Returns + ------- + visited_neighbors : set[int] + The updated set that contains the ids of the nodes that have + already been visited + """ if atom_id in visited_neighbors: return visited_neighbors visited_neighbors.add(atom_id) @@ -138,7 +272,28 @@ def get_all_nrot_neighbors(self, atom_id, visited_neighbors): atom.set_as_branch() def set_parents(self): + """ + It sets the parent of each atom according to the molecular graph. + """ + def recursive_child_visitor(parent, already_visited=set()): + """ + A recursive function that hierarchically visits all the childs of + each atom. + + Parameters + ---------- + parent : an offpele.topology.Atom + The atom whose childs will be visited + already_visited : set[offpele.topology.Atom] + The Atom objects that have already been visited + + Returns + ------- + visited_neighbors : set[offpele.topology.Atom] + The updated set that contains the Atom objects that have + already been visited + """ if parent in already_visited: return already_visited @@ -172,12 +327,26 @@ def recursive_child_visitor(parent, already_visited=set()): assert len(already_visited) == len(self.molecule.atoms), 'Not all ' \ 'nodes were explored' - # Assert absolut parent is the only with None parent value + # Assert absolut parent is the only with a None parent value assert parent.parent is None and \ sum([int(a.parent is not None) for a in self.molecule.atoms]) \ == len(self.molecule.atoms) - 1, 'Found descendant without parent' def _get_rot_bonds_per_group(self, branch_groups): + """ + It constructs the rotatable bonds of each branch group. + + Parameters + ---------- + branch_groups : list[list[int]] + The node ids of each branch + + Returns + ------- + rot_bonds_per_group : list[tuple[int, int]] + The atom ids of all the graph's edges that belong to a rotatable + bond + """ rot_bonds_per_group = list() for group in branch_groups: rot_bonds = list() @@ -196,6 +365,22 @@ def _get_rot_bonds_per_group(self, branch_groups): return rot_bonds_per_group def _get_core_atom_per_group(self, rot_bonds_per_group, core_indexes): + """ + It obtains the core atom for each group. + + Parameters + ---------- + rot_bonds_per_group : list[tuple[int, int]] + The atom ids of all the graph's edges that belong to a rotatable + bond + core_indexes : list[int] + The atom ids of atoms in the core + + Returns + ------- + core_atom_per_group : list[int] + The atom id of the atom that belongs to the core for each branch + """ core_atom_per_group = list() for rot_bonds in rot_bonds_per_group: for (a1, a2) in rot_bonds: @@ -212,6 +397,26 @@ def _get_core_atom_per_group(self, rot_bonds_per_group, core_indexes): def _get_sorted_bonds_per_group(self, core_atom_per_group, rot_bonds_per_group, distances): + """ + It sorts in increasing order the rotamers of each group according + to their distance with respect to the corresponding core atom. + + Parameters + ---------- + core_atom_per_group : list[int] + The atom id of the atom that belongs to the core for each branch + rot_bonds_per_group : list[tuple[int, int]] + The atom ids of all the graph's edges that belong to a rotatable + bond + distances : dict[int, dict[int, int]] + The distance between each pair of nodes (or atoms) + + Returns + ------- + sorted_rot_bonds_per_group : list[list] + The rotatable bonds per group, sorted in increasing order by + their distance with respect to the corresponding core atom + """ sorted_rot_bonds_per_group = list() for core_atom, rot_bonds in zip(core_atom_per_group, rot_bonds_per_group): @@ -228,6 +433,19 @@ def _get_sorted_bonds_per_group(self, core_atom_per_group, return sorted_rot_bonds_per_group def build_rotamer_library(self, resolution): + """ + It builds the RotamerLibrary object. + + Parameters + ---------- + resolution : float + The resolution to discretize the rotamer's conformational space + + Returns + ------- + rotamer_library : a RotamerLibrary object + The RotamerLibrary for the supplied Molecule object. + """ core_atoms = set() for atom in self.molecule.atoms: if atom.core: @@ -270,4 +488,12 @@ def build_rotamer_library(self, resolution): @property def molecule(self): + """ + The offpele's Molecule. + + Returns + ------- + molecule : an offpele.topology.Molecule + The offpele's Molecule object + """ return self._molecule From 3d31eda6c3ff3c873f38d8fc115011a8cbc4492b Mon Sep 17 00:00:00 2001 From: Marti Municoy Date: Fri, 17 Jul 2020 14:37:33 +0200 Subject: [PATCH 57/67] Add docstrings to toolkits module --- offpele/utils/toolkits.py | 489 +++++++++++++++++++++++++++++++++++++- 1 file changed, 487 insertions(+), 2 deletions(-) diff --git a/offpele/utils/toolkits.py b/offpele/utils/toolkits.py index 4e00bb8f..d396e4aa 100644 --- a/offpele/utils/toolkits.py +++ b/offpele/utils/toolkits.py @@ -1,3 +1,7 @@ +""" +This module contains miscellaneous set of handy classes and functions. +""" + import importlib from distutils.spawn import find_executable import tempfile @@ -12,7 +16,6 @@ from offpele.utils import temporary_cd -# Exceptions class ToolkitUnavailableException(Exception): """The requested toolkit is unavailable.""" pass @@ -27,11 +30,20 @@ class ToolkitWrapper(object): """ Toolkit wrapper base class. """ + _is_available = None _toolkit_name = None @property def toolkit_name(self): + """ + The name of the toolkit. + + Returns + ------- + toolkit_name : str + The name of this ToolkitWrapper object + """ return self._toolkit_name @staticmethod @@ -47,9 +59,16 @@ def is_available(): class RDKitToolkitWrapper(ToolkitWrapper): + """ + RDKitToolkitWrapper class. + """ + _toolkit_name = 'RDKit Toolkit' def __init__(self): + """ + It initializes a RDKitToolkitWrapper object. + """ super().__init__() if not self.is_available(): @@ -61,6 +80,7 @@ def __init__(self): def is_available(): """ Check whether the RDKit toolkit can be imported + Returns ------- is_installed : bool @@ -73,23 +93,69 @@ def is_available(): return False def from_pdb(self, path): + """ + It initializes an RDKit's Molecule object from a PDB file. + + Parameters + ---------- + path : str + The path to the molecule's PDB file. + + Returns + ------- + molecule : an rdkit.Chem.rdchem.Mol object + The RDKit's Molecule object + """ from rdkit import Chem return Chem.rdmolfiles.MolFromPDBFile(path, removeHs=False) def assign_stereochemistry_from_3D(self, molecule): + """ + It assigns the stereochemistry to an RDKit molecule according to the + 3D coordinates in the PDB structure. + + Parameters + ---------- + molecule : an offpele.topology.Molecule + The offpele's Molecule object + """ from rdkit import Chem rdkit_molecule = molecule.rdkit_molecule Chem.rdmolops.AssignStereochemistryFrom3D(rdkit_molecule) def get_residue_name(self, molecule): + """ + It returns the name of the residue according to the RDKit molecule + object. + + Parameters + ---------- + molecule : an offpele.topology.Molecule + The offpele's Molecule object + + Returns + ------- + residue_name : str + The name of the residue + """ rdkit_molecule = molecule.rdkit_molecule first_atom = list(rdkit_molecule.GetAtoms())[0] return first_atom.GetPDBResidueInfo().GetResidueName() def to_sfd_file(self, molecule, path): + """ + It writes the RDKit molecule to an sdf file. + + Parameters + ---------- + molecule : an offpele.topology.Molecule + The offpele's Molecule object + path : str + Path to write to + """ from rdkit import Chem assert Path(path).suffix == '.sdf', 'Wrong extension' @@ -101,6 +167,16 @@ def to_sfd_file(self, molecule, path): writer.close() def to_xyz_file(self, molecule, path): + """ + It writes the RDKit molecule to an xyz file. + + Parameters + ---------- + molecule : an offpele.topology.Molecule + The offpele's Molecule object + path : str + Path to write to + """ from rdkit import Chem assert Path(path).suffix == '.xyz', 'Wrong extension' @@ -109,6 +185,20 @@ def to_xyz_file(self, molecule, path): Chem.MolToXYZFile(rdkit_molecule, path) def get_atom_ids_with_rotatable_bonds(self, molecule): + """ + It returns the atom ids with rotatable bonds according to the + RDKit molecule. + + Parameters + ---------- + molecule : an offpele.topology.Molecule + The offpele's Molecule object + + Returns + ------- + rot_bonds_atom_ids : tuple[tuple[int, int]] + The set of atom id pairs that belong to rotatable bonds + """ from rdkit import Chem rdkit_molecule = molecule.rdkit_molecule @@ -120,6 +210,19 @@ def get_atom_ids_with_rotatable_bonds(self, molecule): return rot_bonds_atom_ids def get_coordinates(self, molecule): + """ + It returns the 3D coordinates of all atoms in the RDKit molecule. + + Parameters + ---------- + molecule : an offpele.topology.Molecule + The offpele's Molecule object + + Returns + ------- + coordinates : numpy.ndarray + The array of 3D coordinates of all the atoms in the molecule + """ rdkit_molecule = molecule.rdkit_molecule conformer = rdkit_molecule.GetConformer() @@ -127,9 +230,16 @@ def get_coordinates(self, molecule): class AmberToolkitWrapper(ToolkitWrapper): + """ + AmberToolkitWrapper class. + """ + _toolkit_name = 'Amber Toolkit' def __init__(self): + """ + It initializes a AmberToolkitWrapper object. + """ super().__init__() if not self.is_available(): @@ -143,6 +253,7 @@ def __init__(self): def is_available(): """ Check whether the AmberTools toolkit is installed + Returns ------- is_installed : bool @@ -156,6 +267,20 @@ def is_available(): return True def compute_partial_charges_am1bcc(self, molecule): + """ + It computes the partial charges using antechamber and the am1bcc + method. + + Parameters + ---------- + molecule : an offpele.topology.Molecule + The offpele's Molecule object + + Returns + ------- + charges : simtk.unit.Quantity + The array of partial charges + """ off_molecule = molecule.off_molecule with tempfile.TemporaryDirectory() as tmpdir: @@ -198,9 +323,16 @@ def compute_partial_charges_am1bcc(self, molecule): class OpenForceFieldToolkitWrapper(ToolkitWrapper): + """ + OpenForceFieldToolkitWrapper class. + """ + _toolkit_name = 'OpenForceField Toolkit' def __init__(self): + """ + It initializes a OpenForceFieldToolkitWrapper object. + """ super().__init__() if not self.is_available(): @@ -212,6 +344,7 @@ def __init__(self): def is_available(): """ Check whether the OpenForceField toolkit is installed + Returns ------- is_installed : bool @@ -224,12 +357,41 @@ def is_available(): return False def from_rdkit(self, molecule): + """ + It initializes an OpenForceField's Molecule object from an RDKit + molecule. + + Parameters + ---------- + molecule : an offpele.topology.Molecule + The offpele's Molecule object + + Returns + ------- + molecule : an openforcefield.topology.molecule object + The OpenForceField's Molecule + """ from openforcefield.topology.molecule import Molecule rdkit_molecule = molecule.rdkit_molecule return Molecule.from_rdkit(rdkit_molecule) def get_forcefield(self, forcefield_name): + """ + It returns the OpenForceField's object that matches with the name + that is supplied. + + Parameters + ---------- + forcefield_name : str + The name of the requested forcefield + + Returns + ------- + forcefield : an openforcefield.typing.engines.smirnoff.ForceField + object + The OpenForceField's forcefield + """ from openforcefield.typing.engines.smirnoff import ForceField if isinstance(forcefield_name, str): @@ -240,6 +402,23 @@ def get_forcefield(self, forcefield_name): return forcefield def get_parameters_from_forcefield(self, forcefield, molecule): + """ + It returns the parameters that are obtained with the supplied + forcefield for a certain offpele's molecule. + + Parameters + ---------- + forcefield : an openforcefield.typing.engines.smirnoff.ForceField + object + The forcefield from which the parameters will be obtained + molecule : an offpele.topology.Molecule + The offpele's Molecule object + + Returns + ------- + openforcefield_parameters : an OpenForceFieldParameters object + The OpenForceFieldParameters object + """ from openforcefield.typing.engines.smirnoff import ForceField from openforcefield.topology import Topology @@ -261,6 +440,24 @@ def get_parameters_from_forcefield(self, forcefield, molecule): def get_parameter_handler_from_forcefield(self, parameter_handler_name, forcefield): + """ + It returns a parameter handler from the forcefield based on its + name. + + Parameters + ---------- + parameter_handler_name : str + The name of the parameter handler that is requested + forcefield : an openforcefield.typing.engines.smirnoff.ForceField + object + The forcefield from which the parameter handler will be obtained + + Returns + ------- + parameter_handler : an openforcefield.typing.engines.smirnoff.parameters.ParameterHandler + object + The ParameterHandler that was requested + """ from openforcefield.typing.engines.smirnoff import ForceField if isinstance(forcefield, str): @@ -273,13 +470,23 @@ def get_parameter_handler_from_forcefield(self, parameter_handler_name, return forcefield.get_parameter_handler(parameter_handler_name) class OpenForceFieldParameters(dict): + """ + OpenForceFieldParameters class that inherits from dict. + """ + def __init__(self, parameters_list): + """ + It initializes an OpenForceFieldParameters object. + + parameters_list : dict + A dictionary keyed by force type + """ for key, value in parameters_list.items(): self[key] = value def sigmas_from_rmin_halves(func): """ - Convert rmin_half values to sigmas according to: + It converts rmin_half values to sigmas according to: http://ambermd.org/Questions/vdwequation.pdf """ FACTOR = 0.8908987181403393 # The inverse of the sixth root of 2 @@ -296,6 +503,14 @@ def function_wrapper(x): return function_wrapper def __str__(self): + """ + It returns the readable representation string of this object. + + Returns + ------- + output : str + The readable representation string + """ output = '' for force_tag, force_dict in self.items(): output += f"\n{force_tag}:\n" @@ -308,6 +523,23 @@ def __str__(self): return output def _build_dict(self, parameters, attribute_name): + """ + It builds the dictionary of parameters of a specific force type. + + Parameters + ---------- + parameters : dict[tuple, openforcefield.typing.engines.smirnoff.parameters.ParameterHandler] + The parameters of a specific force type grouped by tuples + with the atom ids that the parameters belong to + attribute_name : str + The name of the attribute that is requested + + Returns + ------- + value_by_index : dict[tuple, parameter_value] + The parameter values that were requested grouped by the atom + ids they belong to (arranged as a tuple) + """ if parameters: value_by_index = dict() for index, parameter in parameters.items(): @@ -316,6 +548,31 @@ def _build_dict(self, parameters, attribute_name): return value_by_index def _build_dynamic_dicts(self, parameters, attr_core_name): + """ + It builds the dynamically the dictionaries of parameters of a + specific force type. + + It works with the same idea as _build_dict(), however it can + handle multiple dictionary definitions were consecutive + parameters of the same type are found in the force type's + parameters dictionary. It works, for example, with the multiple + proper and improper definitions found in the OpenForceField API. + More information in the and + sections at: https://open-forcefield-toolkit.readthedocs.io/en/0.7.0/smirnoff.html + + Parameters + ---------- + parameters : dict[tuple, openforcefield.typing.engines.smirnoff.parameters.ParameterHandler] + The parameters of a specific force type grouped by tuples + with the atom ids that the parameters belong to + attribute_name : str + The name of the attribute that is requested + + Returns + ------- + value_by_index : dict[tuple, parameter_value] + The parameter values that were requested grouped by the atom + ids they belong to (arranged as a tuple) """ if parameters: parameters_by_index = defaultdict(dict) all_attr_ids_found = set() @@ -345,102 +602,330 @@ def _build_dynamic_dicts(self, parameters, attr_core_name): # Van der Waals parameters def get_vdW_parameters(self): + """ + It returns the parameters that belong to the van der Waals force + type. + + Returns + ------- + vdW_parameters : dict[tuple, openforcefield.typing.engines.smirnoff.parameters.ParameterHandler] + The parameters grouped by the atom ids they belong to + (arranged as tuples) + """ if 'vdW' in self: return self['vdW'] def get_vdW_sigmas(self): + """ + It gets the sigma values of the parameterized molecule. + + Returns + ------- + sigmas : dict[tuple[int], simtk.unit.Quantity] + The dictionary of sigma values grouped by the atom ids + they belong to (arranged as tuples) + """ parameters = self.get_vdW_parameters() return self._build_dict(parameters, 'sigma') def get_vdW_epsilons(self): + """ + It gets the epsilon values of the parameterized molecule. + + Returns + ------- + epsilons : dict[tuple[int], simtk.unit.Quantity] + The dictionary of epsilon values grouped by the atom ids + they belong to (arranged as tuples) + """ parameters = self.get_vdW_parameters() return self._build_dict(parameters, 'epsilon') def get_vdW_rmin_halves(self): + """ + It gets the rmin half values of the parameterized molecule. + + Returns + ------- + rmin_halves : dict[tuple[int], simtk.unit.Quantity] + The dictionary of rmin half values grouped by the atom ids + they belong to (arranged as tuples) + """ parameters = self.get_vdW_parameters() return self._build_dict(parameters, 'rmin_half') @sigmas_from_rmin_halves def get_vdW_sigmas_from_rmin_halves(self): + """ + It gets the rmin half values of the parameterized molecule. + Then, a decorator converts them into sigmas. + + Returns + ------- + sigmas : dict[tuple[int], simtk.unit.Quantity] + The dictionary of sigma values grouped by the atom ids + they belong to (arranged as tuples) + """ return self.get_vdW_rmin_halves() # Bond parameters def get_bond_parameters(self): + """ + It returns the parameters that belong to the bonding force type. + + Returns + ------- + bond_parameters : dict[tuple, openforcefield.typing.engines.smirnoff.parameters.ParameterHandler] + The parameters grouped by the atom ids they belong to + (arranged as tuples) + """ if 'Bonds' in self: return self['Bonds'] def get_bond_lengths(self): + """ + It gets the bond length values of the parameterized molecule. + + Returns + ------- + bond_lengths : dict[tuple[int], simtk.unit.Quantity] + The dictionary of bond length values grouped by the atom ids + they belong to (arranged as tuples) + """ parameters = self.get_bond_parameters() return self._build_dict(parameters, 'length') def get_bond_ks(self): + """ + It gets the bond k values of the parameterized molecule. + + Returns + ------- + bond_ks : dict[tuple[int], simtk.unit.Quantity] + The dictionary of bond k values grouped by the atom ids + they belong to (arranged as tuples) + """ parameters = self.get_bond_parameters() return self._build_dict(parameters, 'k') # Angle parameters def get_angle_parameters(self): + """ + It returns the parameters that belong to the angular force type. + + Returns + ------- + angle_parameters : dict[tuple, openforcefield.typing.engines.smirnoff.parameters.ParameterHandler] + The parameters grouped by the atom ids they belong to + (arranged as tuples) + """ if 'Angles' in self: return self['Angles'] def get_angle_angles(self): + """ + It gets the angle values of the parameterized molecule. + + Returns + ------- + angles : dict[tuple[int], simtk.unit.Quantity] + The dictionary of angle values grouped by the atom ids + they belong to (arranged as tuples) + """ parameters = self.get_angle_parameters() return self._build_dict(parameters, 'angle') def get_angle_ks(self): + """ + It gets the angle k values of the parameterized molecule. + + Returns + ------- + angle_ks : dict[tuple[int], simtk.unit.Quantity] + The dictionary of angle k values grouped by the atom ids + they belong to (arranged as tuples) + """ parameters = self.get_angle_parameters() return self._build_dict(parameters, 'k') # Dihedral parameters def get_dihedral_parameters(self): + """ + It returns the parameters that belong to the proper dihedrals + force type. + + Returns + ------- + proper_parameters : dict[tuple, openforcefield.typing.engines.smirnoff.parameters.ParameterHandler] + The parameters grouped by the atom ids they belong to + (arranged as tuples) + """ if 'ProperTorsions' in self: return self['ProperTorsions'] def get_dihedral_periodicities(self): + """ + It gets the dihedral periodicity values of the parameterized + molecule. + + Returns + ------- + dihedral_periodicities : list[dict[tuple[int], simtk.unit.Quantity]] + The list of dictionaries of dihedral periodicity values + grouped by the atom ids they belong to (arranged as tuples) + """ parameters = self.get_dihedral_parameters() return self._build_dynamic_dicts(parameters, 'periodicity') def get_dihedral_phases(self): + """ + It gets the dihedral phase values of the parameterized + molecule. + + Returns + ------- + dihedral_phases : list[dict[tuple[int], simtk.unit.Quantity]] + The list of dictionaries of dihedral phase values grouped + by the atom ids they belong to (arranged as tuples) + """ parameters = self.get_dihedral_parameters() return self._build_dynamic_dicts(parameters, 'phase') def get_dihedral_ks(self): + """ + It gets the dihedral periodicity values of the parameterized + molecule. + + Returns + ------- + dihedral_periodicities : list[dict[tuple[int], simtk.unit.Quantity]] + The list of dictionaries of dihedral periodicity values + grouped by the atom ids they belong to (arranged as tuples) + """ parameters = self.get_dihedral_parameters() return self._build_dynamic_dicts(parameters, 'k') def get_dihedral_idivfs(self): + """ + It gets the dihedral idivf values of the parameterized + molecule. + + Returns + ------- + dihedral_idivfs : list[dict[tuple[int], simtk.unit.Quantity]] + The list of dictionaries of dihedral idivf values + grouped by the atom ids they belong to (arranged as tuples) + """ parameters = self.get_dihedral_parameters() return self._build_dynamic_dicts(parameters, 'idivf') # Improper parameters def get_improper_parameters(self): + """ + It returns the parameters that belong to the improper dihedrals + force type. + + Returns + ------- + improper_parameters : dict[tuple, openforcefield.typing.engines.smirnoff.parameters.ParameterHandler] + The parameters grouped by the atom ids they belong to + (arranged as tuples) + """ if 'ImproperTorsions' in self: return self['ImproperTorsions'] def get_improper_periodicities(self): + """ + It gets the improper periodicity values of the parameterized + molecule. + + Returns + ------- + improper_periodicities : list[dict[tuple[int], simtk.unit.Quantity]] + The list of dictionaries of improper periodicity values + grouped by the atom ids they belong to (arranged as tuples) + """ parameters = self.get_improper_parameters() return self._build_dynamic_dicts(parameters, 'periodicity') def get_improper_phases(self): + """ + It gets the improper phase values of the parameterized + molecule. + + Returns + ------- + improper_phases : list[dict[tuple[int], simtk.unit.Quantity]] + The list of dictionaries of improper phase values + grouped by the atom ids they belong to (arranged as tuples) + """ parameters = self.get_improper_parameters() return self._build_dynamic_dicts(parameters, 'phase') def get_improper_ks(self): + """ + It gets the improper k values of the parameterized + molecule. + + Returns + ------- + improper_ks : list[dict[tuple[int], simtk.unit.Quantity]] + The list of dictionaries of improper k values + grouped by the atom ids they belong to (arranged as tuples) + """ parameters = self.get_improper_parameters() return self._build_dynamic_dicts(parameters, 'k') def get_improper_idivfs(self): + """ + It gets the improper idivf values of the parameterized + molecule. + + Returns + ------- + improper_idivfs : list[dict[tuple[int], simtk.unit.Quantity]] + The list of dictionaries of improper idivf values + grouped by the atom ids they belong to (arranged as tuples) + """ parameters = self.get_improper_parameters() return self._build_dynamic_dicts(parameters, 'idivf') # GBSA solvent parameters def get_GBSA_parameters(self): + """ + It returns the parameters that belong to the GBSA force type. + + Returns + ------- + GSBA_parameters : dict[tuple, openforcefield.typing.engines.smirnoff.parameters.ParameterHandler] + The parameters grouped by the atom ids they belong to + (arranged as tuples) + """ if 'GBSA' in self: return self['GBSA'] def get_GBSA_radii(self): + """ + It gets the GBSA radius values of the parameterized molecule. + + Returns + ------- + GBSA_radii : dict[tuple[int], simtk.unit.Quantity] + The dictionary of GBSA radius values grouped by the atom ids + they belong to (arranged as tuples) + """ parameters = self.get_GBSA_parameters() return self._build_dict(parameters, 'radius') def get_GBSA_scales(self): + """ + It gets the GBSA scale values of the parameterized molecule. + + Returns + ------- + GBSA_scales : dict[tuple[int], simtk.unit.Quantity] + The dictionary of GBSA scale values grouped by the atom ids + they belong to (arranged as tuples) + """ parameters = self.get_GBSA_parameters() return self._build_dict(parameters, 'scale') From 88b72c003469e9708bfec3c35cfa548742fa19b7 Mon Sep 17 00:00:00 2001 From: Marti Municoy Date: Fri, 17 Jul 2020 14:40:57 +0200 Subject: [PATCH 58/67] Minor changes in docstrings --- offpele/utils/toolkits.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/offpele/utils/toolkits.py b/offpele/utils/toolkits.py index d396e4aa..5fb9eaa2 100644 --- a/offpele/utils/toolkits.py +++ b/offpele/utils/toolkits.py @@ -1,5 +1,6 @@ """ -This module contains miscellaneous set of handy classes and functions. +This module contains external toolkit wrappers that are required by the +main offpele modules. """ import importlib From 9b2a775c703d197138f940ad357514a08869ab53 Mon Sep 17 00:00:00 2001 From: Marti Municoy Date: Fri, 17 Jul 2020 14:52:45 +0200 Subject: [PATCH 59/67] Add docstrings to utils module --- offpele/utils/utils.py | 54 +++++++++++++++++++++++++++++++++++++----- 1 file changed, 48 insertions(+), 6 deletions(-) diff --git a/offpele/utils/utils.py b/offpele/utils/utils.py index 5f6cce33..3978551e 100644 --- a/offpele/utils/utils.py +++ b/offpele/utils/utils.py @@ -1,23 +1,47 @@ +""" +This module contains miscellaneous set of handy classes and functions. +""" + from pkg_resources import resource_filename import os import contextlib def get_data_file_path(relative_path): + """ + It returns the path in the package's data location. + + Parameters + ---------- + relative_path : str + The relative path to the file that is required - fn = resource_filename('offpele', os.path.join( + Returns + ------- + output_path : str + The path in the package's data location, if found + """ + output_path = resource_filename('offpele', os.path.join( 'data', relative_path)) - if not os.path.exists(fn): + if not os.path.exists(output_path): raise ValueError( - "Sorry! {fn} does not exist. If you just added it, you'll have to " - + " re-install") + "Sorry! {output_path} does not exist. If you just added it, " + + "you'll have to re-install") - return fn + return output_path @contextlib.contextmanager def temporary_cd(path): + """ + A context that applies a temporary move to certain path. + + Parameters + ---------- + path : str + The path to move to + """ old_path = os.getcwd() os.chdir(os.path.abspath(path)) try: @@ -26,11 +50,21 @@ def temporary_cd(path): os.chdir(old_path) -def warning_on_one_line(message, category, filename, lineno, file=None, line=None): +def warning_on_one_line(message, category, filename, lineno, file=None, + line=None): + """A customized warning output in a single line.""" return ' %s:%s: %s:%s' % (filename, lineno, category.__name__, message) def check_if_path_exists(path): + """ + It checks if the supplied path exists and raises a ValueError otherwise. + + Parameters + ---------- + path : str or pathlib.Path + The path to check + """ from pathlib import Path if not isinstance(path, Path): @@ -41,5 +75,13 @@ def check_if_path_exists(path): def create_path(path): + """ + It creates a path. + + Parameters + ---------- + path : str + The path that will be created + """ import os os.makedirs(str(path), exist_ok=True) From acbfabfcfcaabd858cb12e91e29c31417dc61742 Mon Sep 17 00:00:00 2001 From: Marti Municoy Date: Fri, 17 Jul 2020 14:53:43 +0200 Subject: [PATCH 60/67] Minor changes to docstrings --- offpele/template/impact.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/offpele/template/impact.py b/offpele/template/impact.py index 50e5d9f8..9f6975f5 100644 --- a/offpele/template/impact.py +++ b/offpele/template/impact.py @@ -61,7 +61,7 @@ def _initialize_from_molecule(self, molecule): self._sort() def _sort(self): - """ Sort and reindex atoms in a Molecule.""" + """Sort and reindex atoms in a Molecule.""" sorted_atoms = list() # Sort by core attribute and parent index From 0619582121ee1b54efd623c1fcf89ec60b544fa1 Mon Sep 17 00:00:00 2001 From: Marti Municoy Date: Fri, 17 Jul 2020 16:34:27 +0200 Subject: [PATCH 61/67] Add docstrings to molecule module --- offpele/topology/molecule.py | 475 ++++++++++++++++++++++++++++++++++- 1 file changed, 472 insertions(+), 3 deletions(-) diff --git a/offpele/topology/molecule.py b/offpele/topology/molecule.py index b8562b0c..9aa17211 100644 --- a/offpele/topology/molecule.py +++ b/offpele/topology/molecule.py @@ -1,5 +1,8 @@ +""" +This module handles all classes and functions related with molecular +representations. +""" -# Global imports from pathlib import Path from .topology import Bond, Angle, OFFProper, OFFImproper @@ -10,10 +13,52 @@ class Atom(object): + """ + It represents the properties of an atom. + """ + def __init__(self, index=-1, core=None, OPLS_type=None, PDB_name=None, unknown=None, x=None, y=None, z=None, sigma=None, epsilon=None, charge=None, born_radius=None, SASA_radius=None, nonpolar_gamma=None, nonpolar_alpha=None, parent=None): + """ + It initializes an Atom object. + + Parameters + ---------- + index : int + The index of the atom + core : bool + Whether atom is in the core or in a branch + OPLS_type : str + The OPLS type of the atom + PDB_name : str + The PDB name of the atom + unknown : int + The unknown value of the atom + x : float + The x coordinate of the atom + y : float + The y coordinate of the atom + z : float + The z coordinate of the atom + sigma : simtk.unit.Quantity + The sigma parameter of the atom + epsilon : simtk.unit.Quantity + The epsilon parameter of the atom + charge : simtk.unit.Quantity + The partial charge parameter of the atom + born_radius : simtk.unit.Quantity + The SGB born parameter radius of the atom + SASA_radius : simtk.unit.Quantity + The SASA radius parameter of the atom + nonpolar_gamma : simtk.unit.Quantity + The nonpolar gamma parameter of the atom + nonpolar_alpha : simtk.unit.Quantity + The nonpolar alpha parameter of the atom + parent : offpele.topology.Atom + The parent of the atom + """ self._index = index self._core = core self._OPLS_type = OPLS_type @@ -32,89 +77,273 @@ def __init__(self, index=-1, core=None, OPLS_type=None, PDB_name=None, self._parent = parent def set_index(self, index): + """ + It sets the index of the atom. + + Parameters + ---------- + index : int + The index of this Atom object + """ self._index = index def set_as_core(self): + """It sets the atom as core""" self._core = True def set_as_branch(self): + """It sets the atom as branch""" self._core = False def set_parent(self, parent): + """ + It sets the parent of the atom. + + Parameters + ---------- + parent : offpele.topology.Atom + The parent of the atom + """ self._parent = parent def set_coords(self, coords): + """ + It sets the coordinates of the atom. + + Parameters + ---------- + coords : list + The coordinates array to set to this Atom object + """ assert len(coords) == 3, '3D array is expected' self._x, self._y, self._z = coords @property def index(self): + """ + Atom's index. + + Returns + ------- + index : int + The index of this Atom object + """ return self._index @property def core(self): + """ + Atom's core position. + + Returns + ------- + core : bool + Whether this Atom object is in the core or in a branch + """ return self._core @property def OPLS_type(self): + """ + Atom's OPLS type. + + .. todo :: + + * Consider removing any reference to OPLS, if possible + Otherwise, use SMIRks to find the best match + + Returns + ------- + OPLS_type : str + The OLPS type of this Atom object + """ return self._OPLS_type @property def PDB_name(self): + """ + Atom's PDB name. + + .. todo :: + + * Consider removing any reference to OPLS, if possible + Otherwise, use SMIRks to find the best match + + Returns + ------- + PDB_name : str + The PDB name of this Atom object + """ return self._PDB_name @property def unknown(self): + """ + Atom's unknown int. + + .. todo :: + + * Review the actual purpose of this attribute in PELE + + Returns + ------- + unknown : int + The unknown int of this Atom object + """ return self._unknown @property def x(self): + """ + Atom's x coordinate. + + Returns + ------- + x : float + The x coordinate of this Atom object + """ return self._x @property def y(self): + """ + Atom's y coordinate. + + Returns + ------- + y : float + The y coordinate of this Atom object + """ return self._y @property def z(self): + """ + Atom's z coordinate. + + Returns + ------- + z : float + The z coordinate of this Atom object + """ return self._z @property def sigma(self): + """ + Atom's sigma. + + Returns + ------- + sigma : simtk.unit.Quantity + The sigma parameter of this Atom object + """ return self._sigma @property def epsilon(self): + """ + Atom's epsilon. + + Returns + ------- + epsilon : simtk.unit.Quantity + The epsilon parameter of this Atom object + """ return self._epsilon @property def charge(self): + """ + Atom's charge. + + Returns + ------- + charge : simtk.unit.Quantity + The charge parameter of this Atom object + """ return self._charge @property def born_radius(self): + """ + Atom's born radius. + + Returns + ------- + born_radius : simtk.unit.Quantity + The SGB Born radius parameter of this Atom object + """ return self._born_radius @property def SASA_radius(self): + """ + Atom's SASA radius. + + Returns + ------- + SASA_radius : simtk.unit.Quantity + The SASA radius parameter of this Atom object + """ return self._SASA_radius @property def nonpolar_gamma(self): + """ + Atom's nonpolar gamma. + + Returns + ------- + nonpolar_gamma : simtk.unit.Quantity + The nonpolar gamma parameter of this Atom object + """ return self._nonpolar_gamma @property def nonpolar_alpha(self): + """ + Atom's nonpolar alpha. + + Returns + ------- + nonpolar_alpha : simtk.unit.Quantity + The nonpolar alpha parameter of this Atom object + """ return self._nonpolar_alpha @property def parent(self): + """ + Atom's parent. + + Returns + ------- + parent : simtk.unit.Quantity + The nonpolar gamma parameter of this Atom object + """ return self._parent class DummyAtom(Atom): + """ + It represents a dummy atom. + """ + def __init__(self, index=-1, PDB_name='DUMM', parent=None): + """ + It initializes a DummyAtom object. + + Parameters + ---------- + index : int + The index of the atom + PDB_name : str + The PDB name of the atom + parent : offpele.topology.Atom + The parent of the atom + """ if parent is None: parent = self super().__init__(index, False, None, PDB_name, None, None, None, None, @@ -122,7 +351,40 @@ def __init__(self, index=-1, PDB_name='DUMM', parent=None): class Molecule(object): + """ + It represent wraps up all the tools to parameterize a molecule with + the OpenForceField toolkit for PELE. + """ + def __init__(self, path=None): + """ + It initializes a Molecule object. + + Parameters + ---------- + path : str + The path to a PDB with the molecule structure + + Examples + -------- + + Load a molecule from a PDB file and parameterize it + + >>> from offpele.topology import Molecule + + >>> molecule = Molecule('molecule.pdb') + >>> molecule.parameterize('openff_unconstrained-1.1.1.offxml') + + Generate the rotamer library of a molecule + + >>> from offpele.topology import Molecule + + >>> molecule = Molecule('molecule.pdb') + >>> molecule.parameterize('openff_unconstrained-1.1.1.offxml') + >>> molecule.build_rotamer_library(resolution=30) + >>> molecule.rotamer_library.to_file('MOL.rot.assign') + + """ if isinstance(path, str): from pathlib import Path extension = Path(path).suffix @@ -136,6 +398,7 @@ def __init__(self, path=None): self._initialize() def _initialize(self): + """It initializes an empty molecule.""" self._name = '' self._forcefield = None self._atoms = list() @@ -151,6 +414,15 @@ def _initialize(self): self._graph = None def _initialize_from_pdb(self, path): + """ + It initializes a molecule with the molecule structure read from + a PDB file. + + Parameters + ---------- + path : str + The path to a PDB with the molecule structure + """ self._initialize() print(' - Loading molecule from RDKit') @@ -169,6 +441,14 @@ def _initialize_from_pdb(self, path): self._off_molecule = openforcefield_toolkit.from_rdkit(self) def set_name(self, name): + """ + It sets the name of the molecule. + + Parameters + ---------- + name : str + The name to set to the molecule + """ if isinstance(name, str) and len(name) > 2: name = name[0:3].upper() self._name = name @@ -177,6 +457,15 @@ def set_name(self, name): self.off_molecule.name = name def parameterize(self, forcefield): + """ + It parameterizes the molecule with a certain forcefield. + + Parameters + ---------- + forcefield : str or openforcefield.typing.engines.smirnoff.ForceField + object + The forcefield from which the parameters will be obtained + """ if not self.off_molecule and not self.rdkit_molecule: raise Exception('OpenForceField molecule was not initialized ' + 'correctly') @@ -205,6 +494,18 @@ def parameterize(self, forcefield): self._build_impropers() def build_rotamer_library(self, resolution): + """ + It builds the rotamer library of a parameterized molecule. + + .. todo :: + + * Consider moving this to the rotamer module. + + Parameters + ---------- + resolution : float + The resolution to discretize the rotamer's conformational space + """ self._assert_parameterized() print(' - Generating rotamer library') @@ -218,6 +519,7 @@ def build_rotamer_library(self, resolution): self._rotamer_library = self.graph.build_rotamer_library(resolution) def plot_rotamer_graph(self): + """It plots the rotamer graph in screen.""" self._assert_parameterized() try: @@ -225,7 +527,7 @@ def plot_rotamer_graph(self): except ImportError: raise Exception('RDKit Python API not found') - # Fins rotatable bond ids as in Lipinski module in RDKit + # Find rotatable bond ids as in Lipinski module in RDKit # https://github.com/rdkit/rdkit/blob/1bf6ef3d65f5c7b06b56862b3fb9116a3839b229/rdkit/Chem/Lipinski.py#L47 rot_bonds_atom_ids = self._rdkit_molecule.GetSubstructMatches( Chem.MolFromSmarts('[!$(*#*)&!D1]-&!@[!$(*#*)&!D1]')) @@ -255,12 +557,17 @@ def plot_rotamer_graph(self): plt.show() def _assert_parameterized(self): + """ + It checks that the molecule has been parameterized, raises an + AssertionError otherwise. + """ try: assert self.off_molecule is not None except AssertionError: raise Exception('Molecule not parameterized') def _calculate_am1bcc_charges(self): + """It computes the partial charges using the am1bcc method.""" amber_toolkit = AmberToolkitWrapper() charges = amber_toolkit.compute_partial_charges_am1bcc(self) @@ -268,6 +575,7 @@ def _calculate_am1bcc_charges(self): self.off_molecule.partial_charges = charges def _build_atoms(self): + """It builds the atoms of the molecule.""" # PELE needs underscores instead of whitespaces pdb_atom_names = {(i, ): name.replace(' ', '_',) for i, name in enumerate(self.get_pdb_atom_names())} @@ -323,9 +631,18 @@ def _build_atoms(self): self._add_atom(atom) def _add_atom(self, atom): + """ + It adds an atom to the molecule's list of atoms. + + Parameters + ---------- + atom : an offpele.topology.Atom + The Atom to add + """ self._atoms.append(atom) def _build_bonds(self): + """It builds the bonds of the molecule.""" lengths = self.parameters.get_bond_lengths() ks = self.parameters.get_bond_ks() @@ -340,9 +657,18 @@ def _build_bonds(self): self._add_bond(bond) def _add_bond(self, bond): + """ + It adds a bond to the molecule's list of bonds. + + Parameters + ---------- + bond : an offpele.topology.Bond + The Bond to add + """ self._bonds.append(bond) def _build_angles(self): + """It builds the angles of the molecule.""" angles = self.parameters.get_angle_angles() ks = self.parameters.get_angle_ks() @@ -358,9 +684,18 @@ def _build_angles(self): self._add_angle(angle) def _add_angle(self, angle): + """ + It adds an angle to the molecule's list of angles. + + Parameters + ---------- + angle : an offpele.topology.Angle + The Angle to add + """ self._angles.append(angle) def _build_propers(self): + """It builds the propers of the molecule.""" periodicities = self.parameters.get_dihedral_periodicities() phases = self.parameters.get_dihedral_phases() ks = self.parameters.get_dihedral_ks() @@ -409,12 +744,29 @@ def _build_propers(self): self._add_OFF_proper(off_proper) def _add_proper(self, proper): + """ + It adds a proper dihedral to the molecule's list of propers. + + Parameters + ---------- + proper : an offpele.topology.Proper + The Proper to add + """ self._propers.append(proper) def _add_OFF_proper(self, proper): + """ + It adds a proper dihedral to the molecule's list of OFF propers. + + Parameters + ---------- + proper : an offpele.topology.OFFProper + The OFFProper to add + """ self._OFF_propers.append(proper) def _build_impropers(self): + """It builds the impropers of the molecule.""" periodicities = self.parameters.get_improper_periodicities() phases = self.parameters.get_improper_phases() ks = self.parameters.get_improper_ks() @@ -463,12 +815,36 @@ def _build_impropers(self): self._add_OFF_improper(off_improper) def _add_improper(self, improper): + """ + It adds an improper dihedral to the molecule's list of impropers. + + Parameters + ---------- + improper : an offpele.topology.Improper + The Improper to add + """ self._impropers.append(improper) def _add_OFF_improper(self, improper): + """ + It adds an improper dihedral to the molecule's list of OFF impropers. + + Parameters + ---------- + improper : an offpele.topology.OFFImproper + The OFFImproper to add + """ self._OFF_impropers.append(improper) def get_pdb_atom_names(self): + """ + It returns the PDB atom names of all the atoms in the molecule. + + Returns + ------- + pdb_atom_names : str + The PDB atom names of all the atoms in this Molecule object + """ self._assert_parameterized() pdb_atom_names = list() @@ -480,48 +856,141 @@ def get_pdb_atom_names(self): return pdb_atom_names def to_impact(self, path): + """ + .. todo :: + + * We still need to implement this + """ pass @property def off_molecule(self): - return self._off_molecule + """ + The OpenForceField's molecule instance linked to the molecule. + + Returns + ------- + off_molecule : an openforcefield.topology.Molecule + The OpenForceField's molecule linked to this Molecule object + """ @property def rdkit_molecule(self): + """ + The RDKit's molecule instance linked to the molecule. + + Returns + ------- + rdkit_molecule : an rdkit.Chem.rdchem.Mol object + The RDKit's molecule linked to this Molecule object + """ return self._rdkit_molecule @property def rotamer_library(self): + """ + The rotamer library of the molecule. + + Returns + ------- + rotamer_library : an offpele.topology.rotamer.RotamerLibrary object + The rotamer library of this Molecule object + """ return self._rotamer_library @property def name(self): + """ + Molecule's name. + + Returns + ------- + name : str + The name of this Molecule object + """ return self._name @property def forcefield(self): + """ + The forcefield employed to parameterize the molecule. + + Returns + ------- + forcefield : an openforcefield.typing.engines.smirnoff.ForceField + object + The forcefield employed to parameterize this Molecule object + """ return self._forcefield @property def atoms(self): + """ + The list of atoms of the molecule. + + Returns + ------- + atoms : list[offpele.topology.molecule.Atom] + The list of atoms of this Molecule object. + """ return self._atoms @property def bonds(self): + """ + The list of bonds of the molecule. + + Returns + ------- + bonds : list[offpele.topology.Bond] + The list of bonds of this Molecule object. + """ return self._bonds @property def angles(self): + """ + The list of angles of the molecule. + + Returns + ------- + angles : list[offpele.topology.Angle] + The list of angles of this Molecule object. + """ return self._angles @property def propers(self): + """ + The list of propers of the molecule. + + Returns + ------- + propers : list[offpele.topology.Proper] + The list of propers of this Molecule object. + """ return self._propers @property def impropers(self): + """ + The list of impropers of the molecule. + + Returns + ------- + impropers : list[offpele.topology.Improper] + The list of impropers of this Molecule object. + """ return self._impropers @property def graph(self): + """ + The topological graph of the molecule. + + Returns + ------- + graph : an offpele.topology.rotamer.MolecularGraph object + The topological graph of this Molecule object. + """ return self._graph From 1bf8599c8dc04888f443e5ae67f9a07946dd9dae Mon Sep 17 00:00:00 2001 From: Marti Municoy Date: Fri, 17 Jul 2020 16:34:45 +0200 Subject: [PATCH 62/67] Minor changes to docstrings --- offpele/utils/toolkits.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/offpele/utils/toolkits.py b/offpele/utils/toolkits.py index 5fb9eaa2..a1492b27 100644 --- a/offpele/utils/toolkits.py +++ b/offpele/utils/toolkits.py @@ -369,7 +369,7 @@ def from_rdkit(self, molecule): Returns ------- - molecule : an openforcefield.topology.molecule object + molecule : an openforcefield.topology.Molecule object The OpenForceField's Molecule """ from openforcefield.topology.molecule import Molecule @@ -409,7 +409,7 @@ def get_parameters_from_forcefield(self, forcefield, molecule): Parameters ---------- - forcefield : an openforcefield.typing.engines.smirnoff.ForceField + forcefield : str or an openforcefield.typing.engines.smirnoff.ForceField object The forcefield from which the parameters will be obtained molecule : an offpele.topology.Molecule From 912e8da57a6191e5399bcfdbb25060fa51a09859 Mon Sep 17 00:00:00 2001 From: Marti Municoy Date: Fri, 17 Jul 2020 20:31:46 +0200 Subject: [PATCH 63/67] Add docstrings to Sphinx documentation --- docs/Makefile | 20 ++++++++ docs/_templates/class.rst | 24 ++++++++++ docs/conf.py | 96 +++++++++++++++++++++++++++++++++++++++ docs/index.rst | 25 ++++++++++ docs/make.bat | 35 ++++++++++++++ docs/solvent.rst | 20 ++++++++ docs/template.rst | 35 ++++++++++++++ docs/topology.rst | 44 ++++++++++++++++++ 8 files changed, 299 insertions(+) create mode 100644 docs/Makefile create mode 100644 docs/_templates/class.rst create mode 100644 docs/conf.py create mode 100644 docs/index.rst create mode 100644 docs/make.bat create mode 100644 docs/solvent.rst create mode 100644 docs/template.rst create mode 100644 docs/topology.rst diff --git a/docs/Makefile b/docs/Makefile new file mode 100644 index 00000000..d4bb2cbb --- /dev/null +++ b/docs/Makefile @@ -0,0 +1,20 @@ +# Minimal makefile for Sphinx documentation +# + +# You can set these variables from the command line, and also +# from the environment for the first two. +SPHINXOPTS ?= +SPHINXBUILD ?= sphinx-build +SOURCEDIR = . +BUILDDIR = _build + +# Put it first so that "make" without argument is like "make help". +help: + @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) + +.PHONY: help Makefile + +# Catch-all target: route all unknown targets to Sphinx using the new +# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). +%: Makefile + @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) diff --git a/docs/_templates/class.rst b/docs/_templates/class.rst new file mode 100644 index 00000000..afbed2d4 --- /dev/null +++ b/docs/_templates/class.rst @@ -0,0 +1,24 @@ +{{ fullname | escape | underline}} + +.. currentmodule:: {{ module }} + +.. autoclass:: {{ objname }} + + {% block methods %} + {% if methods %} + {% for item in methods %} + .. automethod:: {{ item }} + {%- endfor %} + {% endif %} + {% endblock %} + + {% block attributes %} + {% if attributes %} + .. rubric:: {{ _('Attributes') }} + + .. autosummary:: + {% for item in attributes %} + ~{{ name }}.{{ item }} + {%- endfor %} + {% endif %} + {% endblock %} diff --git a/docs/conf.py b/docs/conf.py new file mode 100644 index 00000000..df9b1676 --- /dev/null +++ b/docs/conf.py @@ -0,0 +1,96 @@ +# Configuration file for the Sphinx documentation builder. +# +# This file only contains a selection of the most common options. For a full +# list see the documentation: +# https://www.sphinx-doc.org/en/master/usage/configuration.html + +# -- Path setup -------------------------------------------------------------- + +# If extensions (or modules to document with autodoc) are in another directory, +# add these directories to sys.path here. If the directory is relative to the +# documentation root, use os.path.abspath to make it absolute, like shown here. +# +import os +import sys +sys.path.insert(0, os.path.abspath('..')) + +import sphinx + + +# -- Project information ----------------------------------------------------- + +project = 'Open Force Field for PELE' +copyright = '2020, Barcelona Supercomputing Center' +author = 'Martí Municoy' + + +# -- General configuration --------------------------------------------------- + +# Add any Sphinx extension module names here, as strings. They can be +# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom +# ones. +extensions = ['sphinx.ext.autodoc', 'sphinx.ext.autosummary', 'm2r', + 'sphinx.ext.napoleon', 'sphinx.ext.viewcode', ] + +# Add any paths that contain templates here, relative to this directory. +templates_path = ['_templates'] + +# List of patterns, relative to source directory, that match files and +# directories to ignore when looking for source files. +# This pattern also affects html_static_path and html_extra_path. +exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store'] + + +# -- Options for HTML output ------------------------------------------------- + +# The theme to use for HTML and HTML Help pages. See the documentation for +# a list of builtin themes. +# +html_theme = 'alabaster' + +# Add any paths that contain custom static files (such as style sheets) here, +# relative to this directory. They are copied after the builtin static files, +# so a file named "default.css" will overwrite the builtin "default.css". +html_static_path = ['_static'] + + +def monkeypatch(cls): + """ decorator to monkey-patch methods """ + def decorator(f): + method = f.__name__ + old_method = getattr(cls, method) + setattr(cls, method, lambda self, *args, **kwargs: f(old_method, self, *args, **kwargs)) + return decorator + + +# workaround until https://github.com/miyakogi/m2r/pull/55 is merged +@monkeypatch(sphinx.registry.SphinxComponentRegistry) +def add_source_parser(_old_add_source_parser, self, *args, **kwargs): + # signature is (parser: Type[Parser], **kwargs), but m2r expects + # the removed (str, parser: Type[Parser], **kwargs). + if isinstance(args[0], str): + args = args[1:] + return _old_add_source_parser(self, *args, **kwargs) + + +# Custom options +autosummary_generate = True +#autoclass_content = "class" +#autodoc_default_flags = ['members', 'inherited-members'] +autodoc_member_order = 'bysource' +#numpydoc_class_members_toctree = False +source_suffix = ['.rst', '.md'] +master_doc = 'index' + +import offpele +version = offpele.__version__ + +pygments_style = 'sphinx' + +html_theme = 'sphinx_rtd_theme' + +napoleon_google_docstring = False +napoleon_use_param = False +napoleon_use_ivar = True +#html_theme = 'bootstrap' +#html_theme_path = sphinx_bootstrap_theme.get_html_theme_path() diff --git a/docs/index.rst b/docs/index.rst new file mode 100644 index 00000000..92e2ca78 --- /dev/null +++ b/docs/index.rst @@ -0,0 +1,25 @@ +Open Force Field for PELE +========================= + +The Open Force Field for PELE is a Python package that builds +PELE-compatible force field templates using the Open Force Field +toolkit. + + +User guide +---------- + +.. toctree:: + :maxdepth: 2 + :caption: Contents: + + +API documentation +----------------- + +.. toctree:: + :maxdepth: 1 + + topology + template + solvent diff --git a/docs/make.bat b/docs/make.bat new file mode 100644 index 00000000..2119f510 --- /dev/null +++ b/docs/make.bat @@ -0,0 +1,35 @@ +@ECHO OFF + +pushd %~dp0 + +REM Command file for Sphinx documentation + +if "%SPHINXBUILD%" == "" ( + set SPHINXBUILD=sphinx-build +) +set SOURCEDIR=. +set BUILDDIR=_build + +if "%1" == "" goto help + +%SPHINXBUILD% >NUL 2>NUL +if errorlevel 9009 ( + echo. + echo.The 'sphinx-build' command was not found. Make sure you have Sphinx + echo.installed, then set the SPHINXBUILD environment variable to point + echo.to the full path of the 'sphinx-build' executable. Alternatively you + echo.may add the Sphinx directory to PATH. + echo. + echo.If you don't have Sphinx installed, grab it from + echo.http://sphinx-doc.org/ + exit /b 1 +) + +%SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% +goto end + +:help +%SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% + +:end +popd diff --git a/docs/solvent.rst b/docs/solvent.rst new file mode 100644 index 00000000..1e48e96f --- /dev/null +++ b/docs/solvent.rst @@ -0,0 +1,20 @@ +.. _solvent :: + +Solvent models +============== + +This module provides different methods to parameterize solvent models +for PELE. + +.. currentmodule:: offpele.solvent + +Primary objects +--------------- + +.. autosummary:: + :nosignatures: + :toctree: api/autogenerated + :template: class.rst + + OBC1 + OBC2 diff --git a/docs/template.rst b/docs/template.rst new file mode 100644 index 00000000..45858503 --- /dev/null +++ b/docs/template.rst @@ -0,0 +1,35 @@ +.. _template :: + +Template handlers +================= + +This module provides a toolkit to generate parameter templates for PELE. + +.. currentmodule:: offpele.template + +Primary objects +--------------- + +.. autosummary:: + :nosignatures: + :toctree: api/autogenerated + :template: class.rst + + Impact + + +Secondary objects +----------------- + +.. autosummary:: + :nosignatures: + :toctree: api/autogenerated + :template: class.rst + + impact.WritableWrapper + impact.WritableAtom + impact.WritableBond + impact.WritableAngle + impact.WritableProper + impact.WritableImproper + diff --git a/docs/topology.rst b/docs/topology.rst new file mode 100644 index 00000000..3aa8dda3 --- /dev/null +++ b/docs/topology.rst @@ -0,0 +1,44 @@ +.. _topology :: + +Topology representations +======================== + +This module provides different topological representations to +translate from external toolkits the different molecular parameters +for PELE. + +.. currentmodule:: offpele.topology + +Primary objects +--------------- + +.. autosummary:: + :nosignatures: + :toctree: api/autogenerated + :template: class.rst + + Molecule + + +Secondary objects +----------------- + +.. autosummary:: + :nosignatures: + :toctree: api/autogenerated + :template: class.rst + + Atom + Bond + Angle + Dihedral + Proper + Improper + molecule.DummyAtom + topology.OFFDihedral + topology.OFFProper + topology.OFFImproper + ZMatrix + rotamer.Rotamer + rotamer.RotamerLibrary + rotamer.MolecularGraph From d63e127f4f2e282cd523e62b16f6a6d8d3ac9fa8 Mon Sep 17 00:00:00 2001 From: Marti Municoy Date: Fri, 17 Jul 2020 20:32:28 +0200 Subject: [PATCH 64/67] Minor changes in solvent module --- offpele/solvent/__init__.py | 2 +- offpele/solvent/solvent.py | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/offpele/solvent/__init__.py b/offpele/solvent/__init__.py index c5ba5def..e54c8b12 100644 --- a/offpele/solvent/__init__.py +++ b/offpele/solvent/__init__.py @@ -1 +1 @@ -from .solvent import * +from .solvent import OBC1, OBC2 diff --git a/offpele/solvent/solvent.py b/offpele/solvent/solvent.py index 5028f599..c2145fde 100644 --- a/offpele/solvent/solvent.py +++ b/offpele/solvent/solvent.py @@ -237,7 +237,7 @@ def _initialize_from_molecule(self): class OBC2(_SolventWrapper): """ - Implementation of the OBC1 solvent. + Implementation of the OBC2 solvent. """ _ff_file = get_data_file_path('forcefields/GBSA_OBC1-1.0.offxml') @@ -257,7 +257,7 @@ def __init__(self, molecule): Generate the solvent parameters of a molecule - >>> from offpele.topology import Molecule + >>> from offpele.topology import Molecule >>> from offpele.solvent import OBC2 >>> molecule = Molecule('molecule.pdb') From 2eedf9d4daab32669842fec281629c8cb9719258 Mon Sep 17 00:00:00 2001 From: Marti Municoy Date: Fri, 17 Jul 2020 20:32:54 +0200 Subject: [PATCH 65/67] Ignore Sphinx's autogenerated api --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index b6e47617..76739042 100644 --- a/.gitignore +++ b/.gitignore @@ -70,6 +70,7 @@ instance/ # Sphinx documentation docs/_build/ +docs/api/autogenerated/ # PyBuilder target/ From 6c785101936b455ca80ace0ce05477715374a00d Mon Sep 17 00:00:00 2001 From: Marti Municoy Date: Fri, 17 Jul 2020 20:33:13 +0200 Subject: [PATCH 66/67] Minor changes in topology module --- offpele/topology/__init__.py | 4 ++-- offpele/topology/molecule.py | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/offpele/topology/__init__.py b/offpele/topology/__init__.py index f6e06276..b9f25ef0 100644 --- a/offpele/topology/__init__.py +++ b/offpele/topology/__init__.py @@ -1,3 +1,3 @@ -from .topology import Bond, Angle, Proper, Improper -from .molecule import Molecule +from .topology import Bond, Angle, Dihedral, Proper, Improper +from .molecule import Atom, Molecule from .zmatrix import ZMatrix diff --git a/offpele/topology/molecule.py b/offpele/topology/molecule.py index 9aa17211..ca8258fd 100644 --- a/offpele/topology/molecule.py +++ b/offpele/topology/molecule.py @@ -370,14 +370,14 @@ def __init__(self, path=None): Load a molecule from a PDB file and parameterize it - >>> from offpele.topology import Molecule + >>> from offpele.topology import Molecule >>> molecule = Molecule('molecule.pdb') >>> molecule.parameterize('openff_unconstrained-1.1.1.offxml') Generate the rotamer library of a molecule - >>> from offpele.topology import Molecule + >>> from offpele.topology import Molecule >>> molecule = Molecule('molecule.pdb') >>> molecule.parameterize('openff_unconstrained-1.1.1.offxml') From 6fa3b07af950412c4d141ea4c4c343c953bd5492 Mon Sep 17 00:00:00 2001 From: Marti Municoy Date: Fri, 17 Jul 2020 20:33:29 +0200 Subject: [PATCH 67/67] Minor changes in impact module --- offpele/template/impact.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/offpele/template/impact.py b/offpele/template/impact.py index 9f6975f5..4ca5fa9f 100644 --- a/offpele/template/impact.py +++ b/offpele/template/impact.py @@ -31,7 +31,7 @@ def __init__(self, molecule): Write the Impact template of a offpele's molecule - >>> from offpele.topology import Molecule + >>> from offpele.topology import Molecule >>> from offpele.template import Impact >>> molecule = Molecule('molecule.pdb')