Examples: Working with Szybki TK

The basic Szybki TK API is provided to the users in the OESzybki, OESzybkiOptions, OESzybkiResults and OESzybkiEnsembleResults classes. In addition, when the purpose is to calculate compound properties, such as solvation free energy or free energy of selecting specific conformations out of the ensemble, the higher level API are defined in the free functions, OEEstimateSolvFreeEnergy and OEEstimateConfFreeEnergies.

Ligand Energetics and Optimization

Single ligand in vacuum

The following example illustrates how to optimize a single ligand in vacuum. As one can see assuming a molecule is successfully read, only two objects are needed to perform the optimization: OESzybki and OESzybkiResults. The latter is passed as the second parameter to the parenthesis operator OESzybki.operator(). Molecule with the optimized coordinates is returned as a first parameter. Optimization is done using the default MMFF94. Final energy results are available as SD tags in the returned molecule and optionally with a call of a method OESzybkiResults.Print.

Listing 1: Simple Ligand in a Vacuum

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

import sys
from openeye import oechem
from openeye import oeszybki


def main(args=[__name__]):
    if len(args) != 3:
        oechem.OEThrow.Usage("%s <molfile> <outfile>" % args[0])

    ifs = oechem.oemolistream()
    if not ifs.open(args[1]):
        oechem.OEThrow.Fatal("Unable to open %s for reading" % args[1])

    ofs = oechem.oemolostream()
    if not ofs.open(args[2]):
        oechem.OEThrow.Fatal("Unable to open %s for writing" % args[2])

    mol = oechem.OEMol()
    oechem.OEReadMolecule(ifs, mol)

    opts = oeszybki.OESzybkiOptions()
    sz = oeszybki.OESzybki(opts)
    results = oeszybki.OESzybkiResults()
    if not sz(mol, results):
        return 1

    oechem.OEWriteMolecule(ofs, mol)
    results.Print(oechem.oeout)

    return 0


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

Download code

simple_vacuum.py

Single ligand in vacuum using SMIRNOFF

The following example illustrates how to optimize a single ligand in vacuum using SMIRNOFF (see SMIRNOFF). Only two objects are needed to perform the optimization: OESzybki and OESzybkiResults. The latter is passed as the second parameter to the parenthesis operator OESzybki.operator(). Partial charges have to be preassigned to the input molecule. Molecule with the optimized coordinates is returned as a first parameter. Final energy results are available as SD tags in the returned molecule and optionally with a call of a method OESzybkiResults.Print.

Listing 2: Simple Ligand in a Vacuum Using SMIRNOFF

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

import sys
from openeye import oechem
from openeye import oeszybki


def main(args=[__name__]):
    if len(args) != 3:
        oechem.OEThrow.Usage("%s <molfile> <outfile>" % args[0])

    ifs = oechem.oemolistream()
    if not ifs.open(args[1]):
        oechem.OEThrow.Fatal("Unable to open %s for reading" % args[1])

    ofs = oechem.oemolostream()
    if not ofs.open(args[2]):
        oechem.OEThrow.Fatal("Unable to open %s for writing" % args[2])

    mol = oechem.OEMol()
    oechem.OEReadMolecule(ifs, mol)

    opts = oeszybki.OESzybkiOptions()
    opts.GetGeneralOptions().SetForceFieldType(oeszybki.OEForceFieldType_SMIRNOFF99FROSST)
    sz = oeszybki.OESzybki(opts)
    results = oeszybki.OESzybkiResults()
    if not sz(mol, results):
        return 1

    oechem.OEWriteMolecule(ofs, mol)
    results.Print(oechem.oeout)

    return 0


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

Download code

simple_smirnoff.py

Optimization of a set of ligands

The next example illustrates the usage of Szybki TK to optimize a set of compounds with the MMFF94 force field in vacuum or in solution using Sheffield solvation model. Optionally attractive VdW can be removed. The optimization is done by default in full Cartesian coordinates, however torsion space optimization or single point calculation could be done too. A group of atoms which belong to specified SMARTS pattern might be excluded from optimization so their positions will be fixed at their initial coordinates. Note that the OESzybki object is made with a constructor which takes the instance of the OESzybkiOptions class.

Listing 3: Optimization of a Set of Ligands

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

import sys
from openeye import oechem
from openeye import oeszybki


def main(argv=[__name__]):
    itf = oechem.OEInterface()
    if not SetupInterface(argv, itf):
        return 1

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

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

    logfile = oechem.oeout
    if itf.HasString("-log"):
        if not logfile.open(itf.GetString("-log")):
            oechem.OEThrow.Fatal("Unable to open %s for writing" % itf.GetString("-log"))

    # Szybki options
    opts = oeszybki.OESzybkiOptions()

    # select run type
    if itf.GetBool("-t"):
        opts.SetRunType(oeszybki.OERunType_TorsionsOpt)
    if itf.GetBool("-n"):
        opts.SetRunType(oeszybki.OERunType_SinglePoint)

    # apply solvent model
    if itf.GetBool("-s"):
        opts.GetSolventOptions().SetSolventModel(oeszybki.OESolventModel_Sheffield)

    # remove attractive VdW forces
    if itf.GetBool("-a"):
        opts.GetGeneralOptions().SetRemoveAttractiveVdWForces(True)

    # Szybki object
    sz = oeszybki.OESzybki(opts)

    # fix atoms
    if itf.HasString("-f"):
        if not sz.FixAtoms(itf.GetString("-f")):
            oechem.OEThrow.Warning("Failed to fix atoms for %s" % itf.GetString("-f"))

    # process molecules
    mol = oechem.OEMol()
    while oechem.OEReadMolecule(ifs, mol):
        logfile.write("\nMolecule %s\n" % mol.GetTitle())
        no_res = True
        for results in sz(mol):
            results.Print(logfile)
            no_res = False

        if no_res:
            oechem.OEThrow.Warning("No results processing molecule: %s" % mol.GetTitle())
            continue
        else:
            oechem.OEWriteMolecule(ofs, mol)

    return 0


InterfaceData = """
!PARAMETER -in
  !TYPE string
  !REQUIRED true
  !BRIEF Input molecule file name.
!END

!PARAMETER -out
  !TYPE string
  !REQUIRED true
  !BRIEF Output molecule file name.
!END

!PARAMETER -log
  !TYPE string
  !REQUIRED false
  !BRIEF Log file name. Defaults to standard out.
!END

!PARAMETER -s
  !TYPE bool
  !DEFAULT false
  !REQUIRED false
  !BRIEF Optimization in solution.
!END

!PARAMETER -t
  !TYPE bool
  !DEFAULT false
  !REQUIRED false
  !BRIEF Optimization of torsions.
!END

!PARAMETER -n
  !TYPE bool
  !DEFAULT false
  !REQUIRED false
  !BRIEF Single point calculation.
!END

!PARAMETER -a
  !TYPE bool
  !DEFAULT false
  !REQUIRED false
  !BRIEF No attractive VdW forces.
!END

!PARAMETER -f
  !TYPE string
  !REQUIRED false
  !BRIEF SMARTS pattern of fixed atoms.
!END
"""


def SetupInterface(argv, itf):
    oechem.OEConfigure(itf, InterfaceData)
    if oechem.OECheckHelp(itf, argv):
        return False
    if not oechem.OEParseCommandLine(itf, argv):
        return False
    if not oechem.OEIsReadable(oechem.OEGetFileType(
                  oechem.OEGetFileExtension(itf.GetString("-in")))):
        oechem.OEThrow.Warning("%s is not a readable input file" % itf.GetString("-in"))
        return False
    if not oechem.OEIsWriteable(oechem.OEGetFileType(
                  oechem.OEGetFileExtension(itf.GetString("-out")))):
        oechem.OEThrow.Warning("%s is not a writable output file" % itf.GetString("-out"))
        return False
    return True


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

