Appendix: Additional Examples in Python

These are full listings of programming examples that are excerpted or offered for download, elsewhere in this chapter. For a full list of examples, see the list in this chapter.

Listing 1: Example of molecule fragmentation.

#!/usr/bin/env python
# (C) 2022 Cadence Design Systems, Inc. (Cadence) 
# All rights reserved.
# TERMS FOR USE OF SAMPLE CODE The software below ("Sample Code") is
# provided to current licensees or subscribers of Cadence products or
# SaaS offerings (each a "Customer").
# Customer is hereby permitted to use, copy, and modify the Sample Code,
# subject to these terms. Cadence claims no rights to Customer's
# modifications. Modification of Sample Code is at Customer's sole and
# exclusive risk. Sample Code may require Customer to have a then
# current license or subscription to the applicable Cadence offering.
# THE SAMPLE CODE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
# EXPRESS OR IMPLIED.  OPENEYE DISCLAIMS ALL WARRANTIES, INCLUDING, BUT
# NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
# PARTICULAR PURPOSE AND NONINFRINGEMENT. In no event shall Cadence be
# liable for any damages or liability in connection with the Sample Code
# or its use.

from openeye import oechem
from openeye import oemedchem

mol = oechem.OEGraphMol()
oechem.OESmilesToMol(mol, "COc1ccc(cc1)CC(=O)N")

for frag in oemedchem.OEGetRingChainFragments(mol):
    fragatompred = oechem.OEIsAtomMember(frag.GetAtoms())
    fragbondpred = oechem.OEIsBondMember(frag.GetBonds())

    fragment = oechem.OEGraphMol()
    adjustHCount = True
    oechem.OESubsetMol(fragment, mol, fragatompred, fragbondpred, adjustHCount)
    print(oechem.OEMolToSmiles(fragment))

Listing 2: Example of molecule fragmentation with annotations.

#!/usr/bin/env python
# (C) 2022 Cadence Design Systems, Inc. (Cadence) 
# All rights reserved.
# TERMS FOR USE OF SAMPLE CODE The software below ("Sample Code") is
# provided to current licensees or subscribers of Cadence products or
# SaaS offerings (each a "Customer").
# Customer is hereby permitted to use, copy, and modify the Sample Code,
# subject to these terms. Cadence claims no rights to Customer's
# modifications. Modification of Sample Code is at Customer's sole and
# exclusive risk. Sample Code may require Customer to have a then
# current license or subscription to the applicable Cadence offering.
# THE SAMPLE CODE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
# EXPRESS OR IMPLIED.  OPENEYE DISCLAIMS ALL WARRANTIES, INCLUDING, BUT
# NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
# PARTICULAR PURPOSE AND NONINFRINGEMENT. In no event shall Cadence be
# liable for any damages or liability in connection with the Sample Code
# or its use.

from openeye import oechem
from openeye import oemedchem

mol = oechem.OEGraphMol()
oechem.OESmilesToMol(mol, "CCOc1ccc(cc1)CC(OC)c2ccccc2CC(=O)N")

adjustHCount = True
for frag in oemedchem.OEGetBemisMurcko(mol):
    fragment = oechem.OEGraphMol()
    oechem.OESubsetMol(fragment, mol, frag, adjustHCount)
    print(".".join(r.GetName() for r in frag.GetRoles()), oechem.OEMolToSmiles(fragment))

Listing 3: Example of custom molecule fragmentation.

#!/usr/bin/env python
# (C) 2022 Cadence Design Systems, Inc. (Cadence) 
# All rights reserved.
# TERMS FOR USE OF SAMPLE CODE The software below ("Sample Code") is
# provided to current licensees or subscribers of Cadence products or
# SaaS offerings (each a "Customer").
# Customer is hereby permitted to use, copy, and modify the Sample Code,
# subject to these terms. Cadence claims no rights to Customer's
# modifications. Modification of Sample Code is at Customer's sole and
# exclusive risk. Sample Code may require Customer to have a then
# current license or subscription to the applicable Cadence offering.
# THE SAMPLE CODE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
# EXPRESS OR IMPLIED.  OPENEYE DISCLAIMS ALL WARRANTIES, INCLUDING, BUT
# NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
# PARTICULAR PURPOSE AND NONINFRINGEMENT. In no event shall Cadence be
# liable for any damages or liability in connection with the Sample Code
# or its use.

from openeye import oechem
from openeye import oemedchem

mol = oechem.OEGraphMol()
oechem.OESmilesToMol(mol, "CCc1nc(nc(n1)OC)NC(CC(=O)N)NS(=O)(=O)c2ccccc2CC(=O)N")
subsearch = oechem.OESubSearch()
subsearch.Init("[#6]-CC(=O)N")
options = oemedchem.OEBemisMurckoOptions()
options.SetSubstituentSearch(subsearch)

adjustHCount = True
for frag in oemedchem.OEGetBemisMurcko(mol, options):
    fragment = oechem.OEGraphMol()
    oechem.OESubsetMol(fragment, mol, frag, adjustHCount)
    print(".".join(r.GetName() for r in frag.GetRoles()), oechem.OEMolToSmiles(fragment))

Listing 4: Example of custom molecule fragmentation.

#!/usr/bin/env python
# (C) 2022 Cadence Design Systems, Inc. (Cadence) 
# All rights reserved.
# TERMS FOR USE OF SAMPLE CODE The software below ("Sample Code") is
# provided to current licensees or subscribers of Cadence products or
# SaaS offerings (each a "Customer").
# Customer is hereby permitted to use, copy, and modify the Sample Code,
# subject to these terms. Cadence claims no rights to Customer's
# modifications. Modification of Sample Code is at Customer's sole and
# exclusive risk. Sample Code may require Customer to have a then
# current license or subscription to the applicable Cadence offering.
# THE SAMPLE CODE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
# EXPRESS OR IMPLIED.  OPENEYE DISCLAIMS ALL WARRANTIES, INCLUDING, BUT
# NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
# PARTICULAR PURPOSE AND NONINFRINGEMENT. In no event shall Cadence be
# liable for any damages or liability in connection with the Sample Code
# or its use.

from openeye import oechem
from openeye import oemedchem

mol = oechem.OEGraphMol()
oechem.OESmilesToMol(mol, "CCc1nc(nc(n1)OC)NC(=O)NS(=O)(=O)c2ccccc2OC")
options = oemedchem.OEBemisMurckoOptions()
options.SetUnsaturatedHeteroBonds(True)

adjustHCount = True
for frag in oemedchem.OEGetBemisMurcko(mol, options):
    fragment = oechem.OEGraphMol()
    oechem.OESubsetMol(fragment, mol, frag, adjustHCount)
    print(".".join(r.GetName() for r in frag.GetRoles()), oechem.OEMolToSmiles(fragment))

Listing 5: Introductory usage of matched molecular pair analysis.

#!/usr/bin/env python
# (C) 2022 Cadence Design Systems, Inc. (Cadence) 
# All rights reserved.
# TERMS FOR USE OF SAMPLE CODE The software below ("Sample Code") is
# provided to current licensees or subscribers of Cadence products or
# SaaS offerings (each a "Customer").
# Customer is hereby permitted to use, copy, and modify the Sample Code,
# subject to these terms. Cadence claims no rights to Customer's
# modifications. Modification of Sample Code is at Customer's sole and
# exclusive risk. Sample Code may require Customer to have a then
# current license or subscription to the applicable Cadence offering.
# THE SAMPLE CODE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
# EXPRESS OR IMPLIED.  OPENEYE DISCLAIMS ALL WARRANTIES, INCLUDING, BUT
# NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
# PARTICULAR PURPOSE AND NONINFRINGEMENT. In no event shall Cadence be
# liable for any damages or liability in connection with the Sample Code
# or its use.

from openeye import oechem
from openeye import oemedchem
import sys


################################################################
# USED TO GENERATE CODE SNIPPETS FOR THE OEMEDCHEM DOCUMENTATION
# - please look at actual examples for useful utility code
################################################################


