January 27, 2012
SMARTCyp with ChemDoodle web components
We have done this for two major reasons, the first one is speed. Creating HTML output by writing text files with javascript is much faster than generating three png files for each molecule. While the old version output is still available in SMARTCyp, the default HTML output is HTML5 using ChemDoodle web components. Not only is it faster, it looks nicer too.
The second reason is platform compatibility, the new HTML output can also respond to input from touch-screens. A touch input on the structures (when using your mobile phone or your tablet device) will display atom numbers in the same way a mouseover effect does it on a standard computer. To get this working we simply made duplicate functions in the javascript. There are mousover and mouseout functions for displaying and not displaying atom numbers. The same functions also exist as touchstart and touchend functions. If you want the details, just check out the resulting HTML you get when you run a molecule on our web server.
When we did this we also changed the sketcher on our web server start page. It used to be a JchemPaint sketcher applet. Since this is java it simply does not work on all mobile devices (and Ipads). Now we instead use the ChemDoodle sketcher, which loads much faster, and is compatible for all mobile devices as well.
January 10, 2012
Chemdoodle web components tricks #4: showing atom numbers with the altLabel property
A canvas with atom numbers shown:
The javascript code for a canvas with atom numbers:
var tutorial4_testmol2 = new ChemDoodle.ViewerCanvas('tutorial4_testmol2', 300, 300); tutorial4_testmol2.specs.atoms_useJMOLColors = true; var caffeineMolFile = 'Molecule Name\n CHEMDOOD08070920033D 0 0.00000 0.00000 0\n[Insert Comment Here]\n 14 15 0 0 0 0 0 0 0 0 1 V2000\n -0.3318 2.0000 0.0000 O 0 0 0 1 0 0 0 0 0 0 0 0\n -0.3318 1.0000 0.0000 C 0 0 0 1 0 0 0 0 0 0 0 0\n -1.1980 0.5000 0.0000 N 0 0 0 1 0 0 0 0 0 0 0 0\n 0.5342 0.5000 0.0000 C 0 0 0 1 0 0 0 0 0 0 0 0\n -1.1980 -0.5000 0.0000 C 0 0 0 1 0 0 0 0 0 0 0 0\n -2.0640 1.0000 0.0000 C 0 0 0 4 0 0 0 0 0 0 0 0\n 1.4804 0.8047 0.0000 N 0 0 0 1 0 0 0 0 0 0 0 0\n 0.5342 -0.5000 0.0000 C 0 0 0 1 0 0 0 0 0 0 0 0\n -2.0640 -1.0000 0.0000 O 0 0 0 1 0 0 0 0 0 0 0 0\n -0.3318 -1.0000 0.0000 N 0 0 0 1 0 0 0 0 0 0 0 0\n 2.0640 -0.0000 0.0000 C 0 0 0 2 0 0 0 0 0 0 0 0\n 1.7910 1.7553 0.0000 C 0 0 0 4 0 0 0 0 0 0 0 0\n 1.4804 -0.8047 0.0000 N 0 0 0 1 0 0 0 0 0 0 0 0\n -0.3318 -2.0000 0.0000 C 0 0 0 4 0 0 0 0 0 0 0 0\n 1 2 2 0 0 0 0\n 3 2 1 0 0 0 0\n 4 2 1 0 0 0 0\n 3 5 1 0 0 0 0\n 3 6 1 0 0 0 0\n 7 4 1 0 0 0 0\n 4 8 2 0 0 0 0\n 9 5 2 0 0 0 0\n 10 5 1 0 0 0 0\n 10 8 1 0 0 0 0\n 7 11 1 0 0 0 0\n 7 12 1 0 0 0 0\n 13 8 1 0 0 0 0\n 13 11 2 0 0 0 0\n 10 14 1 0 0 0 0\nM END\n>\n07-08-2009\n'; var caffeine = ChemDoodle.readMOL(caffeineMolFile); // get the dimension of the molecule var size = caffeine.getDimension(); // find the scale by taking the minimum of the canvas/size ratios var scale = Math.min(tutorial4_testmol2.width/size.x, tutorial4_testmol2.height/size.y); // load the molecule first (this function automatically sets scale, so we need to change specs after) tutorial4_testmol2.loadMolecule(caffeine); // change the specs.scale value to the scale calculated, shrinking it slightly so that text is not cut off tutorial4_testmol2.specs.scale = scale*.9; //now display atom numbers instead of element letter for (var i = 0, ii=caffeine.atoms.length; i<ii; i++) { caffeine.atoms[i].altLabel = i+1; } //repaint the canvas in correct scale with atom numbers tutorial4_testmol2.repaint();
January 2, 2012
Using CDK to output a ChemDoodle web component canvas
What ChemDoodle web components needs is actually a molfile with 2D coordinates on one line without line breaks (and explicit \n in place of the line breaks). So that's what we're generating here.
The molecule (variable name "molecule" is assumed to have 2D coordinates, if it only has 3D coordinates it will not look very nice, and without coordinates it will not work at all.
ByteArrayOutputStream baos = new ByteArrayOutputStream(); MDLV2000Writer writer = new MDLV2000Writer(baos); //force 2D coordinates even if 3D exists Properties customSettings = new Properties(); customSettings.setProperty("ForceWriteAs2DCoordinates", "true"); PropertiesListener listener = new PropertiesListener(customSettings); writer.addChemObjectIOListener(listener); //end force 2D coordinates //write the molecule to the outputstream try { writer.write(molecule); } catch (CDKException e) { e.printStackTrace(); } //convert the outputstream to a string String MoleculeString = baos.toString(); //now split MoleculeString into multiple lines to enable explicit printout of \n String Moleculelines[] = MoleculeString.split("\\r?\\n"); //now we print the javascript variable in the canvas outfile.print("var myMolFile = '"); for(int i=0; i<Moleculelines.length; i++){ outfile.print(Moleculelines[i]); outfile.print("\\n"); }And then you just have to surround this javascript variable with the required settings and canvas definitions as described in my earlier posts about ChemDoodle: Chemdoodle web components tricks #1: scaling molecules, Chemdoodle web components tricks #2: showing atom numbers , Chemdoodle web components tricks #3: Using mouseover functions to do multiple repaints on a canvas
December 31, 2011
Chemdoodle web components tricks #3: Using mouseover functions to do multiple repaints on a canvas
Here I show how you can use mouseover, and mouseout functions to redraw the canvas over and over again, and infinite number of times. The trick is to minimize the mouseover and mouseout functions, and use the drawChildExtras function to do all the drawings. Also, the first four lines and the last line in the drawChildExtras function are required to make this work (thanks to Kevin Theisen for helping me with those).
Here is the canvas, and below is the annotated code.
And here is the code:
var tutorial3_testmol = new ChemDoodle.ViewerCanvas('tutorial3_testmol', 300, 300); tutorial3_testmol.specs.atoms_useJMOLColors = true; var caffeineMolFile = 'Molecule Name\n CHEMDOOD08070920033D 0 0.00000 0.00000 0\n[Insert Comment Here]\n 14 15 0 0 0 0 0 0 0 0 1 V2000\n -0.3318 2.0000 0.0000 O 0 0 0 1 0 0 0 0 0 0 0 0\n -0.3318 1.0000 0.0000 C 0 0 0 1 0 0 0 0 0 0 0 0\n -1.1980 0.5000 0.0000 N 0 0 0 1 0 0 0 0 0 0 0 0\n 0.5342 0.5000 0.0000 C 0 0 0 1 0 0 0 0 0 0 0 0\n -1.1980 -0.5000 0.0000 C 0 0 0 1 0 0 0 0 0 0 0 0\n -2.0640 1.0000 0.0000 C 0 0 0 4 0 0 0 0 0 0 0 0\n 1.4804 0.8047 0.0000 N 0 0 0 1 0 0 0 0 0 0 0 0\n 0.5342 -0.5000 0.0000 C 0 0 0 1 0 0 0 0 0 0 0 0\n -2.0640 -1.0000 0.0000 O 0 0 0 1 0 0 0 0 0 0 0 0\n -0.3318 -1.0000 0.0000 N 0 0 0 1 0 0 0 0 0 0 0 0\n 2.0640 -0.0000 0.0000 C 0 0 0 2 0 0 0 0 0 0 0 0\n 1.7910 1.7553 0.0000 C 0 0 0 4 0 0 0 0 0 0 0 0\n 1.4804 -0.8047 0.0000 N 0 0 0 1 0 0 0 0 0 0 0 0\n -0.3318 -2.0000 0.0000 C 0 0 0 4 0 0 0 0 0 0 0 0\n 1 2 2 0 0 0 0\n 3 2 1 0 0 0 0\n 4 2 1 0 0 0 0\n 3 5 1 0 0 0 0\n 3 6 1 0 0 0 0\n 7 4 1 0 0 0 0\n 4 8 2 0 0 0 0\n 9 5 2 0 0 0 0\n 10 5 1 0 0 0 0\n 10 8 1 0 0 0 0\n 7 11 1 0 0 0 0\n 7 12 1 0 0 0 0\n 13 8 1 0 0 0 0\n 13 11 2 0 0 0 0\n 10 14 1 0 0 0 0\nM END\n>\n07-08-2009\n'; var caffeine = ChemDoodle.readMOL(caffeineMolFile); // get the dimension of the molecule var size = caffeine.getDimension(); // find the scale by taking the minimum of the canvas/size ratios var scale = Math.min(tutorial3_testmol.width/size.x, tutorial3_testmol.height/size.y); // load the molecule first (this function automatically sets scale, so we need to change specs after) tutorial3_testmol.loadMolecule(caffeine); // change the specs.scale value to the scale calculated, shrinking it slightly so that text is not cut off tutorial3_testmol.specs.scale = scale*.8; //we are not showing atom numbers right away var showatomnumbers = false; tutorial3_testmol.mouseover = function(){ //set atom numbers to be displayed showatomnumbers = true; this.repaint(); } tutorial3_testmol.mouseout = function(){ //set atom numbers to be hidden showatomnumbers = false; this.repaint(); } tutorial3_testmol.drawChildExtras = function(ctx){ //four lines to make sure atom numbering, coordinates and scaling work correctly ctx.save(); ctx.translate(this.width/2, this.height/2); ctx.rotate(this.specs.rotateAngle); ctx.scale(this.specs.scale, this.specs.scale); ctx.translate(-this.width/2, -this.height/2); //set the font size relative to the scaling of the molecule ctx.font = 'bold ' + 2.5*scale + 'px sans-serif'; //center the atom numbers over the x,y coordinates of the atoms ctx.textAlign = 'center'; ctx.textBaseline = 'middle'; //iterate through all atoms for (var i = 0, ii=caffeine.atoms.length; i<ii; i++) { var atom = caffeine.atoms[i]; if(showatomnumbers){ //draw a white circle behind the atom number ctx.fillStyle = "white"; ctx.beginPath(); ctx.arc(atom.x, atom.y, scale*1.8, 0, Math.PI*2, true); ctx.fill(); //draw the atom number in the color ctx.fillStyle = ChemDoodle.ELEMENT[atom.label].jmolColor; //the "+scale*0.7" is to adjust the text on the y-center of the atoms. ctx.fillText(i + 1, atom.x, atom.y); } } //restore the ctx settings so that application next time will start from scratch ctx.restore(); } tutorial3_testmol.repaint();
December 26, 2011
Chemdoodle web components tricks #2: showing atom numbers
My second try on using the chemdoodle web compontents.
Very nice GPL licensed javascript library for chemical 2D (and 3D if you have a webGL supporting browser).
Standard canvas with a caffeine molecule and colored atom labels (from my last post on scaling):
And here, the same canvas with atom numbers shown:
The javascript code for the standard scaled canvas:
var tutorial2_testmol = new ChemDoodle.ViewerCanvas('tutorial2_testmol', 300, 300); tutorial2_testmol.specs.atoms_useJMOLColors = true; var caffeineMolFile = 'Molecule Name\n CHEMDOOD08070920033D 0 0.00000 0.00000 0\n[Insert Comment Here]\n 14 15 0 0 0 0 0 0 0 0 1 V2000\n -0.3318 2.0000 0.0000 O 0 0 0 1 0 0 0 0 0 0 0 0\n -0.3318 1.0000 0.0000 C 0 0 0 1 0 0 0 0 0 0 0 0\n -1.1980 0.5000 0.0000 N 0 0 0 1 0 0 0 0 0 0 0 0\n 0.5342 0.5000 0.0000 C 0 0 0 1 0 0 0 0 0 0 0 0\n -1.1980 -0.5000 0.0000 C 0 0 0 1 0 0 0 0 0 0 0 0\n -2.0640 1.0000 0.0000 C 0 0 0 4 0 0 0 0 0 0 0 0\n 1.4804 0.8047 0.0000 N 0 0 0 1 0 0 0 0 0 0 0 0\n 0.5342 -0.5000 0.0000 C 0 0 0 1 0 0 0 0 0 0 0 0\n -2.0640 -1.0000 0.0000 O 0 0 0 1 0 0 0 0 0 0 0 0\n -0.3318 -1.0000 0.0000 N 0 0 0 1 0 0 0 0 0 0 0 0\n 2.0640 -0.0000 0.0000 C 0 0 0 2 0 0 0 0 0 0 0 0\n 1.7910 1.7553 0.0000 C 0 0 0 4 0 0 0 0 0 0 0 0\n 1.4804 -0.8047 0.0000 N 0 0 0 1 0 0 0 0 0 0 0 0\n -0.3318 -2.0000 0.0000 C 0 0 0 4 0 0 0 0 0 0 0 0\n 1 2 2 0 0 0 0\n 3 2 1 0 0 0 0\n 4 2 1 0 0 0 0\n 3 5 1 0 0 0 0\n 3 6 1 0 0 0 0\n 7 4 1 0 0 0 0\n 4 8 2 0 0 0 0\n 9 5 2 0 0 0 0\n 10 5 1 0 0 0 0\n 10 8 1 0 0 0 0\n 7 11 1 0 0 0 0\n 7 12 1 0 0 0 0\n 13 8 1 0 0 0 0\n 13 11 2 0 0 0 0\n 10 14 1 0 0 0 0\nM END\n>\n07-08-2009\n'; var caffeine = ChemDoodle.readMOL(caffeineMolFile); // get the dimension of the molecule var size = caffeine.getDimension(); // find the scale by taking the minimum of the canvas/size ratios var scale = Math.min(tutorial2_testmol.width/size.x, tutorial2_testmol.height/size.y); // load the molecule first (this function automatically sets scale, so we need to change specs after) tutorial2_testmol.loadMolecule(caffeine); // change the specs.scale value to the scale calculated, shrinking it slightly so that text is not cut off tutorial2_testmol.specs.scale = scale*.9; // repaint the canvas tutorial2_testmol.repaint();
and the javascript code for the canvas with the atom numbers:
var tutorial2_testmol2 = new ChemDoodle.ViewerCanvas('tutorial2_testmol2', 300, 300); tutorial2_testmol2.specs.atoms_useJMOLColors = true; var caffeineMolFile = 'Molecule Name\n CHEMDOOD08070920033D 0 0.00000 0.00000 0\n[Insert Comment Here]\n 14 15 0 0 0 0 0 0 0 0 1 V2000\n -0.3318 2.0000 0.0000 O 0 0 0 1 0 0 0 0 0 0 0 0\n -0.3318 1.0000 0.0000 C 0 0 0 1 0 0 0 0 0 0 0 0\n -1.1980 0.5000 0.0000 N 0 0 0 1 0 0 0 0 0 0 0 0\n 0.5342 0.5000 0.0000 C 0 0 0 1 0 0 0 0 0 0 0 0\n -1.1980 -0.5000 0.0000 C 0 0 0 1 0 0 0 0 0 0 0 0\n -2.0640 1.0000 0.0000 C 0 0 0 4 0 0 0 0 0 0 0 0\n 1.4804 0.8047 0.0000 N 0 0 0 1 0 0 0 0 0 0 0 0\n 0.5342 -0.5000 0.0000 C 0 0 0 1 0 0 0 0 0 0 0 0\n -2.0640 -1.0000 0.0000 O 0 0 0 1 0 0 0 0 0 0 0 0\n -0.3318 -1.0000 0.0000 N 0 0 0 1 0 0 0 0 0 0 0 0\n 2.0640 -0.0000 0.0000 C 0 0 0 2 0 0 0 0 0 0 0 0\n 1.7910 1.7553 0.0000 C 0 0 0 4 0 0 0 0 0 0 0 0\n 1.4804 -0.8047 0.0000 N 0 0 0 1 0 0 0 0 0 0 0 0\n -0.3318 -2.0000 0.0000 C 0 0 0 4 0 0 0 0 0 0 0 0\n 1 2 2 0 0 0 0\n 3 2 1 0 0 0 0\n 4 2 1 0 0 0 0\n 3 5 1 0 0 0 0\n 3 6 1 0 0 0 0\n 7 4 1 0 0 0 0\n 4 8 2 0 0 0 0\n 9 5 2 0 0 0 0\n 10 5 1 0 0 0 0\n 10 8 1 0 0 0 0\n 7 11 1 0 0 0 0\n 7 12 1 0 0 0 0\n 13 8 1 0 0 0 0\n 13 11 2 0 0 0 0\n 10 14 1 0 0 0 0\nM END\n>\n07-08-2009\n'; var caffeine = ChemDoodle.readMOL(caffeineMolFile); // get the dimension of the molecule var size = caffeine.getDimension(); // find the scale by taking the minimum of the canvas/size ratios var scale = Math.min(tutorial2_testmol2.width/size.x, tutorial2_testmol2.height/size.y); // load the molecule first (this function automatically sets scale, so we need to change specs after) tutorial2_testmol2.loadMolecule(caffeine); // change the specs.scale value to the scale calculated, shrinking it slightly so that text is not cut off tutorial2_testmol2.specs.scale = scale*.9; tutorial2_testmol2.repaint(); var molcenter = caffeine.getCenter(); tutorial2_testmol2.drawChildExtras = function(ctx){ ctx.translate(this.width/2, this.height/2); ctx.rotate(this.specs.rotateAngle); ctx.scale(this.specs.scale, this.specs.scale); ctx.translate(-this.width/2, -this.height/2); //draw atom numbers ctx.font = 'bold ' + 2.5*scale + 'px sans-serif'; ctx.textAlign = 'center'; ctx.textBaseline = 'middle'; //iterate through all atoms for (var i = 0, ii=caffeine.atoms.length; i<ii; i++) { var atom = caffeine.atoms[i]; //draw a white circle behind the atom number ctx.fillStyle = "white"; ctx.strokeStyle = "white"; ctx.beginPath(); ctx.arc(atom['x'],atom['y'],scale*1.8,0,Math.PI*2,true); ctx.fill(); ctx.stroke(); //draw the atom number thisatomcolor = ChemDoodle.ELEMENT[atom['label']].jmolColor; ctx.fillStyle = thisatomcolor; ctx.fillText(i + 1, atom['x'], atom['y']); } } tutorial2_testmol2.repaint();
The trickiest part about this is that while the first four lines in the drawChildExtras function (as suggested by Kevin in the comments and the fourth line is needed to simplify the atom locations), do scale the drawing on the canvas correctly, they do not scale or translate the molecule. That's why I had to subtract the x and y coordinates of the center of the molecule to get the positions right.
December 23, 2011
Chemdoodle web components tricks #1: scaling molecules
However, the standard API still is missing some functionality. But you can fix most things by using standard javascript (at least as long as you're only using a standard viewer canvas, without zoom functionality).
Here I will show how you can scale a molecule to the size of the canvas. The standard viewercanvas will not scale molecules to the size of the canvas. So I added this to my code.
Standard canvas with a caffeine molecule and colored atom labels:
And here, the same canvas with the molecule scaled by the size of the canvas:
The javascript code for the standard canvas:
var testmol = new ChemDoodle.ViewerCanvas('testmol', 300, 300); testmol.specs.atoms_useJMOLColors = true; var caffeineMolFile = 'Molecule Name\n CHEMDOOD08070920033D 0 0.00000 0.00000 0\n[Insert Comment Here]\n 14 15 0 0 0 0 0 0 0 0 1 V2000\n -0.3318 2.0000 0.0000 O 0 0 0 1 0 0 0 0 0 0 0 0\n -0.3318 1.0000 0.0000 C 0 0 0 1 0 0 0 0 0 0 0 0\n -1.1980 0.5000 0.0000 N 0 0 0 1 0 0 0 0 0 0 0 0\n 0.5342 0.5000 0.0000 C 0 0 0 1 0 0 0 0 0 0 0 0\n -1.1980 -0.5000 0.0000 C 0 0 0 1 0 0 0 0 0 0 0 0\n -2.0640 1.0000 0.0000 C 0 0 0 4 0 0 0 0 0 0 0 0\n 1.4804 0.8047 0.0000 N 0 0 0 1 0 0 0 0 0 0 0 0\n 0.5342 -0.5000 0.0000 C 0 0 0 1 0 0 0 0 0 0 0 0\n -2.0640 -1.0000 0.0000 O 0 0 0 1 0 0 0 0 0 0 0 0\n -0.3318 -1.0000 0.0000 N 0 0 0 1 0 0 0 0 0 0 0 0\n 2.0640 -0.0000 0.0000 C 0 0 0 2 0 0 0 0 0 0 0 0\n 1.7910 1.7553 0.0000 C 0 0 0 4 0 0 0 0 0 0 0 0\n 1.4804 -0.8047 0.0000 N 0 0 0 1 0 0 0 0 0 0 0 0\n -0.3318 -2.0000 0.0000 C 0 0 0 4 0 0 0 0 0 0 0 0\n 1 2 2 0 0 0 0\n 3 2 1 0 0 0 0\n 4 2 1 0 0 0 0\n 3 5 1 0 0 0 0\n 3 6 1 0 0 0 0\n 7 4 1 0 0 0 0\n 4 8 2 0 0 0 0\n 9 5 2 0 0 0 0\n 10 5 1 0 0 0 0\n 10 8 1 0 0 0 0\n 7 11 1 0 0 0 0\n 7 12 1 0 0 0 0\n 13 8 1 0 0 0 0\n 13 11 2 0 0 0 0\n 10 14 1 0 0 0 0\nM END\n>\n07-08-2009\n'; var caffeine = ChemDoodle.readMOL(caffeineMolFile); testmol.loadMolecule(caffeine);
and the javascript code for the canvas with the scaled molecule:
var testmol2 = new ChemDoodle.ViewerCanvas('testmol2', 300, 300); testmol2.specs.atoms_useJMOLColors = true; var caffeineMolFile = 'Molecule Name\n CHEMDOOD08070920033D 0 0.00000 0.00000 0\n[Insert Comment Here]\n 14 15 0 0 0 0 0 0 0 0 1 V2000\n -0.3318 2.0000 0.0000 O 0 0 0 1 0 0 0 0 0 0 0 0\n -0.3318 1.0000 0.0000 C 0 0 0 1 0 0 0 0 0 0 0 0\n -1.1980 0.5000 0.0000 N 0 0 0 1 0 0 0 0 0 0 0 0\n 0.5342 0.5000 0.0000 C 0 0 0 1 0 0 0 0 0 0 0 0\n -1.1980 -0.5000 0.0000 C 0 0 0 1 0 0 0 0 0 0 0 0\n -2.0640 1.0000 0.0000 C 0 0 0 4 0 0 0 0 0 0 0 0\n 1.4804 0.8047 0.0000 N 0 0 0 1 0 0 0 0 0 0 0 0\n 0.5342 -0.5000 0.0000 C 0 0 0 1 0 0 0 0 0 0 0 0\n -2.0640 -1.0000 0.0000 O 0 0 0 1 0 0 0 0 0 0 0 0\n -0.3318 -1.0000 0.0000 N 0 0 0 1 0 0 0 0 0 0 0 0\n 2.0640 -0.0000 0.0000 C 0 0 0 2 0 0 0 0 0 0 0 0\n 1.7910 1.7553 0.0000 C 0 0 0 4 0 0 0 0 0 0 0 0\n 1.4804 -0.8047 0.0000 N 0 0 0 1 0 0 0 0 0 0 0 0\n -0.3318 -2.0000 0.0000 C 0 0 0 4 0 0 0 0 0 0 0 0\n 1 2 2 0 0 0 0\n 3 2 1 0 0 0 0\n 4 2 1 0 0 0 0\n 3 5 1 0 0 0 0\n 3 6 1 0 0 0 0\n 7 4 1 0 0 0 0\n 4 8 2 0 0 0 0\n 9 5 2 0 0 0 0\n 10 5 1 0 0 0 0\n 10 8 1 0 0 0 0\n 7 11 1 0 0 0 0\n 7 12 1 0 0 0 0\n 13 8 1 0 0 0 0\n 13 11 2 0 0 0 0\n 10 14 1 0 0 0 0\nM END\n>\n07-08-2009\n'; var caffeine = ChemDoodle.readMOL(caffeineMolFile); // get the dimension of the molecule var size = caffeine.getDimension(); // find the scale by taking the minimum of the canvas/size ratios var scale = Math.min(testmol2.width/size.x, testmol2.height/size.y); // load the molecule first (this function automatically sets scale, so we need to change specs after) testmol2.loadMolecule(caffeine); // change the specs.scale value to the scale calculated, shrinking it slightly so that text is not cut off testmol2.specs.scale = scale*.9; // repaint the canvas testmol2.repaint();
The code for the scaled figure updated after the comment below from Kevin Theisen. So now the code is simpler, but requires a repaint() command instead. Thanks to Kevin for this.
December 4, 2011
Circular fingerprints in CDK
The code implements the circular fingerprints from a paper by Xing et al. (J. Chem. Inf. Comput. Sci. 2003, 43, 870-879).
If anyone who has the skills and time would turn this into a proper CDK function which could be implemented into the CDK library that would probably be helpful for other people. Here follows my code with assumes that it's applied in java class where this is an AtomContainer.
// Calculates the atom environment descriptor of all atoms public void calculateAtomEnvironmentDescriptor() throws CDKException{ //maxLevel is how many bonds from the atom we will count atom types int maxLevel = 5; IAtomType[] atomTypes = null; int natoms = this.getAtomCount(); //do atom type matching IAtomTypeMatcher atm = SybylAtomTypeMatcher.getInstance(NoNotificationChemObjectBuilder.getInstance()); InputStream ins = this.getClass().getClassLoader().getResourceAsStream("org/openscience/cdk/dict/data/sybyl-atom-types.owl"); AtomTypeFactory factory = AtomTypeFactory.getInstance(ins,"owl",NoNotificationChemObjectBuilder.getInstance()); atomTypes = factory.getAllAtomTypes(); //map atomtypes to the atomIndex integer array TreeMapBig thanks to Nina Jeliazkova who gave me a preliminary version of the code from her old Ambit code. I have rewritten her code so now it's bug free and faster.map = new TreeMap (); for (int i = 0; i < atomTypes.length; i++) { map.put(atomTypes[i].getAtomTypeName(),new Integer(i)); } int[] atomIndex = new int[natoms]; //array of atom type integers for (int i = 0; i < natoms; i++) { try { IAtomType a = atm.findMatchingAtomType(this,this.getAtom(i)); if ( a != null) { Object mappedType = map.get(a.getAtomTypeName()); if (mappedType != null) atomIndex[i] = ((Integer) mappedType).intValue(); else { //System.out.println(a.getAtomTypeName() + " not found in " + map); atomIndex[i] = -1; } } else //atom type not found atomIndex[i] = -1; } catch (Exception x) { x.printStackTrace(); throw new CDKException(x.getMessage() + "\ninitConnectionMatrix"); } } //compute bond distances between all atoms int[][] aMatrix = PathTools.computeFloydAPSP(AdjacencyMatrix.getMatrix(this)); //assign values to the results arrays for all atoms int L = (atomTypes.length +1) ; int [][] result = new int[natoms][L*(maxLevel)+2]; //create result array for (int i = 0; i < natoms; i++) { //for every atom, iterate through its connections to all other atoms for (int j=0; j < natoms; j++) { if (aMatrix[i][j] == 0) result[i][1] = atomIndex[j]; //atom j is atom i else if (aMatrix[i][j] > 0 && aMatrix[i][j] <= maxLevel){ //j is not atom i and bonds less or equal to maxlevel if (atomIndex[j] >= 0) //atom type defined in factory result[i][L*(aMatrix[i][j]-1)+atomIndex[j]+2]++; else if (atomIndex[j] == -1) //-1, unknown type result[i][L*(aMatrix[i][j]-1)+(L-1)+2]++; } } //checksum for easy comparison for (int j = 1; j < result[i].length; j++) result[i][0] += result[i][j]; } if (debug == 1){ //print out the names of atom types for reference use System.out.print("Sum\tAtomType\t"); for (int j=0; j < factory.getSize(); j++) { System.out.print(j); System.out.print("."); System.out.print(atomTypes[j].getAtomTypeName()); System.out.print("\t"); } System.out.println(""); for (int i = 0; i < natoms; i++) System.out.println(Arrays.toString(result[i])); } }