Optimization of a single ligand with the Newton-Raphson method

The next example in this section shows how to use Newton-Raphson optimization method, rather than the default BFGS:

Listing 4: Optimization of a Single Ligand with the Newton-Raphson Method

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

import sys

from openeye import oechem
from openeye import oeszybki


def main(args):
    if len(args) != 3:
        oechem.OEThrow.Usage("%s input_molecule output_molecule" % args[0])

    ifs = oechem.oemolistream()
    if not ifs.open(args[1]):
        oechem.OEThrow.Fatal("Unable to open %s for reading" % args[1])

    ofs = oechem.oemolostream()
    if not ofs.open(args[2]):
        oechem.OEThrow.Fatal("Unable to open %s for writing" % args[2])

    mol = oechem.OEMol()
    oechem.OEReadMolecule(ifs, mol)

    opts = oeszybki.OESzybkiOptions()
    opts.GetOptOptions().SetOptimizerType(oeszybki.OEOptType_NEWTON)
    opts.GetSolventOptions().SetSolventModel(oeszybki.OESolventModel_Sheffield)

    sz = oeszybki.OESzybki(opts)
    res = oeszybki.OESzybkiResults()
    if (sz(mol, res)):
        oechem.OEWriteMolecule(ofs, mol)
        res.Print(oechem.oeout)

    return 0


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

Download code

simple_newton.py

Optimization of all conformers of a ligand

Finally, the last example in this section shows how to use Newton-Raphson optimization method on all conformers of a ligand. The current charges of the ligand are used and will not be changed during the optimization.

Listing 5: Optimization of All Conformers of a Ligand

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

import sys

from openeye import oechem
from openeye import oequacpac
from openeye import oeszybki


def main(args):
    if len(args) != 3:
        oechem.OEThrow.Usage("%s input_molecule output_molecule" % args[0])

    ifs = oechem.oemolistream()
    if not ifs.open(args[1]):
        oechem.OEThrow.Fatal("Unable to open %s for reading" % args[1])

    ofs = oechem.oemolostream()
    if not ofs.open(args[2]):
        oechem.OEThrow.Fatal("Unable to open %s for writing" % args[2])

    opts = oeszybki.OESzybkiOptions()
    opts.GetOptOptions().SetOptimizerType(oeszybki.OEOptType_NEWTON)
    opts.GetGeneralOptions().SetForceFieldType(oeszybki.OEForceFieldType_MMFF94S)
    opts.GetSolventOptions().SetSolventModel(oeszybki.OESolventModel_Sheffield)
    opts.GetSolventOptions().SetChargeEngine(oequacpac.OEChargeEngineNoOp())
    sz = oeszybki.OESzybki(opts)
    res = oeszybki.OESzybkiResults()
    for mol in ifs.GetOEMols():
        for conf in mol.GetConfs():
            if sz(conf, res):
                oechem.OESetSDData(conf, oechem.OESDDataPair('Total_energy', "%0.4f"
                                                             % res.GetTotalEnergy()))

        oechem.OEWriteMolecule(ofs, mol)

    ifs.close()
    ofs.close()

    return 0


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

Download code

simple_conformer.py

Optimization of a single bound ligand

The simplest case is illustrated below. Notice the usage of the method OESzybki.SetProtein which tells Szybki that the ligand is placed inside the protein. Since no protein-ligand electrostatics have been specified, neither the coordinates types which should be used by the optimizer, the code below performs the optimization for a rigid ligand using 6 translational-rotational coordinates in the MMFF94 VdW potential field.

Listing 5: Optimization of a Single Bound Ligand

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

import sys
from openeye import oechem
from openeye import oeszybki


def main(argv=[__name__]):
    if len(argv) != 4:
        oechem.OEThrow.Usage("%s <molfile> <protein> <outfile>" % argv[0])

    lfs = oechem.oemolistream()
    if not lfs.open(argv[1]):
        oechem.OEThrow.Fatal("Unable to open %s for reading" % argv[1])

    pfs = oechem.oemolistream()
    if not pfs.open(argv[2]):
        oechem.OEThrow.Fatal("Unable to open %s for reading" % argv[2])

    ofs = oechem.oemolostream()
    if not ofs.open(argv[3]):
        oechem.OEThrow.Fatal("Unable to open %s for writing" % argv[3])

    mol = oechem.OEGraphMol()
    oechem.OEReadMolecule(lfs, mol)

    protein = oechem.OEGraphMol()
    oechem.OEReadMolecule(pfs, protein)

    opts = oeszybki.OESzybkiOptions()
    sz = oeszybki.OESzybki(opts)
    sz.SetProtein(protein)
    res = oeszybki.OESzybkiResults()
    if not sz(mol, res):
        return 1

    oechem.OEWriteMolecule(ofs, mol)
    res.Print(oechem.oeout)

    return 0


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

Download code

simple_protein.py

Protein-Ligand Energetics and Optimization

Examples in this section show how to optimize a bound ligand.

Optimization of a set of bound ligands in a rigid receptor

The next example illustrates the usage of Szybki TK to optimize a set of ligands with MMFF94 force field inside a protein receptor. By default only VdW protein-ligand interaction is used. Optionally exact or grid Coulomb potential as well as PB solvent screening potentials could be added. When grid potential is selected (either Coulomb or PB) optionally it could be saved or read in when the corresponding grid file is present in the specified directory. Notice that when the exact Coulomb electrostatics is chosen, also the exact VdW potential is chosen (method OESzybkiProteinOptions.SetExactVdWProteinLigand) which allows for tight gradients convergence (methods OESzybkiOptOptions.SetMaxIter and OESzybkiOptOptions.SetGradTolerance). By default ligand is treated as a solid body, that is only its translational and rotational degrees of freedom are optimized. Optionally also torsional degrees could be optimized. In this example protein receptor is rigid. Molecular input file should contain initial 3D coordinates of molecules in any format supported by OEChem TK. Output file is specified with the -out flag. In addition a log file containing energy data terms values is written to stdout or a file specified by -log.

Listing 6: Optimization of a Set of Bound Ligands in a Rigid Receptor

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

import sys

from openeye import oechem
from openeye import oeszybki


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

    lfs = oechem.oemolistream()
    if not lfs.open(itf.GetString("-in")):
        oechem.OEThrow.Fatal("Unable to open %s for reading" % itf.GetString("-in"))

    pfs = oechem.oemolistream()
    if not pfs.open(itf.GetString("-p")):
        oechem.OEThrow.Fatal("Unable to open %s for reading", itf.GetString("-p"))

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

    logfile = oechem.oeout
    if itf.HasString("-log"):
        if not logfile.open(itf.GetString("-log")):
            oechem.OEThrow.Fatal("Unable to open %s for writing" % itf.GetString("-log"))

    # Szybki options
    opts = oeszybki.OESzybkiOptions()

    # select optimization type
    if(itf.GetBool("-t")):
        opts.SetRunType(oeszybki.OERunType_TorsionsOpt)
    else:
        opts.SetRunType(oeszybki.OERunType_CartesiansOpt)

    # select protein-electrostatic model
    emodel = itf.GetString("-e")
    elecModel = oeszybki.OEProteinElectrostatics_NoElectrostatics
    if emodel == "VdW":
        elecModel = oeszybki.OEProteinElectrostatics_NoElectrostatics
    elif emodel == "PB":
        elecModel = oeszybki.OEProteinElectrostatics_GridPB
    elif emodel == "Coulomb":
        elecModel = oeszybki.OEProteinElectrostatics_GridCoulomb
    elif emodel == "ExactCoulomb":
        elecModel = oeszybki.OEProteinElectrostatics_ExactCoulomb
        opts.GetProteinOptions().SetExactVdWProteinLigand(True)
        opts.GetOptOptions().SetMaxIter(1000)
        opts.GetOptOptions().SetGradTolerance(1e-6)
    opts.GetProteinOptions().SetProteinElectrostaticModel(elecModel)

    # Szybki object
    sz = oeszybki.OESzybki(opts)

    # read and setup protein
    protein = oechem.OEGraphMol()
    oechem.OEReadMolecule(pfs, protein)
    sz.SetProtein(protein)

    # save or load grid potential
    if(emodel == "PB" or emodel == "Coulomb"):
        if(itf.HasString("-s")):
            sz.SavePotentialGrid(itf.GetString("-s"))
        if(itf.HasString("-l")):
            sz.LoadPotentialGrid(itf.GetString("-l"))

    # process molecules
    for mol in lfs.GetOEMols():
        logfile.write("\nMolecule %s\n" % mol.GetTitle())
        no_res = True
        for res in sz(mol):
            res.Print(logfile)
            no_res = False

        if no_res:
            oechem.OEThrow.Warning("No results processing molecule: %s" % mol.GetTitle())
            continue
        else:
            oechem.OEWriteMolecule(ofs, mol)

    return 0


