OEChem Examples

Convert molecule files

/****************************************************************************
* Copyright (C) 2009-2011 OpenEye Scientific Software, Inc.
*****************************************************************************
* Program to convert from one molecule format to another
****************************************************************************/
using System;
using OpenEye.OEChem;

public class Convert
{
    public static void Main(string[] args)
    {
        if (args.Length != 2)
        {
            OEChem.OEThrow.Usage("Convert <infile> <outfile>");
        }
        ConvertFile(args[0], args[1]);
    }

    private static void ConvertFile(string infile, string outfile)
    {
        OEMol mol = new OEMol();

        oemolistream ifs = new oemolistream();
        if (!ifs.open(infile))
        {
            OEChem.OEThrow.Fatal("Unable to open " + infile + " for reading");
        }

        oemolostream ofs = new oemolostream();
        if (!ofs.open(outfile))
        {
            OEChem.OEThrow.Fatal("Unable to open " + outfile + " for writing");
        }

        while (OEChem.OEReadMolecule(ifs, mol))
        {
            OEChem.OEWriteMolecule(ofs, mol);
        }
    }
}

See also

Concatenating molecules

/****************************************************************************
* Copyright (C) 2011 OpenEye Scientific Software, Inc.
*****************************************************************************
* This program concatenates molecules into one file.
* It can be useful for generating ROCS queries or reattach ligands to an
* protein structure
****************************************************************************/
using System;
using OpenEye.OEChem;

public class CatMols
{
    public static void Main(string[] args)
    {
        OEInterface itf = new OEInterface(interfaceData, "CatMols", args);

        OEGraphMol omol = new OEGraphMol();
        foreach (string filename in itf.GetStringList("-i"))
        {
            oemolistream ifs = new oemolistream();
            if (ifs.open(filename))
            {
                OEGraphMol imol = new OEGraphMol();
                while (OEChem.OEReadMolecule(ifs, imol))
                {
                    OEChem.OEAddMols(omol, imol);
                }
            }
            else
            {
                OEChem.OEThrow.Fatal("Unable to open " + filename + " for reading");
            }
        }

        oemolostream ofs = new oemolostream();
        if (!ofs.open(itf.GetString("-o")))
        {
            OEChem.OEThrow.Fatal("Unable to open " + itf.GetString("-o") + " for writing");
        }

        OEChem.OEWriteMolecule(ofs, omol);
    }

    private static string interfaceData=@"
!BRIEF -i <infile1> [<infile2>...] -o <outfile>
!PARAMETER -i
  !ALIAS -in
  !TYPE string
  !LIST true
  !REQUIRED true
  !BRIEF input file name(s)
!END
!PARAMETER -o
  !ALIAS -out
  !TYPE string
  !REQUIRED true
  !BRIEF output file name
!END
";
}

See also

Splitting multicomponent molecules

/****************************************************************************
* Copyright (C) 2009-2011 OpenEye Scientific Software, Inc.
*****************************************************************************
* Writes each component of a molecule as a separate molecule
****************************************************************************/
using System;
using OpenEye.OEChem;

public class Parts2Mols
{
    public static void Main(string[] args)
    {
        if (args.Length < 1 || args.Length > 2)
        {
            OEChem.OEThrow.Usage("Parts2Mols <infile> [<outfile>]");
        }

        oemolistream ifs = new oemolistream();
        if (!ifs.open(args[0]))
        {
            OEChem.OEThrow.Fatal("Unable to open " + args[0] + " for reading");
        }

        oemolostream ofs = new oemolostream(".ism");
        if (args.Length == 2)
        {
            if (!ofs.open(args[1]))
            {
                OEChem.OEThrow.Fatal("Unable to open " + args[1] + " for writing");
            }
        }

        int incount = 0;
        int outcount = 0;
        OEGraphMol mol = new OEGraphMol();
        while (OEChem.OEReadMolecule(ifs, mol))
        {
            incount++;
            uint[] parts = new uint[mol.GetMaxAtomIdx()];
            uint pcount = OEChem.OEDetermineComponents(mol, parts);
            OEPartPredAtom pred = new OEPartPredAtom(parts, (uint)parts.Length);
            for (uint i = 1; i <= pcount; ++i)
            {
                outcount++;
                pred.SelectPart(i);
                OEGraphMol partmol = new OEGraphMol();
                bool adjustHCount = true;
                OEChem.OESubsetMol(partmol, mol, pred, adjustHCount);
                OEChem.OEWriteMolecule(ofs, partmol);
            }
        }
        Console.Error.WriteLine("results:  in: " + incount + "  out: " + outcount);
    }
}

Extract molecules by title

/****************************************************************************
* Copyright (C) 2009-2011, 2013 OpenEye Scientific Software, Inc.
*****************************************************************************
* Extract compound(s) from a file based on molecule title
****************************************************************************/
using System;
using System.IO;
using System.Collections.Generic;
using OpenEye.OEChem;

public class MolExtract
{
    private static HashSet<string> FillTitleSet(OEInterface itf)
    {
        HashSet<string> titles = new HashSet<string>();

        if (itf.HasString("-title"))
        {
            titles.Add(itf.GetString("-title"));
        }
        else if (itf.HasString("-list"))
        {
            StreamReader sr = null;
            try
            {
                sr = new StreamReader(itf.GetString("-list"));
                string line;
                while ((line = sr.ReadLine()) != null)
                {
                    titles.Add(line.Trim());
                }
            }
            catch
            {
                OEChem.OEThrow.Fatal("Unable to open " + itf.GetString("-list") + " for reading");
            }
            finally
            {
                if (sr != null)
                {
                    sr.Close();
                }

            }
        }
        else
        {
            OEChem.OEThrow.Usage("Must give either -list or -title");
        }
        return titles;
    }

    private static void Extract(OEInterface itf)
    {
        HashSet<string> titleSet = FillTitleSet(itf);
        if (titleSet.Count == 0)
        {
            OEChem.OEThrow.Fatal("No titles requested");
        }

        oemolistream ifs = new oemolistream();
        if (!ifs.open(itf.GetString("-i")))
        {
            OEChem.OEThrow.Fatal("Unable to open " + itf.GetString("-i") + " for reading");
        }

        oemolostream ofs = new oemolostream();
        if (!ofs.open(itf.GetString("-o")))
        {
            OEChem.OEThrow.Fatal("Unable to open " + itf.GetString("-o") + " for writing");
        }

        OEGraphMol mol = new OEGraphMol();
        while (OEChem.OEReadMolecule(ifs, mol))
        {
            if (titleSet.Contains(mol.GetTitle()))
            {
                OEChem.OEWriteMolecule(ofs, mol);
            }
        }
    }

    public static void Main(string[] args)
    {
        OEInterface itf = new OEInterface(interfaceData, "MolExtract", args);
        Extract(itf);
    }

    private static string interfaceData=@"
!BRIEF -title title | -list <moltitles.file> [-i] <input> [-o] <output>
!PARAMETER -i
  !ALIAS -in
  !TYPE string
  !REQUIRED true
  !BRIEF Input file name
  !KEYLESS 1
!END
!PARAMETER -o
  !ALIAS -out
  !TYPE string
  !REQUIRED true
  !BRIEF Output file name
  !KEYLESS 2
!END
!PARAMETER -title
  !ALIAS -t
  !TYPE string
  !BRIEF Single mol title to extract
!END
!PARAMETER -list
  !ALIAS -l
  !TYPE string
  !BRIEF List file of mol titles to extract 
!END
";
}

See also

Write out unique molecules

/****************************************************************************
* Copyright (C) 2009-2013 OpenEye Scientific Software, Inc.
*****************************************************************************
* Read molecules and write out the unique ones. Two molecules are considered
* identical if their canonical isomeric smiles are identical.
****************************************************************************/
using System;
using System.Collections.Generic;
using OpenEye.OEChem;

public class UniqMol
{
    public static void Main(string[] args)
    {
        if (args.Length != 2)
        {
            OEChem.OEThrow.Usage("UniqMol <infile> <outfile>");
        }

        oemolistream ifs = new oemolistream();
        if (!ifs.open(args[0]))
        {
            OEChem.OEThrow.Fatal("Unable to open " + args[0] + " for reading");
        }

        oemolostream ofs = new oemolostream();
        if (!ofs.open(args[1]))
        {
            OEChem.OEThrow.Fatal("Unable to open " + args[1] + " for writing");
        }
        ProcessFile(ifs, ofs);
    }

    private static void ProcessFile(oemolistream ifs, oemolostream ofs)
    {
        OEGraphMol mol = new OEGraphMol();
        HashSet<string> UniqSmiles = new HashSet<string>();
        while (OEChem.OEReadMolecule(ifs, mol))
        {
            string smi = OEChem.OECreateIsoSmiString(mol);
            if (UniqSmiles.Add(smi))
            {
                OEChem.OEWriteMolecule(ofs, mol);
            }
        }
    }
}
/****************************************************************************
* Copyright (C) 2013 OpenEye Scientific Software, Inc.
*****************************************************************************
* Read molecules and write out the unique ones. Two molecules are considered
* identical if their InChIs are identical.
****************************************************************************/
using System;
using System.Collections.Generic;
using OpenEye.OEChem;

public class UniqInChI
{
    public static void Main(string[] args)
    {
        if (args.Length != 2)
        {
            OEChem.OEThrow.Usage("UniqInChI <infile> <outfile>");
        }

        oemolistream ifs = new oemolistream();
        if (!ifs.open(args[0]))
        {
            OEChem.OEThrow.Fatal("Unable to open " + args[0] + " for reading");
        }

        oemolostream ofs = new oemolostream();
        if (!ofs.open(args[1]))
        {
            OEChem.OEThrow.Fatal("Unable to open " + args[1] + " for writing");
        }
        ProcessFile(ifs, ofs);
    }

    private static void ProcessFile(oemolistream ifs, oemolostream ofs)
    {
        OEGraphMol mol = new OEGraphMol();
        HashSet<string> UniqInChIs = new HashSet<string>();
        while (OEChem.OEReadMolecule(ifs, mol))
        {
            string inchi = OEChem.OECreateInChI(mol);
            if (UniqInChIs.Add(inchi))
            {
                OEChem.OEWriteMolecule(ofs, mol);
            }
        }
    }
}

See also

Randomize atoms of molecules

/****************************************************************************
* Copyright (C) 2011 OpenEye Scientific Software, Inc.
*****************************************************************************
* Demonstrates how to randomly reorder atoms and bonds of a molecule
****************************************************************************/
using System;
using OpenEye.OEChem;

public class RandomizeAtoms
{

    public static void Main(string[] args)
    {
        if (args.Length != 2)
        {
            OEChem.OEThrow.Usage("RandomizeAtoms <infile> <outfile>");
        }

        oemolistream ifs = new oemolistream();
        if (!ifs.open(args[0]))
        {
            OEChem.OEThrow.Fatal("Unable to open " + args[0] + " for reading");
        }

        oemolostream ofs = new oemolostream();
        if (!ofs.open(args[1]))
        {
            OEChem.OEThrow.Fatal("Unable to open " + args[1] + " for writing");
        }

        OEGraphMol mol = new OEGraphMol();
        while (OEChem.OEReadMolecule(ifs, mol))
        {
            OEChem.OEScrambleMolecule(mol);
            OEChem.OEWriteMolecule(ofs, mol);
        }
    }
}

See also

Generate canonical smiles

/****************************************************************************
* Copyright (C) 2011 OpenEye Scientific Software, Inc.
*****************************************************************************
* Generate canonical smiles of various flavors
****************************************************************************/
using System;
using System.IO;
using OpenEye.OEChem;

