Performing a reaction

A program that uses a SMIRKS specification to perform individual reaction transformations on each input molecule. This utility demonstrates how a loop using OEGetUniMolecularRxnIter would be coded which could then be augmented to score or choose the “best” transformed product by some user specified criteria if there were multiple sites where the transformation could occur.

Example

prompt> applytransformiter.py '[NH2:1]>>[Nh3+:1]' dbase.oeb.gz output.oeb.gz

Code

Download code

applytransformiter.py

#!/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.

#############################################################################
# Apply a transformation
#############################################################################
import sys
from openeye import oechem


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

    opts = oechem.OEUniMolecularRxnOptions()

    opts.SetStrictSmirks(itf.GetBool("-strict"))
    opts.SetClearCoordinates(itf.GetBool("-clearcoords"))
    opts.SetValidateKekule(itf.GetBool("-validkek"))
    opts.SetMaxMatches(itf.GetInt("-max"))

    altered = itf.GetString("-alteredtag")
    opts.SetAlteredTag("")
    if altered:
        opts.SetAlteredTag(altered)

    fixval = itf.GetString("-fixval")
    if fixval.upper() == "EXPLICIT" or fixval.upper() == "NONE":
        opts.SetFixValence(oechem.OEUniMolecularRxnFixValence_Explicit)
    elif fixval.upper() == "ALTERED":
        opts.SetFixValence(oechem.OEUniMolecularRxnFixValence_Altered)
    elif fixval.upper() == "ALL":
        opts.SetFixValence(oechem.OEUniMolecularRxnFixValence_All)
    else:
        oechem.Error("Unknown fix valence request: {}".format(fixval))

    xform = itf.GetString("-smirks")
    xformname = None
    if " " in xform:
        xform, xformname = xform.split(" ")[:2]

    qrxn = oechem.OEQMol()
    if not oechem.OEParseSmirks(qrxn, xform):
        oechem.Fatal("SMIRKS parse error: {}".format(xform))

    ifs = oechem.oemolistream()
    if not ifs.open(itf.GetString("-in")):
        oechem.OEThrow.Fatal(
            "Unable to open {} for reading".format(itf.GetString("-in"))
        )

    ofs = oechem.oemolostream()
    if not ofs.open(itf.GetString("-out")):
        oechem.OEThrow.Fatal(
            "Unable to open {} for writing".format(itf.GetString("-out"))
        )

    outfails = None
    if itf.HasString("-noxform"):
        print('noform=[{}]'.format(itf.GetString("-noxform")))
        outfails = oechem.oemolostream()
        if not outfails.open(itf.GetString("-noxform")):
            oechem.OEThrow.Fatal(
                "Unable to open failure file {} for writing".format(itf.GetString("-noxform"))
            )

    all2output = itf.GetBool("-passfail")
    asrxn = itf.GetBool("-asrxn")

    outxfmmol = oechem.OEGraphMol()
    for mol in ifs.GetOEGraphMols():
        title = mol.GetTitle()
        insmi = oechem.OEMolToSmiles(mol)

        nxforms = 0
        for xfmmol in oechem.OEGetUniMolecularRxnIter(mol, qrxn, opts):
            nxforms += 1
            if not asrxn:
                if xformname:
                    xfmmol.SetTitle("{}:{}({})".format(nxforms, xformname, mol.GetTitle()))
                if (
                    oechem.OEWriteMolecule(ofs, xfmmol)
                    != oechem.OEWriteMolReturnCode_Success
                ):
                    oechem.Fatal(
                        "Error writing molecule: {}".format(oechem.OEMolToSmiles(xfmmol))
                    )
            else:
                oechem.OESmilesToMol(
                    outxfmmol, "{}>>{}".format(insmi, oechem.OEMolToSmiles(xfmmol))
                )
                if xformname:
                    outxfmmol.SetTitle("{}:{}({})".format(nxforms, xformname, title))
                else:
                    outxfmmol.SetTitle(title)
                if (
                    oechem.OEWriteMolecule(ofs, outxfmmol)
                    != oechem.OEWriteMolReturnCode_Success
                ):
                    oechem.Fatal(
                        "Error writing molecule: {}".format(
                            oechem.OEMolToSmiles(outxfmmol)
                        )
                    )

        if not nxforms:
            if all2output:
                if (
                    oechem.OEWriteMolecule(ofs, mol)
                    != oechem.OEWriteMolReturnCode_Success
                ):
                    oechem.Fatal(
                        "Error writing untransformed molecule: {}".format(oechem.OEMolToSmiles(xfmmol))
                    )
            elif outfails:
                if (
                    oechem.OEWriteMolecule(outfails, mol)
                    != oechem.OEWriteMolReturnCode_Success
                ):
                    oechem.Fatal(
                        "Error writing untransformed molecule: {}".format(oechem.OEMolToSmiles(mol))
                    )
            
    return 0


InterfaceData = """
!BRIEF -smirks SMIRKS -in <input> -out <output>
    !CATEGORY I/O
        !PARAMETER -smirks 1
          !ALIAS -xform
          !TYPE string
          !REQUIRED true
          !BRIEF Transformation SMIRKS
          !KEYLESS 1
        !END
        !PARAMETER -in 2
          !ALIAS -i
          !TYPE string
          !REQUIRED true
          !BRIEF Input file name
          !KEYLESS 2
        !END
        !PARAMETER -out 3
          !ALIAS -o
          !ALIAS -success
          !TYPE string
          !REQUIRED true
          !BRIEF Output file name
          !KEYLESS 3
        !END
        !PARAMETER -noxform 4
          !ALIAS -fails
          !ALIAS -failures
          !TYPE string
          !REQUIRED false
          !BRIEF Output file name for untransformed structures
        !END
    !END
    !CATEGORY Options
        !PARAMETER -strict 1
          !ALIAS -strictsmirks
          !TYPE bool
          !REQUIRED false
          !DEFAULT true
          !BRIEF  requested strict flag which controls the interpretation of the transformation SMIRKS (true:Daylight convention, false:OpenEye convention)
        !END
        !PARAMETER -clearcoords 2
          !TYPE bool
          !REQUIRED false
          !DEFAULT true
          !BRIEF whether to clear coordinates for transformed products
        !END
        !PARAMETER -validkek 3
          !ALIAS -validkekule
          !TYPE bool
          !REQUIRED false
          !DEFAULT true
          !BRIEF whether the transformation validates the Kekule form of the transformed products
        !END
        !PARAMETER -fixval 4
          !TYPE string
          !REQUIRED false
          !DEFAULT Explicit
          !BRIEF type of valence correction to apply to the transformed products: Explicit(None), Altered, All
        !END
        !PARAMETER -max 5
          !ALIAS -maxxforms
          !TYPE int
          !REQUIRED false
          !DEFAULT 10
          !BRIEF maximum number of transformation to apply to each processed molecule
        !END
        !PARAMETER -alteredtag 6
          !TYPE string
          !REQUIRED false
          !DEFAULT None
          !BRIEF A generic data tag to mark altered atom information from transformed products
        !END
        !PARAMETER -passfail 7
          !TYPE bool
          !REQUIRED false
          !DEFAULT false
          !BRIEF If true, include untransformed structures in -out
        !END
        !PARAMETER -asrxn 8
          !TYPE bool
          !REQUIRED false
          !DEFAULT false
          !BRIEF If true, output the transformation as a reaction
        !END
    !END
!END
"""

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

See also