Interface = """
!PARAMETER -in
  !TYPE string
  !REQUIRED true
  !BRIEF Input molecule file name.
!END

!PARAMETER -p
  !TYPE string
  !REQUIRED true
  !BRIEF Input protein file name.
!END

!PARAMETER -out
  !TYPE string
  !REQUIRED true
  !BRIEF Output molecule file name.
!END

!PARAMETER -log
  !TYPE string
  !REQUIRED false
  !BRIEF Log file name. Defaults to standard out.
!END

!PARAMETER -e
  !TYPE string
  !DEFAULT VdW
  !LEGAL_VALUE VdW
  !LEGAL_VALUE PB
  !LEGAL_VALUE Coulomb
  !LEGAL_VALUE ExactCoulomb
  !BRIEF Protein ligand electrostatic model.
!END

!PARAMETER -t
  !TYPE bool
  !DEFAULT false
  !REQUIRED false
  !BRIEF Torsions added to the optimized variables.
!END

!PARAMETER -l
  !TYPE string
  !REQUIRED false
  !BRIEF File name of the potential grid to be read.
!END

!PARAMETER -s
  !TYPE string
  !REQUIRED false
  !BRIEF File name of the potential grid to be saved.
!END
"""


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

Optimization of a set of bound ligands in a partially flexible receptor

The next example is very similar with respect to the previous one, but the side chains of the protein which are within the specified range from the ligand, are made flexible during optimization (methods OESzybkiProteinOptions.SetProteinFlexibilityType and OESzybkiProteinOptions.SetProteinFlexibilityRange). Optionally, partially optimized structure can be saved to a file.

Listing 7: Optimization of a Set of Bound Ligands in a Partially Flexible Receptor

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

import sys

from openeye import oechem
from openeye import oeszybki


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

    lfs = oechem.oemolistream()
    if not lfs.open(itf.GetString("-in")):
        oechem.OEThrow.Fatal("Unable to open %s for reading" % itf.GetString("-in"))

    pfs = oechem.oemolistream()
    if not pfs.open(itf.GetString("-p")):
        oechem.OEThrow.Fatal("Unable to open %s for reading", itf.GetString("-p"))

    olfs = oechem.oemolostream()
    if not olfs.open(itf.GetString("-out")):
        oechem.OEThrow.Fatal("Unable to open %s for writing" % itf.GetString("-out"))

    opfs = oechem.oemolostream()
    if itf.HasString("-s"):
        if not opfs.open(itf.GetString("-s")):
            oechem.OEThrow.Fatal("Unable to open %s for writing" % itf.GetString("-s"))

    logfile = oechem.oeout
    if itf.HasString("-log"):
        if not logfile.open(itf.GetString("-log")):
            oechem.OEThrow.Fatal("Unable to open %s for writing" % itf.GetString("-log"))

    # Szybki options
    opts = oeszybki.OESzybkiOptions()

    # select optimization type
    opt = itf.GetString("-opt")
    if opt == "Cartesian":
        opts.SetRunType(oeszybki.OERunType_CartesiansOpt)
    if opt == "Torsion":
        opts.SetRunType(oeszybki.OERunType_TorsionsOpt)
    if opt == "SolidBody":
        opts.SetRunType(oeszybki.OERunType_SolidBodyOpt)

    # select protein-electrostatic model
    emodel = itf.GetString("-e")
    elecModel = oeszybki.OEProteinElectrostatics_NoElectrostatics
    if emodel == "VdW":
        elecModel = oeszybki.OEProteinElectrostatics_NoElectrostatics
    elif emodel == "PB":
        elecModel = oeszybki.OEProteinElectrostatics_GridPB
    elif emodel == "Coulomb":
        elecModel = oeszybki.OEProteinElectrostatics_GridCoulomb
    elif emodel == "ExactCoulomb":
        elecModel = oeszybki.OEProteinElectrostatics_ExactCoulomb
    opts.GetProteinOptions().SetProteinElectrostaticModel(elecModel)

    # use smooth potential and tight convergence
    if (emodel == "VdW" or emodel == "ExactCoulomb"):
        opts.GetProteinOptions().SetExactVdWProteinLigand(True)
        opts.GetOptOptions().SetMaxIter(1000)
        opts.GetOptOptions().SetGradTolerance(1e-6)

    # protein flexibility
    opts.GetProteinOptions().SetProteinFlexibilityType(oeszybki.OEProtFlex_SideChains)
    opts.GetProteinOptions().SetProteinFlexibilityRange(itf.GetDouble("-d"))

    # Szybki object
    sz = oeszybki.OESzybki(opts)

    # read and setup protein
    protein = oechem.OEGraphMol()
    oprotein = oechem.OEGraphMol()  # optimized protein
    oechem.OEReadMolecule(pfs, protein)
    sz.SetProtein(protein)

    # process molecules
    for mol in lfs.GetOEMols():
        logfile.write("\nMolecule %s\n" % mol.GetTitle())
        for res in sz(mol):
            res.Print(logfile)

        oechem.OEWriteMolecule(olfs, mol)
        if itf.HasString("-s"):
            sz.GetProtein(oprotein)
            oechem.OEWriteMolecule(opfs, oprotein)

    return 0


Interface = """
!BRIEF -in input_molecule -p protein -out output_molecule
!PARAMETER -in
  !TYPE string
  !REQUIRED true
  !BRIEF Input molecule file name.
!END

!PARAMETER -p
  !TYPE string
  !REQUIRED true
  !BRIEF Input protein file name.
!END

!PARAMETER -out
  !TYPE string
  !REQUIRED true
  !BRIEF Output molecule file name.
!END

!PARAMETER -log
  !TYPE string
  !REQUIRED false
  !BRIEF Log file name. Defaults to standard out.
!END

!PARAMETER -e
  !TYPE string
  !DEFAULT VdW
  !LEGAL_VALUE VdW
  !LEGAL_VALUE PB
  !LEGAL_VALUE Coulomb
  !LEGAL_VALUE ExactCoulomb
  !BRIEF Protein ligand electrostatic model.
!END

!PARAMETER -opt
  !TYPE string
  !DEFAULT Cartesian
  !LEGAL_VALUE Cartesian
  !LEGAL_VALUE Torsion
  !LEGAL_VALUE SolidBody
  !BRIEF Optimization method
!END

!PARAMETER -d
  !TYPE double
  !DEFAULT 5.0
  !BRIEF Distance criteria from protein side-chains flexibility.
!END

!PARAMETER -s
  !TYPE string
  !REQUIRED false
  !BRIEF File name the partially optimized protein will be saved.
!END
"""


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