/***************************************************************************
 To create unique Kekule smiles, must reperceive bond orders from
 scratch to avoid arbitrary nondeterministic variations, e.g.,
 CC1=C(O)C=CC=C1 vs. CC1=CC=CC=C1O
 This is why OESMILESFlag_Kekule is not sufficient and not used.
***************************************************************************/

public class CanSmi
{
    private static string CreateCanSmi(OEGraphMol mol, bool isomeric, bool kekule)
    {
        OEChem.OEFindRingAtomsAndBonds(mol);
        OEChem.OEAssignAromaticFlags(mol, OEAroModel.OpenEye);
        uint smiflag = OESMILESFlag.Canonical;
        if (isomeric)
        {
            smiflag |= OESMILESFlag.ISOMERIC;
        }
        if (kekule)
        {
            foreach (OEBondBase bond in mol.GetBonds(new OEIsAromaticBond()))
            {
                bond.SetIntType(5);
            }
            OEChem.OECanonicalOrderAtoms(mol);
            OEChem.OECanonicalOrderBonds(mol);
            OEChem.OEClearAromaticFlags(mol);
            OEChem.OEKekulize(mol);
        }
        string smi = OEChem.OECreateSmiString(mol, smiflag);
        return smi;
    }

    public static void Main(string[] args)
    {
        OEInterface itf = new OEInterface(interfaceData, "CanSmi", args);

        bool isomeric = itf.GetBool("-isomeric");
        bool kekule   = itf.GetBool("-kekule");
        bool from3d   = itf.GetBool("-from3d");

        if (from3d)
        {
            isomeric = true;
        }

        oemolistream ifs = new oemolistream();
        if (!ifs.open(itf.GetString("-i")))
        {
            OEChem.OEThrow.Fatal("Unable to open " + itf.GetString("-i") + " for reading");
        }

        StreamWriter sw = null;
        if (itf.HasString("-o"))
        {
            try
            {
                sw = new StreamWriter(itf.GetString("-o"));
                Console.SetOut(sw);
            }
            catch
            {
                OEChem.OEThrow.Fatal("Unable to open " + itf.GetString("-o") + " for writing");
            }
        }

        OEGraphMol mol = new OEGraphMol();
        while (OEChem.OEReadMolecule(ifs, mol))
        {
            if (from3d)
            {
                OEChem.OE3DToInternalStereo(mol);
            }
            string smi = CreateCanSmi(mol, isomeric, kekule);
            string title = mol.GetTitle();
            if (!string.IsNullOrEmpty(title))
            {
                smi += " " + title;
            }
            Console.WriteLine(smi);
        }
        if (itf.HasString("-o"))
        {
            sw.Close();
        }
    }

    private static string interfaceData=@"
!BRIEF [options] [-i] <input> [[-o] <output>]
!PARAMETER -i
  !ALIAS -in
  !TYPE string
  !REQUIRED true
  !BRIEF input file name
  !KEYLESS 1
!END
!PARAMETER -o
  !ALIAS -out
  !TYPE string
  !BRIEF output file name
  !KEYLESS 2
!END
!PARAMETER -isomeric
  !TYPE bool
  !DEFAULT false
  !BRIEF generate isomeric smiles
!END
!PARAMETER -from3d
  !TYPE bool
  !DEFAULT false
  !BRIEF perceive stereo from 3D coords
!END
!PARAMETER -kekule
  !TYPE bool
  !DEFAULT false
  !BRIEF generate kekule form
!END
";
}

Filter molecules by weight or heavy atom count

/****************************************************************************
* Copyright (C) 2011 OpenEye Scientific Software, Inc.
*****************************************************************************
* Filter out molecules by their molecular weight or heavy atom count
****************************************************************************/
using System;
using OpenEye.OEChem;

public class SizeFilter
{
    public static void Main(string[] args)
    {
        OEInterface itf = new OEInterface(interfaceData, "SizeFilter", args);

        oemolistream ifs = new oemolistream();
        if (!ifs.open(itf.GetString("-i")))
        {
            OEChem.OEThrow.Fatal("Unable to open " + itf.GetString("-i") + " for reading");
        }

        oemolostream ofs = new oemolostream(".ism");
        if (itf.HasString("-o"))
        {
            if (!ofs.open(itf.GetString("-o")))
            {
                OEChem.OEThrow.Fatal("Unable to open " + itf.GetString("-o") + " for writing");
            }
        }

        int minhac = int.MinValue;
        if (itf.HasInt("-minhac"))
        {
            minhac = itf.GetInt("-minhac");
        }

        int maxhac = int.MaxValue;
        if (itf.HasInt("-maxhac"))
        {
            maxhac = itf.GetInt("-maxhac");
        }

        double minwt = double.MinValue;
        if (itf.HasDouble("-minwt"))
        {
            minwt = itf.GetDouble("-minwt");
        }

        double maxwt = double.MaxValue;
        if (itf.HasDouble("-maxwt"))
        {
            maxwt = itf.GetDouble("-maxwt");
        }

        OEMol mol = new OEMol();
        while (OEChem.OEReadMolecule(ifs, mol))
        {
            if (!IsMoleculeInHeavyAtomCountRange(minhac, maxhac, mol))
            {
                continue;
            }

            if (!IsMoleculeInMolWtRange(minwt, maxwt, mol))
            {
                continue;
            }

            OEChem.OEWriteMolecule(ofs, mol);
        }
    }

    private static bool IsBetween(int min, int max, int val)
    {
        if (val >= min && val <= max)
        {
            return true;
        }
        return false;
    }

    private static bool IsBetween(double min, double max, double val)
    {
        if (val >= min && val <= max)
        {
            return true;
        }
        return false;
    }

    private static bool IsMoleculeInHeavyAtomCountRange(int minhac, int maxhac, OEMol mol)
    {
        uint count = OEChem.OECount(mol, new OEIsHeavy());
        return IsBetween(minhac, maxhac, count);
    }

    private static bool IsMoleculeInMolWtRange(double minwt, double maxwt, OEMol mol)
    {
        double molwt = OEChem.OECalculateMolecularWeight(mol);
        return IsBetween(minwt, maxwt, molwt);
    }

    private static string interfaceData=@"
!BRIEF [-minhac <num>] [-maxhac <num>] [-minwt <num>] [-maxwt <num>] [-i] <input> [[-o] <output>]
!PARAMETER -i
  !TYPE string
  !REQUIRED true
  !BRIEF Input file name
  !KEYLESS 1
!END
!PARAMETER -o
  !TYPE string
  !REQUIRED false
  !BRIEF Output file name
  !KEYLESS 2
!END
!PARAMETER -minhac
  !TYPE int
  !REQUIRED false
  !BRIEF minimum heavy atom count
!END
!PARAMETER -maxhac
  !TYPE int
  !REQUIRED false
  !BRIEF maximum heavy atom count
!END
!PARAMETER -minwt
  !TYPE double
  !REQUIRED false
  !BRIEF minimum molecular weight
!END
!PARAMETER -maxwt
  !TYPE double
  !REQUIRED false
  !BRIEF maximum molecular weight
!END
";
}

See also

Strip salts

/****************************************************************************
* Copyright (C) 2011 OpenEye Scientific Software, Inc.
*****************************************************************************
*  Remove salts and/or remove all but the largest molecule
****************************************************************************/
using System;
using OpenEye.OEChem;

public class StripSalts
{

    public static void Main(string[] args)
    {
        if (args.Length != 2)
        {
            OEChem.OEThrow.Usage("StripSalts <infile> <outfile>");
        }

        oemolistream ifs = new oemolistream();
        if (!ifs.open(args[0]))
        {
            OEChem.OEThrow.Fatal("Unable to open " + args[0] + " for reading");
        }

        oemolostream ofs = new oemolostream();
        if (!ofs.open(args[1]))
        {
            OEChem.OEThrow.Fatal("Unable to open " + args[1] + " for writing");
        }

        OEMol mol = new OEMol();
        while (OEChem.OEReadMolecule(ifs, mol))
        {
            OEChem.OETheFunctionFormerlyKnownAsStripSalts(mol);
            OEChem.OEWriteMolecule(ofs, mol);
        }
    }
}

Extract rings

/****************************************************************************
* Copyright (C) 2009-2011 OpenEye Scientific Software, Inc.
*****************************************************************************
* Extracting rings/ring systems from input molecules
****************************************************************************/
using System;
using OpenEye.OEChem;

public class RingSubset
{
    public static void Main(string[] args)
    {
        OEInterface itf = new OEInterface(interfaceData, "RingSubset", args);

        bool exo_dbl_bonds = itf.GetBool("-exo");

        oemolistream ifs = new oemolistream();
        if (!ifs.open(itf.GetString("-i")))
        {
            OEChem.OEThrow.Fatal("Unable to open " + itf.GetString("-i") + " for reading");
        }

        oemolostream ofs = new oemolostream(".ism");
        if (itf.HasString("-o"))
        {
            if (!ofs.open(itf.GetString("-o")))
            {
                OEChem.OEThrow.Fatal("Unable to open " + itf.GetString("-o") + " for writing");
            }
        }
        RingSubSet(ifs, ofs, exo_dbl_bonds);
    }

    private static void RingSubSet(oemolistream ifs, oemolostream ofs, bool exo)
    {
        OEGraphMol mol = new OEGraphMol();
        while (OEChem.OEReadMolecule(ifs, mol))
        {
            OEGraphMol submol = new OEGraphMol();
            OEUnaryAtomPred pred = new OEAtomIsInRing();
            if (exo)
            {
                pred = new OEOrAtom(pred, new OEIsNonRingAtomDoubleBondedToRing());
            }
            bool adjustHCount = true;
            OEChem.OESubsetMol(submol, mol, pred, adjustHCount);

            string title = mol.GetTitle() + "_rings";
            submol.SetTitle(title);
            if (submol.NumAtoms() != 0)
            {
                OEChem.OEWriteMolecule(ofs, submol);
            }
        }
    }

    private static string interfaceData=@"
!BRIEF [-exo] [-i] <infile> [[-o] <outfile>]
!PARAMETER -i
  !ALIAS -in
  !TYPE string
  !REQUIRED true
  !BRIEF input file name
  !KEYLESS 1
!END
!PARAMETER -o
  !ALIAS -out
  !TYPE string
  !REQUIRED false
  !BRIEF output file name
  !KEYLESS 2
!END
!PARAMETER -exo
  !TYPE bool
  !DEFAULT true
  !BRIEF Include non-ring atoms double bonded to a ring
!END
";
}

Extract molecule scaffolds

/****************************************************************************
* Copyright (C) 2009-2011 OpenEye Scientific Software, Inc.
*****************************************************************************
* Extract the ring scaffold of a molecule
****************************************************************************/
using System;
using OpenEye.OEChem;

public class ExtractScaffold
{
    public static void Main(string[] args)
    {
        OEInterface itf = new OEInterface(interfaceData, "ExtractScaffold", args);

        bool exo_dbl_bonds = itf.GetBool("-exo");

        oemolistream ifs = new oemolistream();
        if (!ifs.open(itf.GetString("-i")))
        {
            OEChem.OEThrow.Fatal("Unable to open " + itf.GetString("-i") + " for reading");
        }

        oemolostream ofs = new oemolostream();
        if (!ofs.open(itf.GetString("-o")))
        {
            OEChem.OEThrow.Fatal("Unable to open " + itf.GetString("-o") + " for writing");
        }

        OEMol src = new OEMol();
        OEMol dst = new OEMol();
        while (OEChem.OEReadMolecule(ifs, src))
        {
            bool adjustHCount = true;
            if (exo_dbl_bonds)
            {
                OEChem.OESubsetMol(dst, src, new OEOrAtom(new IsInScaffold(), new OEIsNonRingAtomDoubleBondedToRing()), adjustHCount);
            }
            else
            {
                OEChem.OESubsetMol(dst, src, new IsInScaffold(), adjustHCount);
            }

            if (dst.IsValid())
            {
                OEChem.OEWriteMolecule(ofs, dst);
            }
        }
    }

