def testRoundTripOps(self): """Test IO operation on generated related molecules""" try: oeIoU = OeIoUtils() mU = MarshalUtil() mU.mkdir(self.__molfileDirPath) ccMolD = self.__getChemCompDefs() oemf = OeMoleculeFactory() for ccId, ccObj in list(ccMolD.items())[:10]: # ---- tId = oemf.setChemCompDef(ccObj) self.assertEqual(tId, ccId) relatedIdxD = oemf.buildRelated(limitPerceptions=False) logger.info("%s generated %d molecular forms", ccId, len(relatedIdxD)) for sId, idxD in relatedIdxD.items(): logger.info("sId %r smiles %r", sId, idxD["smiles"]) mol2Path = os.path.join(self.__molfileDirPath, sId + ".mol2") oeMol = oeIoU.descriptorToMol(idxD["smiles"], "oe-iso-smiles", limitPerceptions=False, messageTag=None) oeIoU.write(mol2Path, oeMol, constantMol=True, addSdTags=True) tMolL = oeIoU.fileToMols(mol2Path) # nextMol2Path = os.path.join(self.__molfileDirPath, sId + "-next.mol2") oeIoU.write(nextMol2Path, tMolL[0], constantMol=True, addSdTags=True) sdfPath = os.path.join(self.__molfileDirPath, sId + ".mol") oeMol = oeIoU.descriptorToMol(idxD["smiles"], "oe-iso-smiles", limitPerceptions=False, messageTag=None) oeIoU.write(sdfPath, oeMol, constantMol=True, addSdTags=True) # tMolL = oeIoU.fileToMols(sdfPath) nextSdfPath = os.path.join(self.__molfileDirPath, sId + "-next.sdf") oeIoU.write(nextSdfPath, tMolL[0], constantMol=True, addSdTags=True) # ---- except Exception as e: logger.exception("Failing with %s", str(e)) self.fail()
def __fingerPrintSearch(self, numMols, **kwargs): maxFpResults = kwargs.get("maxFpResults", 50) limitPerceptions = kwargs.get("limitPerceptions", False) fpTypeCuttoffList = kwargs.get("fpTypeCuttoffList", [("TREE", 0.6)]) buildTypeList = kwargs.get("buildTypeList", ["oe-iso-smiles"]) # oesmP, ccIdxD = self.__getSearchDataProviders(**kwargs) oesU = OeSearchUtils(oesmP, fpTypeList=[tup[0] for tup in fpTypeCuttoffList]) oeioU = OeIoUtils() # This will reload the oe binary cache. oeMol = oesmP.getMol("004") self.assertGreaterEqual(len(list(oeMol.GetAtoms())), 12) missedFpD = {} missedBuildD = {} numMols = min(len(ccIdxD), numMols) if numMols else len(ccIdxD) logger.info("Begin finger print search on %d molecules", numMols) # ---- startTime = time.time() for ccId, ccD in list(ccIdxD.items())[:numMols]: for buildType in buildTypeList: if buildType in ccD: oeMol = oeioU.descriptorToMol( ccD[buildType], buildType, limitPerceptions=limitPerceptions, messageTag=ccId + ":" + buildType) if not oeMol: continue selfHit = False for fpType, minFpScore in fpTypeCuttoffList: retStatus, mL = oesU.searchFingerPrints( oeMol, fpType=fpType, minFpScore=minFpScore, maxFpResults=maxFpResults) self.assertTrue(retStatus) # matchedSelf = self.__resultContains(ccId, mL) selfHit = selfHit or matchedSelf if not matchedSelf: missedFpD.setdefault(ccId, []).append( (buildType, fpType, len(mL))) # if not selfHit: missedBuildD.setdefault(ccId, []).append(buildType) # ------ for ccId, bTL in missedBuildD.items(): logger.info("%s missed all fptypes: buildtype list %r", ccId, bTL) if ccId in missedFpD: logger.info("%s unmatched by fpTypes %r", ccId, missedFpD[ccId]) # ---- logger.info("%s fingerprints search on %d in (%.4f seconds)", len(fpTypeCuttoffList), numMols, time.time() - startTime) # ---- return True
def matchByDescriptor(self, descriptor, descriptorType, matchOpts="graph-relaxed", searchId=None): """Return graph match (w/ finger print pre-filtering) and finger print search results for the input desriptor. Args: descriptor (str): molecular descriptor (SMILES, InChI) descriptorType (str): descriptor type (SMILES, InChI matchOpts (str, optional): graph match criteria (graph-relaxed, graph-relaxed-stereo, graph-strict, fingerprint-similarity, Defaults to "graph-relaxed") searchId (str, optional): search identifier for logging. Defaults to None. Returns: (statusCode, list, list): status, graph match and finger match lists of type (MatchResults) -100 descriptor processing error -200 search execution error 0 search execution success """ ssL = fpL = [] retStatus = False statusCode = -200 try: fpTypeCuttoffD = self.__configD["oesmpKwargs"][ "fpTypeCuttoffD"] if "fpTypeCuttoffD" in self.__configD[ "oesmpKwargs"] else {} maxFpResults = self.__configD["oesmpKwargs"][ "maxFpResults"] if "maxFpResults" in self.__configD[ "oesmpKwargs"] else 50 limitPerceptions = self.__configD["oesmpKwargs"][ "limitPerceptions"] if "limitPerceptions" in self.__configD[ "oesmpKwargs"] else False # searchId = searchId if searchId else "query" messageTag = searchId + ":" + descriptorType oeioU = OeIoUtils() oeMol = oeioU.descriptorToMol(descriptor, descriptorType, limitPerceptions=limitPerceptions, messageTag=messageTag) oeMol = oeioU.suppressHydrogens(oeMol) if not oeMol: logger.warning("descriptor type %r molecule build fails: %r", descriptorType, descriptor) return self.__statusDescriptorError, ssL, fpL # retStatus, ssL, fpL = self.__oesU.searchSubStructureAndFingerPrint( oeMol, list(fpTypeCuttoffD.items())[:2], maxFpResults, matchOpts=matchOpts) statusCode = 0 if retStatus else self.__searchError except Exception as e: logger.exception("Failing with %s", str(e)) # return statusCode, ssL, fpL
def __subStructureSearchScreened(self, numMols, **kwargs): # buildTypeList = kwargs.get("buildTypeList", ["oe-iso-smiles"]) screenTypeList = kwargs.get("screenTypeList", ["SMARTS"]) oesmP, ccIdxD = self.__getSearchDataProviders(**kwargs) for screenType in screenTypeList: oesU = OeSearchUtils(oesmP, screenType=screenType, numProc=self.__numProc) oeioU = OeIoUtils() # missL = [] numMols = min(len(ccIdxD), numMols) if numMols else len(ccIdxD) for ( ii, ccId, ) in enumerate(list(ccIdxD.keys())[:numMols]): ccD = ccIdxD[ccId] for buildType in buildTypeList: if buildType in ccD: if screenType == "SMARTS": smiles = oeioU.descriptorToSmiles(ccD[buildType], buildType, messageTag=ccId + ":" + buildType) oeQMol = oeioU.descriptorToMol(smiles, "SMARTS", messageTag=ccId + ":" + buildType) else: oeQMol = oeioU.descriptorToQMol(ccD[buildType], "SMARTS", messageTag=ccId + ":" + buildType) if not oeQMol: logger.debug("%s build failed for %s - skipping", ccId, buildType) continue # ---- startTime = time.time() retStatus, mL = oesU.searchSubStructureScreened( oeQMol, maxMatches=100) if retStatus: logger.debug( "%s - %s - %s (status=%r) match length %d in (%.4f seconds)", ccId, buildType, screenType, retStatus, len(mL), time.time() - startTime) if not self.__resultContains(ccId, mL): missL.append((ccId, buildType, screenType)) # ---- if ii % 100 == 0: logger.info("Completed %d of %d missed count %d", ii, numMols, len(missL)) logger.info("Screen %r missed searches (%d) %r", screenType, len(missL), missL) return True
def subStructSearchByDescriptor(self, descriptor, descriptorType, matchOpts="sub-struct-graph-relaxed", searchId=None): """Return graph match (w/ finger print pre-filtering) and finger print search results for the input desriptor. Args: descriptor (str): molecular descriptor (SMILES, InChI) descriptorType (str): descriptor type (SMILES, InChI) matchOpts (str, optional): graph match criteria (sub-struct-graph-relaxed, sub-struct-graph-relaxed-stereo, sub-struct-graph-strict). Defaults to "sub-struct-graph-relaxed". searchId (str, optional): search identifier for logging. Defaults to None. Returns: (statusCode, list, list): status, substructure search results of type (MatchResults), empty list placeholder -100 descriptor processing error -200 search execution error 0 search execution success """ ssL = [] retStatus = False statusCode = -200 try: limitPerceptions = self.__configD["oesmpKwargs"][ "limitPerceptions"] if "limitPerceptions" in self.__configD[ "oesmpKwargs"] else False numProc = self.__configD["oesmpKwargs"][ "numProc"] if "numProc" in self.__configD["oesmpKwargs"] else 4 # searchId = searchId if searchId else "query" messageTag = searchId + ":" + descriptorType oeioU = OeIoUtils() oeMol = oeioU.descriptorToMol(descriptor, descriptorType, limitPerceptions=limitPerceptions, messageTag=messageTag) oeMol = oeioU.suppressHydrogens(oeMol) if not oeMol: logger.warning("descriptor type %r molecule build fails: %r", descriptorType, descriptor) return self.__statusDescriptorError, ssL, [] # ccIdL = self.__oesubsU.prefilterIndex(oeMol, self.__siIdxP, matchOpts=matchOpts) retStatus, ssL = self.__oesubsU.searchSubStructure( oeMol, ccIdList=ccIdL, matchOpts=matchOpts, numProc=numProc) statusCode = 0 if retStatus else self.__searchError except Exception as e: logger.exception("Failing with %s", str(e)) # return statusCode, ssL, []
def __exhaustiveSubStructureSearch(self, numMols, **kwargs): """Exhaustive substructure search.""" try: limitPerceptions = kwargs.get("limitPerceptions", False) buildTypeList = kwargs.get("buildTypeList", ["oe-iso-smiles"]) oesmP, ccIdxD = self.__getSearchDataProviders(**kwargs) oesU = OeSearchUtils(oesmP, fpTypeList=[]) oeioU = OeIoUtils() # for ccId, ccD in list(ccIdxD.items())[:numMols]: matchCount = 0 mtS = set() for buildType in buildTypeList: if buildType in ccD: oeMol = oeioU.descriptorToMol( ccD[buildType], buildType, limitPerceptions=limitPerceptions, messageTag=ccId + ":" + buildType) if not oeMol: logger.error( "%s %s build query molecule build fails (skipping)", ccId, buildType) continue # ---- startTime = time.time() retStatus, mL = oesU.searchSubStructure( oeMol, matchOpts="graph-strict") if not retStatus: logger.info("%s match fails for build type %s", ccId, buildType) elif not self.__resultContains(ccId, mL): logger.info( "%s failed match length %d build type %s in (%.4f seconds)", ccId, len(mL), buildType, time.time() - startTime) elif self.__resultContains(ccId, mL): mtS.update([m.ccId for m in mL]) matchCount += 1 self.assertTrue(retStatus) self.assertTrue(self.__resultContains(ccId, mL)) if matchCount: logger.info("%s MATCHES %d: %r", ccId, matchCount, mtS) else: logger.info("%s NO MATCHES", ccId) # ---- return True except Exception as e: logger.exception("Failing with %s", str(e)) self.fail() return False
def __displayAlignedDescriptorPair(self, ccId, descrRef, buildTypeRef, descrFit, buildTypeFit, title=None, limitPerceptions=True): oeioU = OeIoUtils() oeMolRef = oeioU.descriptorToMol(descrRef, buildTypeRef, limitPerceptions=limitPerceptions, messageTag=ccId + ":" + buildTypeRef) oeMolFit = oeioU.descriptorToMol(descrFit, buildTypeFit, limitPerceptions=limitPerceptions, messageTag=ccId + ":" + buildTypeFit) # oed = OeDepictMCSAlignPage() oed.setSearchType(sType="graph-relaxed", minAtomMatchFraction=0.50) oed.setDisplayOptions(labelAtomName=True, labelAtomCIPStereo=True, labelAtomIndex=False, labelBondIndex=False, highlightStyleFit="ballAndStickInverse", bondDisplayWidth=0.5) oed.setRefMol(oeMolRef, ccId) oed.setFitMol(oeMolFit, ccId) myTitle = title if title else buildTypeRef + "-" + buildTypeFit imgPath = os.path.join(self.__workPath, myTitle + "-" + ccId + ".svg") logger.info("Using image path %r", imgPath) aML = oed.alignPair(imagePath=imgPath) if aML: logger.info("%s aligned image path %r", ccId, imgPath) for (rCC, rAt, tCC, tAt) in aML: logger.debug("%5s %-5s %5s %-5s", rCC, rAt, tCC, tAt)
def __getMol(self, query, queryType, queryId, limitPerceptions=False, suppressHydrogens=True): oeioU = OeIoUtils() if queryType == "CC": oeMol = self.__oesmP.getMol(query) else: oeMol = oeioU.descriptorToMol(query, queryType, limitPerceptions=limitPerceptions, messageTag=queryId) # if suppressHydrogens: oeMol = oeioU.suppressHydrogens(oeMol) oeMol.SetTitle(queryId) return oeMol
def __exhaustiveSubStructureSearch(self, numMols, **kwargs): """Exhaustive substructure search.""" try: limitPerceptions = kwargs.get("limitPerceptions", False) buildTypeList = kwargs.get("buildTypeList", ["oe-iso-smiles"]) oesmP, ccIdxD = self.__getSearchDataProviders(**kwargs) oesU = OeSearchUtils(oesmP, fpTypeList=[]) oeioU = OeIoUtils() # for ccId, ccD in list(ccIdxD.items())[:numMols]: for buildType in buildTypeList: if buildType in ccD: oeMol = oeioU.descriptorToMol( ccD[buildType], buildType, limitPerceptions=limitPerceptions, messageTag=ccId + ":" + buildType) if not oeMol: continue # ---- startTime = time.time() retStatus, mL = oesU.searchSubStructure( oeMol, matchOpts="graph-strict") if not self.__resultContains(ccId, mL): logger.info( "%s match length %d build type %s in (%.4f seconds)", ccId, len(mL), buildType, time.time() - startTime) self.assertTrue(retStatus) self.assertTrue(self.__resultContains(ccId, mL)) # ---- return True except Exception as e: logger.exception("Failing with %s", str(e)) self.fail() return False
def __sssWithFingerPrintFromDescriptor(self, numMols, **kwargs): maxFpResults = kwargs.get("maxResults", 50) limitPerceptions = kwargs.get("limitPerceptions", False) fpTypeCuttoffList = kwargs.get("fpTypeCuttoffList", [("TREE", 0.6)]) buildTypeList = kwargs.get("buildTypeList", ["oe-iso-smiles"]) doDisplay = kwargs.get("doDisplay", False) # oesmP, ccIdxD = self.__getSearchDataProviders(**kwargs) oesU = OeSearchUtils(oesmP, fpTypeList=[tup[0] for tup in fpTypeCuttoffList]) oeioU = OeIoUtils() # This will reload the oe binary cache. oeMol = oesmP.getMol("004") self.assertGreaterEqual(len(list(oeMol.GetAtoms())), 12) # matchOpts = "graph-relaxed" matchOpts = "graph-strict" missTupL = [] missedD = {} missedFpD = {} numMols = min(len(ccIdxD), numMols) if numMols else len(ccIdxD) logger.info( "Begin substructure search w/ finger print filter on %d molecules", numMols) # ---- startTime = time.time() for ( ii, ccId, ) in enumerate(list(ccIdxD.keys())[:numMols]): ccD = ccIdxD[ccId] for buildType in buildTypeList: if buildType in ccD: startTime1 = time.time() oeMol = oeioU.descriptorToMol( ccD[buildType], buildType, limitPerceptions=limitPerceptions, messageTag=ccId + ":" + buildType) if not oeMol: logger.debug("%s build failed for %s - skipping", ccId, buildType) continue maxHits = 0 minHits = maxFpResults selfHit = False for fpType, minFpScore in fpTypeCuttoffList: retStatus, mL = oesU.searchSubStructureWithFingerPrint( oeMol, fpType, minFpScore, maxFpResults, matchOpts=matchOpts) self.assertTrue(retStatus) logger.debug("%s fpType %r hits %d", ccId, fpType, len(mL)) maxHits = max(maxHits, len(mL)) minHits = min(minHits, len(mL)) matchedSelf = self.__resultContains(ccId, mL) selfHit = selfHit or matchedSelf if not matchedSelf: missedFpD.setdefault(ccId, []).append( (buildType, fpType, len(mL))) if not selfHit: missedD.setdefault(ccId, []).append(buildType) if maxHits < 1 or not selfHit: logger.info( "%s (%r) buildType %r min hits %d max hits %d (%.4f seconds)", ccId, selfHit, buildType, minHits, maxHits, time.time() - startTime1) else: logger.debug("%s missing descriptor %r", ccId, buildType) if ii % 100 == 0: logger.info("Completed %d of %d missed count %d", ii, numMols, len(missedD)) # for ccId, missL in missedD.items(): logger.info("%s missed list %r", ccId, missL) if ccId in missedFpD: logger.info("%s unmatched for fpTypes %r", ccId, missedFpD[ccId]) # ---- if doDisplay: mD = {} for missTup in missTupL: mD.setdefault(missTup[0], []).append(missTup[1]) for ccId, buildTypeL in mD.items(): idxD = ccIdxD[ccId] if "oe-iso-smiles" in idxD: for buildType in buildTypeL: self.__displayAlignedDescriptorPair( ccId, idxD["oe-iso-smiles"], "oe-iso-smiles", idxD[buildType], buildType, title=None, limitPerceptions=True) logger.info("%s fingerprints search on %d in (%.4f seconds)", len(fpTypeCuttoffList), numMols, time.time() - startTime) return True
def __fingerPrintScores(self, numMols, **kwargs): maxFpResults = kwargs.get("maxResults", 50) limitPerceptions = kwargs.get("limitPerceptions", True) fpTypeCuttoffList = kwargs.get("fpTypeCuttoffList", [("TREE", 0.6)]) buildTypeList = kwargs.get("buildTypeList", ["oe-iso-smiles"]) doDisplay = kwargs.get("doDisplay", False) failedIdList = kwargs.get("failedIdList", []) # oesmP, ccIdxD = self.__getSearchDataProviders(**kwargs) oesU = OeSearchUtils(oesmP, fpTypeList=[tup[0] for tup in fpTypeCuttoffList]) oeioU = OeIoUtils() # This will reload the oe binary cache. oeMol = oesmP.getMol("004") self.assertGreaterEqual(len(list(oeMol.GetAtoms())), 12) # missedFpD = {} missedBuildD = {} numMols = min(len(ccIdxD), numMols) if numMols else len(ccIdxD) logger.info("Begin finger print score search on %d molecules", numMols) # ---- startTime = time.time() # for ccId, ccD in list(ccIdxD.items())[:numMols]: for ii, ccId in enumerate(failedIdList[:numMols]): ccD = ccIdxD[ccId] for buildType in buildTypeList: if buildType in ccD: oeMol = oeioU.descriptorToMol( ccD[buildType], buildType, limitPerceptions=limitPerceptions, messageTag=ccId + ":" + buildType) if not oeMol: logger.debug("%s build failed for %s - skipping", ccId, buildType) continue maxHits = 0 minHits = maxFpResults selfHit = False # startTime1 = time.time() for fpType, minFpScore in fpTypeCuttoffList: retStatus, mL = oesU.getFingerPrintScores( oeMol, fpType, minFpScore, maxFpResults) self.assertTrue(retStatus) logger.debug("%s fpType %r hits %d", ccId, fpType, len(mL)) maxHits = max(maxHits, len(mL)) minHits = min(minHits, len(mL)) matchedSelf = self.__resultContains(ccId, mL) selfHit = selfHit or matchedSelf if not matchedSelf: missedFpD.setdefault(ccId, []).append( (buildType, fpType, len(mL))) # if not selfHit: missedBuildD.setdefault(ccId, []).append(buildType) # if maxHits < 1 or not selfHit: logger.info( "%s MISSED for buildType %r min hits %d max hits %d (%.4f seconds)", ccId, buildType, minHits, maxHits, time.time() - startTime1) else: logger.debug( "%s MATCHED for buildType %r min hits %d max hits %d (%.4f seconds)", ccId, buildType, minHits, maxHits, time.time() - startTime1) else: logger.debug("%s missing descriptor %r", ccId, buildType) if ii % 100 == 0: logger.info( "Completed %d of %d missed count %d in (%.4f seconds)", ii, len(failedIdList), len(missedBuildD), time.time() - startTime) # ------ for ccId, bTL in missedBuildD.items(): logger.info("%s missed all fptypes: buildtype list %r", ccId, bTL) if ccId in missedFpD: logger.info("%s unmatched by fpTypes %r", ccId, missedFpD[ccId]) # if doDisplay: for ccId, bTL in missedBuildD.items(): idxD = ccIdxD[ccId] if "oe-iso-smiles" in idxD: for bT in bTL: self.__displayAlignedDescriptorPair( ccId, idxD["oe-iso-smiles"], "oe-iso-smiles", idxD[bT], bT, title=None, limitPerceptions=True) logger.info("%s fingerprints search on %d in (%.4f seconds)", len(fpTypeCuttoffList), numMols, time.time() - startTime)