Download code

flexible_protein.py

Optimization of a bound ligand in a partially flexible receptor

The next example is very similar with respect to the previous one, but the list of residue numbers of the protein that are made flexible during optimization is specified by the -residues flag (see method OESzybkiProteinOptions.AddFlexibleResidue). Partially optimized ligand and protein structures are saved to files specified by the -outl and -outp flags, respectively.

Listing 8: Optimization of a Bound Ligand in a Partially Flexible Feceptor

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

import sys

from openeye import oechem
from openeye import oeszybki


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

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

    pfs = oechem.oemolistream()
    if not pfs.open(itf.GetString("-protein")):
        oechem.OEThrow.Fatal("Unable to open %s for reading", itf.GetString("-protein"))

    ofs = oechem.oemolostream()
    if not ofs.open(itf.GetString("-outl")):
        oechem.OEThrow.Fatal("Unable to open %s for writing" % itf.GetString("-outl"))

    opfs = oechem.oemolostream()
    if not opfs.open(itf.GetString("-outp")):
        oechem.OEThrow.Fatal("Unable to open %s for writing" % itf.GetString("-outp"))

    ligand = oechem.OEGraphMol()
    oechem.OEReadMolecule(ifs, ligand)
    protein = oechem.OEGraphMol()
    oechem.OEReadMolecule(pfs, protein)

    # Szybki options
    opts = oeszybki.OESzybkiOptions()
    opts.SetRunType(oeszybki.OERunType_CartesiansOpt)
    opts.GetOptOptions().SetMaxIter(2000)
    opts.GetOptOptions().SetGradTolerance(1e-6)
    opts.GetGeneralOptions().SetForceFieldType(oeszybki.OEForceFieldType_MMFF94S)
    opts.GetProteinOptions().SetProteinFlexibilityType(oeszybki.OEProtFlex_SideChainsList)
    opts.GetProteinOptions().SetProteinElectrostaticModel(
                             oeszybki.OEProteinElectrostatics_ExactCoulomb)

    res_num = []
    for res in itf.GetStringList('-residues'):
        intres = None
        try:
            intres = int(res)
        except ValueError:
            print('Illegal residue value: {}'.format(res))

        if intres is None:
            continue
        res_num.append(intres)

    for i in res_num:
        for atom in protein.GetAtoms():
            residue = oechem.OEAtomGetResidue(atom)
            if(residue.GetResidueNumber() == i):
                opts.AddFlexibleResidue(residue)
                break

    sz = oeszybki.OESzybki(opts)
    sz.SetProtein(protein)
    result = oeszybki.OESzybkiResults()
    sz(ligand, result)
    sz.GetProtein(protein)
    oechem.OEWriteMolecule(opfs, protein)
    oechem.OEWriteMolecule(ofs, ligand)

    return 0


Interface = """
!BRIEF -in ligand -protein protein -outl output_ligand -outp output_protein -residues r1 r2 ... rn
!PARAMETER -in
  !TYPE string
  !REQUIRED true
  !BRIEF Input ligand file name.
!END

!PARAMETER -protein
  !TYPE string
  !REQUIRED true
  !BRIEF Input protein file name.
!END

!PARAMETER -outl
  !TYPE string
  !REQUIRED true
  !BRIEF Output ligand file name.
!END

!PARAMETER -outp
  !TYPE string
  !REQUIRED true
  !BRIEF Output protein file name.
!END

!PARAMETER -residues
  !TYPE string
  !LIST true
  !REQUIRED true
  !BRIEF List of residues numbers to be optimized along with the ligand
!END

"""

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

Download code

flex_residues.py

Estimation of PB binding for a set of ligands

This example shows how to fast estimate binding for a set of ligands using PB electrostatics. Two OESzybki objects are instantiated: one for the optimization of bound ligands in VdW-Coulomb potential, and the second one which performs single-point PB calculations. Final results are attached as SD tags to the output molecules.

Listing 9: Estimation of PB Binding for a Set of Ligands

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

import sys

from openeye import oechem
from openeye import oeszybki


def main(args):
    if len(args) != 4:
        oechem.OEThrow.Usage("%s ligand_file protein_file output_file (SDF or OEB)" % args[0])

    lfs = oechem.oemolistream()
    if not lfs.open(args[1]):
        oechem.OEThrow.Fatal("Unable to open %s for reading" % args[1])

    pfs = oechem.oemolistream()
    if not pfs.open(args[2]):
        oechem.OEThrow.Fatal("Unable to open %s for reading" % args[2])

    ofs = oechem.oemolostream()
    if not ofs.open(args[3]):
        oechem.OEThrow.Fatal("Unable to open %s for writing" % args[3])

    if not oechem.OEIsSDDataFormat(ofs.GetFormat()):
        oechem.OEThrow.Fatal("Output file does not support SD data used by this example")

    # Szybki options for VdW-Coulomb calculations
    optsC = oeszybki.OESzybkiOptions()
    optsC.GetProteinOptions().SetProteinElectrostaticModel(
                              oeszybki.OEProteinElectrostatics_ExactCoulomb)
    optsC.SetRunType(oeszybki.OERunType_CartesiansOpt)

    # Szybki options for PB calculations
    optsPB = oeszybki.OESzybkiOptions()
    optsPB.GetProteinOptions().SetProteinElectrostaticModel(
                               oeszybki.OEProteinElectrostatics_SolventPBForces)
    optsPB.SetRunType(oeszybki.OERunType_SinglePoint)

    # Szybki objects
    szC = oeszybki.OESzybki(optsC)
    szPB = oeszybki.OESzybki(optsPB)

    # read and setup protein
    protein = oechem.OEGraphMol()
    oechem.OEReadMolecule(pfs, protein)
    szC.SetProtein(protein)
    szPB.SetProtein(protein)

    terms = set([oeszybki.OEPotentialTerms_ProteinLigandInteraction,
                 oeszybki.OEPotentialTerms_VdWProteinLigand,
                 oeszybki.OEPotentialTerms_CoulombProteinLigand,
                 oeszybki.OEPotentialTerms_ProteinDesolvation,
                 oeszybki.OEPotentialTerms_LigandDesolvation,
                 oeszybki.OEPotentialTerms_SolventScreening])

    # process molecules
    for mol in lfs.GetOEMols():

        # optimize mol
        if not list(szC(mol)):
            oechem.OEThrow.Warning("No results processing molecule: %s" % mol.GetTitle())
            continue

        # do single point with better electrostatics
        for conf, results in zip(mol.GetConfs(), szPB(mol)):
            for i in terms:
                strEnergy = ("%9.4f" % results.GetEnergyTerm(i))
                oechem.OEAddSDData(conf, oeszybki.OEGetEnergyTermName(i), strEnergy)

        oechem.OEWriteMolecule(ofs, mol)

    return 0


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

Download code

protein_ligand_PB.py

Optimization of a bound ligand using Newton-Raphson method

The last example in this section illustrates how to use SzybkiTK to optimize a ligand in partially flexible protein with Newton-Raphson optimization method.

Listing 10: Optimization of a Bound Ligand Using Newton-Raphson Method

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

import sys

from openeye import oechem
from openeye import oeszybki


def main(args):
    if len(args) != 4:
        oechem.OEThrow.Usage("%s protein input_ligand output_ligand" % args[0])

    pfs = oechem.oemolistream()
    if not pfs.open(args[1]):
        oechem.OEThrow.Fatal("Unable to open %s for reading" % args[1])

    lfs = oechem.oemolistream()
    if not lfs.open(args[2]):
        oechem.OEThrow.Fatal("Unable to open %s for reading" % args[2])

    ofs = oechem.oemolostream()
    if not ofs.open(args[3]):
        oechem.OEThrow.Fatal("Unable to open %s for writing" % args[3])

    mol = oechem.OEGraphMol()
    protein = oechem.OEGraphMol()
    oechem.OEReadMolecule(lfs, mol)
    oechem.OEReadMolecule(pfs, protein)

    opts = oeszybki.OESzybkiOptions()
    opts.GetOptOptions().SetOptimizerType(oeszybki.OEOptType_NEWTON)
    opts.GetProteinOptions().SetProteinElectrostaticModel(
                             oeszybki.OEProteinElectrostatics_ExactCoulomb)
    opts.GetProteinOptions().SetProteinFlexibilityType(oeszybki.OEProtFlex_Residues)
    opts.GetProteinOptions().SetProteinFlexibilityRange(2.0)

    sz = oeszybki.OESzybki(opts)
    sz.SetProtein(protein)

    res = oeszybki.OESzybkiResults()
    if (sz(mol, res)):
        oechem.OEWriteMolecule(ofs, mol)
        res.Print(oechem.oeout)

    return 0


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

DU Protein-Ligand Optimization with FF14SB-Parsley

Examples in this section show how to optimize a ligand in the protein active site using the OEFixedProteinLigandOptimizer and the OEFlexProteinLigandOptimizer classes. Both of these classes allow use of the FF14SB-Parsley forcefield, along with the MMFF and the MMFF-AMBER forcefields. These examples also demonstrate how to use design units as a source for the protein or the ligand. The first example optimizes an external ligand in a protein active site from a design unit, and the second example uses both the ligand and the protein from the same design unit.

Optimization of ligand in a rigid active site

This examples shows how to optimize a series of ligands in a rigid active site. The active site input is taken from a OEDesignUnit.

Listing 11: Optimization of Ligand in a Rigid Active Site

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

import sys

from openeye import oechem
from openeye import oeszybki


def main(argv=[__name__]):
    szOpts = oeszybki.OEProteinLigandOptOptions()
    opts = oechem.OERefInputAppOptions(szOpts, "OptimizeLigandInDU", oechem.OEFileStringType_Mol3D,
                                       oechem.OEFileStringType_Mol3D, oechem.OEFileStringType_DU, "-du")
    if oechem.OEConfigureOpts(opts, argv, False) == oechem.OEOptsConfigureStatus_Help:
        return 0
    szOpts.UpdateValues(opts)

    ifs = oechem.oemolistream()
    if not ifs.open(opts.GetInFile()):
        oechem.OEThrow.Fatal("Unable to open %s for reading" % opts.GetInFile())

    rfs = oechem.oeifstream()
    if not rfs.open(opts.GetRefFile()):
        oechem.OEThrow.Fatal("Unable to open %s for reading" % opts.GetRefFile())

    ofs = oechem.oemolostream()
    if not ofs.open(opts.GetOutFile()):
        oechem.OEThrow.Fatal("Unable to open %s for writing" % opts.GetOutFile())

    du = oechem.OEDesignUnit()
    if not oechem.OEReadDesignUnit(rfs, du):
        oechem.OEThrow.Fatal("Failed to read design unit")

    optimizer = oeszybki.OEFixedProteinLigandOptimizer(szOpts)
    optimizer.SetProtein(du, oechem.OEDesignUnitComponents_Protein)

    for mol in ifs.GetOEMols():
        oechem.OEThrow.Info("Title: %s" % mol.GetTitle())
        conf = 0
        for res in optimizer.Optimize(mol):
            conf += 1
            if res.GetReturnCode() == oeszybki.OESzybkiReturnCode_Success:
                oechem.OEThrow.Info("Conformer: %d" % conf)
                initEne = res.GetInitialEnergies()
                oechem.OEThrow.Info("Initial energies:")
                oechem.OEThrow.Info("  Ligand: %0.2f" % initEne.GetLigandEnergy())
                oechem.OEThrow.Info("  Intermolecular: %0.2f" % initEne.GetInterEnergy())
                oechem.OEThrow.Info("  Total: %0.2f" % initEne.GetTotalEnergy())
                finalEne = res.GetFinalEnergies()
                oechem.OEThrow.Info("Final energies:")
                oechem.OEThrow.Info("  Ligand: %0.2f" % finalEne.GetLigandEnergy())
                oechem.OEThrow.Info("  Intermolecular: %0.2f" % finalEne.GetInterEnergy())
                oechem.OEThrow.Info("  Total: %0.2f" % finalEne.GetTotalEnergy())
            else:
                oechem.OEThrow.Warning("Failed: %s" % oeszybki.OEGetSzybkiError(res.GetReturnCode()))
        oechem.OEWriteMolecule(ofs, mol)
    return 0


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

Download code

OptimizeLigandInDU.py

Optimization of ligand in a partially flexible active site

This examples shows how to optimize a ligand in a partially flexible active site. In this example, both the ligand and the active site is taken from a single OEDesignUnit.

Listing 12: Optimization of Ligand in a Rigid Active Site

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

import sys

from openeye import oechem
from openeye import oeszybki


class MyOptions(oechem.OEOptions):
    def __init__(self):
        oechem.OEOptions.__init__(self, "MyOption")
        self._optOpts = oeszybki.OEProteinLigandOptOptions()
        self._flexOpts = oeszybki.OEProteinFlexOptions()
        self.AddOption(self._optOpts)
        self.AddOption(self._flexOpts)
        pass

    def CreateCopy(self):
        return self

    def GetOptOptions(self):
        return self._optOpts

    def GetFlexOptions(self):
        return self._flexOpts


def main(argv=[__name__]):
    myOpts = MyOptions()
    opts = oechem.OESimpleAppOptions(myOpts, "OptimizeDU", oechem.OEFileStringType_DU, oechem.OEFileStringType_DU)
    if oechem.OEConfigureOpts(opts, argv, False) == oechem.OEOptsConfigureStatus_Help:
        return 0
    optOpts = myOpts.GetOptOptions()
    flexOpts = myOpts.GetFlexOptions()
    optOpts.UpdateValues(opts)
    flexOpts.UpdateValues(opts)

    ifs = oechem.oeifstream()
    if not ifs.open(opts.GetInFile()):
        oechem.OEThrow.Fatal("Unable to open %s for reading" % opts.GetInFile())

    ofs = oechem.oeofstream()
    if not ofs.open(opts.GetOutFile()):
        oechem.OEThrow.Fatal("Unable to open %s for writing" % opts.GetOutFile())

    optimizer = oeszybki.OEFlexProteinLigandOptimizer(optOpts)
    du = oechem.OEDesignUnit()
    while oechem.OEReadDesignUnit(ifs, du):
        oechem.OEThrow.Info("Title: %s" % du.GetTitle())
        res = oeszybki.OEProteinLigandOptResults()
        proteinMask = oechem.OEDesignUnitComponents_Protein
        retCode = optimizer.Optimize(res, du, proteinMask, oechem.OEDesignUnitComponents_Ligand, flexOpts)
        if retCode == oeszybki.OESzybkiReturnCode_Success:
            initEne = res.GetInitialEnergies()
            oechem.OEThrow.Info("Initial energies:")
            oechem.OEThrow.Info("  Ligand: %0.2f" % initEne.GetLigandEnergy())
            oechem.OEThrow.Info("  Flexible Protein: %0.2f" % initEne.GetHostEnergy())
            oechem.OEThrow.Info("  Intermolecular: %0.2f" % initEne.GetInterEnergy())
            oechem.OEThrow.Info("  Total: %0.2f" % initEne.GetTotalEnergy())
            finalEne = res.GetFinalEnergies()
            oechem.OEThrow.Info("Final energies:")
            oechem.OEThrow.Info("  Ligand: %0.2f" % finalEne.GetLigandEnergy())
            oechem.OEThrow.Info("  Flexible Protein: %0.2f" % finalEne.GetHostEnergy())
            oechem.OEThrow.Info("  Intermolecular: %0.2f" % finalEne.GetInterEnergy())
            oechem.OEThrow.Info("  Total: %0.2f" % finalEne.GetTotalEnergy())
            oechem.OEWriteDesignUnit(ofs, du)
        else:
            oechem.OEThrow.Warning("%s: %s" % (du.GetTitle(), oeszybki.OEGetSzybkiError(retCode)))
    return 0


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