def FindSimpleMatchedPairs(itf):
    ims = oechem.oemolistream()
    if not ims.open(itf.GetString("-input")):
        oechem.OEThrow.Fatal("Unable to open %s for reading: " +
                             itf.GetString("-input"))

    maxrecs = itf.GetInt("-maxrec")

    oechem.OEThrow.SetLevel(oechem.OEErrorLevel_Warning)

    # create options class with defaults
    mmpOpts = oemedchem.OEMatchedPairAnalyzerOptions()

    # for 'simple' pairs, alter default indexing options
    # - single cuts only, heavy atom substituents only (HMember indexing off)
    mmpOpts.SetOptions(oemedchem.OEMatchedPairOptions_SingleCuts |
                       oemedchem.OEMatchedPairOptions_ComboCuts |
                       oemedchem.OEMatchedPairOptions_UniquesOnly)
    # - limit substituent size to no more than 20% of input structure
    mmpOpts.SetIndexableFragmentRange(80., 100.)

    # create analyzer class with nondefault options
    mmpAnalyzer = oemedchem.OEMatchedPairAnalyzer(mmpOpts)

    # ignore common index status returns
    sIgnoreStatus = 'FragmentRangeFilter,DuplicateStructure,'
    sIgnoreStatus += 'FragmentationLimitFilter,HeavyAtomFilter'

    # index the input structures
    for recindex, mol in enumerate(ims.GetOEGraphMols(), start=1):
        # consider only the largest input fragment
        oechem.OEDeleteEverythingExceptTheFirstLargestComponent(mol)
        # ignore stereochemistry
        oechem.OEUncolorMol(mol,
                            (oechem.OEUncolorStrategy_RemoveAtomStereo |
                             oechem.OEUncolorStrategy_RemoveBondStereo))

        # explicitly provide a 1-based index to refer to indexed structures
        #   - to allow references back to external data elsewhere
        status = mmpAnalyzer.AddMol(mol, recindex)
        if status != recindex:
            if not oemedchem.OEMatchedPairIndexStatusName(status) in sIgnoreStatus:
                oechem.OEThrow.Warning("{0}: molecule indexing error, status={1}"
                                       .format(recindex,
                                               oemedchem.OEMatchedPairIndexStatusName(status)))
        # if limiting input, quit after limit
        if maxrecs and recindex >= maxrecs:
            break

    print("Index complete, matched pairs = {0}"
          .format(mmpAnalyzer.NumMatchedPairs()))

    # specify how transforms are extracted (direction and allowed properties)
    extractMode = (oemedchem.OEMatchedPairTransformExtractMode_Sorted |
                   oemedchem.OEMatchedPairTransformExtractMode_NoSMARTS |
                   oemedchem.OEMatchedPairTransformExtractMode_AddMCSCorrespondence)

    extractOptions = oemedchem.OEMatchedPairTransformExtractOptions()
    # specify amount of chemical context at the site of the substituent change
    #   in the transform
    extractOptions.SetContext(oemedchem.OEMatchedPairContext_Bond0)
    extractOptions.SetOptions(extractMode)

    # walk the transforms and print the matched pairs
    xfmidx = 0
    for mmpxform in oemedchem.OEMatchedPairGetTransforms(mmpAnalyzer,
                                                         extractOptions):
        xfmidx += 1
        print("{0:2} {1}".format(xfmidx, mmpxform.GetTransform()))
        # dump matched molecular pairs and index identifiers
        #   (recindex from indexing loop above)
        for mmppair in mmpxform.GetMatchedPairs():
            print("\tmatched pair molecule indices=({0},{1})".format(mmppair.FromIndex(),
                                                                     mmppair.ToIndex()))

    return True


############################################################
InterfaceData = """
# FindSimpleMatchedPairs docexample
!CATEGORY FindSimpleMatchedPairs
    !CATEGORY I/O
        !PARAMETER -input 1
          !ALIAS -i
          !TYPE string
          !REQUIRED true
          !BRIEF Input filename of structures to analyze
          !KEYLESS 1
        !END

        !PARAMETER -output 2
          !ALIAS -o
          !TYPE string
          !BRIEF Output filename for simple pair transformations
        !END

        !PARAMETER -maxrec 3
          !TYPE int
          !DEFAULT 0
          !BRIEF Only process maxrec records from input file
        !END
    !END
!END
"""


def main(argv=[__name__]):
    itf = oechem.OEInterface(InterfaceData, argv)
    FindSimpleMatchedPairs(itf)


if __name__ == "__main__":
    sys.exit(main(sys.argv))