    private static bool TraverseForRing(bool[] visited, OEAtomBase atom)
    {
        visited[atom.GetIdx()] = true;

        foreach (OEAtomBase nbor in atom.GetAtoms())
        {
            if (!visited[nbor.GetIdx()])
            {
                if (nbor.IsInRing())
                {
                    return true;
                }

                if (TraverseForRing(visited, nbor))
                {
                    return true;
                }
            }
        }

        return false;
    }

    private static bool DepthFirstSearchForRing(OEAtomBase root, OEAtomBase nbor)
    {
        bool[] visited = new bool[root.GetParent().GetMaxAtomIdx()];

        visited[root.GetIdx()] = true;

        return TraverseForRing(visited, nbor);
    }

    private class IsInScaffold : OEUnaryAtomPred
    {
        public override bool Call(OEAtomBase atom)
        {
            if (atom.IsInRing())
            {
                return true;
            }

            int count = 0;
            foreach (OEAtomBase nbor in atom.GetAtoms())
            {
                if (DepthFirstSearchForRing(atom, nbor))
                {
                    ++count;
                }
            }

            return count > 1;
        }

        public override OEUnaryAtomBoolFunc CreateCopy()
        {
            OEUnaryAtomBoolFunc copy = new IsInScaffold();
            copy.ReleaseOwnership();
            return copy;
        }
    }

    private static string interfaceData=@"
!BRIEF [-exo] [-i] <input> [-o] <scaffolds>
!PARAMETER -i
  !ALIAS -in
  !TYPE string
  !REQUIRED true
  !BRIEF input file name
  !KEYLESS 1
!END
!PARAMETER -o
  !ALIAS -out
  !TYPE string
  !REQUIRED true
  !BRIEF output file name
  !KEYLESS 2
!END
!PARAMETER -exo
  !TYPE bool
  !DEFAULT true
  !BRIEF Exclude double bonds exo to ring in scaffold
!END
";
}

Extract random molecule subset

/****************************************************************************
* Copyright (C) 2011 OpenEye Scientific Software, Inc.
*****************************************************************************
* Randomly reorder molecules and optionally obtain a random subset
****************************************************************************/
using System;
using System.Collections;
using System.Collections.Generic;
using ExtensionMethods;
using OpenEye.OEChem;

namespace ExtensionMethods
{
public static class MyExtensions
{
    public static void Shuffle(this ArrayList list, Random r)
    {

        int n = list.Count;
        while (n > 1)
        {
            n--;
            int k = r.Next(n + 1);
            OEMol value = (OEMol)list[k];
            list[k] = list[n];
            list[n] = value;
        }
    }
}
}

public class RandomSample
{

    public static void LoadDatabase(oemolistream ifs, ArrayList mlist, int count)
    {
        int readcount = 0;
        OEMol mol = new OEMol(OEMCMolType.OEDBMCMol);
        while (OEChem.OEReadMolecule(ifs, mol))
        {
            readcount++;
            mol.Compress();
            mlist.Add(mol);
            mol = new OEMol();
            if (readcount == count)
            {
                break;
            }
        }
    }

    public static void WriteDatabase(oemolostream ofs, ArrayList mlist, int count)
    {
        int outcount = 0;
        foreach (OEMol dbmol in mlist)
        {
            dbmol.UnCompress();
            OEChem.OEWriteMolecule(ofs, dbmol);
            outcount++;
            if (outcount == count)
            {
                break;
            }
        }
    }

    public static void RandomizePercent(oemolistream ifs, oemolostream ofs, float percent, Random r)
    {
        ArrayList mlist = new ArrayList();
        LoadDatabase(ifs, mlist, 0);

        mlist.Shuffle(r);

        int size = mlist.Count;
        int count = (int)(percent * 0.01 * size);
        if (count < 1) {
            count = 1;
        }
        WriteDatabase(ofs, mlist, count);
    }

    public static void Randomize(oemolistream ifs, oemolostream ofs, Random r)
    {
        float wholedb = 100;
        RandomizePercent(ifs, ofs, wholedb, r);
    }

    public static void RandomizeN(oemolistream ifs, oemolostream ofs, int count, Random r)
    {
        ArrayList mlist = new ArrayList();
        LoadDatabase(ifs, mlist, count);

        int readcount = 0;
        OEMol mol = new OEMol(OEMCMolType.OEDBMCMol);
        while (OEChem.OEReadMolecule(ifs, mol))
        {
            if ((float)count/(count + readcount + 1) > r.NextDouble())
            {
                int idx = (int) ((float)count * r.NextDouble());
                mol.Compress();
                mlist[idx] = mol;
                mol = new OEMol();
            }
            readcount++;
        }

        mlist.Shuffle(r);
        WriteDatabase(ofs, mlist, count);
    }

    public static void Main(string[] args)
    {
        OEInterface itf = new OEInterface(interfaceData, "RandomSample", args);

        if (itf.HasFloat("-p") && itf.HasInt("-n"))
        {
            OEChem.OEThrow.Usage("Give only one option, -p or -n");
        }

        oemolistream ifs = new oemolistream();
        if (!ifs.open(itf.GetString("-i")))
        {
            OEChem.OEThrow.Fatal("Unable to open " + itf.GetString("-i") + " for reading");
        }

        oemolostream ofs = new oemolostream(".ism");
        if (itf.HasString("-o"))
        {
            if (!ofs.open(itf.GetString("-o")))
            {
                OEChem.OEThrow.Fatal("Unable to open " + itf.GetString("-o") + " for writing");
            }
        }

        Random r = null;
        if (itf.HasInt("-seed")) {
            r = new Random(itf.GetInt("-seed"));
        }
        else {
            r = new Random();
        }

        if (itf.HasInt("-n"))
        {
            RandomizeN(ifs, ofs, itf.GetInt("-n"), r);
        }
        else if (itf.HasFloat("-p"))
        {
            RandomizePercent(ifs, ofs, itf.GetFloat("-p"), r);
        }
        else
        {
            Randomize(ifs, ofs, r);
        }
    }

    private static string interfaceData=@"
!BRIEF [-seed <int>] [-n <number>] [-p <percent>] [-i] <input> [-o] <output>
!PARAMETER -i
  !TYPE string
  !REQUIRED true
  !BRIEF Input file name
  !KEYLESS 1
!END
!PARAMETER -o
  !TYPE string
  !REQUIRED false
  !BRIEF Output file name
  !KEYLESS 2
!END
!PARAMETER -p
  !TYPE float
  !REQUIRED false
  !BRIEF Percentage of output molecules
!END
!PARAMETER -n
  !TYPE int
  !REQUIRED false
  !BRIEF Number of output molecules
!END
!PARAMETER -seed
  !TYPE int
  !REQUIRED false
  !BRIEF Integer value for random seed, default is system time
!END
";
}

See also

Performing a reaction

/****************************************************************************
* Copyright (C) 2009-2017 OpenEye Scientific Software, Inc.
*****************************************************************************
* Perform reactions on the given compounds
****************************************************************************/
using System;
using OpenEye.OEChem;

public class UniMolRxn
{
    public static void Main(string[] args)
    {
        if (args.Length < 2 || args.Length > 3)
        {
            OEChem.OEThrow.Usage("UniMolRxn SMIRKS <infile> [<outfile>]");
        }

        OEQMol qmol = new OEQMol();
        if (!OEChem.OEParseSmirks(qmol, args[0]))
        {
            OEChem.OEThrow.Fatal("Unable to parse SMIRKS: " + args[0]);
        }

        OEUniMolecularRxn umr = new OEUniMolecularRxn();
        if (!umr.Init(qmol))
        {
            OEChem.OEThrow.Fatal("Failed to initialize reaction with " + args[0] + " SMIRKS");
        }
        umr.SetClearCoordinates(true);

        oemolistream ifs = new oemolistream();
        if (!ifs.open(args[1]))
        {
            OEChem.OEThrow.Fatal("Unable to open " + args[1] + " for reading");
        }

        oemolostream ofs = new oemolostream(".ism");
        if (args.Length == 3)
        {
            if (!ofs.open(args[2]))
            {
                OEChem.OEThrow.Fatal("Unable to open " + args[2] + " for writing");
            }

        }
        UniMolecularRxn(ifs, ofs, umr);
    }

    private static void UniMolecularRxn(oemolistream ifs,
                                        oemolostream ofs,
                                        OEUniMolecularRxn umr)
    {

        OEGraphMol mol = new OEGraphMol();
        while (OEChem.OEReadMolecule(ifs, mol))
        {
            if (umr.Call(mol))
            {
                OEChem.OEWriteMolecule(ofs, mol);
            }
        }
    }
}

See also

Library generation

/****************************************************************************
* Copyright (C) 2009-2017 OpenEye Scientific Software, Inc.
*****************************************************************************
* Perform library generation with SMIRKS
****************************************************************************/
using System;
using System.Collections.Generic;
using OpenEye.OEChem;

public class LibGen
{
    private static void LibraryGen(OELibraryGen libgen, oemolostream ofs,
                                   bool isomeric, bool unique)
    {
        uint smiflag = OESMILESFlag.DEFAULT;
        if (isomeric)
        {
            smiflag |= OESMILESFlag.ISOMERIC;
        }
        HashSet<string> uniqueproducts = new HashSet<string>();
        foreach (OEMolBase mol in libgen.GetProducts())
        {
            string smiles = OEChem.OECreateSmiString(mol, smiflag);
            if (!unique || !uniqueproducts.Contains(smiles))
            {
                uniqueproducts.Add(smiles);
                OEChem.OEWriteMolecule(ofs, mol);
            }
        }
    }

    public static void Main(string[] args)
    {
        OEInterface itf = new OEInterface(interfaceData, "LibGen", args);
        if (!(itf.HasString("-smirks") ^ itf.HasString("-rxn")))
        {
            OEChem.OEThrow.Fatal("Please provide SMIRKS string or MDL reaction file");
        }

        OEQMol reaction = new OEQMol();
        if (itf.HasString("-smirks"))
        {
            string smirks = itf.GetString("-smirks");
            if (!OEChem.OEParseSmirks(reaction, smirks))
            {
                OEChem.OEThrow.Fatal("Unable to parse SMIRKS: " + smirks);
            }
        }
        else
        {
            string rxn = itf.GetString("-rxn");
            oemolistream rfile = new oemolistream(rxn);
            uint opt = OEMDLQueryOpts.ReactionQuery|OEMDLQueryOpts.SuppressExplicitH;
            if (!OEChem.OEReadMDLReactionQueryFile(rfile, reaction, opt))
            {
                OEChem.OEThrow.Fatal("Unable to read reaction file: " + rxn);
            }
        }
        bool relax      = itf.GetBool("-relax");
        bool unique     = itf.GetBool("-unique");
        bool implicitH  = itf.GetBool("-implicitH");
        bool valcorrect = itf.GetBool("-valence");
        bool isomeric   = itf.GetBool("-isomeric");

        OELibraryGen libgen = new OELibraryGen();

        // Initialize library generation
        if (!libgen.Init(reaction, !relax))
        {
            OEChem.OEThrow.Fatal("failed to initialize library generator");
        }
        libgen.SetValenceCorrection(valcorrect);
        libgen.SetExplicitHydrogens(!implicitH);
        libgen.SetClearCoordinates(true);

        uint nrReacts = 0;
        foreach (string filename in itf.GetStringList("-reactants"))
        {
            if (nrReacts >= libgen.NumReactants())
            {
                OEChem.OEThrow.Fatal("Number of reactant files exceeds number of reactants specified in reaction");
            }
            oemolistream ifs = new oemolistream();
            if (!ifs.open(filename))
            {
                OEChem.OEThrow.Fatal("Unable to open " + filename + " for reading");
            }
            OEGraphMol mol = new OEGraphMol();
            while (OEChem.OEReadMolecule(ifs, mol))
            {
                libgen.AddStartingMaterial(mol, nrReacts, unique);
            }
            nrReacts++;
        }
        if (nrReacts != libgen.NumReactants())
        {
            OEChem.OEThrow.Fatal("Reactions requires " + libgen.NumReactants() + " reactant files!");
        }

        oemolostream ofs = new oemolostream(".ism");
        if (itf.HasString("-product"))
        {
            if (!ofs.open(itf.GetString("-product")))
            {
                OEChem.OEThrow.Fatal("Unable to open " + itf.GetString("-product") + " for writing");
            }
        }
        LibraryGen(libgen, ofs, isomeric, unique);
    }

