def _get_isomorphisms(self, test_atoms): ref = self.ref mol = test_atoms # Make all bond orders 1 and reassign atom types # this is a magic recipe for bond in ob.OBMolBondIter(ref): bond.SetBondOrder(1) for bond in ob.OBMolBondIter(mol): bond.SetBondOrder(1) ob.OBAtomTyper().AssignTypes(ref) ob.OBAtomTyper().AssignTypes(mol) # DEBUG if False: rt = [a for a in ob.OBMolAtomIter(ref)] mt = [a for a in ob.OBMolAtomIter(mol)] for (r, m) in zip(rt, mt): print(r.GetType(), m.GetType(), r.GetType() == m.GetType()) r = self._atoms2obabel(ref_atoms, ref_type) m = self._atoms2obabel(mol_atoms) obutils.writeMolecule(r, 'ref.mol2', ftype='mol2') obutils.writeMolecule(m, 'mol.mol2', ftype='mol2') # Mapping magic query = ob.CompileMoleculeQuery(ref) mapper = ob.OBIsomorphismMapper.GetInstance(query) isomorphs = ob.vvpairUIntUInt() mapper.MapAll(mol, isomorphs) return isomorphs
def _build_automorphism(self): """ automorphisms are 0-based prune the automorphism map to remove identities and compact multiple mappings """ self._equivalents = {} automorphs = ob.vvpairUIntUInt() mol_copy = ob.OBMol(self.mol) for i in ob.OBMolAtomIter(mol_copy): isotope = i.GetIsotope() if not isotope == 0: n = i.GetAtomicNum() i.SetAtomicNum(n + isotope) ob.FindAutomorphisms(mol_copy, automorphs) self.automorphs = {} for am in automorphs: for i, j in am: if i == j: continue k = i + 1 l = j + 1 if self._is_hydrogen(k): continue if self._is_hydrogen(l): continue if not k in self.automorphs: self.automorphs[k] = [] self.automorphs[k].append(l) for k, v in list(self.automorphs.items()): self.automorphs[k] = set(v) if self.debug: from pprint import pprint print("AUTOMORPHS", end='') pprint(self.automorphs)
def uniform_labels(self, mol1, mol2): """ Pair the geometrically equivalent atoms of the molecules. Calculate RMSD on all possible isomorphism mappings and return mapping with the least RMSD Args: mol1: First molecule. OpenBabel OBMol or pymatgen Molecule object. mol2: Second molecule. OpenBabel OBMol or pymatgen Molecule object. Returns: (list1, list2) if uniform atom order is found. list1 and list2 are for mol1 and mol2, respectively. Their length equal to the number of atoms. They represents the uniform atom order of the two molecules. The value of each element is the original atom index in mol1 or mol2 of the current atom in uniform atom order. (None, None) if unform atom is not available. """ obmol1 = BabelMolAdaptor(mol1).openbabel_mol obmol2 = BabelMolAdaptor(mol2).openbabel_mol h1 = self.get_molecule_hash(obmol1) h2 = self.get_molecule_hash(obmol2) if h1 != h2: return None, None query = ob.CompileMoleculeQuery(obmol1) isomapper = ob.OBIsomorphismMapper.GetInstance(query) isomorph = ob.vvpairUIntUInt() isomapper.MapAll(obmol2, isomorph) sorted_isomorph = [sorted(x, key=lambda morp: morp[0]) for x in isomorph] label2_list = tuple([tuple([p[1] + 1 for p in x]) for x in sorted_isomorph]) vmol1 = obmol1 aligner = ob.OBAlign(True, False) aligner.SetRefMol(vmol1) least_rmsd = float("Inf") best_label2 = None label1 = list(range(1, obmol1.NumAtoms() + 1)) # noinspection PyProtectedMember elements1 = InchiMolAtomMapper._get_elements(vmol1, label1) for label2 in label2_list: # noinspection PyProtectedMember elements2 = InchiMolAtomMapper._get_elements(obmol2, label2) if elements1 != elements2: continue vmol2 = ob.OBMol() for i in label2: vmol2.AddAtom(obmol2.GetAtom(i)) aligner.SetTargetMol(vmol2) aligner.Align() rmsd = aligner.GetRMSD() if rmsd < least_rmsd: least_rmsd = rmsd best_label2 = copy.copy(label2) return label1, best_label2
def _get_automorphisms(self): mol = self._atoms2obabel(self.ref_atoms).OBMol automorphs = ob.vvpairUIntUInt() ob.FindAutomorphisms(mol, automorphs) return automorphs