def __init__(self, topologies): """ Initializes an OBC1 object. Parameters ---------- topologies : a Topology object or list[Topology object] The molecular topology representation to write as a Impact template """ # Not implemented in PELE logger = Logger() logger.warning('OBC1 is not implemented in PELE') super().__init__(topologies)
def _build(self): """The topology builder.""" # In case the molecule has not been initialized if (self.molecule.rdkit_molecule is None or len(list(self.parameters.atom_iterator)) == 0): logger = Logger() logger.warning('Warning: the input molecule has not been ' + ' initialized and its topology will be empty') return self._build_atoms() self._build_bonds() self._build_angles() self._build_propers() self._build_impropers()
def _pdb_checkup(self, path): """ Safety check for PDB files in order to properly handle exceptions related with its format prior running the parser. Parameters ---------- path : str The path to a PDB with the molecule structure """ # Parse PDB file atom_id, res_name, res_id = ([] for i in range(3)) connectivity = False with open(path) as pdb_file: for line in pdb_file: if line.startswith('ATOM') or line.startswith('HETATM'): atom_id.append(line[12:16]) res_name.append(line[17:20]) res_id.append(line[22:26]) if line.startswith('CONECT'): connectivity = True # Handle exceptions related with the PDB file format if not res_id[:-1] == res_id[1:]: raise Exception( 'A single ligand with immutable residue ids is expected') if not res_name[:-1] == res_name[1:]: raise Exception( 'A single ligand with immutable residue names is expected') if not len(atom_id) == len(set(atom_id)): raise Exception('Ligand in input PDB has no unique atom names') if not connectivity and self.connectivity_template is None: log = Logger() log.warning( "Warning: input PDB has no information about the " + "connectivity and this could result in an unexpected " + "bond assignment")
def _extract_molecules_from_chain(self, chain, rotamer_resolution, exclude_terminal_rotamers, allow_undefined_stereo, core_constraints): """ It extracts all hetero molecules found in the selected the chain of a PDB file. Parameters ---------- chain_id : str Chain ID. rotamer_resolution : float The resolution in degrees to discretize the rotamer's conformational space. Default is 30 exclude_terminal_rotamers : bool Whether to exclude terminal rotamers when generating the rotamers library or not allow_undefined_stereo : bool Whether to allow a molecule with undefined stereochemistry to be defined or try to assign the stereochemistry and raise a complaint if not possible. Default is False core_constraints : list[int or str] It defines the list of atoms to constrain in the core, thus, the core will be forced to contain them. Atoms can be specified through integers that match the atom index or strings that match with the atom PDB name Returns ------- molecules : list[peleffy.topology.Molecule object] Selected molecules """ from peleffy.topology.molecule import Molecule # Check if there is more than one hetero molecule in the same chain residues_ids = set([ line[22:26].strip() for line in self.pdb_content if line.startswith('HETATM') and line[21:22] == chain and not line[17:20].strip() == 'HOH' ]) molecules = [] for residue_id in residues_ids: res_name = set([ line[17:20].strip() for line in self.pdb_content if line.startswith('HETATM') and line[21:22] == chain and line[22:26].strip() == residue_id ]) # Select which atoms compose this hetero molecule atom_ids = [ line[6:11].strip() for line in self.pdb_content if line.startswith('HETATM') and line[21:22] == chain and line[22:26].strip() == residue_id ] # Extract the PDB block of the molecule pdb_block = [ line for line in self.pdb_content if (line.startswith('HETATM') or line.startswith('CONECT')) and any(' {} '.format(a) in line for a in atom_ids) ] try: molecules.append( Molecule( pdb_block=''.join(pdb_block), rotamer_resolution=rotamer_resolution, exclude_terminal_rotamers=exclude_terminal_rotamers, allow_undefined_stereo=allow_undefined_stereo, core_constraints=core_constraints)) except Exception as e: log = Logger() log.warning(' - Skipping {} '.format(list(res_name)[0]) + 'from chain {}'.format(chain)) log.warning(' - The following exception was raised: ' + '{}'.format(e)) return molecules
def _read_and_fix_pdb(self, path): """ It reads the input PDB file returns the corresponding PDB block. It also applies some modifications, in case it requires some fixing prior running the parser. Parameters ---------- path : str The path to a PDB with the molecule structure Returns ------- pdb_block : str The corresponding PDB block, with applied fixes if required """ log = Logger() # Skip PDB fixing if it has been deactivated if not self.fix_pdb: with open(path) as pdb_file: pdb_block = pdb_file.read() return pdb_block # Fix PDB missing_element = False any_fail = False pdb_block = '' with open(path) as pdb_file: for line in pdb_file: if line.startswith('ATOM') or line.startswith('HETATM'): if len(line) < 78 or line[76:78] == ' ': missing_element = True atom_name = line[12:16] # Try to infer element from atom name inferred_element = ''.join([ c for c in atom_name if not c.isdigit() and c != ' ' ]) # Format properly the element identifier if len(inferred_element) == 1: inferred_element = inferred_element.upper() elif len(inferred_element) == 2: inferred_element = inferred_element[0].upper() + \ inferred_element[1].lower() else: # We were expecting an element identifier of 1 or 2 chars any_fail = True break # Remove line breaks, if any line = line.strip() # Fill a short line with white spaces while (len(line) < 79): line += ' ' # Add element to line (right-justified) line = line[:76] + '{:>2s}'.format(inferred_element) \ + line[79:] + '\n' pdb_block += line if missing_element: log.warning("Warning: input PDB has no information about atom " + "elements and they were inferred from atom names. " + "Please, verify that the resulting elements are " + "correct") if any_fail: log.error("Error: PDB could not be fixed") with open(path) as pdb_file: pdb_block = pdb_file.read() return pdb_block