GGA Sofware Services

Page Contents

API

Overview

This page describes the API of Indigo library and its rendering plugin. The API allows developers to integrate Indigo into their C/Java/C#/Python projects. Please note that Indigo is under active development, and you can always post your comments and suggestions to our team.

System

Indigo acts like a state machine that consists of:

It is possible to use more than one Indigo instance at a time. In plain C API, the "active" instance can be switched with indigoSetSession call, while in Python, Java, and C#, the instance is represented as an object of class Indigo.

The objects that belong to the Indigo state machine are represented as integer handles in the C API, while in Python, Java, and C# they are wrapped by the IndigoObject class.

Access to configuration settings is done via indigoSetOption*** functions in the C API, while in Python, Java, and C# a number of Indigo.setOption methods can accomplish it.

Error handling in C is done via return codes, indigoGetLastError, and indigoSetErrorHandler. In Python, Java, and C#, as soon as some Indigo function terminates with an error, an IndigoException is thrown.

Several library instances may be created to act simultaneously and independently. However, each instance requires a certain amount of memory, and thus it is recommended to have as few instances as possible.

It is allowable to have multiple Indigo instances within one program and even in different threads. However, using a single Indigo instance across multiple threads is prohibited.

From now on, only the Python, Java, and C# interfaces are explained. For those who are interested in plain C interface, please read the C API page.

Indigo Constructor

Java:

import com.ggasoftware.indigo.*;
...
Indigo indigo = new Indigo();

C#:

using com.ggasoftware.indigo;
....
Indigo indigo = new Indigo();

Python:

from indigo import *
...
indigo = Indigo()

Python will assume the Indigo binaries stored in the lib directory in the directory where indigo.py is located. In C# and Java, the binaries are unpacked automatically into the system temporary folder.

Getting the Version String

You can use the Indigo.version method to get the string containing the Indigo library version number.

Java:

System.out.println("Indigo version " + indigo.version());

C#:

System.Console.WriteLine("Indigo version " + indigo.version());

Python:

print "Indigo version " + indigo.version()

Loading Molecules and Query Molecules

The Indigo object provides methods for loading molecules and query molecules from: strings, byte[] buffers, and files. The input format is detected automatically, except for SMARTS expressions, for which there are special methods.

Java and C#:

IndigoObject mol1 = indigo.loadMolecule("ONc1cccc1");
IndigoObject mol2 = indigo.loadMoleculeFromFile("structure.mol");
IndigoObject qmol1 = indigo.loadQueryMolecule("C1-C-C-C-1");
IndigoObject qmol2 = indigo.loadQueryMoleculeFromFile("query.mol");
IndigoObject qmol3 = indigo.loadSmarts("[N,n,O;!H0]");
IndigoObject qmol4 = indigo.loadSmartsFromFile("query.sma");

Python: the same with the IndigoObject omitted.

Instrumenting Molecules

You can programmatically add atoms and bonds to a molecule. Atoms can be added with the addAtom method of the molecule. This method accepts an atom symbol (a string) — an element from the periodic table, or a pseudoatom. Similarly, bonds can be added by calling addBond method of an atom. This method accepts another atom and the order of the new bond. You can also create an empty molecule by calling the createMolecule method.

Java and C#:

IndigoObject mol = indigo.createMolecule();
IndigoObject atom1 = mol.addAtom("C");
IndigoObject atom2 = mol.addAtom("C");
IndigoObject atom3 = mol.addAtom("C");
IndigoObject atom4 = mol.addAtom("C");
IndigoObject atom5 = mol.addAtom("C");
IndigoObject atom6 = mol.addAtom("N");
IndigoObject bond1 = atom1.addBond(atom2, 2);
IndigoObject bond2 = atom2.addBond(atom3, 2);
IndigoObject bond3 = atom3.addBond(atom4, 1);
IndigoObject bond4 = atom4.addBond(atom5, 2);
IndigoObject bond5 = atom5.addBond(atom6, 1);
IndigoObject bond6 = atom6.addBond(atom1, 2);

Python: the same with the IndigoObject omitted.

Merging Molecules

You can merge one molecule into another using the merge method of a molecule. This method accepts a molecule that is to be merged into the first molecule, and returns a "mapping" object. You can call the mapAtom method of the mapping object to know what is the (new) atom of the first molecule that was transferred from the second molecule.

Java and C#:

IndigoObject mol = indigo.loadMolecule("c1ccccc1");
IndigoObject mol2 = indigo.loadMolecule("ON");
IndigoObject mapping = mol.merge(mol2);
mapping.mapAtom(mol2.getAtom(0)).addBond(mol.getAtom(3), 1);

Python: the same with the IndigoObject omitted.

Removing Atoms and Bonds from Molecules

You can call the IndigoObject.remove method on an atom or a bond to remove it from the molecule it belongs to. Also, if you want to remove many atoms at once, you can call IndigoObject.removeAtoms method, providing to it an array of indices of atoms that you want to remove.

Submolecules

The IndigoObject.createSubmolecule method is applicable to a molecule or a query molecule. It accepts an array of atom indices and returns a new molecule containing the given atoms copied from the molecule, and the bonds between them.

Similarly, the IndigoObject.createEdgeSubmolecule method accepts two arrays — atom indices and bond indices — and returns a new molecule containing the given atoms and bonds copied from the molecule.

Indigo allowes to create a reference on a submolecule of a molecule with method IndigoObject.getSubmolecule. Such molecule can be later used for finding layout of a molecule part.

Accessing Molecules

Accessing Atoms and Bonds

The following methods can be applied to a molecule or query molecule:

Getting the Properties of Atoms and Bonds

The following methods of a molecule's atom can be called to obtain information:

The following IndigoObject methods can be applied to molecule's bonds:

Modifying Atoms and Bonds

The following methods of a molecule's atom can be called to modify the atom:

Accessing Neighbor Atoms

With iterateNeighbors method you can access the neighbors atoms of an atom. Also, these "neighbor" objects respond to the bond method, which returns the bond connecting the atom with the neighbor.

Java:

for (IndigoObject atom : mol.iterateAtoms())
{
  System.out.printf("atom %d: %d neighbors\n", atom.index(), atom.degree());
  for (IndigoObject nei : atom.iterateNeighbors())
    System.out.printf("neighbor atom %d is connected by bond %d\n", nei.index(), nei.bond().index());
}

C#:

foreach (IndigoObject atom in mol.iterateAtoms())
{
  System.Console.WriteLine("atom {0}: {1} neighbors\n", atom.index(), atom.degree());
  foreach (IndigoObject nei in atom.iterateNeighbors())
    System.Console.WriteLine("neighbor atom {0} is connected by bond {1}\n", nei.index(), nei.bond().index());
}