Download code

OptimizeDU.py

Entropy estimation

Estimation of solution ligand entropy

The following code illustrates how to estimate compound entropy in solution with Szybki TK.

Listing 13: Ligand Entropy

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

import sys

from openeye import oechem
from openeye import oeszybki


def main(argv=[__name__]):
    szOpts = oeszybki.OELigandEntropyOptions()
    opts = oechem.OESimpleAppOptions(szOpts, "LigandEntropy", oechem.OEFileStringType_Mol3D)
    if oechem.OEConfigureOpts(opts, argv, False) == oechem.OEOptsConfigureStatus_Help:
        return 0
    szOpts.UpdateValues(opts)

    ifs = oechem.oemolistream()
    if not ifs.open(opts.GetInFile()):
        oechem.OEThrow.Fatal("Unable to open %s for reading" % opts.GetInFile())

    for mol in ifs.GetOEMols():
        oechem.OEThrow.Info("Title: %s" % mol.GetTitle())
        res = oeszybki.OEEntropyResults()
        ret_code = oeszybki.OELigandEntropy(res, mol, szOpts)
        if ret_code == oeszybki.OESzybkiReturnCode_Success:
            oechem.OEThrow.Info("  Configurational Entropy: %0.2f" % res.GetConfigurationalEntropy())
            oechem.OEThrow.Info("  Solvation Entropy: %0.2f" % res.GetSolvationEntropy())
            oechem.OEThrow.Info("  Total Entropy: %0.2f" % res.GetTotalEntropy())
        else:
            oechem.OEThrow.Warning("Failed: %s" % oeszybki.OEGetSzybkiError(ret_code))
    return 0


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

Download code

ligand_entropy.py

Estimation of bound ligand entropy

The next example below shows how to calculate entropy of a bound ligand.

Listing 15: Estimation of Bound Ligand Entropy

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

import sys

from openeye import oechem
from openeye import oeszybki


def main(argv=[__name__]):
    szOpts = oeszybki.OEBoundEntropyOptions()
    opts = oechem.OERefInputAppOptions(szOpts, "BoundEntropy", oechem.OEFileStringType_Mol3D,
                                       oechem.OEFileStringType_DU, "-du")
    if oechem.OEConfigureOpts(opts, argv, False) == oechem.OEOptsConfigureStatus_Help:
        return 0
    szOpts.UpdateValues(opts)

    ifs = oechem.oemolistream()
    if not ifs.open(opts.GetInFile()):
        oechem.OEThrow.Fatal("Unable to open %s for reading" % opts.GetInFile())

    rfs = oechem.oeifstream()
    if not rfs.open(opts.GetRefFile()):
        oechem.OEThrow.Fatal("Unable to open %s for reading" % opts.GetRefFile())

    du = oechem.OEDesignUnit()
    if not oechem.OEReadDesignUnit(rfs, du):
        oechem.OEThrow.Fatal("Failed to read design unit")

    for mol in ifs.GetOEMols():
        oechem.OEThrow.Info("Title: %s" % mol.GetTitle())
        res = oeszybki.OEEntropyResults()
        ret_code = oeszybki.OEBoundLigandEntropy(res, du, oechem.OEDesignUnitComponents_Protein, mol, szOpts)
        if ret_code == oeszybki.OESzybkiReturnCode_Success:
            oechem.OEThrow.Info("  Configurational Entropy: %0.2f" % res.GetConfigurationalEntropy())
            oechem.OEThrow.Info("  Solvation Entropy: %0.2f" % res.GetSolvationEntropy())
            oechem.OEThrow.Info("  Total Entropy: %0.2f" % res.GetTotalEntropy())
        else:
            oechem.OEThrow.Warning("Failed: %s" % oeszybki.OEGetSzybkiError(ret_code))
    return 0


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

Download code

bound_entropy.py

Solvation free energy estimation

Listing 16: Solvation Free Energy Estimation

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

import sys

from openeye import oechem
from openeye import oeszybki


def main(args):
    if len(args) != 3:
        oechem.OEThrow.Usage("%s <input> <output>" % args[0])

    ifs = oechem.oemolistream()
    if not ifs.open(args[1]):
        oechem.OEThrow.Fatal("Unable to open %s for reading" % args[1])

    ofs = oechem.oemolostream()
    if not ofs.open(args[2]):
        oechem.OEThrow.Fatal("Unable to open %s for writing" % args[2])

    mol = oechem.OEMol()
    oechem.OEReadMolecule(ifs, mol)

    opts = oeszybki.OEFreeFormSolvOptions()
    opts.SetIonicState(oeszybki.OEFreeFormIonicState_Uncharged)
    res = oeszybki.OEFreeFormSolvResults()

    omol = oechem.OEGraphMol()
    if not oeszybki.OEEstimateSolvFreeEnergy(res, omol, mol, opts):
        oechem.OEThrow.Error("Failed to calculate solvation free energy for molecule %s" %
                             mol.GetTitle())

    solvenergy = res.GetSolvationFreeEnergy()
    oechem.OEThrow.Info("Solvation free energy for compound %s is %6.2f kcal/mol" %
                        (mol.GetTitle(), solvenergy))

    oechem.OEWriteMolecule(ofs, omol)

    return 0


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

Download code

freeformsolv.py

Conformations free energy estimation

Warning

This capability should not be used on 32-bit platforms because the memory requirements are too high.

Simple free energy estimation

The following code illustrates how to use the high level commands from OEFreeFormConf to estimate conformer free energies in solution with Szybki TK.

Listing 17: Simple Free Energy Estimation

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

import sys

from openeye import oechem
from openeye import oeszybki


def main(args):
    if len(args) != 3:
        oechem.OEThrow.Usage("%s <input> <output>" % args[0])

    ifs = oechem.oemolistream()
    if not ifs.open(args[1]):
        oechem.OEThrow.Fatal("Unable to open %s for reading" % args[1])

    ofs = oechem.oemolostream()
    if not ofs.open(args[2]):
        oechem.OEThrow.Fatal("Unable to open %s for writing" % args[2])

    mol = oechem.OEMol()
    oechem.OEReadMolecule(ifs, mol)

    opts = oeszybki.OEFreeFormConfOptions()
    ffconf = oeszybki.OEFreeFormConf(opts)

    omol = oechem.OEMol(mol)
    if not (ffconf.EstimateFreeEnergies(omol) == oeszybki.OEFreeFormReturnCode_Success):
        oechem.OEThrow.Error("Failed to estimate conformational free energies")

    res = oeszybki.OEFreeFormConfResults(omol)
    oechem.OEThrow.Info("Number of unique conformations: %d" % res.GetNumUniqueConfs())
    oechem.OEThrow.Info("Conf.  Delta_G   Vibrational_Entropy")
    oechem.OEThrow.Info("      [kcal/mol]     [J/(mol K)]")
    for r in res.GetResultsForConformations():
        oechem.OEThrow.Info("%2d %10.2f %14.2f" % (r.GetConfIdx(), r.GetDeltaG(),
                                                   r.GetVibrationalEntropy()))

    oechem.OEWriteMolecule(ofs, omol)

    return 0


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

Download code

freeformconf.py

