def test_distance_is_minimum_pairwise(protein): res1 = protein.residues[0] res2 = protein.residues[2] assert res1.distance(res2) == _get_minimum_pairwise(res1, res2) assert res1.distance(res2.atoms[3]) == _get_minimum_pairwise(res1, mdt.AtomList([res2.atoms[3]]))
def __init__(self, atoms, value=None, tolerance=None, force_constant=None): self.atoms = mdt.AtomList(atoms) self.mol = self.atoms[0].molecule self.tolerance = tolerance self.force_constant = force_constant for atom in self.atoms: assert atom.molecule is self.mol self.value = mdt.utils.if_not_none(value, self.current())
def get_atoms(self, *keywords, **queries): """Allows keyword-based atom queries. Returns atoms that match ALL queries. Args: *keywords (list): pre-set keywords (currently, just selects by residue type) **queries (dict): attributes (or residue attributes) to match Examples: >>> mol.get_atoms('protein') # returns all atoms in proteins >>> mol.get_atoms(name='CA') # returns all alpha carbons >>> mol.get_atoms('dna', symbol='P') # returns all phosphorus in DNA Returns: AtomList: the atoms matching this query """ if not (queries or keywords): return mdt.AtomList(self.atoms) atoms = self.atoms KEYS = 'protein dna rna water unknown ion'.split() for key in keywords: if key in KEYS: atoms = mdt.AtomList(atom for atom in atoms if atom.residue.type == key) else: raise ValueError("Invalid keyword '%s': valid values are %s" % (key, KEYS)) result = mdt.AtomList() for atom in atoms: for field, val in queries.items(): if getattr(atom, field, None) != val and getattr( atom.residue, field, None) != val: break else: result.append(atom) return result
def add_atoms(self, newatoms): """Add new atoms to this molecule. *Copies* of the passed atoms will be added if they already belong to another molecule. Args: newatoms (List[moldesign.Atom])) """ owner = newatoms[0].molecule for atom in newatoms: if atom.molecule is not owner: raise ValueError( 'Cannot add atoms from multiple sources - add them separately.' ) if owner is not None: # copy if the atoms are already owned newatoms = mdt.AtomList(newatoms).copy() self.atoms.extend(newatoms) self.bond_graph._add_atoms(newatoms) self._rebuild_from_atoms()
def __init__(self, mol, carbon_labels=True, names=None, display=False, _forcebig=False, **kwargs): self.carbon_labels = carbon_labels try: self.atoms = mol.atoms except AttributeError: self.atoms = mdt.AtomList(mol) self.mol = self.atoms else: self.mol = mol if not _forcebig and len(self.atoms) > self.MAXATOMS: raise ValueError( 'Refusing to draw more than 200 atoms in 2D visualization. ' 'Override this with _forcebig=True') if names is None: names = [] for atom in self.atoms: if atom.formal_charge == 0: names.append(atom.name) else: names.append(atom.name + _charge_str(atom.formal_charge)) self.names = names self.atom_indices = {atom: i for i, atom in enumerate(self.atoms)} self.selection_group = None self.selection_id = None super(ChemicalGraphViewer, self).__init__(self.atoms, **kwargs) if display: dsp.display(self)
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 atomlist(protein): return mdt.AtomList(random.sample(protein.atoms, 10))
def __add__(self, other): l = mdt.AtomList(self.atoms) l.extend(other.atoms) return l