Python:

for atom in mol.iterateAtoms():
  print "atom %d: %d neighbors" % (atom.index(), atom.degree())
  for nei in atom.iterateNeighbors():
    print "neighbor atom %d is connected by bond %d\n" % (nei.index(), nei.bond().index())

Accessing R-Groups

Note: This section applies exclusively to query molecules.

The iterateRGroups method iterates over a query molecule's R-groups. Each of the R-groups has a collection of possible "R-group fragments", which in turn can be accessed via the iterateRGroupFragments method.

Java:

for (IndigoObject rg : mol.iterateRGroups())
{
  System.out.println("RGROUP #" + rg.index());
  for (IndigoObject frag : rg.iterateRGroupFragments())
  {
     System.out.println("  FRAGMENT #" + rg.index());
     System.out.println(frag.molfile());
  }
}

C#:

foreach (IndigoObject rg in mol.iterateRGroups())
{
  System.Console.WriteLine("RGROUP #" + rg.index());
  foreach (IndigoObject frag in rg.iterateRGroupFragments())
  {
     System.Console.WriteLine("  FRAGMENT #" + rg.index());
     System.Console.WriteLine(frag.molfile());
  }
}

Python:

for rg in mol.iterateRGroups():
  print "RGROUP #" + rg.index()
  for frag in rg.iterateRGroupFragments():
     print "  FRAGMENT #" + rg.index()
     print frag.molfile()

Calculating Molecule Properties

The following IndigoObject methods can be applied to a molecule or query molecule:

Working with Connected Components

You can use the countComponents method to calculate the number of connected components in a structure. Via the componentIndex method, you can obtain the number of the component to which the given atom belongs. Also, you can obtain the whole "component" object via the component method. You can also iterate over the components using the iterateComponents method.

The "component" objects respond to the countAtoms, countBonds, iterateAtoms, and iterateBonds calls. However, they can not be used as molecules. If you want to have a separate molecule representing a connected component, you should clone it.

Note: The numbering of the components in zero-based.

Java:

System.out.printf("%d components\n", mol.countComponents());

for (IndigoObject comp : mol.iterateComponents())
{
   System.out.println(comp.clone().smiles());
   System.out.printf("component %d: %d atoms, %d bonds\n", comp.index(), comp.countAtoms(), comp.countBonds());

   for (IndigoObject atom : comp.iterateAtoms())
      System.out.println(atom.index());

}

for (IndigoObject atom : mol.iterateAtoms())
   System.out.println(atom.componentIndex());

for (IndigoObject atom : mol.component(0).iterateAtoms())
   System.out.println(atom.index());

C#:

System.Console.WriteLine("{0} components", mol.countComponents());

foreach (IndigoObject comp in mol.iterateComponents())
{
   System.Console.WriteLine(comp.clone().smiles());
   System.Console.WriteLine("component {0}: {0} atoms, {0} bonds\n", comp.index(), comp.countAtoms(), comp.countBonds());
   foreach (IndigoObject atom in comp.iterateAtoms())
      System.Console.WriteLine(atom.index());

}

foreach (IndigoObject atom in mol.iterateAtoms())
   System.Console.WriteLine(atom.componentIndex());

foreach (IndigoObject atom in mol.component(0).iterateAtoms())
   System.Console.WriteLine(atom.index());

Python:

print mol.countComponents(), 'components'

for comp in mol.iterateComponents():
  print comp.clone().smiles()
  print "component %d: %d atoms, %d bonds\n", (comp.index(), comp.countAtoms(), comp.countBonds())
  for atom in comp.iterateAtoms():
    print atom.index()

for atom in mol.iterateAtoms():
  print atom.compomentIndex()

for atom in mol.component(0).iterateAtoms():
  print atom.index()

Canonical SMILES

IndigoObject.canonicalSmiles method computes the canonical SMILES string for a molecule.

Java:

System.out.println(mol2.canonicalSmiles());

C#:

System.Console.WriteLine(mol2.canonicalSmiles());

Python:

print mol2.canonicalSmiles()

Saving Molecules

IndigoObject.smiles, when applied to a molecule, returns a SMILES string. Similarly, IndigoObject.molfile returns a string with a Molfile, while IndigoObject.cml returns a string with CML representation. IndigoObject.saveMolfile and IndigoObject.saveCml methods save Molfile and CML to disk.

Java:

System.out.println(mol1.molfile());
System.out.println(mol2.smiles());
qmol1.saveMolfile("query.mol");

C#:

System.Console.WriteLine(mol1.molfile());
System.Console.WriteLine(mol2.smiles());
qmol1.saveMolfile("query.mol");

Python:

print mol1.molfile()
print mol2.smiles()
qmol1.saveMolfile("query.mol")

Loading Reactions and Query Reactions

Java and C#:

IndigoObject rxn1 = indigo.loadReaction("[I-].[Na+].C=CCBr>>[Na+].[Br-].C=CCI");
IndigoObject rxn2 = indigo.loadReactionFromFile("reaction.rxn");
IndigoObject qrxn1 = indigo.loadQueryReaction("CBr>>CCl");
IndigoObject qrxn2 = indigo.loadQueryReactionFromFile("query.rxn");
IndigoObject rs    = indigo.loadReactionSmarts("[C$(CO)]>>[C$(CN)]");
IndigoObject rs2   = indigo.loadReactionSmartsFromFile("query.sma");

Python: the same with the IndigoObject omitted.

Instrumenting Reactions

The Indigo.createReaction method returns an empty reaction. The Indigo.createQueryReaction method returns an empty query reaction. The IndigoObject.addReactant, IndigoObject.addProduct, and IndigoObject.addCatalyst methods can then be used to fill it up.

Java and C#:

IndigoObject rxn = indigo.createReaction();
rxn.addReactant(mol1);
rxn.addReactant(mol2);
rxn.addProduct(indigo.loadMolecule("ClC1CCCCC1));

Python: the same with the IndigoObject omitted.

Accessing Reactions

Reactions respond to the following IndigoObject methods:

You can also call the IndigoObject.remove method of the reaction molecule to remove it from the reaction.

Java:

System.out.println(rxn.countMolecules());
for (IndigoObject item : rxn.iterateReactants())
   System.out.println(item.molfile());

for (IndigoObject item : rxn.iterateCatalysts())
   item.remove();

C#:

System.Console.WriteLine(rxn.countMolecules());
foreach (IndigoObject item in rxn.iterateReactants())
   System.Console.WriteLine(item.molfile());

foreach (IndigoObject item in rxn.iterateCatalysts())
   item.remove();

Python:

print rxn.countMolecules()
for item in rxn.iterateReactants():
   print item.molfile()

for item in rxn.iterateCatalysts():
   item.remove();

Saving Reactions

The IndigoObject.smiles, when applied to a reaction, returns a reaction SMILES string. Similarly, the IndigoObject.rxnfile returns a string with an Rxnfile. The IndigoObject.saveRxnfile method saves the Rxnfile to disk.

Java:

System.out.println(rxn.smiles());
System.out.println(rxn.rxnfile());
rxn.saveRxnfile("reaction.rxn");

C#:

System.Console.WriteLine(rxn.smiles());
System.Console.WriteLine(rxn.rxnfile());
rxn.saveRxnfile("reaction.rxn");

Python:

print rxn.smiles()
print rxn.rxnfile()
rxn.saveRxnfile("reaction.rxn")

Reacting Centers

Reacting centers include bonds that are involded in the reaction. Indigo supports the following types of reacting centers:

These values are bit flags, and can be combinded. IndigoObject.reactingCenter and IndigoObject.setReactingCenter are the getter and setter of the bond reacting center property.

Python:

print("reacting centers:")
for m in rxn.iterateMolecules():
    for b in m.iterateBonds():
        print(rxn.reactingCenter(b))
for m in rxn.iterateMolecules():
    for b in m.iterateBonds():
        rxn.setReactingCenter(b, Indigo.RC_CENTER | Indigo.RC_UNCHANGED)

Reaction Atom-to-Atom Mapping

The IndigoObject.automap method is purposed for generating reaction atom-to-atom mapping (AAM). The method accepts a string parameter called mode. The following modes are available:

Java, C#, and Python:

rxn1.automap("keep");
rxn1.saveRxnfile("rxn1_aam.rxn");
rxn1.automap("clear");
rxn1.saveSmiles("rxn1_noaam.smi");

The IndigoObject.clearAAM method resets current atom-to-atom mapping. Reaction atom has method IndigoObject.atomMappingNumber and IndigoObject.setAtomMappingNumber to get and set atom-to-atom mapping manually.

Python:

rxn.automap("keep");
foreach mol in rxn.iterateMolecules():
    for atom in mol.iterateAtom():
        print("Atom ", atom.index(), atom.atomMappingNumber())

Attachment points

Every molecule can have many attachment points. They are grouped by order - the number of connections. For example, a molecule can have 2 attachment points with order 1, and 3 attachment points with order 2. The following methods of IndigoObject for a molecule are available for working with attachment points:

Python:

count = mol.countAttachmentPoints()
print("%s Number of attachment points: %s" % (offset, count))
for order in range(1, count + 1):
    for a in mol.iterateAttachmentPoints(order):
        print("%s   Index: %d. Order %d" % (offset, a.index(), order))
 mol.clearAttachmentPoints()

Layout

The IndigoObject.layout method performs the cleanup of the object it is applied to.

Java, C#, and Python:

mol1.layout();
rxn.layout();

Aromaticity

The IndigoObject.aromatize and IndigoObject.dearomatize methods convert molecules/reactions to aromatic and Kekule forms respectively.

Java, C#, and Python:

mol1.dearomatize();
rxn.aromatize();

Implicit and Explicit Hydrogens

Indigo does not change the representation of the hydrogens automatically. If the hydrogens in the input structure or reaction are implicit (this is usually the case), Indigo does not add the missing hydrogens to the structure or reaction. If some (or all) of hydrogens in the input are explicitly drawn, Indigo does not remove them.

You can force folding (i.e. removal) or unfolding (i.e. addition) the hydrogens of a molecule or reaction by calling IndigoObject.foldHydrogens and IndigoObject.unfoldHydrogens methods.

Java, C#, and Python:

mol.unfoldHydrogens();
mol.foldHydrogens();
rxn.unfoldHydrogens();
rxn.foldHydrogens();

Stereochemistry

The following methods of IndigoObject are available for accessing molecule's stereo configuration:

The following methods are useful for keeping cis-trans stereochemistry intact when converting to/from SMILES:

Java:

  IndigoObject mol = indigo.loadMolecule("chiral.mol");

  System.output.println("%d chiral atoms\n", mol.countStereocenters());
  for (IndigoObject atom : mol.iterateStereocenters())
  {
     System.out.printf("atom %d -- stereocenter type %d\n", atom.index(), atom.stereocenterType());
     atom.invertStereo();
  }

  for (IndigoObject bond : mol.iterateBonds())
     if (bond.bondStereo() != 0)
       System.out.printf("bond %d -- stereo type %d\n", bond.index(), bond.bondStereo());

  System.out.println(mol.smiles());
  mol.clearStereocenters();
  mol.clearCisTrans();
  System.out.println(mol.smiles());

C#:

  IndigoObject mol = indigo.loadMolecule("chiral.mol");

  System.Console.WriteLine("{0} chiral atoms\n", mol.countStereocenters());
  foreach (IndigoObject atom in mol.iterateStereocenters())
  {
     System.Console.WriteLine("atom {0} -- stereocenter type {1}\n", atom.index(), atom.stereocenterType());
     atom.invertStereo();
  }

  foreach (IndigoObject bond in mol.iterateBonds())
     if (bond.bondStereo() != 0)
       System.Console.WriteLine("bond {0} -- stereo type {1}\n", bond.index(), bond.bondStereo());

  System.Console.WriteLine(mol.smiles());
  mol.clearStereocenters();
  mol.clearCisTrans();
  System.out.println(mol.smiles());

Python:

  IndigoObject mol = indigo.loadMolecule("chiral.mol");

  print mol.countStereocenters(), "chiral atoms"
  for atom in mol.iterateStereocenters():
     print "atom", atom.index(), "-- stereocenter type", atom.stereocenterType()
     atom.invertStereo();

  for bond in mol.iterateBonds():
     if bond.bondStereo() != 0:
       print "bond", bond.index(), "-- stereo type", bond.bondStereo()

  print mol.smiles()
  mol.clearStereocenters()
  mol.clearCisTrans()
  print mol.smiles()

Groups

In a molecule loaded from a Molfile, arbitrary subsets of a its atoms and bonds can be joined in groups. There are many kinds of groups, Indigo supports five of them:

The following methods of IndigoObject are available for reading molecule's groups:

The iterator methods return "group" objects. Each "group" object responds to IndigoObject.iterateAtoms and IndigoObject.iterateBonds methods.

Java:

for (IndigoObject dsg : mol.iterateDataSGroups())
{
   System.out.println("data sgroup " + dsg.index());
   for (IndigoObject atom : dsg.iterateAtoms())
      System.out.println("  atom " + atom.index());  
}

C#:

foreach (IndigoObject dsg in mol.iterateDataSGroups())
{
   System.Console.WriteLine("data sgroup " + dsg.index());
   foreach (IndigoObject atom in dsg.iterateAtoms())
      System.Console.WriteLine("  atom " + atom.index());
}

Python:

for dsg in mol.iterateDataSGroups():
   print "data sgroup", dsg.index()
   for atom in dsg.iterateAtoms():
      print atom.index()

You can also add data SGroups to an existing structure using IndigoObject.addDataSGroup() method. It returns the added group. By default, the data SGroup is added in "attached" mode — that is, the data is attached to each of the group's atoms. To make the data SGroup detached, you can call the IndigoObject.setDataSGroupXY method of the data SGroup object. To get a description of a data SGroup use method IndigoObject.description().

To add a superatom use IndigoObject.addSuperatom() method:

mol.addSuperatom(list_with_atom_indices, "Abbreviation")

Reading SDF, RDF, CML, multiline SMILES files

The following methods of the Indigo class can be used to enumerate files with multiple molecules/reactions:

Java:

for (IndigoObject item : indigo.iterateSDFile("structures.sdf"))
   System.out.println(item.grossFormula());

C#:

foreach (IndigoObject item in indigo.iterateSDFile("structures.sdf"))
   System.Console.WriteLine(item.grossFormula());

Python:

for item in indigo.iterateSDFile("structures.sdf"):
   print item.grossFormula()

Indexed access

You can access items from SDF/RDF/CML/SMILES files by index, using the at method. The numbering of the items is zero-based.

Java, C#:

IndigoObject reader = indigo.iterateSDFile("structures.sdf");
String s = reader.at(15).smiles()

Python: the same with the IndigoObject and String omitted.

Accessing Molecule and Reaction Properties

Names

Molecule or reaction name is associated with the first line of the Molfile/Rxnfile the molecule/reaction was loaded from. In case it was loaded from SMILES string, the word immediately following the SMILES code is taken.

IndigoObject.name and IndigoObject.setName are the getter and setter of the molecule/reaction name.

Java, C#:

String name = mol2.name();
mol2.setName("another name");
mol2.saveMolfile("mol2.mol");

Python: the same with the IndigoObject and String omitted.

SDF/RDF Properties

The following methods are used to get the named properties of the molecule/reaction loaded from an SDF or RDF file:

Java:

for (IndigoObject item : indigo.iterateSDFile("structures.sdf"))
   if (item.hasProperty("cdbregno"))
      System.out.println(item.getProperty("cdbregno"));

C#:

foreach (IndigoObject item in indigo.iterateSDFile("structures.sdf"))
   if (item.hasProperty("cdbregno"))
      System.Console.WriteLine(item.getProperty("cdbregno"));

Python:

for item in indigo.iterateSDFile("structures.sdf"):
   if item.hasProperty("cdbregno"):
      print item.getProperty("cdbregno")

It is also possible to iterate over all properties of a particular record in SDF or RDF file.

Java:

for (IndigoObject item : indigo.iterateRDfile("reactions.rdf"))
   for (IndigoObject prop : item.iterateProperties())
      System.out.println(prop.name() + " : " + prop.rawData())

C#:

foreach (IndigoObject item in indigo.iterateRDfile("reactions.rdf"))
   foreach (IndigoObject prop in item.iterateProperties())
      System.Console.WriteLine(prop.name() + " : " + prop.rawData())

Python:

for item in indigo.iterateRDFile("reactions.rdf"):
   for prop in item.iterateProperties():
      print prop.name(), ":", prop.rawData()

Writing Multiple Molecules or Reactions to a File

Writing SDF Files

It is possible to write molecules to SDF files, along with arbitrary properties assigned.

Java and C#:

IndigoObject saver = indigo.writeFile("structures.sdf");

IndigoObject mol = indigo.loadMolecule("C1CCC1");
mol.setName("cyclobutane");
mol.setProperty("id", "8506");
saver.sdfAppend(mol);

mol = indigo.loadMolecule("C(NNN)C");
mol.setProperty("id", "42");
saver.sdfAppend(mol);

Python: the same with the IndigoObject omitted.

Writing RDF Files

Molecules and reactions can be written to an RDF file with the rdfAppend method. However, the special rdfHeader method must be called exactly once before anything is written into the RDF file.

Java and C#:

IndigoObject f = indigo.writeFile("test.rdf");
f.rdfHeader();
mol.setProperty("WHAT", "a molecule");
rxn.setProperty("WHAT", "a reaction");
f.rdfAppend(mol);
f.rdfAppend(rxn);

Python: the same with the IndigoObject omitted.

Writing CML Files

Molecules can be written to a CML file with the cmlAppend method. However, the cmlHeader method must be called exactly once before anything is written into the CML file, and the cmlFooter method must be called after all the molecules has been written.

Java and C#:

IndigoObject f = indigo.writeFile("structures.cml");
f.cmlHeader();
f.cmlAppend(mol1);
f.cmlAppend(mol2);
f.cmlFooter();

Python: the same with the IndigoObject omitted.

Writing Multiline SMILES Files

Java and C#:

IndigoObject f = indigo.writeFile("test.smi");
f.smilesAppend(mol);
f.smilesAppend(rxn);

Python: the same with the IndigoObject omitted.

Closing Files

The file output stream is closed on the object's destructor. However, you may need to close it explicitly. You can use the close method:

f.close();

You may need to be sure that the file will be closed after some block of code has finished executing. In Java, you can call the close method in finally block:

IndigoObject f = null;
try
{
  f = indigo.writeFile("test.sdf");
  f.sdfAppend(mol);
}
finally
{
  if (f != null)
    f.close();
}

In C#, the "using" statement can make the job easier:

using (IndigoObject f = indigo.writeFile("test.sdf"))
{
  f.sdfAppend(mol);  
}

In Python, the "with" syntax serves the same purpose:

with indigo.writeFile("test.sdf") as f:
  f.sdfAppend(mol)

Generic Interface to Writing Files

There is also a generic interface to writing multiple molecules/reactions in a file. You can create a generic file saver (IndigoObject.createFileSaver), specifying the desired format to it, and then append items to it (IndigoObject.append), not bothering about header and footer — the saver will write them for you automatically.

The IndigoObject.createFileSaver method accepts the output file name and a string with the desired format, which is "sdf", "rdf", "cml", or "smi".

Java:

IndigoObject saver = null;
try
{
  saver = indigo.createFileSaver("reactions.cml", "cml");
  saver.append(rxn1);
  saver.append(rxn2);
}
finally
{
  if (saver != null)
    saver.close();
}

C#:

using (IndigoObject saver = indigo.createFileSaver("reactions.cml", "cml"))
{
   saver.append(rxn1);
   saver.append(rxn2);
}

Python:

with indigo.createFileSaver("reactions.cml", "cml") as saver:
   saver.append(rxn1);
   saver.append(rxn2);

Writing into a Memory Buffer

You can write the SDF or RDF data into a memory buffer instead of a file. Indigo.writeBuffer method creates and returns a memory output stream. After you have finished writing, you can call the toString method to obtain the written data.

Java, C#:

IndigoObject buf = indigo.writeBuffer();
mol.setProperty("name", "cyclobutane");
buf.sdfAppend(mol);
String s = buf.toString();

Python: the same with the IndigoObject and String omitted.

You can also create a generic saver on top of an existing buffer writer

Java, C#:

IndigoObject saver = indigo.createSaver(buf, "cml");

Python: the same with the IndigoObject omitted.

Enumeration of Submolecules

Indigo provides methods to enumerate submolecules of different kinds, namely:

The "submolecule" objects returned by these methods respond to the countAtoms, countBonds, iterateAtoms, and iterateBonds calls. However, they can not be used as molecules. If you want to have a separate molecule representing the obtained submolecule, you should clone it.

Java:

for (IndigoObject submol : mol.iterateEdgeSubmolecules(1, mol.countBonds())
{
  System.out.printf("submolecule #%d: %s\n", submol.index(), submol.clone().smiles());
  for (IndigoObject atom : item.iterateAtoms())
    System.out.printf("%d ", atom.index());
  System.out.printf("\n");
  for (IndigoObject bond : item.iterateBonds())
    System.out.printf("%d ", bond.index());
  System.out.printf("\n");
}

C#:

foreach (IndigoObject item in mol.iterateEdgeSubmolecules(1, mol.countAtoms()))
{
  System.Console.WriteLine("{0} {1}", item.index(), item.clone().smiles());
  foreach (IndigoObject atom in item.iterateAtoms())
    System.Console.Write("{0} ", atom.index());
  System.Console.WriteLine();
  foreach (IndigoObject bond in item.iterateBonds())
    System.Console.Write("{0} ", bond.index());
  System.Console.WriteLine();
}

Python:

for submol in mol.iterateEdgeSubmolecules(1, mol.countBonds()):
  print "submolecule", submol.index(), ":", submol.clone().smiles())
  print [atom.index() for atom in item.iterateAtoms()]
  print [bond.index() for bond in item.iterateBonds()]

Fingerprints

The IndigoObject.fingerprint method works for molecules and reactions (including query molecules and query reactions) and returns a fingerprint object. IndigoObject.toString and IndigoObject.toBuffer methods of that object can be called to obtain a hex-string representation or a byte array of a fingerprint, respectively.

The fingerprint method accepts a string with a requested fingerprint type. The following fingerprint types are available:

The size of the fingerprint can be controlled via a number of fingerprinting options.

Java:

fp1 = mol1.fingerprint("sim");
fp2 = mol2.fingerprint("sim");
String fp1string = fp1.toString();
byte[] fp2bytes = fp1.toBuffer();

Python: the same with IndigoObject and String omitted.

The IndigoObject.countBits method calculates the number of nonzero bits in a fingerprint. The Indigo.commonBits method calculates the number of coincident nonzero bits in two fingerprints.

Java and C#:

int bits1 = fp1.countBits();
int bits2 = fp2.countBits();
int bits12 = indigo.commonBits(fp1, fp2);

Python: the same with the int omitted.

Molecule and Reaction Similarity

The Indigo.similarity method accepts two molecules, two reactions, or two fingerprints. It also accepts a "metrics" string and returns a float value — the similarity measure between the two given items. There are three available metrics, which are calculated in the following way:

Where:

Java and C#:

float sim1 = indigo.similarity(fp1, fp2, "tanimoto");
float sim2 = indigo.similarity(rxn1, rxn2, "tversky");
float sim2 = indigo.similarity(mol1, mol2, "tversky 0.1 0.9");
float sim4 = indigo.similarity(mol1, mol2, "euclid-sub");

Python: the same with the float omitted.

Exact Match

The Indigo.exactMatch method accepts two molecules or reactions and returns a "mapping" object — the result of the exact match of two given molecules or reactions. If match is not possible, it returns null. If you are interested only in does the match exist or not, you can just check if the result of the method is null. Otherwise, please check below how to work with the mapping objects.

Note: You can not pass query molecules or reactions to exactMatch.

Exact Matching Flags for Molecules

The Indigo.exactMatch method accepts an optional string. In this string, you can pass the following flags to the matching procedure:

Flag Comment
ELE Distribution of electrons: bond types, atom charges, radicals, valences
MAS Atom isotopes
STE Stereochemistry: chiral centers, stereogroups, and cis-trans bonds
FRA Connected fragments: disallows match of separate ions in salts
ALL All of the above (the most permissive matching)
TAU Tautomer matching (not compatible to other flags)
NONE No conditions (the most flexible kind of search)
$number Maximum allowed RMS value for affine transformation match

The flags should go in the parameters string separated by space. Each flag specifies a constraint for the matching procefure. The more flags you set, the more restrictive the matching is. You can write the minus sign before the flag to exclude it from the 'ALL' flag. For example, 'ALL -MAS' means that all the described features except the isotopes must match.

The TAU flag stands for tautomer matching. It can not be combined with any other flags. You can see examples of exact matching, affine transformation matching, and exact tautomer matching in the Bingo User Manual.

Note: When no flags are specified, the behavior is equivalent to the ALL flag.

The $number, if present, should go after the flags; for example: ALL 0.1. The given number is the maximum allowed root-mean-square deviation between the atoms of the two molecules, measured in angstroms. Prior to the calculation of the RMS value, the optimal affine transformation (translation+rotation+scale) is applied to one of the molecules to make it as close as possible to the other molecule.

Note: Affine transformation matching is not possible when the molecule's atoms do not have coordinates (e.g. the molecule was loaded from SMILES).

Java and C#:

IndigoObject match = indigo.exactMatch(mol1, mol2, "ALL 0.1");

if (match == null) // affine matching has failed?
   match = indigo.exactMatch(mol1, mol2);

if (match == null) // exact match has failed, trying to ignore stereochemistry
   match = indigo.exactMatch(mol1, mol2, "ALL -STE");

if (match == null) // failed again; trying the most permissive matching
   match = indigo.exactMatch(mol1, mol2, "NONE");

Python:

match = indigo.exactMatch(mol1, mol2, "ALL 0.1")
if not match:
   match = indigo.exactMatch(mol1, mol2) # eqiuvalent to ALL
if not match:
   match = indigo.exactMatch(mol1, mol2, "ALL -STE") # equivalent to "ELE MAS FRA"  
if not match:
   match = indigo.exactMatch(mol1, mol2, "NONE")

Exact Matching Flags for Reactions

When calling the Indigo.exactMatch method for reactions, you can pass it the "ELE", "MAS", and "STE" flags, which have the same meaning as in molecule exact matching. You can also pass two reaction-specific flags:

Flag Comment
AAM Atom-atom mapping
RCT Reacting centers

Note: FRA, TAU, and affine matching are not available for reactions.

Molecule Substructure Matching

The Indigo.substructureMatcher method accepts a molecule (but not a query molecule) and returns a "substructure matcher" object. The given molecule is going to be the "target" molecule for the substructure match.

Molecule Substructure Matching Flags

The Indigo.substructureMatcher method accepts an optional string, in which you can specify one of the following flags:

Methods of Substructure Matcher

Also, please take a look on some options available for substructure matchers.

Reaction Substructure Matching

You can pass a reaction to the Indigo.substructureMatcher method to obtain a "reaction substructure matcher" object. It responds to the IndigoObject.match method similarly to the molecule matcher. This method returns a "reaction match" object, or null if the matching is not possible.

You can specify optional DAYLIGHT-AAM flag to the matcher. When this flag is present, the matching of the atom-atom mapping (reaction AAM) is following the Daylight's rules for reaction SMARTS. Otherwise, it follows ordinary rules that are normal for matching Rxnfiles.

Java and C#:

IndigoObject rxn1 = indigo.loadReactionSmarts("[C:1][C:1]>>[C:1]");
IndigoObject rxn2 = indigo.loadReaction("[CH3:7][CH3:8]>>[CH3:7][CH3:8]");
IndigoObject match = indigo.substructureMatcher(rxn2, "DAYLIGHT-AAM").match(rxn1);

Python: the same with the IndigoObject omitted.

Note: ignoreAtom, unignoreAtoms, unignoreAllAtoms, countMatches, countMatchesWithLimit, and iterateMatches methods are not supported by reaction substructure matcher.

Converting the Substructure Query to the Aromatic Form

If your query is loaded from a Molfile or SMILES and its aromatic rings are represented in Kekule form, you should transform it to aromatic form prior to matching. Otherwise, it will not match the aromatic rings in the target structure.

Java and C#:

IndigoObject query = indigo.loadMoleculeFromFile("kekule.mol");
query.aromatize();

Python: the same with the IndigoObject omitted.

Note: aromatize does not have any effect for SMARTS queries (and should not be called on them).

Optimizing the Substructure Query

If you have a complex molecule or reaction SMARTS query, you can "optimize" it in-memory so that the matching performs faster.

Java and C#:

IndigoObject query = indigo.loadSmarts("[$([a;r4,!R1&r3])]1:[$([a;r4,!R1&r3])]:[$([a;r4,!R1&r3])]:[$([a;r4,!R1&r3])]:1");
query.optimize();

Python: the same with the IndigoObject omitted.

Methods of "mapping" object

You can get the detailed information about the succeeded matching via the returned "mapping" IndigoObject. It responds to the following method calls:

Note: The IndigoObject.mapAtom and IndigoObject.ignoreAtom methods accepts only atoms, and not atom indices. Similarly, the IndigoObject.mapBond method accepts only bonds, and not bond indices.

Example 1 (mapping query molecule atoms)

Java:

IndigoObject match = indigo.substructureMatcher(mol).match(query);

if (match != null)
{
   match.highlightedTarget().saveMolfile("highlighted.mol");
   for (IndigoObject atom : qmol2.iterateAtoms())
      System.out.printf("atom %d mapped to atom %d\n", atom.index(), match.mapAtom(atom).index());
}

C#:

IndigoObject match = indigo.substructureMatcher(mol).match(query);

if (match != null)
{
   match.highlightedTarget().saveMolfile("highlighted.mol");
   foreach (IndigoObject atom in qmol2.iterateAtoms())
      System.Console.WriteLine("atom {0} mapped to atom {1}", atom.index(), match.mapAtom(atom).index());
}

Python:

match = indigo.substructureMatcher(mol).match(query)

if match:
   match.highlightedTarget().saveMolfile("highlighted.mol")
   for atom in qmol2.iterateAtoms():
      print "atom", atom.index(), "mapped to atom", match.mapAtom(atom).index())

Example 2 (getting the highlighted target molecule)

Java:

IndigoObject matcher = indigo.substructureMatcher(mol);
IndigoObject query = indigo.loadSmarts("O=[!C;R]");

System.out.println(matcher.countMatches(query);
for (IndigoObject match : matcher.iterateMatches(query))
   System.out.println(match.highlightedTarget().smiles());

C#:

IndigoObject matcher = indigo.substructureMatcher(mol);
IndigoObject query = indigo.loadSmarts("O=[!C;R]");

System.Console.WriteLine(matcher.countMatches(query);
foreach (IndigoObject match in matcher.iterateMatches(query))
   System.Console.WriteLine(match.highlightedTarget().smiles());

Python:

matcher = indigo.substructureMatcher(mol)
query = indigo.loadSmarts("O=[!C;R]")

print matcher.countMatches(query)
for match in matcher.iterateMatches(query):
   print match.highlightedTarget().smiles()

Example 3 (exact match between reactions)

Java:

IndigoObject match = indigo.exactMatch(rxn1, rxn2, "ALL -AAM");

if (match != null)
{
   for (IndigoObject mol : rxn1.iterateMolecules())
   {
      System.out.println("molecule #" + mol.index());

      for (IndigoObject atom : mol.iterateAtoms())
        if (match.mapAtom(atom) != null)
           System.out.printf("atom #%d matched\n", atom.index());

      for (IndigoObject bond : mol.iterateBonds())
        if (match.mapBond(atom) != null)
           System.out.printf("bond #%d matched\n", bond.index());
   }
}

C#:

IndigoObject match = indigo.exactMatch(rxn1, rxn2, "ALL -AAM");

if (match != null)
{
   foreach (IndigoObject mol in rxn1.iterateMolecules())
   {
      System.Console.writeLine("molecule #" + mol.index());

      foreach (IndigoObject atom in mol.iterateAtoms())
        if (match.mapAtom(atom) != null)
           System.Console.WriteLine("atom #{0} matched\n", atom.index());

      foreach (IndigoObject bond in mol.iterateBonds())
        if (match.mapBond(bond) != null)
           System.Console.WriteLine("bond #{0} matched\n", bond.index());

   }
}

Python:

match = indigo.exactMatch(rxn1, rxn2, "ALL -AAM")

if match:
  foreach mol in rxn1.iterateMolecules():
    print "molecule #" + mol.index();
    for atom in mol.iterateAtoms():
      if match.mapAtom(atom):
        print "atom #", atom.index(), "matched"

    for bond in mol.iterateBonds():
      if match.mapBond(bond):
        print "bond #", bond.index(), "matched"

Tautomer Matching Rules

The following three rules are recommended and are used in examples:

Customizing the rules

Indigo provides thee methods to customize the rules: clearTautomerRules, setTautomerRule, and removeTautomerRule. There are no rules by default. The Indigo.setTautomerRule method accepts an ID number of the rule (must be from 1 to 32), and two strings (for two bound atoms of the chain), containing allowed elements are separated by commas. '1' at the beginning means an aromatic atom, and '0' means an aliphatic (non-aromatic) atom.

The three rules defined above can be set in the following way:

Java and C#:

  indigo.setTautomerRule(1, "N,O,P,S,As,Se,Sb,Te", "N,O,P,S,As,Se,Sb,Te");
  indigo.setTautomerRule(2, "0C", "N,O,P,S");
  indigo.setTautomerRule(3, "1C", "N,O");

  IndigoObject mol1 = indigo.loadQueryMolecule("OC1=CC=CNC1");
  IndigoObject mol2 = indigo.loadMolecule("O=C1CNCC2=CC=CC=C12");

  IndigoObject matcher = indigo.substructureMatcher(mol2, "TAU R2");
  IndigoObject match = matcher.match(mol1);

Python: the same with IndigoObject omitted

Highlighting Atoms and Bonds

The IndigoObject.highlight and IndigoObject.unhighlight methods can be applied to an atom or a bond. Also, the IndigoObject.unhighlight method can be applied to a molecule or reaction to dismiss the highlighting on the whole molecule or reaction.

The following example shows how to highlight the matched atoms and bonds on a substructure matcher's target, along with explicit hydrogens attached to the matched atoms.

Java:

IndigoObject matcher = indigo.substructureMatcher(target);
IndigoObject match = matcher.match(query);

for (IndigoObject item : query.iterateAtoms())
{
   IndigoObject atom = match.mapAtom(item);
   atom.highlight();

   for (IndigoObject nei : atom.iterateNeighbors())
   {
      if (!nei.isPseudoatom() && !nei.isRSite() && nei.atomicNumber() == 1)
      {
         nei.highlight();
         nei.bond().highlight();
      }
   }
}

for (IndigoObject bond : query.iterateBonds())
   match.mapBond(bond).highlight();

System.out.println(target.smiles());
target.unhighlight();
System.out.println(target.smiles());

C#:

IndigoObject matcher = indigo.substructureMatcher(target);
IndigoObject match = matcher.match(query);

foreach (IndigoObject qatom in query.iterateAtoms())
{
   IndigoObject atom = match.mapAtom(qatom);
   atom.highlight();

   foreach (IndigoObject nei in atom.iterateNeighbors())
   {
      if (!nei.isPseudoatom() && !nei.isRSite() && nei.atomicNumber() == 1)
      {
         nei.highlight();
         nei.bond().highlight();
      }
   }
}

foreach (IndigoObject bond in query.iterateBonds())
   match.mapBond(bond).highlight();

System.Console.WriteLine(target.smiles());
target.unhighlight();
System.Console.WriteLine(target.smiles());

Python:

matcher = indigo.substructureMatcher(target)
match = matcher.match(query)

for qatom in query.iterateAtoms():
  atom = match.mapAtom(qatom)
  atom.highlight()

  for nei in atom.iterateNeighbors():
    if not nei.isPseudoatom() and not nei.isRSite() and nei.atomicNumber() == 1:
      nei.highlight()
      nei.bond().highlight()

for bond in query.iterateBonds():
  match.mapBond(bond).highlight()

print target.smiles()
target.unhighlight()
print target.smiles()

Serialization

You can use the IndigoObject.serialize method to serialize a molecule or a reaction into a binary byte array. All molecule and reaction features are serialized, including atom coordinates, stereochemistry, bond orientations, highlighting, AAM numbers, etc. To restore the molecule/reaction back, use the Indigo.unzerialize method.

Java, C#:

byte[] data = mol.serialize();
...
IndigoObject mol2 = indigo.unserialize(data);

Python: the same with the IndigoObject omitted.

Alignment of Atoms

The IndigoObject.alignAtoms method can be used to calculate and apply the transformation (scale + rotatation + translation) of a molecule so that some subset of its atoms will become as close as possible to the desired positions. The method accepts an integer array of atom indices and a float array of desired coordinates (three times bigger that the array of indices, storing resired x,y,z coordinates for each atom).

Java:

  IndigoObject query = indigo.loadSmarts("[#7]1~[#6]~[#6]~[#7]~[#6]~[#6]2~[#6]~[#6]~[#6]~[#6]~[#6]~1~2");
  int[] atoms = new int[query.countAtoms()];
  float[] xyz = new float[query.countAtoms() * 3];

  for (IndigoObject structure : indigo.iterateSDFile("structures.sdf.gz"))
  {
     IndigoObject match = indigo.substructureMatcher(structure).match(query);
     int i = 0;

     if (structure.index() == 0)
        for (IndigoObject atom : query.iterateAtoms())
           System.arraycopy(match.mapAtom(atom).xyz(), 0, xyz, i++ * 3, 3);
     else
     {
        for (IndigoObject atom : query.iterateAtoms())
           atoms[i++] = match.mapAtom(atom).index();

        structure.alignAtoms(atoms, xyz);
     }
  }

C#:

IndigoObject query = indigo.loadSmarts("[#7]1~[#6]~[#6]~[#7]~[#6]~[#6]2~[#6]~[#6]~[#6]~[#6]~[#6]~1~2");
int[] atoms = new int[query.countAtoms()];
float[] xyz = new float[query.countAtoms() * 3];

foreach (IndigoObject structure in indigo.iterateSDFile("structures.sdf.gz"))
{
   IndigoObject match = indigo.substructureMatcher(structure).match(query);
   int i = 0;

   if (structure.index() == 0)
      foreach (IndigoObject atom in query.iterateAtoms())
         Array.Copy(match.mapAtom(atom).xyz(), 0, xyz, i++ * 3, 3);
   else
   {
      foreach (IndigoObject atom in query.iterateAtoms())
      atoms[i++] = match.mapAtom(atom).index();

      structure.alignAtoms(atoms, xyz);
   }
}

Python:

query = indigo.loadSmarts("[#7]1~[#6]~[#6]~[#7]~[#6]~[#6]2~[#6]~[#6]~[#6]~[#6]~[#6]~1~2");
xyz = []
for structure in indigo.iterateSDFile("structures.sdf.gz"):
  match = indigo.substructureMatcher(structure).match(query)
  if structure.index() == 0:
    for atom in query.iterateAtoms():
      xyz.extend(match.mapAtom(atom).xyz())
  else:
    atoms = []
    for atom in query.iterateAtoms():
      atoms.append(match.mapAtom(atom).index())
    structure.alignAtoms(atoms, xyz);

Scaffold Detection

Java:

  IndigoObject arr = indigo.createArray();

  for (IndigoObject item : indigo.iterateSDFile("structures.sdf"))
     arr.arrayAdd(item);

  IndigoObject scaf = indigo.extractCommonScaffold(arr, "exact");

  if (scaf != null)
    System.out.println("scaffold: " + scaf.smiles());

C#:

  IndigoObject arr = indigo.createArray();

  foreach (IndigoObject item in indigo.iterateSDFile("structures.sdf"))
     arr.arrayAdd(item);

  IndigoObject scaf = indigo.extractCommonScaffold(arr, "exact");

  if (scaf != null)
    System.Console.WriteLine("scaffold: " + scaf.smiles());

Python:

  arr = indigo.createArray();

  for item in indigo.iterateSDFile("structures.sdf"):
     arr.arrayAdd(item);

  scaf = indigo.extractCommonScaffold(arr, "exact");

  if scaf:
    print "scaffold:", + scaf.smiles()

R-Group Deconvolution

Java:

  IndigoObject deco = indigo.decomposeMolecules(scaf, arr);
  deco.decomposedMoleculeHighlighted().saveMolfile("highlighted.mol");
  IndigoObject scaffold = deco.decomposedMoleculeScaffold();
  scaffold.layout();
  scaffold.saveMolfile("scaffold.mol");
  for (IndigoObject item : deco.iterateDecomposedMolecules())
     System.out.println(item.decomposedMoleculeWithRGroups().molfile());

C#:

  IndigoObject deco = indigo.decomposeMolecules(scaf, arr);
  deco.decomposedMoleculeHighlighted().saveMolfile("highlighted.mol");
  IndigoObject scaffold = deco.decomposedMoleculeScaffold();
  scaffold.layout();
  scaffold.saveMolfile("scaffold.mol");
  foreach (IndigoObject item in deco.iterateDecomposedMolecules())
     System.Console.WriteLine(item.decomposedMoleculeWithRGroups().molfile());

Python:

  deco = indigo.decomposeMolecules(scaf, arr);
  deco.decomposedMoleculeHighlighted().saveMolfile("highlighted.mol");
  scaffold = deco.decomposedMoleculeScaffold();
  scaffold.layout();
  scaffold.saveMolfile("scaffold.mol");
  for item in deco.iterateDecomposedMolecules():
     print item.decomposedMoleculeWithRGroups().molfile()

Reaction Products Enumeration

Java:

  IndigoObject reaction = indigo.loadQueryReactionFromFile(rxn_path);
  IndigoObject monomers_table = indigo.createArray();
  for (int i = 0; i < reaction.countReactants(); i++)
  {
     monomers_table.arrayAdd(indigo.createArray());

     for (IndigoObject iterr : indigo.iterateSDFile(mon_paths[i])
     {
        monomers_table.at(i).arrayAdd(iterr.clone());
     }
  }
  IndigoObject output_reactions = indigo.reactionProductEnumerate(reaction, monomers_table);

Reaction-based Molecule Transformations

Examples of usage are avialible here.

Java:

  IndigoObject reaction = indigo.loadQueryReaction("[NH:3]=[N:1]#[N:2]>>[NH:3]=[N+:1]=[#7-:2]");
  IndigoObject molecule = indigo.loadMolecule("N#N=NC1=CC(=CC=C1)N=N#N");
  indigo.transform(reaction, molecule);
  System.out.println(molecule.smiles); // N(C1=CC=CC(N=[N+]=[N-])=C1)=[N+]=[N-]

Rendering

Rending in Indigo is done by the IndigoRenderer plugin which is included in the Indigo distribution. The plugin is available for C (as a separate dynamic library), and has wrappers for all supported languages.

To work with the rendering plugin in C#/Java/Python wrappers, one needs to create an instance of IndigoRenderer, passing an existing Indigo instance to it.

Java and C#:

IndigoRenderer renderer = new IndigoRenderer();

A large number of options can be set for the rendering plugin. They are set via the ordinary Indigo instance. One of the options is obligatory: render-output-format tells which format the image should be rendered to.

The IndigoRenderer.renderToBuffer accepts an IndigoObject and returns a byte buffer with PNG, SVG, or PDF image (on the Windows platform, EMF format is supported too). Similarly, the IndigoRenderer.renderToFile method saves the image to a file.

Java and C#:

indigo.setOption("render-output-format", "png");
indigo.setOption("render-margins", 10, 10);
mol1.layout();
indigo.setOption("render-comment", "N-Hydroxyaniline")
renderer.renderToFile(mol1, "mol.png");

indigo.setOption("render-output-format", "svg");
byte[] svg = renderer.renderToBuffer(rxn);

Python: the same with the byte[] omitted.

Rendering Multiple Items to Grid

IndigoRenderer.renderGridToFile and IndigoRenderer.renderGridToBuffer methods can be used to render multiple molecules or reactions at once. The rendered items are placed in grid specified by its number of columns. Some options are available for placing titles under (or above) the items.

Java:

IndigoObject arr = indigo.createArray();

for (IndigoObject item : indigo.iterateSDFile("structures.sdf"))
   arr.arrayAdd(item);

renderer.renderGridToFile(collection, null, 4, "structures.png");

C#:

IndigoObject arr = indigo.createArray();

foreach (IndigoObject item in indigo.iterateSDFile("structures.sdf"))
   arr.arrayAdd(item);

renderer.renderGridToFile(collection, null, 4, "structures.png");

Python:

arr = indigo.createArray();

for item in indigo.iterateSDFile("structures.sdf"):
   arr.arrayAdd(item);

renderer.renderGridToFile(collection, None, 4, "structures.png")

The second parameter of the IndigoRenderer.renderGridToFile and IndigoRenderer.renderGridToBuffer methods is optional. You can specify it only for molecules, not for reactions. If this parameter is not null, it has to be an integer array whose number of elements is equal to the number of given molecules. Each element of this array is the index of the "referene atom" in the corresponding molecule. The rendering is then done in such a way that the reference atoms are grid-aligned. You can see the examples of this at CTR.

Win32 and .NET Support

In the .NET API, additional IndigoRenderer methods are available for working with Win32 HDC and System.Drawing objects directly: