## Monday, April 05, 2010

### CDK-JChemPaint #1: rendering molecules

I reported earlier that the CDK-JChemPaint patch is now a clean add-on from the CDK releases. This means that you download cdk-1.3.4.jar and cdk-jchempaint-8.jar separately, put them in your class path, and get started with, for example, Groovy:
$export CLASSPATH=cdk-1.3.4.jar:cdk-jchempaint-8.jar$ groovy renderMol.groovy


I have tuned to code in this tutorial by Gilleain a bit, resulting in this code:
import java.util.List;

import java.awt.*;
import java.awt.image.*;

import javax.imageio.*;

import org.openscience.cdk.*;
import org.openscience.cdk.interfaces.*;
import org.openscience.cdk.layout.*;
import org.openscience.cdk.renderer.*;
import org.openscience.cdk.renderer.font.*;
import org.openscience.cdk.renderer.generators.*;
import org.openscience.cdk.renderer.visitor.*;
import org.openscience.cdk.templates.*;

int WIDTH = 600;
int HEIGHT = 600;

// the draw area and the image should be the same size
Rectangle drawArea = new Rectangle(WIDTH, HEIGHT);
Image image = new BufferedImage(
WIDTH, HEIGHT, BufferedImage.TYPE_INT_RGB
);

IMolecule triazole = MoleculeFactory.make123Triazole();
StructureDiagramGenerator sdg = new StructureDiagramGenerator();
sdg.setMolecule(triazole);
sdg.generateCoordinates();
triazole = sdg.getMolecule();

// generators make the image elements
List generators = new ArrayList();

// the renderer needs to have a toolkit-specific font manager
AtomContainerRenderer renderer =
new AtomContainerRenderer(generators, new AWTFontManager());

// the call to 'setup' only needs to be done on the first paint
renderer.setup(triazole, drawArea);

// paint the background
Graphics2D g2 = (Graphics2D)image.getGraphics();
g2.setColor(Color.WHITE);
g2.fillRect(0, 0, WIDTH, HEIGHT);

// the paint method also needs a toolkit-specific renderer
renderer.paint(triazole, new AWTDrawVisitor(g2));

ImageIO.write((RenderedImage)image, "PNG", new File("triazole.png"));

1. Thanks for the tutorial.

2. Thank you Egon for your article. With your help I was able to render the molecule. I also tried to do it with the help of tutorial by Gilleain but I could not manage to do that. I used cdk v.1.2.4 and cdk-jchemaint-15 and Java could not load BasicBondGenerator class.

3. Dear Паша Мусієнко,

I hope that helps.

4. I actually did. I have downloaded CDK 1.3.4. It helped. :)

5. Dear Egon, I am trying now to render the molecules with adjustable dimensions. In your example they are fixed - 600x600 px.
I would appreciate any information of yours on how to do it. Thanks in advance.
Paul.

6. I have managed to render molecules with canvas adjustable to molecules dimensions. These tutorials helped me - Renderer Tutorial-Molecule Table and Renderer Tutorial-Editing a molecule
I don't know if someone it might help but the following is the code snippet from this article a bit reworked

import java.util.List;

import java.awt.*;
import java.awt.image.*;

import javax.imageio.*;

import org.openscience.cdk.*;
import org.openscience.cdk.interfaces.*;
import org.openscience.cdk.layout.*;
import org.openscience.cdk.renderer.*;
import org.openscience.cdk.renderer.font.*;
import org.openscience.cdk.renderer.generators.*;
import org.openscience.cdk.renderer.visitor.*;
import org.openscience.cdk.templates.*;

int WIDTH = 1;
int HEIGHT = 1;

// the draw area and the image should be the same size
Rectangle drawArea = new Rectangle(0, 0, WIDTH, HEIGHT);

IMolecule triazole = MoleculeFactory.make123Triazole();
StructureDiagramGenerator sdg = new StructureDiagramGenerator();
sdg.setMolecule(triazole);
try {
sdg.generateCoordinates();
} catch (Exception ex) {}
triazole = sdg.getMolecule();

// generators make the image elements
List generators = new ArrayList();

// the renderer needs to have a toolkit-specific font manager
AtomContainerRenderer renderer =
new AtomContainerRenderer(generators, new AWTFontManager());

// the call to 'setup' only needs to be done on the first paint
renderer.setup(triazole, drawArea);

Rectangle diagramRectangle = renderer.calculateDiagramBounds(triazole);
Rectangle result = renderer.shift(drawArea, diagramRectangle);

HEIGHT = (int) (result.getHeight() + result.y);
WIDTH = (int) (result.getWidth() + result.x);

// paint the background
Image image = new BufferedImage(
WIDTH, HEIGHT, BufferedImage.TYPE_INT_RGB
);
Graphics2D g2 = (Graphics2D)image.getGraphics();
g2.setColor(Color.WHITE);
g2.fillRect(0, 0, WIDTH, HEIGHT);

// the paint method also needs a toolkit-specific renderer
renderer.paint(triazole, new AWTDrawVisitor(g2));

ImageIO.write((RenderedImage)image, "PNG", new File("triazole.png"));

7. Happy to hear you got it worked out. I'm quite busy right now; finishing some stuff with deadlines today.

You should start a blog :) Thanx for the code snippet; I'm sure others will find it useful too!

8. Thanks, Egon! In its time maybe I will start one. For now I am a newbie in java.
Thanks again and let your code run smoothly :)

9. Thanks for the post, these code snippets are really useful.