    private static string interfaceData=@"
!BRIEF [options] [-smirks <string> | -rxn <rfile>] -reactants <infile> [-product <outfile>]
!CATEGORY ""input/output options""
!PARAMETER -smirks
!ALIAS -s
!TYPE string
!VISIBILITY simple
!BRIEF SMIRKS reaction string
!END

!PARAMETER -rxn
!ALIAS -s
!TYPE string
!VISIBILITY simple
!BRIEF MDL reaction file
!END

!PARAMETER -reactants
!ALIAS -r
!TYPE string
!LIST true
!REQUIRED true
!VISIBILITY simple
!BRIEF list of input reactant filenames
!END

!PARAMETER -product
!ALIAS -p
!TYPE string
!REQUIRED false
!VISIBILITY simple
!BRIEF output product filename
!END
!END

!CATEGORY ""OELibraryGen options""
!PARAMETER -relax
!TYPE bool
!REQUIRED false
!DEFAULT false
!VISIBILITY simple
!BRIEF unmapped atoms on reactant side are not deleted during reaction
!END

!PARAMETER -implicitH
!TYPE bool
!REQUIRED false
!DEFAULT false
!VISIBILITY simple
!BRIEF reaction will be perfomed using implicit hydrogens
!END

!PARAMETER -valence
!TYPE bool
!REQUIRED false
!DEFAULT false
!VISIBILITY simple
!BRIEF automatic valence correction will be applied
!END
!END

!CATEGORY ""product smiles generation options""
!PARAMETER -unique
!TYPE bool
!REQUIRED false
!DEFAULT false
!VISIBILITY simple
!BRIEF only unique product canonical smiles will be written
!END

!PARAMETER -isomeric
!TYPE bool
!REQUIRED false
!DEFAULT false
!VISIBILITY simple
!BRIEF include atom and bond stereochemistry in product smiles string
!END
!END
";
}

See also

Perform substructure searches

/****************************************************************************
* Copyright (C) 2009-2011, 2013 OpenEye Scientific Software, Inc.
*****************************************************************************
* Perform substructure search on molecule file
****************************************************************************/
using System;
using OpenEye.OEChem;

public class MolGrep
{
    public static void Main(string[] args)
    {
        OEInterface itf = new OEInterface(interfaceData, "MolGrep", args);
        if (!(itf.GetBool("-c") ^ itf.HasString("-o")))
        {
            OEChem.OEThrow.Fatal("Counting (-c) or output (-o) must be specified and are mutually exclusive.");
        }

        oemolistream ifs = new oemolistream();
        if (!ifs.open(itf.GetString("-i")))
        {
            OEChem.OEThrow.Fatal("Unable to open " + itf.GetString("-i") + " for reading");
        }

        oemolostream ofs = new oemolostream();
        if (!itf.GetBool("-c"))
        {
            if (!ofs.open(itf.GetString("-o")))
            {
                OEChem.OEThrow.Fatal("Unable to open " + itf.GetString("-o") + " for writing");
            }
        }

        string smarts = itf.GetString("-p");
        OESubSearch ss = new OESubSearch();
        if (!ss.Init(smarts))
        {
            OEChem.OEThrow.Fatal("Unable to parse SMARTS: " + smarts);
        }

        SubSearch(itf, ss, ifs, ofs);

    }

    public static void SubSearch(OEInterface itf, OESubSearch ss,
                                 oemolistream ifs, oemolostream ofs)
    {
        bool reverseflag = itf.GetBool("-r");
        bool countflag   = itf.GetBool("-c");
        int count = 0;
        OEGraphMol mol = new OEGraphMol();
        while (OEChem.OEReadMolecule(ifs, mol))
        {
            OEChem.OEPrepareSearch(mol, ss);
            if (ss.SingleMatch(mol) != reverseflag)
            {
                if (countflag)
                {
                    count++;
                }
                else
                {
                    OEChem.OEWriteMolecule(ofs, mol);
                }
            }
        }
        if (countflag)
        {
            Console.WriteLine(count + " matching molecules");
        }
    }

    private static string interfaceData=@"
!BRIEF [-r][-c] -p smarts [-i] <input> [[-o] <output>]
!PARAMETER -i 1
  !ALIAS -in
  !TYPE string
  !REQUIRED true
  !BRIEF Input file name
  !KEYLESS 1
!END
!PARAMETER -p 2
  !TYPE string
  !REQUIRED true
  !BRIEF SMARTS pattern, quote for safety
!END
!PARAMETER -o 3
  !ALIAS -out
  !TYPE string
  !BRIEF Output file name
  !KEYLESS 2
!END
!PARAMETER -r 4
  !ALIAS -v
  !TYPE bool
  !DEFAULT false
  !BRIEF Reverse logic, not matched
!END
!PARAMETER -c 5
  !TYPE bool
  !DEFAULT false
  !BRIEF Just output count of number matched
!END
";
}

See also

Align molecules by maximum common substructure

/****************************************************************************
* Copyright (C) 2011, 2012 OpenEye Scientific Software, Inc.
*****************************************************************************
* Align two compounds based on the maximum common substructure
****************************************************************************/
using System;
using OpenEye.OEChem;

public class MCS3DAlign {
    public static void MCSAlign(OEMolBase refmol, OEMolBase fitmol,
                                oemolostream ofs)
    {
        uint atomexpr = OEExprOpts.AtomicNumber|OEExprOpts.Aromaticity;
        uint bondexpr =  0; // ignore bond order
        uint mcsstype = OEMCSType.Exhaustive;
        OEMCSSearch mcss = new OEMCSSearch(refmol, atomexpr, bondexpr, mcsstype);
        mcss.SetMCSFunc(new OEMCSMaxBondsCompleteCycles());

        bool unique = true;
        foreach (OEMatchBase match in mcss.Match(fitmol, unique))
        {
            double[] rmat = new double[9];
            double[] trans = new double[3];
            bool overlay = true;
            double rms = OEChem.OERMSD(mcss.GetPattern(), fitmol, match, overlay, rmat, trans);
            if (rms < 0.0)
            {
                OEChem.OEThrow.Warning("RMS overlay failure");
                continue;
            }
            OEChem.OERotate(fitmol, rmat);
            OEChem.OETranslate(fitmol, trans);
            OEChem.OEWriteMolecule(ofs, fitmol);
        }
    }

    public static bool Is3DFormat(uint fmt)
    {
        if (fmt == OEFormat.SMI || fmt == OEFormat.ISM ||
            fmt == OEFormat.CAN || fmt == OEFormat.MF)
        {
            return false;
        }
        return true;
    }

    public static void Main(string[] args)
    {
        if (args.Length != 3)
        {
            OEChem.OEThrow.Usage("MCS3DAlign <refmol> <fitmol> <outfile>");
        }

        oemolistream reffs = new oemolistream();
        if (!reffs.open(args[0]))
        {
            OEChem.OEThrow.Fatal("Unable to open " + args[0] + " for reading");
        }
        if (!Is3DFormat(reffs.GetFormat()))
        {
            OEChem.OEThrow.Fatal("Invalid input format: need 3D coordinates");
        }
        OEGraphMol refmol = new OEGraphMol();
        if (!OEChem.OEReadMolecule(reffs, refmol))
        {
            OEChem.OEThrow.Fatal("Unable to read molecule in " + args[0]);
        }
        if (refmol.GetDimension() != 3)
        {
            OEChem.OEThrow.Fatal(refmol.GetTitle() + " doesn't have 3D coordinates");
        }

        oemolistream fitfs = new oemolistream();
        if (!fitfs.open(args[1]))
        {
            OEChem.OEThrow.Fatal("Unable to open " + args[1] + " for reading");
        }
        if (!Is3DFormat(fitfs.GetFormat()))
        {
            OEChem.OEThrow.Fatal("Invalid input format: need 3D coordinates");
        }

        oemolostream ofs = new oemolostream();
        if (!ofs.open(args[2]))
        {
            OEChem.OEThrow.Fatal("Unable to open " + args[2] + " for writing");
        }
        if (!Is3DFormat(ofs.GetFormat()))
        {
            OEChem.OEThrow.Fatal("Invalid output format: need 3D coordinates");
        }

        OEChem.OEWriteConstMolecule(ofs, refmol);
        OEChem.OESuppressHydrogens(refmol);

        OEGraphMol fitmol = new OEGraphMol();
        while (OEChem.OEReadMolecule(fitfs, fitmol))
        {
            if (fitmol.GetDimension() != 3)
            {
                OEChem.OEThrow.Warning(fitmol.GetTitle() + " doesn't have 3D coordinates");
                continue;
            }
            MCSAlign(refmol, fitmol, ofs);
        }
    }
}

See also

Align molecules by clique match

/****************************************************************************
* Copyright (C) 2011 OpenEye Scientific Software, Inc.
*****************************************************************************
* Align two compounds based on the clique match
****************************************************************************/
using System;
using OpenEye.OEChem;

public class CliqueAlign
{
    private static void CliqueAlignMols(OEMolBase refmol, OEMolBase fitmol,
                                        oemolostream ofs)
    {
        uint atomexpr = OEExprOpts.DefaultAtoms;
        uint bondexpr = OEExprOpts.DefaultBonds;
        OECliqueSearch cs = new OECliqueSearch(refmol, atomexpr, bondexpr);
        cs.SetSaveRange(5);
        cs.SetMinAtoms(6);
        foreach (OEMatchBase match in cs.Match(fitmol))
        {
            double[] rmat = new double[9];
            double[] trans = new double[3];
            bool overlay = true;
            OEChem.OERMSD(cs.GetPattern(), fitmol, match, overlay, rmat, trans);
            OEChem.OERotate(fitmol, rmat);
            OEChem.OETranslate(fitmol, trans);
            OEChem.OEWriteMolecule(ofs, fitmol);
        }
    }

    public static bool Is3DFormat(uint fmt)
    {
        if (fmt == OEFormat.SMI || fmt == OEFormat.ISM ||
            fmt == OEFormat.CAN || fmt == OEFormat.MF)
        {
            return false;
        }
        return true;
    }