Simple restriction energy estimation

The following code illustrates how to use the high level commands from OEFreeFormConf to estimate restriction energies on conformers, along with conformer free energies in solution, with Szybki TK.

Listing 18: Simple Restriction Energy Estimation

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

import sys

from openeye import oechem
from openeye import oeszybki


def main(args):
    if len(args) != 3:
        oechem.OEThrow.Usage("%s <input> <output>" % args[0])

    ifs = oechem.oemolistream()
    if not ifs.open(args[1]):
        oechem.OEThrow.Fatal("Unable to open %s for reading" % args[1])

    ofs = oechem.oemolostream()
    if not ofs.open(args[2]):
        oechem.OEThrow.Fatal("Unable to open %s for writing" % args[2])

    mol = oechem.OEMol()
    oechem.OEReadMolecule(ifs, mol)

    opts = oeszybki.OEFreeFormConfOptions()
    ffconf = oeszybki.OEFreeFormConf(opts)

    omol = oechem.OEMol(mol)
    rmol = oechem.OEMol(mol)
    if not (ffconf.EstimateFreeEnergies(omol, rmol) == oeszybki.OEFreeFormReturnCode_Success):
        oechem.OEThrow.Error("Failed to estimate conformational free energies")

    res = oeszybki.OEFreeFormConfResults(omol)
    oechem.OEThrow.Info("Number of unique conformations: %d" % res.GetNumUniqueConfs())
    oechem.OEThrow.Info("Conf.  Delta_G   Vibrational_Entropy")
    oechem.OEThrow.Info("      [kcal/mol]     [J/(mol K)]")
    for r in res.GetResultsForConformations():
        oechem.OEThrow.Info("%2d %10.2f %14.2f" % (r.GetConfIdx(), r.GetDeltaG(),
                                                   r.GetVibrationalEntropy()))

    rstrRes = oeszybki.OERestrictionEnergyResult(rmol)
    oechem.OEThrow.Info("Global strain: %d" % rstrRes.GetGlobalStrain())
    oechem.OEThrow.Info("Local strain: %d" % rstrRes.GetLocalStrain())

    oechem.OEWriteMolecule(ofs, omol)

    return 0


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

Download code

freeformconfrstr.py

Advanced free energy estimation

The following code illustrates how to use the low level commands from OEFreeFormConfAdvanced to estimate the conformer free energies in solution with Szybki TK. These low level methods of estimation gives an advantage over the high level methods of OEFreeFormConf in that these gives the user control over better managing certain expensive parts of the calculation.

Listing 19: Advanced Free Energy Estimation

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

import sys

from openeye import oechem
from openeye import oeszybki


def main(args):
    if len(args) != 3:
        oechem.OEThrow.Usage("%s <input> <output>" % args[0])

    ifs = oechem.oemolistream()
    if not ifs.open(args[1]):
        oechem.OEThrow.Fatal("Unable to open %s for reading" % args[1])

    ofs = oechem.oemolostream()
    if not ofs.open(args[2]):
        oechem.OEThrow.Fatal("Unable to open %s for writing" % args[2])

    mol = oechem.OEMol()
    oechem.OEReadMolecule(ifs, mol)

    opts = oeszybki.OEFreeFormConfOptions()
    ffconf = oeszybki.OEFreeFormConfAdvanced(opts)

    # Make a copy of our MCMol.  We will execute the FreeFormConf commands on
    # the copied molecule so that our original molecule stays intact.
    omol = oechem.OEMol(mol)

    # Prepare a comprehensive ensemble of molecule conformers. This will
    # generate a comprehensive set of conformers, assign solvent charges on the molecule
    # and check that the ensemble is otherwise ready for FreeFormConf calculations.
    if not (ffconf.PrepareEnsemble(omol) == oeszybki.OEFreeFormReturnCode_Success):
        oechem.OEThrow.Error("Failed to prepare ensemble for FreeFormConf calculations")

    # Perform loose optimization of the ensemble conformers.  We will remove
    # duplicates based on the loose optimization, to reduce the time needed for
    # tighter, more stricter optimization
    if not (ffconf.PreOptimizeEnsemble(omol) == oeszybki.OEFreeFormReturnCode_Success):
        oechem.OEThrow.Error("Pre-optimization of the ensembles failed")

    # Remove duplicates from the pre-optimized ensemble
    if not (ffconf.RemoveDuplicates(omol) == oeszybki.OEFreeFormReturnCode_Success):
        oechem.OEThrow.Error("Duplicate removal from the ensembles failed")

    # Perform the desired optimization.  This uses a stricter convergence
    # criteria in the default settings.
    if not (ffconf.Optimize(omol) == oeszybki.OEFreeFormReturnCode_Success):
        oechem.OEThrow.Error("Optimization of the ensembles failed")

    # Remove duplicates to obtain the set of minimum energy conformers
    if not (ffconf.RemoveDuplicates(omol) == oeszybki.OEFreeFormReturnCode_Success):
        oechem.OEThrow.Error("Duplicate removal from the ensembles failed")

    # Perform FreeFormConf free energy calculations.  When all the above steps
    # have already been performed on the ensemble, this energy calculation
    # step is fast.
    if not (ffconf.EstimateEnergies(omol) == oeszybki.OEFreeFormReturnCode_Success):
        oechem.OEThrow.Error("Estimation of FreeFormConf energies failed")

    # Gather results of calculation into a results object for ease of viewing, etc.
    res = oeszybki.OEFreeFormConfResults(omol)
    oechem.OEThrow.Info("Number of unique conformations: %d" % res.GetNumUniqueConfs())
    oechem.OEThrow.Info("Conf.  Delta_G   Vibrational_Entropy")
    oechem.OEThrow.Info("      [kcal/mol]     [J/(mol K)]")
    for r in res.GetResultsForConformations():
        oechem.OEThrow.Info("%2d %10.2f %14.2f" % (r.GetConfIdx(), r.GetDeltaG(),
                                                   r.GetVibrationalEntropy()))

    oechem.OEWriteMolecule(ofs, omol)

    return 0


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

Download code

freeformconfadvanced.py

Advanced restriction energy estimation

The following code illustrates how to use the low level commands from OEFreeFormConfAdvanced to estimate the restriction energies of conformers, along with conformer free energies in solution, with Szybki TK. These low level methods of estimation gives an advantage over the high level methods of OEFreeFormConf in that these gives the user control over better managing certain expensive parts of the calculation.

Listing 20: Advanced Restriction Energy Estimation

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

import sys

from openeye import oechem
from openeye import oeszybki


