CoolFace
Modelpublic

OneScience-Group/SurfDock

sourceHugging Facemitupdated 16d agoView on Hugging Face
0likes25downloads
cleaup.py122 linesDownload Raw Back to force_optimize
1# Copyright 2021 DeepMind Technologies Limited2#3# Licensed under the Apache License, Version 2.0 (the "License");4# you may not use this file except in compliance with the License.5# You may obtain a copy of the License at6#7#      http://www.apache.org/licenses/LICENSE-2.08#9# Unless required by applicable law or agreed to in writing, software10# distributed under the License is distributed on an "AS IS" BASIS,11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.12# See the License for the specific language governing permissions and13# limitations under the License.14 15"""Cleans up a PDB file using pdbfixer in preparation for OpenMM simulations.16fix_pdb uses a third-party tool. We also support fixing some additional edge17cases like removing chains of length one (see clean_structure).18"""19import io20 21from pdbfixer import PDBFixer22from openmm import app23from openmm.app import element24from openmm.app.internal import pdbstructure25 26def pdb_to_structure(pdb_str):27  handle = io.StringIO(pdb_str)28  return pdbstructure.PdbStructure(handle)29 30def fix_pdb(pdbfile, alterations_info):31  """Apply pdbfixer to the contents of a PDB file; return a PDB string result.32  1) Replaces nonstandard residues.33  2) Removes heterogens (non protein residues) including water.34  3) Adds missing residues and missing atoms within existing residues.35  4) Adds hydrogens assuming pH=7.0.36  5) KeepIds is currently true, so the fixer must keep the existing chain and37     residue identifiers. This will fail for some files in wider PDB that have38     invalid IDs.39  Args:40    pdbfile: Input PDB file handle.41    alterations_info: A dict that will store details of changes made.42  Returns:43    A PDB string representing the fixed structure.44  """45  fixer = PDBFixer(pdbfile)46  fixer.findNonstandardResidues()47  alterations_info['nonstandard_residues'] = fixer.nonstandardResidues48  fixer.replaceNonstandardResidues()49  _remove_heterogens(fixer, alterations_info, keep_water=False)50  fixer.findMissingResidues()51  alterations_info['missing_residues'] = fixer.missingResidues52  fixer.findMissingAtoms()53  alterations_info['missing_heavy_atoms'] = fixer.missingAtoms54  alterations_info['missing_terminals'] = fixer.missingTerminals55  fixer.addMissingAtoms(seed=0)56  fixer.addMissingHydrogens()57  out_handle = io.StringIO()58  app.PDBFile.writeFile(fixer.topology, fixer.positions, out_handle,59                        keepIds=True)60  return out_handle.getvalue()61 62def clean_structure(pdb_structure, alterations_info):63  """Applies additional fixes to an OpenMM structure, to handle edge cases.64  Args:65    pdb_structure: An OpenMM structure to modify and fix.66    alterations_info: A dict that will store details of changes made.67  """68  _replace_met_se(pdb_structure, alterations_info)69  _remove_chains_of_length_one(pdb_structure, alterations_info)70 71 72def _remove_heterogens(fixer, alterations_info, keep_water):73  """Removes the residues that Pdbfixer considers to be heterogens.74  Args:75    fixer: A Pdbfixer instance.76    alterations_info: A dict that will store details of changes made.77    keep_water: If True, water (HOH) is not considered to be a heterogen.78  """79  initial_resnames = set()80  for chain in fixer.topology.chains():81    for residue in chain.residues():82      initial_resnames.add(residue.name)83  fixer.removeHeterogens(keepWater=keep_water)84  final_resnames = set()85  for chain in fixer.topology.chains():86    for residue in chain.residues():87      final_resnames.add(residue.name)88  alterations_info['removed_heterogens'] = (89      initial_resnames.difference(final_resnames))90 91 92def _replace_met_se(pdb_structure, alterations_info):93  """Replace the Se in any MET residues that were not marked as modified."""94  modified_met_residues = []95  for res in pdb_structure.iter_residues():96    name = res.get_name_with_spaces().strip()97    if name == 'MET':98      s_atom = res.get_atom('SD')99      if s_atom.element_symbol == 'Se':100        s_atom.element_symbol = 'S'101        s_atom.element = element.get_by_symbol('S')102        modified_met_residues.append(s_atom.residue_number)103  alterations_info['Se_in_MET'] = modified_met_residues104 105 106def _remove_chains_of_length_one(pdb_structure, alterations_info):107  """Removes chains that correspond to a single amino acid.108  A single amino acid in a chain is both N and C terminus. There is no force109  template for this case.110  Args:111    pdb_structure: An OpenMM pdb_structure to modify and fix.112    alterations_info: A dict that will store details of changes made.113  """114  removed_chains = {}115  for model in pdb_structure.iter_models():116    valid_chains = [c for c in model.iter_chains() if len(c) > 1]117    invalid_chain_ids = [c.chain_id for c in model.iter_chains() if len(c) <= 1]118    model.chains = valid_chains119    for chain_id in invalid_chain_ids:120      model.chains_by_id.pop(chain_id)121    removed_chains[model.number] = invalid_chain_ids122  alterations_info['removed_chains'] = removed_chains