    public static void Main(string[] args)
    {
        if (args.Length != 3)
        {
            OEChem.OEThrow.Usage("CliqueAlign <refmol> <fitmol> <outfile>");
        }

        oemolistream reffs = new oemolistream();
        if (!reffs.open(args[0]))
        {
            OEChem.OEThrow.Fatal("Unable to open " + args[0] + " for reading");
        }
        if (!Is3DFormat(reffs.GetFormat()))
        {
            OEChem.OEThrow.Fatal("Invalid input format: need 3D coordinates");
        }
        OEGraphMol refmol = new OEGraphMol();
        if (!OEChem.OEReadMolecule(reffs, refmol))
        {
            OEChem.OEThrow.Fatal("Unable to read molecule in " + args[0]);
        }
        if (refmol.GetDimension() != 3)
        {
            OEChem.OEThrow.Fatal(refmol.GetTitle() + " doesn't have 3D coordinates");
        }

        oemolistream fitfs = new oemolistream();
        if (!fitfs.open(args[1]))
        {
            OEChem.OEThrow.Fatal("Unable to open " + args[1] + " for reading");
        }
        if (!Is3DFormat(fitfs.GetFormat()))
        {
            OEChem.OEThrow.Fatal("Invalid input format: need 3D coordinates");
        }

        oemolostream ofs = new oemolostream();
        if (!ofs.open(args[2]))
        {
            OEChem.OEThrow.Fatal("Unable to open " + args[2] + " for writing");
        }
        if (!Is3DFormat(ofs.GetFormat()))
        {
            OEChem.OEThrow.Fatal("Invalid output format: need 3D coordinates");
        }

        OEChem.OEWriteConstMolecule(ofs, refmol);
        OEChem.OESuppressHydrogens(refmol);

        OEGraphMol fitmol = new OEGraphMol();
        while (OEChem.OEReadMolecule(fitfs, fitmol))
        {
            if (fitmol.GetDimension() != 3)
            {
                OEChem.OEThrow.Warning(fitmol.GetTitle() + " doesn't have 3D coordinates");
                continue;
            }
            CliqueAlignMols(refmol, fitmol, ofs);
        }

    }

}

See also

Align molecules by SMARTS

/****************************************************************************
* Copyright (C) 2009-2011 OpenEye Scientific Software, Inc.
*****************************************************************************
* Align two compounds based on smarts match
****************************************************************************/
using System;
using OpenEye.OEChem;

public class SMARTSAlign
{
    public static void SmartsAlign(OEMolBase refmol, OEMolBase fitmol,
                                   OESubSearch ss, oemolostream ofs)
    {
        bool unique = true;
        foreach (OEMatchBase match1 in ss.Match(refmol, unique))
        {
            foreach (OEMatchBase match2 in ss.Match(fitmol, unique))
            {
                OEMatch match = new OEMatch();
                OEMatchPairAtomIter mbi1 = match1.GetAtoms();
                OEMatchPairAtomIter mbi2 = match2.GetAtoms();
                while (mbi1.IsValid() && mbi2.IsValid())
                {
                    match.AddPair(mbi1.Target().target, mbi2.Target().target);
                    mbi1.Increment();
                    mbi2.Increment();
                }
                bool overlay = true;
                double[] rmat = new double[9];
                double[] trans = new double[3];
                OEChem.OERMSD(refmol, fitmol, match, overlay, rmat, trans);
                OEChem.OERotate(fitmol, rmat);
                OEChem.OETranslate(fitmol, trans);
                OEChem.OEWriteConstMolecule(ofs, fitmol);
            }
        }
    }

    public static void Main(string[] args)
    {
        if (args.Length != 4)
        {
            OEChem.OEThrow.Usage("SMARTSAlign <refmol> <fitmol> <outfile> <smarts>");
        }

        oemolistream reffs = new oemolistream();
        if (!reffs.open(args[0]))
        {
            OEChem.OEThrow.Fatal("Unable to open " + args[0] + " for reading");
        }
        if (!OEChem.OEIs3DFormat(reffs.GetFormat()))
        {
            OEChem.OEThrow.Fatal("Invalid input format: need 3D coordinates");
        }
        OEGraphMol refmol = new OEGraphMol();
        if (!OEChem.OEReadMolecule(reffs, refmol))
        {
            OEChem.OEThrow.Fatal("Unable to read molecule in " + args[0]);
        }
        if (refmol.GetDimension() != 3)
        {
            OEChem.OEThrow.Fatal(refmol.GetTitle() + " doesn't have 3D coordinates");
        }

        oemolistream fitfs = new oemolistream();
        if (!fitfs.open(args[1]))
        {
            OEChem.OEThrow.Fatal("Unable to open " + args[1] + " for reading");
        }
        if (!OEChem.OEIs3DFormat(fitfs.GetFormat()))
        {
            OEChem.OEThrow.Fatal("Invalid input format: need 3D coordinates");
        }

        oemolostream ofs = new oemolostream();
        if (!ofs.open(args[2]))
        {
            OEChem.OEThrow.Fatal("Unable to open " + args[2] + " for writing");
        }
        if (!OEChem.OEIs3DFormat(ofs.GetFormat()))
        {
            OEChem.OEThrow.Fatal("Invalid output format: need 3D coordinates");
        }

        OEChem.OEWriteConstMolecule(ofs, refmol);

        OESubSearch ss = new OESubSearch();
        if (!ss.Init(args[3]))
        {
            OEChem.OEThrow.Fatal("Unable to parse SMARTS: " + args[3]);
        }

	OEChem.OEPrepareSearch(refmol, ss);
        if (!ss.SingleMatch(refmol))
        {
            OEChem.OEThrow.Fatal("SMARTS fails to match refmol");
        }

        OEGraphMol fitmol = new OEGraphMol();
        while (OEChem.OEReadMolecule(fitfs, fitmol))
        {
            if (fitmol.GetDimension() != 3)
            {
                OEChem.OEThrow.Warning(fitmol.GetTitle() + " doesn't have 3D coordinates");
                continue;
            }
	    OEChem.OEPrepareSearch(fitmol, ss);
            if (!ss.SingleMatch(fitmol))
            {
                OEChem.OEThrow.Warning("SMARTS fails to match fitmol " + fitmol.GetTitle());
                continue;
            }

            SmartsAlign(refmol, fitmol, ss, ofs);
        }
    }
}

See also

Align multi-conformer molecules

/****************************************************************************
 * Copyright 2015 OpenEye Scientific Software, Inc.
 *****************************************************************************
 * Performing RMSD calculation between a 3D reference molecule and
 * multi-conformer molecules
 ****************************************************************************/
using OpenEye.OEChem;
using System;

public class RMSD
{
    private static void RMSDUtility(OEInterface itf)
    {
        if (!itf.GetBool("-verbose"))
        {
            OEChem.OEThrow.SetLevel(OEErrorLevel.Warning);
        }

        string rfname = itf.GetString("-ref");
        string ifname = itf.GetString("-in");

        bool automorph = itf.GetBool("-automorph");
        bool heavy = itf.GetBool("-heavyonly");
        bool overlay = itf.GetBool("-overlay");

        oemolistream refifs = new oemolistream();
        if (!refifs.open(rfname))
        {
            OEChem.OEThrow.Fatal("Unable to open " + rfname + " for reading");
        }

        OEGraphMol rmol = new OEGraphMol();
        if (!OEChem.OEReadMolecule(refifs, rmol))
        {
            OEChem.OEThrow.Fatal("Unable to read reference molecule");
        }
        refifs.close();

        oemolistream ifs = new oemolistream();
        if (!ifs.open(ifname))
        {
            OEChem.OEThrow.Fatal("Unable to open " + ifname + " for reading");
        }

        oemolostream ofs = null;
        if (itf.HasString("-out"))
        {
            string ofname = itf.GetString("-out");
            ofs = new oemolostream();
            if (!ofs.open(ofname))
                OEChem.OEThrow.Fatal("Unable to open " + ofname + " for writing");
            if (!overlay)
                OEChem.OEThrow.Warning("Output is the same as input when overlay is false");
        }

        foreach (OEMCMolBase mol in ifs.GetMCMolBases())
        {
            OEChem.OEThrow.Info(mol.GetTitle());

            uint maxIdx = mol.GetMaxConfIdx();
            double[] rmsds = new double[maxIdx];
            double[] rmtx = new double[9 * maxIdx];
            double[] tmtx = new double[3 * maxIdx];

            // performing RMSD for all conformers
            OEChem.OERMSD(rmol, mol, rmsds, automorph, heavy, overlay, rmtx, tmtx);

            foreach (OEConfBase conf in mol.GetConfs())
            {
                uint cidx = conf.GetIdx();
                OEChem.OEThrow.Info("Conformer " + cidx + ": rmsd = " + rmsds[cidx]);

                if (overlay)
                {
                    OEChem.OERotate(conf, RMSD.slice(rmtx, cidx * 9, cidx * 9 + 9));
                    OEChem.OETranslate(conf, RMSD.slice(tmtx, cidx * 3, cidx * 3 + 3));
                }
            }

            if (ofs != null)
            {
                OEChem.OEWriteMolecule(ofs, mol);
            }
        }

        if (ofs != null)
        {
            ofs.close();
        }
    }

    private static double[] slice(double[] src, uint begin, uint end)
    {
        double[] ret = new double[end - begin];
        uint cnt = 0;
        for (uint i = begin; i != end; i++, cnt++)
        {
            ret[cnt] = src[i];
        }
        return ret;
    }

    public static void Main(String[] args)
    {
        OEInterface itf = new OEInterface();
        OEChem.OEConfigure(itf, InterfaceData);
        if (OEChem.OEParseCommandLine(itf, args, "RMSD"))
            RMSDUtility(itf);
    }

    private static String InterfaceData = @"
!BRIEF [options] [-ref <mol file>] [-in <mol file>] [-out <mol file>]

!CATEGORY ""input/output options""

  !PARAMETER -ref
    !TYPE string
    !REQUIRED true
    !BRIEF input reference mol file name
    !KEYLESS 1
  !END

  !PARAMETER -in
    !ALIAS -i
    !TYPE string
    !REQUIRED true
    !BRIEF input mol file name
    !KEYLESS 2
  !END

  !PARAMETER -out
    !ALIAS -o
    !TYPE string
    !REQUIRED false
    !BRIEF output file name, this implies that -overlay should be true
    !KEYLESS 3
  !END

!END

!CATEGORY ""options""

  !PARAMETER -automorph
    !TYPE bool
    !DEFAULT true
    !BRIEF assign best atom association
    !DETAIL
        If false, atoms are associated by order.
        If true, graph isomorphism is determined with symmetry perception.
  !END

  !PARAMETER -overlay
    !TYPE bool
    !DEFAULT true
    !BRIEF Minimize to the smallest RMSD
  !END

  !PARAMETER -heavyonly
    !TYPE bool
    !DEFAULT true
    !BRIEF Ignore hydrogens for RMSD calculation
  !END

  !PARAMETER -verbose
    !ALIAS -v
    !TYPE bool
    !DEFAULT false
    !BRIEF verbose
  !END

!END
";
}

See also

Modifying SD tags

/****************************************************************************
* Copyright (C) 2011 OpenEye Scientific Software, Inc.
*****************************************************************************
* Modifies the SD data of a set of input molecules by clearing all tags,
* defining which tags to keep or defining which tags to remove
****************************************************************************/
using System;
using System.Collections.Generic;
using OpenEye.OEChem;

public class SDFModProps
{
    public static void ClearProps(oemolistream ifs,
                                  oemolostream ofs)
    {
        OEGraphMol mol = new OEGraphMol();
        while (OEChem.OEReadMolecule(ifs, mol))
        {
            OEChem.OEClearSDData(mol);
            OEChem.OEWriteMolecule(ofs, mol);
        }
    }

    public static void KeepProps(HashSet<string> props,
                                 oemolistream ifs,
                                 oemolostream ofs)
    {
        OEGraphMol mol = new OEGraphMol();
        while (OEChem.OEReadMolecule(ifs, mol))
        {
            foreach (OESDDataPair dp in OEChem.OEGetSDDataPairs(mol))
            {
                if (!props.Contains(dp.GetTag()))
                {
                    OEChem.OEDeleteSDData(mol, dp.GetTag());
                }
            }
            OEChem.OEWriteMolecule(ofs, mol);
        }
    }

