def biopy_to_mol(struc): """Convert a biopython PDB structure to an MDT molecule. Because Biopython doesn't assign bonds, assign connectivity using templates. Args: struc (Bio.PDB.Structure.Structure): Biopython PDB structure to convert Returns: moldesign.Molecule: converted molecule """ # TODO: assign bonds using 1) CONECT records, 2) residue templates, 3) distance newatoms = [] for chain in struc.get_chains(): tmp, pdbidx, pdbid = chain.get_full_id() newchain = mdt.Chain(pdbname=pdbid.strip()) for residue in chain.get_residues(): newresidue = mdt.Residue(pdbname=residue.resname.strip(), pdbindex=residue.id[1]) newchain.add(newresidue) for atom in residue.get_atom(): newatom = mdt.Atom(element=atom.element, name=atom.get_name(), pdbname=atom.get_name(), pdbindex=atom.get_serial_number()) newatom.position = atom.coord * u.angstrom newresidue.add(newatom) newatoms.append(newatom) return mdt.Molecule(newatoms, name=struc.get_full_id()[0])
def parmed_to_mdt(pmdmol): """ Convert parmed Structure to MDT Structure Args: pmdmol (parmed.Structure): parmed structure to convert Returns: mdt.Molecule: converted molecule """ atoms = collections.OrderedDict() residues = {} chains = {} masses = [pa.mass for pa in pmdmol.atoms] * u.dalton positions = [[pa.xx, pa.xy, pa.xz] for pa in pmdmol.atoms] * u.angstrom for iatom, patm in enumerate(pmdmol.atoms): if patm.residue.chain not in chains: chains[patm.residue.chain] = mdt.Chain(pdbname=patm.residue.chain) chain = chains[patm.residue.chain] if patm.residue not in residues: residues[patm.residue] = mdt.Residue(resname=patm.residue.name, pdbindex=patm.residue.number) residues[patm.residue].chain = chain chain.add(residues[patm.residue]) residue = residues[patm.residue] atom = mdt.Atom(name=patm.name, atnum=patm.atomic_number, pdbindex=patm.number, mass=masses[iatom]) atom.position = positions[iatom] atom.residue = residue residue.add(atom) assert patm not in atoms atoms[patm] = atom for pbnd in pmdmol.bonds: atoms[pbnd.atom1].bond_to(atoms[pbnd.atom2], int(pbnd.order)) mol = mdt.Molecule(list(atoms.values()), metadata=_get_pdb_metadata(pmdmol)) return mol
def biopy_to_mol(struc): """Convert a biopython PDB structure to an MDT molecule. Note: Biopython doesn't deal with bond data, so no bonds will be present in the Molecule Args: struc (Bio.PDB.Structure.Structure): Biopython PDB structure to convert Returns: moldesign.Molecule: converted molecule """ # TODO: assign bonds using 1) CONECT records, 2) residue templates, 3) distance newatoms = [] backup_chain_names = list(string.ascii_uppercase) for chain in struc.get_chains(): tmp, pdbidx, pdbid = chain.get_full_id() if not pdbid.strip(): pdbid = backup_chain_names.pop() newchain = mdt.Chain(pdbname=pdbid.strip()) for residue in chain.get_residues(): newresidue = mdt.Residue(pdbname=residue.resname.strip(), pdbindex=residue.id[1]) newchain.add(newresidue) for atom in residue.get_atom(): elem = atom.element if len(elem) == 2: elem = elem[0] + elem[1].lower() newatom = mdt.Atom(element=elem, name=atom.get_name(), pdbname=atom.get_name(), pdbindex=atom.get_serial_number()) newatom.position = atom.coord * u.angstrom newresidue.add(newatom) newatoms.append(newatom) return mdt.Molecule(newatoms, name=struc.get_full_id()[0])
def pybel_to_mol(pbmol, reorder_atoms_by_residue=False, primary_structure=True, **kwargs): """ Translate a pybel molecule object into a moldesign object. Note: The focus is on translating topology and biomolecular structure - we don't translate any metadata. Args: pbmol (pybel.Molecule): molecule to translate reorder_atoms_by_residue (bool): change atom order so that all atoms in a residue are stored contiguously primary_structure (bool): translate primary structure data as well as atomic data **kwargs (dict): keyword arguments to moldesign.Molecule __init__ method Returns: moldesign.Molecule: translated molecule """ newatom_map = {} newresidues = {} newchains = {} newatoms = mdt.AtomList([]) backup_chain_names = list(string.ascii_uppercase) for pybatom in pbmol.atoms: obres = pybatom.OBAtom.GetResidue() name = obres.GetAtomID(pybatom.OBAtom).strip() if pybatom.atomicnum == 67: print(( "WARNING: openbabel parsed atom serial %d (name:%s) as Holmium; " "correcting to hydrogen. ") % (pybatom.OBAtom.GetIdx(), name)) atnum = 1 elif pybatom.atomicnum == 0: print( "WARNING: openbabel failed to parse atom serial %d (name:%s); guessing %s. " % (pybatom.OBAtom.GetIdx(), name, name[0])) atnum = mdt.data.ATOMIC_NUMBERS[name[0]] else: atnum = pybatom.atomicnum mdtatom = mdt.Atom(atnum=atnum, name=name, formal_charge=pybatom.formalcharge * u.q_e, pdbname=name, pdbindex=pybatom.OBAtom.GetIdx()) newatom_map[pybatom.OBAtom.GetIdx()] = mdtatom mdtatom.position = pybatom.coords * u.angstrom if primary_structure: obres = pybatom.OBAtom.GetResidue() resname = obres.GetName() residx = obres.GetIdx() chain_id = obres.GetChain() chain_id_num = obres.GetChainNum() if chain_id_num not in newchains: # create new chain if not mdt.utils.is_printable( chain_id.strip()) or not chain_id.strip(): chain_id = backup_chain_names.pop() print( 'WARNING: assigned name %s to unnamed chain object @ %s' % (chain_id, hex(chain_id_num))) chn = mdt.Chain(pdbname=str(chain_id)) newchains[chain_id_num] = chn else: chn = newchains[chain_id_num] if residx not in newresidues: # Create new residue pdb_idx = obres.GetNum() res = mdt.Residue(pdbname=resname, pdbindex=pdb_idx) newresidues[residx] = res chn.add(res) res.chain = chn else: res = newresidues[residx] res.add(mdtatom) newatoms.append(mdtatom) for ibond in range(pbmol.OBMol.NumBonds()): obbond = pbmol.OBMol.GetBond(ibond) a1 = newatom_map[obbond.GetBeginAtomIdx()] a2 = newatom_map[obbond.GetEndAtomIdx()] order = obbond.GetBondOrder() bond = mdt.Bond(a1, a2) bond.order = order if reorder_atoms_by_residue and primary_structure: resorder = {} for atom in newatoms: resorder.setdefault(atom.residue, len(resorder)) newatoms.sort(key=lambda a: resorder[a.residue]) return mdt.Molecule(newatoms, **kwargs)
def topology_to_mol(topo, name=None, positions=None, velocities=None, assign_bond_orders=True): """ Convert an OpenMM topology object into an MDT molecule. Args: topo (simtk.openmm.app.topology.Topology): topology to convert name (str): name to assign to molecule positions (list): simtk list of atomic positions velocities (list): simtk list of atomic velocities assign_bond_orders (bool): assign bond orders from templates (simtk topologies do not store bond orders) """ from simtk import unit as stku # Atoms atommap = {} newatoms = [] masses = u.amu * [ atom.element.mass.value_in_unit(stku.amu) for atom in topo.atoms() ] for atom, mass in zip(topo.atoms(), masses): newatom = mdt.Atom(atnum=atom.element.atomic_number, name=atom.name, mass=mass) atommap[atom] = newatom newatoms.append(newatom) # Coordinates if positions is not None: poslist = np.array( [p.value_in_unit(stku.nanometer) for p in positions]) * u.nm poslist.ito(u.default.length) for newatom, position in zip(newatoms, poslist): newatom.position = position if velocities is not None: velolist = np.array([ v.value_in_unit(stku.nanometer / stku.femtosecond) for v in velocities ]) * u.nm / u.fs velolist = u.default.convert(velolist) for newatom, velocity in zip(newatoms, velolist): newatom.momentum = newatom.mass * simtk2pint(velocity) # Biounits chains = {} for chain in topo.chains(): if chain.id not in chains: chains[chain.id] = mdt.Chain(name=chain.id, index=chain.index) newchain = chains[chain.id] for residue in chain.residues(): newresidue = mdt.Residue(name='%s%d' % (residue.name, residue.index), chain=newchain, pdbindex=int(residue.id), pdbname=residue.name) newchain.add(newresidue) for atom in residue.atoms(): newatom = atommap[atom] newatom.residue = newresidue newresidue.add(newatom) # Bonds bonds = {} for bond in topo.bonds(): a1, a2 = bond na1, na2 = atommap[a1], atommap[a2] if na1 not in bonds: bonds[na1] = {} if na2 not in bonds: bonds[na2] = {} b = mdt.Bond(na1, na2) b.order = 1 if name is None: name = 'Unnamed molecule from OpenMM' newmol = mdt.Molecule(newatoms, name=name) if assign_bond_orders: for residue in newmol.residues: try: residue.assign_template_bonds() except (KeyError, ValueError): pass return newmol