def main(args):
    if len(args) != 3:
        oechem.OEThrow.Usage("%s <input> <output>" % args[0])

    ifs = oechem.oemolistream()
    if not ifs.open(args[1]):
        oechem.OEThrow.Fatal("Unable to open %s for reading" % args[1])

    ofs = oechem.oemolostream()
    if not ofs.open(args[2]):
        oechem.OEThrow.Fatal("Unable to open %s for writing" % args[2])

    mol = oechem.OEMol()
    oechem.OEReadMolecule(ifs, mol)

    opts = oeszybki.OEFreeFormConfOptions()
    ffconf = oeszybki.OEFreeFormConfAdvanced(opts)

    # Make a copy of our MCMol.  We will execute the FreeFormConf commands on
    # the copied molecule so that our original molecule stays intact.
    omol = oechem.OEMol(mol)

    # Make further copies of our original molecule.  The copied molecule(s) would be used
    # as source on which retriction energies would be calculated
    rmol = oechem.OEMol(mol)
    fmol = oechem.OEMol(mol)

    # Prepare a comprehensive ensemble of molecule conformers.  For calculation
    # of restriction energies we want to make sure that all the corresponding free
    # conformers are also part of the comprehensive ensemble.  This will also
    # assign solvent charges on the molecule and check that the ensemble is
    # otherwise ready for FreeFormConf calculations. The resulting `fmol`
    # contains the correspondig free conformers.
    if not (ffconf.PrepareEnsemble(omol, rmol, fmol) == oeszybki.OEFreeFormReturnCode_Success):
        oechem.OEThrow.Error("Failed to prepare ensemble for FreeFormConf calculations")

    # Perform loose optimization of the ensemble conformers.  We will remove
    # duplicates based on the loose optimization, to reduce the time needed for
    # tighter, more stricter optimization
    if not (ffconf.PreOptimizeEnsemble(omol) == oeszybki.OEFreeFormReturnCode_Success):
        oechem.OEThrow.Error("Pre-optimization of the ensembles failed")

    # Remove duplicates from the pre-optimized ensemble
    if not (ffconf.RemoveDuplicates(omol) == oeszybki.OEFreeFormReturnCode_Success):
        oechem.OEThrow.Error("Duplicate removal from the ensembles failed")

    # Perform the desired optimization.  This uses a stricter convergence
    # criteria in the default settings.
    if not (ffconf.Optimize(omol) == oeszybki.OEFreeFormReturnCode_Success):
        oechem.OEThrow.Error("Optimization of the ensembles failed")

    # Remove duplicates to obtain the set of minimum energy conformers
    if not (ffconf.RemoveDuplicates(omol) == oeszybki.OEFreeFormReturnCode_Success):
        oechem.OEThrow.Error("Duplicate removal from the ensembles failed")

    # Perform FreeFormConf free energy calculations.  When all the above steps
    # have already been performed on the ensemble, this energy calculation
    # step is fast.
    if not (ffconf.EstimateEnergies(omol) == oeszybki.OEFreeFormReturnCode_Success):
        oechem.OEThrow.Error("Estimation of FreeFormConf energies failed")

    # Gather results of calculation into a results object for ease of viewing, etc.
    res = oeszybki.OEFreeFormConfResults(omol)
    oechem.OEThrow.Info("Number of unique conformations: %d" % res.GetNumUniqueConfs())
    oechem.OEThrow.Info("Conf.  Delta_G   Vibrational_Entropy")
    oechem.OEThrow.Info("      [kcal/mol]     [J/(mol K)]")
    for r in res.GetResultsForConformations():
        oechem.OEThrow.Info("%2d %10.2f %14.2f" % (r.GetConfIdx(), r.GetDeltaG(),
                                                   r.GetVibrationalEntropy()))

    # Identify the corresponding conformer(s) to the free minimized conformer(s).
    # If identified, the corresponding (Conf)Free energy information is also
    # copied to the free conformers
    if not (ffconf.IdentifyConformer(fmol, omol) == oeszybki.OEFreeFormReturnCode_Success):
        oechem.OEThrow.Error("Identification of free conformer(s) failed")

    # Estimate restriction energies. Since both restricted and free conformer
    # energy components are already available, this operation is fast.
    if not (ffconf.EstimateRestrictionEnergy(fmol, rmol) == oeszybki.OEFreeFormReturnCode_Success):
        oechem.OEThrow.Error("Restriction energy estimation failed")

    # Gather restriction energies into a results object for ease of viewing, etc.
    rstrRes = oeszybki.OERestrictionEnergyResult(fmol)
    oechem.OEThrow.Info("Global strain: %f" % rstrRes.GetGlobalStrain())
    oechem.OEThrow.Info("Local strain: %f" % rstrRes.GetLocalStrain())

    # Optionally it is desired to perform a restrained optimization of the
    # restricted conformer(s) to brush out any energy differences due to
    # force field constaints or the sources of coonformer coordinates.  Note: The
    # high level EstimateFreeEnergy method does not perform this opertion.
    if not (ffconf.OptimizeRestraint(rmol) == oeszybki.OEFreeFormReturnCode_Success):
        oechem.OEThrow.Error("Restraint optimization of the conformer(s) failed")

    # Estimate restriction energies on this optimized conformers.
    # Since both restricted and free conformer energy components
    # are already available, this operation is fast.
    if not (ffconf.EstimateRestrictionEnergy(fmol, rmol) == oeszybki.OEFreeFormReturnCode_Success):
        oechem.OEThrow.Error("Restriction energy estimation failed")

    # Gather restriction energies into a results object for ease of viewing, etc.
    rstrRes = oeszybki.OERestrictionEnergyResult(fmol)
    oechem.OEThrow.Info("Global strain: %f" % rstrRes.GetGlobalStrain())
    oechem.OEThrow.Info("Local strain: %f" % rstrRes.GetLocalStrain())

    oechem.OEWriteMolecule(ofs, omol)

    return 0


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

Download code

freeformconfadvrstr.py

Finding similar conformers

The following code illustrates how to find similar conformers to the ones at hand, from a pool of minimum energy conformers.

Listing 21: Finding Similar Conformers

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

import sys

from openeye import oechem
from openeye import oeszybki


def main(args):
    if len(args) != 3:
        oechem.OEThrow.Usage("%s <input> <output>" % args[0])

    ifs = oechem.oemolistream()
    if not ifs.open(args[1]):
        oechem.OEThrow.Fatal("Unable to open %s for reading" % args[1])

    ofs = oechem.oemolostream()
    if not ofs.open(args[2]):
        oechem.OEThrow.Fatal("Unable to open %s for writing" % args[2])

    mol = oechem.OEMol()
    oechem.OEReadMolecule(ifs, mol)

    opts = oeszybki.OEFreeFormConfOptions()
    ffconf = oeszybki.OEFreeFormConf(opts)

    # Estimate free energies to ontain the minimum energy conformers
    omol = oechem.OEMol(mol)
    if not (ffconf.EstimateFreeEnergies(omol) == oeszybki.OEFreeFormReturnCode_Success):
        oechem.OEThrow.Error("Failed to estimate conformational free energies")

    # Find similar conformers to the ones we started with, from the
    # pool of minimum energy conformers
    fmol = oechem.OEMol(mol)
    for conf in mol.GetConfs():
        ffconf.FindSimilarConfs(fmol, omol, conf, oechem.OESimilarByRMSD(0.05))

    oechem.OEWriteMolecule(ofs, fmol)

    return 0


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

Download code

findsimilarconfs.py

Torsion scan

The following code shows how to scan all torsions in the input molecule

Listing 22: Perform torsion scan for all torsions in the input molecule

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

import sys
from openeye import oechem
from openeye import oeszybki

###############################################################
# USED TO GENERATE CODE SNIPPETS FOR THE SZYBKI DOCUMENTATION
###############################################################


def main(argv=sys.argv):
    if len(argv) != 2:
        oechem.OEThrow.Usage("%s <infile>" % argv[0])

    ifs = oechem.oemolistream()
    if not ifs.open(argv[1]):
        oechem.OEThrow.Fatal("Unable to open %s for reading" % argv[1])

    mol = oechem.OEMol()
    oechem.OEReadMolecule(ifs, mol)

    outmol = oechem.OEMol()

    opts = oeszybki.OETorsionScanOptions()
    opts.SetDelta(30.0)
    opts.SetForceFieldType(oeszybki.OEForceFieldType_MMFF94)
    opts.SetSolvationType(oeszybki.OESolventModel_NoSolv)

    for tor in oechem.OEGetTorsions(mol):
        print("Torsion: %d %d %d %d" %
              (tor.a.GetIdx(), tor.b.GetIdx(), tor.c.GetIdx(), tor.d.GetIdx()))
        for res in oeszybki.OETorsionScan(outmol, mol, tor, opts):
            print("%.2f %.2f" % (res.GetAngle(), res.GetEnergy()))


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

Download code

TorsionScan.py