    public static void RemoveProps(HashSet<string> props,
                                   oemolistream ifs,
                                   oemolostream ofs)
    {
        OEGraphMol mol = new OEGraphMol();
        while (OEChem.OEReadMolecule(ifs, mol))
        {
            foreach (string prop in props)
            {
                OEChem.OEDeleteSDData(mol, prop);
            }
            OEChem.OEWriteMolecule(ofs, mol);
        }
    }

    private static HashSet<string> FillSet(OEStringIter proplist)
    {
        HashSet<string> props = new HashSet<string>();
        foreach (string prop in proplist)
        {
            props.Add(prop);
        }
        return props;
    }

    public static void ModProps(OEInterface itf,
                                oemolistream ifs,
                                oemolostream ofs)
    {
        if (itf.HasString("-keep"))
        {
            OEStringIter proplist = itf.GetStringList("-keep");
            HashSet<string> props = FillSet(proplist);
            KeepProps(props, ifs, ofs);
        }
        else if (itf.HasString("-remove"))
        {
            OEStringIter proplist = itf.GetStringList("-remove");
            HashSet<string> props = FillSet(proplist);
            RemoveProps(props, ifs, ofs);
        }
        else if (itf.GetBool("-clearAll"))
        {
            ClearProps(ifs, ofs);
        }
    }

    public static void Main(string[] args)
    {
        OEInterface itf = new OEInterface(interfaceData, "SDFModProps", args);

        int numoption = 0;
        if (itf.HasString("-keep"))
        {
            numoption++;
        }
        if (itf.HasString("-remove"))
        {
            numoption++;
        }
        if (itf.GetBool("-clearAll"))
        {
            numoption++;
        }
        if (numoption != 1)
        {
            OEChem.OEThrow.Usage("Need to pick one from -keep, -remove, or -clearAll");
        }

        oemolistream ifs = new oemolistream();
        if (!ifs.open(itf.GetString("-i")))
        {
            OEChem.OEThrow.Fatal("Unable to open " + itf.GetString("-i") + " for reading");
        }
        if (!OEChem.OEIsSDDataFormat(ifs.GetFormat()))
        {
            OEChem.OEThrow.Fatal("Only works for input file formats that support SD data (sdf,oeb,csv)");
        }

        oemolostream ofs = new oemolostream();
        if (!ofs.open(itf.GetString("-o")))
        {
            OEChem.OEThrow.Fatal("Unable to open " + itf.GetString("-o") + " for writing");
        }
        if (!OEChem.OEIsSDDataFormat(ofs.GetFormat()))
        {
            OEChem.OEThrow.Fatal("Only works for output file formats that support SD data (sdf,oeb,csv)");
        }

        ModProps(itf, ifs, ofs);
    }

    private static string interfaceData=@"
!BRIEF [-remove] <prop1 prop2...> [-keep] <prop1 prop2...> [-clearAll] -i <input> -o <output>
!PARAMETER -i
  !ALIAS -in
  !TYPE string
  !REQUIRED true
  !BRIEF Input file name
!END
!PARAMETER -o
  !ALIAS -out
  !TYPE string
  !REQUIRED true
  !BRIEF Output file name
!END
!PARAMETER -keep
  !ALIAS -k
  !TYPE string
  !LIST true
  !BRIEF SD tags to be kept
!END
!PARAMETER -remove
  !ALIAS -r
  !TYPE string
  !LIST true
  !BRIEF SD tags to be removed
!END
!PARAMETER -clearAll
  !ALIAS -c
  !TYPE bool
  !DEFAULT false
  !BRIEF Removes all SD tags
!END
";
}

See also

Exporting SD data to a csv file

/****************************************************************************
* Copyright (C) 2011 OpenEye Scientific Software, Inc.
*****************************************************************************
* Extract properties from SD file and save as CSV
****************************************************************************/
using System;
using System.Collections.Generic;
using System.IO;
using OpenEye.OEChem;

public class SDF2CSV
{
    public static void SDFtoCSV(oemolistream ifs, StreamWriter csv)
    {
        List<string> tagList = new List<string>();
        OEGraphMol mol = new OEGraphMol();
        // read through once to find all unique tags
        while (OEChem.OEReadMolecule(ifs, mol))
        {
            foreach (OESDDataPair dp in OEChem.OEGetSDDataPairs(mol))
            {
                if (!tagList.Contains(dp.GetTag()))
                {
                    tagList.Add(dp.GetTag());
                }
            }
        }

        // output the header row
        csv.Write("Title");
        foreach (string tag in tagList)
        {
            csv.Write(",{0}", tag);
        }
        csv.WriteLine();

        // read through again filling rows for each molecule
        ifs.rewind();
        while (OEChem.OEReadMolecule(ifs, mol))
        {
            csv.Write("{0}", mol.GetTitle());
            foreach (string tag in tagList)
            {
                csv.Write(",{0}", OEChem.OEGetSDData(mol, tag));
            }
            csv.WriteLine();
        }
    }

    public static void Main(string[] args)
    {
        if (args.Length != 2)
        {
            OEChem.OEThrow.Usage("SDF2CSV <infile> <csvfile>");
        }

        oemolistream ifs = new oemolistream();
        if (!ifs.open(args[0]))
        {
            OEChem.OEThrow.Fatal("Unable to open " + args[0] + " for reading");
        }
        uint fmt = ifs.GetFormat();
        if (fmt != OEFormat.SDF && fmt != OEFormat.OEB)
        {
            OEChem.OEThrow.Fatal("Only works for sdf or oeb input files");
        }

        StreamWriter csv = null;
        try
        {
            csv = new StreamWriter(args[1]);
            SDFtoCSV(ifs, csv);
            csv.Close();
        }
        catch
        {
            OEChem.OEThrow.Fatal("Unable to open " + args[1] + " for writing");
        }
    }
}

See also

Adding csv data as SD tags

/****************************************************************************
* Copyright (C) 2011 OpenEye Scientific Software, Inc.
*****************************************************************************
* Merge a CSV file of data/properties, key on compound name in first column
* and use column titles as keys.  All data is read/written as strings
****************************************************************************/
using System;
using System.IO;
using System.Collections.Generic;
using System.Collections;
using OpenEye.OEChem;

public class CSV2SDF
{
    public static void CSVtoSDF(StreamReader csv,
                                oemolistream ifs,
                                oemolostream ofs)
    {
        string line = csv.ReadLine();

        ArrayList propnameslist = new ArrayList(line.Split(new char[] { ',' }));
        propnameslist.RemoveAt(0);

        Dictionary<string, ArrayList> values = new Dictionary<string, ArrayList>();
        while ( (line = csv.ReadLine()) != null )
        {
            ArrayList tokenlist = new ArrayList(line.Split(new char[] { ',' }));
            if (tokenlist.Count > 1)
            {
                string title = (string)tokenlist[0];
                if (string.IsNullOrEmpty(title))
                {
                    OEChem.OEThrow.Warning("Skipping entry with no title");
                    continue;
                }
                tokenlist.RemoveAt(0);
                values.Add(title, tokenlist);
            }
        }

        OEGraphMol mol = new OEGraphMol();
        while (OEChem.OEReadMolecule(ifs, mol))
        {
            if (values.ContainsKey(mol.GetTitle()))
            {
                ArrayList vallist = new ArrayList();
                values.TryGetValue(mol.GetTitle(), out vallist);
                for (int p = 0; p < vallist.Count && p < propnameslist.Count; ++p)
                {
                    string sdval = (string)vallist[p];
                    if (string.IsNullOrEmpty(sdval))
                    {
                        continue;
                    }
                    else
                    {
                        OEChem.OESetSDData(mol, (string)propnameslist[p], sdval);
                    }
                }
            }
            OEChem.OEWriteMolecule(ofs, mol);
        }
    }

    public static void Main(string[] args)
    {
        if (args.Length != 3)
        {
            OEChem.OEThrow.Usage("CSV2SDF <csvfile> <infile> <outsdfile>");
        }

        StreamReader csv = null;
        try
        {
            csv = new System.IO.StreamReader(args[0]);
        }
        catch
        {
            OEChem.OEThrow.Fatal("Unable to open " + args[0] + " for reading");
        }
        oemolistream ifs = new oemolistream();
        if (!ifs.open(args[1]))
        {
            OEChem.OEThrow.Fatal("Unable to open " + args[1] + " for reading");
        }

        oemolostream ofs = new oemolostream();
        if (!ofs.open(args[2]))
        {
            OEChem.OEThrow.Fatal("Unable to open " + args[2] + " for writing");
        }
        uint fmt = ofs.GetFormat();
        if (fmt != OEFormat.SDF && fmt != OEFormat.OEB)
        {
            OEChem.OEThrow.Fatal("Only works for sdf or oeb output files");
        }

        CSVtoSDF(csv, ifs, ofs);
    }
}

See also

Renaming molecules by SD field

/****************************************************************************
* Copyright (C) 2011 OpenEye Scientific Software, Inc.
*****************************************************************************
* Rename SDF molecules by specified field
****************************************************************************/
using System;
using OpenEye.OEChem;

public class SDFRename
{
    public static void ProcessFile(string field, oemolistream ifs, oemolostream ofs)
    {
        OEGraphMol mol = new OEGraphMol();
        while (OEChem.OEReadMolecule(ifs, mol))
        {
            if (OEChem.OEHasSDData(mol, field))
            {
                mol.SetTitle(OEChem.OEGetSDData(mol, field));
            }
            else
            {
                OEChem.OEThrow.Warning("Renaming of molecule " + mol.GetTitle() + " failed; no field " + field);
            }

            OEChem.OEWriteMolecule(ofs, mol);
        }
    }

    public static void Main(string[] args)
    {
        if (args.Length != 3)
        {
            OEChem.OEThrow.Usage("SDFRename <fieldname> <infile> <outfile>");
        }

        oemolistream ifs = new oemolistream();
        if (!ifs.open(args[1]))
        {
            OEChem.OEThrow.Fatal("Unable to open " + args[1] + " for reading");
        }

        if (!OEChem.OEIsSDDataFormat(ifs.GetFormat()))
        {
            OEChem.OEThrow.Fatal("Only works for input file formats that support SD data (sdf,oeb,csv)");
        }

        oemolostream ofs = new oemolostream();
        if (!ofs.open(args[2]))
        {
            OEChem.OEThrow.Fatal("Unable to open " + args[2] + " for writing");
        }

        ProcessFile(args[0], ifs, ofs);
    }
}

See also

Filter molecules by SD data

/****************************************************************************
* Copyright (C) 2011 OpenEye Scientific Software, Inc.
*****************************************************************************
* Filter molecules by SD data
****************************************************************************/
using System;
using OpenEye.OEChem;

public class SDFilter
{
    public static void Main(string[] args)
    {
        OEInterface itf = new OEInterface(interfaceData, "SDFilter", args);
        if (!(itf.HasDouble("-min") || itf.HasDouble("-max")))
        {
            OEChem.OEThrow.Fatal("Please set a filter value with -min or -max");
        }

        oemolistream ifs = new oemolistream();
        if (!ifs.open(itf.GetString("-i")))
        {
            OEChem.OEThrow.Fatal("Unable to open " + itf.GetString("-i") + " for reading");
        }
        if (!OEChem.OEIsSDDataFormat(ifs.GetFormat()))
        {
            OEChem.OEThrow.Fatal("Only works for input file formats that support SD data (sdf,oeb,csv)");
        }

        oemolostream ofs = new oemolostream();
        if (!ofs.open(itf.GetString("-o")))
        {
            OEChem.OEThrow.Fatal("Unable to open " + itf.GetString("-o") + " for writing");
        }
        if (!OEChem.OEIsSDDataFormat(ofs.GetFormat()))
        {
            OEChem.OEThrow.Fatal("Only works for output file formats that support SD data (sdf,oeb,csv)");
        }

        String tag = itf.GetString("-tag");

        double minval = double.MinValue;
        if (itf.HasDouble("-min"))
        {
            minval = itf.GetDouble("-min");
        }

        double maxval = double.MaxValue;
        if (itf.HasDouble("-max"))
        {
            maxval = itf.GetDouble("-max");
        }

        OEGraphMol mol = new OEGraphMol();
        while (OEChem.OEReadMolecule(ifs, mol))
        {
            if (!OEChem.OEHasSDData(mol, tag))
            {
                OEChem.OEThrow.Warning("Unable to find " + tag + " on " + mol.GetTitle());
                continue;
            }
            double tagvalue;
            string value = OEChem.OEGetSDData(mol, tag);
            if (!double.TryParse(value.Trim(), out tagvalue))
            {
                OEChem.OEThrow.Warning("Failed to convert (" + value + ") to a number in " + mol.GetTitle());
                continue;
            }
            if (tagvalue < minval)
            {
                continue;
            }
            if (tagvalue > maxval)
            {
                continue;
            }

            OEChem.OEWriteMolecule(ofs, mol);
        }
    }

    private static string interfaceData=@"
!BRIEF -i <input> -o <output> -tag <name> [-min <num>] [-max <num>]
!PARAMETER -i
  !TYPE string
  !REQUIRED true
  !BRIEF Input file name
  !KEYLESS 1
!END
!PARAMETER -o
  !TYPE string
  !REQUIRED true
  !BRIEF Output file name
  !KEYLESS 2
!END
!PARAMETER -tag
  !TYPE string
  !REQUIRED true
  !BRIEF SD tag
!END
!PARAMETER -min
  !TYPE double
  !REQUIRED false
  !BRIEF minimum value of SD tag
!END
!PARAMETER -max
  !TYPE double
  !REQUIRED false
  !BRIEF maximum value of SD tag
!END
";
}

See also

Counting molecules

/****************************************************************************
* Copyright (C) 2011 OpenEye Scientific Software, Inc.
*****************************************************************************
* Counts molecule (and conformers) in input files
****************************************************************************/
using System;
using OpenEye.OEChem;

public class MolCount
{
    public static void Main(string[] args)
    {
        OEInterface itf = new OEInterface(interfaceData, "MolCount", args);

        bool confs = itf.GetBool("-conf");

        long total = 0;
        long totconfs = 0;
        long nfiles = 0;

        foreach (string filename in itf.GetStringList("-i"))
        {
            oemolistream ifs = new oemolistream();
            if (!ifs.open(filename))
            {
                OEChem.OEThrow.Warning("Unable to open " + filename + " for reading");
                continue;
            }
            else
            {
                nfiles++;
                long count = 0;
                long nconfs = 0;

                OEMol mol = new OEMol();
                while (OEChem.OEReadMolecule(ifs, mol))
                {
                    count++;
                    if (confs)
                    {
                        nconfs += mol.NumConfs();
                    }
                }
                Console.WriteLine(filename + " contains " + count + " molecule(s).");
                if (confs)
                {
                    Console.WriteLine("Total # of conformers:   " + nconfs);
                    Console.WriteLine("Average # of conformers: " + (float)nconfs / (float)count);
                    Console.WriteLine("-----------------------------------------------------------");
                }
                total += count;
                totconfs += nconfs;
            }
        }
        Console.WriteLine("===========================================================");
        Console.WriteLine("Total " + total + " molecules");
        if (confs && (nfiles > 0) )
        {
            Console.WriteLine("Total # of conformers:   " + totconfs);
            Console.WriteLine("Average # of conformers: " + (float)totconfs / (float)total);
        }
    }

    private static string interfaceData=@"
!BRIEF [-conf] [-i] <infile1> [<infile2>...]
!PARAMETER -i
  !ALIAS -in
  !TYPE string
  !LIST true
  !REQUIRED true
  !BRIEF Input file name(s)
  !KEYLESS 1
!END
!PARAMETER -conf
  !ALIAS -c
  !TYPE bool
  !DEFAULT false
  !BRIEF Count conformers
!END
";
}

Get molecule titles

/****************************************************************************
* Copyright (C) 2011 OpenEye Scientific Software, Inc.
*****************************************************************************
* Output all molecule titles
****************************************************************************/
using System;
using System.IO;
using OpenEye.OEChem;

public class GetTitles
{
    public static void Main(string[] args)
    {
        if (args.Length < 1 || args.Length >2)
        {
            OEChem.OEThrow.Usage("GetTitles <infile> [<outfile>]");
        }

        oemolistream ifs = new oemolistream();
        if (!ifs.open(args[0]))
        {
            OEChem.OEThrow.Fatal("Unable to open " + args[0] + " for reading");
        }

        StreamWriter sw = null;
        if (args.Length > 1)
        {
            try
            {
                sw = new StreamWriter(args[1]);
                Console.SetOut(sw);
            }
            catch
            {
                OEChem.OEThrow.Fatal("Unable to open " + args[1] + " for writing");
            }
        }

        OEMol mol = new OEMol();
        while (OEChem.OEReadMolecule(ifs, mol))
        {
            string title = mol.GetTitle();
            if (string.IsNullOrEmpty(title))
            {
                title = "untitled";
            }
            Console.WriteLine(title);
        }
        if (args.Length > 1)
        {
            sw.Close();
        }
    }
}

See also

Find minimum path in a molecule

/****************************************************************************
* Copyright (C) 2011, 2014 OpenEye Scientific Software, Inc.
*****************************************************************************
* Find the minimum path length between 2 smarts patterns
* or the path length between 2 named atoms
****************************************************************************/
using System;
using System.Collections.Generic;
using OpenEye.OEChem;

public class MinPath
{
    public class Pair<T, U>
    {
        public Pair()
        {
        }

        public Pair(T first, U second)
        {
            this.First = first;
            this.Second = second;
        }

        public T First
        {
            get;
            set;
        }
        public U Second
        {
            get;
            set;
        }
    }

    public static void AtomPathLength(oemolistream ifs, oemolostream ofs,
                                      OEInterface itf,
                                      String atm1, String atm2)
    {
        OEGraphMol mol = new OEGraphMol();
        while (OEChem.OEReadMolecule(ifs, mol))
        {
            OEChem.OETriposAtomNames(mol);
            OEAtomBase a1 = null;
            OEAtomBase a2 = null;
            foreach (OEAtomBase atm in mol.GetAtoms())
            {
                if (atm1.Equals(atm.GetName()))
                {
                    a1 = atm;
                }
                if (atm2.Equals(atm.GetName()))
                {
                    a2 = atm;
                }
                if ((object)a1 != null && (object)a2 != null)
                {
                    break;
                }
            }

            if ((object)a1 == null || (object)a2 == null)
            {
                OEChem.OEThrow.Warning("Failed to find atoms " + atm1 + " and " + atm2 + " in molecule");
                continue;
            }

            uint pathlen = OEChem.OEGetPathLength(a1, a2);
            if (itf.GetBool("-verbose") || !itf.HasString("-o"))
            {
                String smiles = OEChem.OECreateIsoSmiString(mol);
                Console.WriteLine("Path length: " + pathlen + " in " + smiles);
            }

            OEAtomBaseIter spath = OEChem.OEShortestPath(a1, a2);
            OEGraphMol spathmol = new OEGraphMol();
            bool adjustHCount = true;
            OEChem.OESubsetMol(spathmol, mol, new OEIsAtomMember(spath), adjustHCount);
            String spathsmiles = OEChem.OECreateIsoSmiString(spathmol);

            if (itf.HasString("-o"))
            {
                OEChem.OEWriteMolecule(ofs, spathmol);
            }
            else if (itf.GetBool("-verbose"))
            {
                Console.WriteLine(spathsmiles);
            }
        }
    }

    public static void SmartsPathLength(oemolistream ifs, oemolostream ofs,
                                        OEInterface itf,
                                        OESubSearch ss1, OESubSearch ss2)
    {
        OEGraphMol mol = new OEGraphMol();
        while (OEChem.OEReadMolecule(ifs, mol))
        {
            OEChem.OEPrepareSearch(mol, ss1);
            OEChem.OEPrepareSearch(mol, ss2);
            if (!(ss1.SingleMatch(mol) && ss2.SingleMatch(mol)))
            {
                OEChem.OEThrow.Warning("Unable to find SMARTS matches in "
                                       + mol.GetTitle() + ", skipping");
                continue;
            }

            List<Pair<OEAtomBase, OEAtomBase> > allatompairs = new List<Pair<OEAtomBase, OEAtomBase> >();
            bool unique = true;
            int allminlen = int.MaxValue;
            foreach (OEMatchBase match1 in ss1.Match(mol, unique))
            {
                foreach (OEMatchBase match2 in ss2.Match(mol, unique))
                {
                    List<Pair<OEAtomBase, OEAtomBase> > atompairs = new List<Pair<OEAtomBase, OEAtomBase> >();
                    int minlen = int.MaxValue;
                    foreach (OEMatchPairAtom mp1 in match1.GetAtoms())
                    {
                        foreach (OEMatchPairAtom mp2 in match2.GetAtoms())
                        {
                            uint pathlen = OEChem.OEGetPathLength(mp1.target, mp2.target);
                            if (minlen > pathlen)
                            {
                                minlen = (int)pathlen;
                                atompairs.Clear();
                                atompairs.Add(new Pair<OEAtomBase, OEAtomBase>(mp1.target, mp2.target));
                            }
                            else if (minlen == pathlen)
                            {
                                atompairs.Add(new Pair<OEAtomBase, OEAtomBase>(mp1.target, mp2.target));
                            }
                        }
                    }
                    if (minlen < allminlen)
                    {
                        allminlen = minlen;
                        allatompairs = atompairs;
                    }
                    else if (minlen == allminlen)
                    {
                        allatompairs.AddRange(atompairs);
                    }
                }
            }

            if (itf.GetBool("-verbose") || !itf.HasString("-o"))
            {
                Console.WriteLine("Shortest path length: " + allminlen + " in " + OEChem.OECreateIsoSmiString(mol));
            }

            HashSet<String> spathlist = new HashSet<String>();
            foreach (Pair<OEAtomBase, OEAtomBase> pair in allatompairs)
            {
                OEAtomBaseIter spath = OEChem.OEShortestPath((OEAtomBase)pair.First, (OEAtomBase)pair.Second);
                OEGraphMol spathmol = new OEGraphMol();
                OEChem.OESubsetMol(spathmol, mol, new OEIsAtomMember(spath));
                String spathsmiles = OEChem.OECreateIsoSmiString(spathmol);
                if (!spathlist.Add(spathsmiles))
                {
                    continue;
                }
                if (itf.HasString("-o"))
                {
                    OEChem.OEWriteMolecule(ofs, spathmol);
                }
                else if (itf.GetBool("-verbose"))
                {
                    Console.WriteLine(spathsmiles);
                }
            }
        }
    }

    public static void Main(String[] args)
    {
        OEInterface itf = new OEInterface(interfaceData, "MinPath", args);

        if (!((itf.HasString("-smarts1") && itf.HasString("-smarts2"))
                ^ (itf.HasString("-atom1") && itf.HasString("-atom2"))))
        {
            OEChem.OEThrow.Fatal("-smarts1 and -smarts2 or -atom1 and -atom2 must be set");
        }

        oemolistream ifs = new oemolistream();
        if (!ifs.open(itf.GetString("-i")))
        {
            OEChem.OEThrow.Fatal("Unable to open " + itf.GetString("-i") + " for reading");
        }

        oemolostream ofs = new oemolostream();
        if (itf.HasString("-o"))
        {
            if (!ofs.open(itf.GetString("-o")))
            {
                OEChem.OEThrow.Fatal("Unable to open " + itf.GetString("-o") + " for writing");
            }
        }

        if (itf.HasString("-smarts1") && itf.HasString("-smarts2"))
        {
            OESubSearch ss1 = new OESubSearch();
            String smarts1 = itf.GetString("-smarts1");
            if (!ss1.Init(smarts1))
            {
                OEChem.OEThrow.Fatal("Unable to parse SMARTS1: " + smarts1);
            }

            OESubSearch ss2 = new OESubSearch();
            String smarts2 = itf.GetString("-smarts2");
            if (!ss2.Init(smarts2))
            {
                OEChem.OEThrow.Fatal("Unable to parse SMARTS2: " + smarts2);
            }

            SmartsPathLength(ifs, ofs, itf, ss1, ss2);
            ofs.close();
        }
        else
        {
            String atom1 = itf.GetString("-atom1");
            String atom2 = itf.GetString("-atom2");
            AtomPathLength(ifs, ofs, itf, atom1, atom2);
        }
    }
    private static string interfaceData=@"
!BRIEF -i <input> [-o <output>] -smarts1 <smarts> -smarts2 <smarts> | -atom1 <name> -atom2 <name>
!PARAMETER -i
  !TYPE string
  !REQUIRED true
  !BRIEF Input file name
  !KEYLESS 1
!END
!PARAMETER -o
  !TYPE string
  !REQUIRED false
  !BRIEF Output file name
  !KEYLESS 2
!END
!PARAMETER -smarts1
  !TYPE string
  !BRIEF Smarts pattern to identify 1st atom
!END
!PARAMETER -smarts2
  !TYPE string
  !BRIEF Smarts pattern to identify 2nd atom
!END
!PARAMETER -atom1
  !TYPE string
  !BRIEF Name of 1st atom
!END
!PARAMETER -atom2
  !TYPE string
  !BRIEF Name of 2nd atom
!END
!PARAMETER -verbose
  !TYPE bool
  !REQUIRED false
  !DEFAULT false
  !BRIEF Print verbose output
!END
";
}

See also

Extract ring templates

/****************************************************************************
* Copyright (C) 2014 OpenEye Scientific Software, Inc.
*****************************************************************************
* Extract ring templates for 2D coordinate generation
****************************************************************************/
using System;
using OpenEye.OEChem;

public class ExtractRingTemplates
{
    public static void Main(string[] args)
    {
        OEInterface itf = new OEInterface(interfaceData, "ExtractRingTemplates", args);

        String ifname = itf.GetString("-in");
        String ofname = itf.GetString("-out");

        oemolistream ifs = new oemolistream();
        if (!ifs.open(ifname))
            OEChem.OEThrow.Fatal("Unable to open " + ifname + " for reading");

        if (!OEChem.OEIs2DFormat(ifs.GetFormat()))
            OEChem.OEThrow.Fatal("Invalid input format: need 2D coordinates");

        oemolostream ofs = new oemolostream();
        if (!ofs.open(ofname))
            OEChem.OEThrow.Fatal("Unable to open " + ofname + " for writing");

        if (!OEChem.OEIs2DFormat(ofs.GetFormat()))
            OEChem.OEThrow.Fatal("Invalid output format: unable to write 2D coordinates");

        uint nrrings = 0;
        OEGraphMol mol = new OEGraphMol();
        while (OEChem.OEReadMolecule(ifs, mol)) 
        {
             foreach (OEMolBase ring in OEChem.OEExtractRingTemplates(mol))
             {
                  nrrings += 1; 
                  OEChem.OEWriteMolecule(ofs, ring);
             }
        }  
        OEChem.OEThrow.Info(nrrings + " number of ring templates extracted");
    }

    private static string interfaceData=@"
!BRIEF [-i] <input> [-o] <output>
!PARAMETER -i
  !ALIAS -in
  !TYPE string
  !REQUIRED true
  !BRIEF input file name
  !KEYLESS 1
!END
!PARAMETER -o
  !ALIAS -out
  !TYPE string
  !REQUIRED true
  !BRIEF output file name
  !KEYLESS 2
!END
";
}

Create 2D ring dictionary

/****************************************************************************
 * Copyright 2015 OpenEye Scientific Software, Inc.
 *****************************************************************************
 * Creates a new 2D ring dictionary
 ****************************************************************************/
using System;
using OpenEye.OEChem;

public class CreateRingDict
{
    public static int Main(string[] args)
    {
        OEInterface itf = new OEInterface(interfaceData, "CreateRingDict", args);

        string ifname = itf.GetString("-in");
        string ofname = itf.GetString("-ringdict");

        oemolistream ifs = new oemolistream();
        if (!ifs.open(ifname))
        {
            OEChem.OEThrow.Fatal("Cannot open input file for reading!");
        }

        if (!OEChem.OEIs2DFormat(ifs.GetFormat()))
        {
            OEChem.OEThrow.Fatal("Invalid input file format for 2D coordinates!");
        }

        oemolostream ofs = new oemolostream();
        if (!ofs.open(ofname))
        {
            OEChem.OEThrow.Fatal("Unable to open output file for writing!");
        }

        if (ofs.GetFormat() != OEFormat.OEB)
        {
            OEChem.OEThrow.Fatal("Output file has to have OEB format!");
        }

        OE2DRingDictionary ringdict = new OE2DRingDictionary();

        OEDots dots = new OEDots(10000, 100, "molecules");

        OEGraphMol mol = new OEGraphMol();
        while (OEChem.OEReadMolecule(ifs, mol)) 
        {
            dots.Update();
            ringdict.AddRings(mol);
        }

        dots.Total();

        uint nrrings = ringdict.NumRings();
        OEChem.OEThrow.Info(nrrings.ToString() + " number of ring templates have been extracted!");

        OEChem.OEWrite2DRingDictionary(ofname, ringdict);

        return 0;
    }
private static string interfaceData = @"
!BRIEF [-in] <input> [-ringdict] <output ringdict>

!CATEGORY ""input/output options :""

  !PARAMETER -in
    !ALIAS -i
    !TYPE string
    !REQUIRED true
    !KEYLESS 1
    !VISIBILITY simple
    !BRIEF Input 2D molecule filename
  !END

  !PARAMETER -ringdict
    !ALIAS -rd
    !TYPE string
    !REQUIRED true
    !KEYLESS 2
    !VISIBILITY simple
    !BRIEF Output ring dictionary OEB filename
  !END

!END
";
}

Append to 2D ring dictionary

/****************************************************************************
 * Copyright 2015, 2016 OpenEye Scientific Software, Inc.
 *****************************************************************************
 * Appends rings to an existing 2D rings dictionary
 ****************************************************************************/
using System;
using OpenEye.OEChem;

public class AppendRingDict
{
    public static int Main(string[] args)
    {
        OEInterface itf = new OEInterface(interfaceData, "AppendRingDict", args);

        string ifname = itf.GetString("-in");
        string irdfname = itf.GetString("-inringdict");
        string ordfname = itf.GetString("-outringdict");

        oemolistream ifs = new oemolistream();
        if (!ifs.open(ifname))
        {
            OEChem.OEThrow.Fatal("Cannot open input file for reading!");
        }

        if (!OEChem.OEIs2DFormat(ifs.GetFormat()))
        {
            OEChem.OEThrow.Fatal("Invalid input file format for 2D coordinates!");
        }

        if (!OEChem.OEIsValid2DRingDictionary(irdfname))
        {
            OEChem.OEThrow.Fatal("Invalid ring dictionary file!");
        }

        OE2DRingDictionary ringdict = new OE2DRingDictionary(irdfname);

        uint nrrings = ringdict.NumRings();

        OEDots dots = new OEDots(10000, 100, "molecules");

        OEGraphMol mol = new OEGraphMol();
        while (OEChem.OEReadMolecule(ifs, mol)) 
        {
            dots.Update();
            ringdict.AddRings(mol);
        }

        dots.Total();

        uint nrnewrings = ringdict.NumRings() - nrrings;
        OEChem.OEThrow.Info(nrnewrings.ToString() + " new ring templates have been added!");

        OEChem.OEWrite2DRingDictionary(ordfname, ringdict);

        return 0;
    }
    private static string interfaceData = @"
!BRIEF [-in] <input> [-inringdict] <input ringdict> [-outringdict] <output ringdict>

!CATEGORY ""input/output options :""

  !PARAMETER -in
    !ALIAS -i
    !TYPE string
    !REQUIRED true
    !KEYLESS 1
    !VISIBILITY simple
    !BRIEF Input 2D molecule filename
  !END

  !PARAMETER -inringdict
    !ALIAS -ird
    !TYPE string
    !REQUIRED true
    !KEYLESS 2
    !VISIBILITY simple
    !BRIEF Input ring dictionary OEB filename
    !DETAIL
        2D ring dictionaries can be generated by the following OEChem examples:
        C++    - createringdict.cpp
        Python - createringdict.py
        Java   - CreateRingDict.java
        C#     - CreateRingDict.cs
  !END

  !PARAMETER -outringdict
    !ALIAS -ord
    !TYPE string
    !REQUIRED true
    !KEYLESS 3
    !VISIBILITY simple
    !BRIEF Output ring dictionary OEB filename
  !END

!END
";    
}

Generate 2D coordinates with user-defined ring templates

/****************************************************************************
 * Copyright 2015 OpenEye Scientific Software, Inc.
 *****************************************************************************
 * Generates 2D coordinates using user-defined ring templates
 ****************************************************************************/
using System;
using OpenEye.OEChem;

public class Generate2D
{
    public static int Main(string[] args)
    {
        OEInterface itf = new OEInterface(interfaceData, "Generate2D", args);

        string ifname = itf.GetString("-in");
        string ofname = itf.GetString("-out");

        oemolistream ifs = new oemolistream();
        if (!ifs.open(ifname))
        {
            OEChem.OEThrow.Fatal("Cannot open input file for reading!");
        }

        oemolostream ofs = new oemolostream();
        if (!ofs.open(ofname))
        {
            OEChem.OEThrow.Fatal("Cannot open output file for writing!");
        }

        if (!OEChem.OEIs2DFormat(ofs.GetFormat()))
        {
            OEChem.OEThrow.Fatal("Invalid output file format for 2D coordinates!");
        }

        if (itf.HasString("-ringdict"))
        {
            string rdfname = itf.GetString("-ringdict");

            if (!OEChem.OEIsValid2DRingDictionary(rdfname))
            {
                OEChem.OEThrow.Warning("Invalid 2D ring dictionary file!");
            }
            else
            {
                OEChem.OEInit2DRingDictionary(rdfname);
            }
        }

        OEGraphMol mol = new OEGraphMol();
        while (OEChem.OEReadMolecule(ifs, mol))
        {
            OEChem.OEGenerate2DCoordinates(mol);
            OEChem.OEWriteMolecule(ofs, mol);
        }

        return 0;
    }
    private static string interfaceData = @"
!BRIEF [-in] <input> [-out] <output> [-ringdict] <ringdict file>

!CATEGORY ""input/output options :""

  !PARAMETER -in
    !ALIAS -i
    !TYPE string
    !REQUIRED true
    !KEYLESS 1
    !VISIBILITY simple
    !BRIEF Input filename
  !END

  !PARAMETER -out
    !ALIAS -o
    !TYPE string
    !REQUIRED true
    !KEYLESS 2
    !VISIBILITY simple
    !BRIEF Output filename
  !END

  !PARAMETER -ringdict
    !ALIAS -rd
    !TYPE string
    !REQUIRED false
    !VISIBILITY simple
    !BRIEF Ring dictionary file
    !DETAIL
        2D ring dictionaries can be generated by the following OEChem examples:
        C++    - createringdict.cpp
        Python - createringdict.py
        Java   - CreateRingDict.java
        C#     - CreateRingDict.cs
  !END

!END
";   
}