Hello all,

I'm coding up a method that displays my molecule as an image so that I
can visually inspect my program's intermediate results. For this the
rendering tutorials on SF and Egon's blog have been extremely helpful.
However, I run into a small problem when trying to render with
aromatic circles.

I'm following this tutorial:
https://sourceforge.net/apps/mediawiki/cdk/index.php?title=Renderer_Tutorial-Standard_Generators

It basically describes that to draw aromatic circles, you switch the
renderer's "BasicBondGenerator" with the more specific
"RingGenerator". When I do this I get an exception about one of the
bond generator parameters (BondLength) not being set (see below). From
the tutorial I understand that the RingGenerator should be a drop-in
replacement for the BasicBondGenerator, but from this exception this
doesn't seem to be the case: the RingGenerator doesn't set something
that the BasicBondGenerator does set..

Is this a bug in the RingGenerator? a bug in my reasoning? or an
oversight of the tutorial?

for reference purposes, I attached my code that draws the image.

On a slightly related note, I'm looking for the bit of code that will
display the title with the molecule, but haven't found it yet. any
help on that will also be greatly appreciated.

kind regards,
Jules

-- exception ---------

Exception in thread "main" java.lang.IllegalAccessError: You requested
the active parameter of type
org.openscience.cdk.renderer.generators.BasicBondGenerator$BondLength,
but it has not been registered yet. Did you make sure the
IGeneratorParameter is registered, by registring the appropriate
IGenerator? Alternatively, you can use getDefault() to query the
default value for any parameter on the classpath.
        at 
org.openscience.cdk.renderer.RendererModel.getParameter(RendererModel.java:347)
        at 
org.openscience.cdk.renderer.AtomContainerRenderer.calculateScaleForBondLength(AtomContainerRenderer.java:515)
        at 
org.openscience.cdk.renderer.AtomContainerRenderer.setScale(AtomContainerRenderer.java:230)
        at 
org.openscience.cdk.renderer.AtomContainerRenderer.setup(AtomContainerRenderer.java:157)
        at 
nl.ru.cmbi.biometa.util.ChemImageTool.makeMolImage(ChemImageTool.java:117)
/**
 * 
 */
package nl.ru.cmbi.biometa.util;

import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Rectangle;
import java.awt.image.BufferedImage;
import java.awt.image.RenderedImage;
import java.io.FileOutputStream;
import java.util.ArrayList;
import java.util.List;

import javax.imageio.ImageIO;

import org.openscience.cdk.CDKConstants;
import org.openscience.cdk.aromaticity.CDKHueckelAromaticityDetector;
import org.openscience.cdk.exception.CDKException;
import org.openscience.cdk.geometry.GeometryTools;
import org.openscience.cdk.interfaces.IAtomContainer;
import org.openscience.cdk.interfaces.IMolecule;
import org.openscience.cdk.layout.StructureDiagramGenerator;
import org.openscience.cdk.renderer.AtomContainerRenderer;
import org.openscience.cdk.renderer.font.AWTFontManager;
import org.openscience.cdk.renderer.generators.BasicAtomGenerator;
import org.openscience.cdk.renderer.generators.BasicBondGenerator;
import org.openscience.cdk.renderer.generators.BasicSceneGenerator;
import org.openscience.cdk.renderer.generators.IGenerator;
import org.openscience.cdk.renderer.generators.RingGenerator;
import org.openscience.cdk.renderer.visitor.AWTDrawVisitor;
import org.openscience.cdk.templates.MoleculeFactory;
import org.openscience.cdk.tools.manipulator.AtomContainerManipulator;

/**
 * @author jkerssem
 *
 */
public class ChemImageTool {
	private StructureDiagramGenerator	structureDiagramGenerator;
	private AtomContainerRenderer	renderer;
	private Color	defaultBGColor;

	/**
	 * @param height
	 * @param width
	 * @throws Exception 
	 */
	public ChemImageTool() {
		super();
		// in case we need to add coordinates
		structureDiagramGenerator = new StructureDiagramGenerator();

		// init the renderer
		List<IGenerator<IAtomContainer>> generators = new ArrayList<IGenerator<IAtomContainer>>();
		generators.add(new BasicSceneGenerator());
		generators.add(new RingGenerator());
//		generators.add(new BasicBondGenerator());
		generators.add(new BasicAtomGenerator());
		renderer = new AtomContainerRenderer(generators, new AWTFontManager());
		
		
		// set defaults
		defaultBGColor = Color.white;
	}

	/**
	 * @return the defaultBGColor
	 */
	public Color getDefaultBGColor() {
		return defaultBGColor;
	}

	/**
	 * @param defaultBGColor the default background color to set
	 */
	public void setDefaultBGColor(Color defaultBGColor) {
		this.defaultBGColor = defaultBGColor;
	}

	/**
	 * generates an image of the molecule, using the default background color.
	 * 
	 * @param	molecule	the molecule to render.
	 * 	Coordinates will be generated by the {...@link StructureDiagramGenerator} 
	 * 	if they are not already provided in the molecule.
	 * @param	width		the desired width of the drawing canvas
	 * @param	height		the desired height of the drawing canvas
	 * @return	a flat, 2D rasterimage of the molecule.
	 * @throws CDKException	when no coordinates could be generated for the input molecule.
	 * 	(Will never occur if coordinates were already provided)
	 */
	public RenderedImage makeMolImage(IMolecule molecule, int width, int height) throws CDKException {
		return makeMolImage(molecule, width, height, this.defaultBGColor);
	}

	public RenderedImage makeMolImage(IMolecule molecule, int width, int height, Color backgroundColor) throws CDKException {
		// perceive atom configuration
		AtomContainerManipulator.percieveAtomTypesAndConfigureAtoms(molecule);
		CDKHueckelAromaticityDetector.detectAromaticity(molecule);
		
		// generate coordinates if necessary
		if (! GeometryTools.has2DCoordinates(molecule)) {
			structureDiagramGenerator.setMolecule(molecule);
			try {
				structureDiagramGenerator.generateCoordinates();
			} catch (Exception e) {
				throw new CDKException("Could not generate coordinates for coordinate-less input", e);
			}
			molecule = structureDiagramGenerator.getMolecule();
		}
		
		// prepare canvas
		Rectangle drawArea = new Rectangle(width, height);
		Image image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
		renderer.setup(molecule, drawArea);

		// fill the background
		Graphics2D g2 = (Graphics2D)image.getGraphics();
		g2.setColor(Color.WHITE);
		g2.fillRect(0, 0, width, height);

		// render
		renderer.paint(molecule, new AWTDrawVisitor(g2));

		return (RenderedImage) image ;
	}

	public static void main(String[] args) {
		try {
			// init
			ChemImageTool cit = new ChemImageTool();
			IMolecule molecule = MoleculeFactory.makePhenylAmine();
			
			// set properties to see which one ends up in title
			molecule.setProperty(CDKConstants.COMMENT, "comment");
			molecule.setProperty(CDKConstants.DESCRIPTION, "descr");
			molecule.setProperty(CDKConstants.NAMES, "names");
			molecule.setProperty(CDKConstants.TITLE, "title");
			
			// make+write image
			RenderedImage molImage = cit.makeMolImage(molecule, 600, 600);
			ImageIO.write(molImage, "PNG", new FileOutputStream("molimage.png"));

		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}
------------------------------------------------------------------------------
This SF.net email is sponsored by Sprint
What will you do first with EVO, the first 4G phone?
Visit sprint.com/first -- http://p.sf.net/sfu/sprint-com-first
_______________________________________________
Cdk-user mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/cdk-user

Reply via email to