Showing posts with label 2D structures. Show all posts
Showing posts with label 2D structures. Show all posts

December 31, 2011

Chemdoodle web components tricks #3: Using mouseover functions to do multiple repaints on a canvas

Another step on the way to integrating ChemDoodle web components into SMARTCyp.

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

Due to the release of ChemDoodle web components version 4.5 showing atom numbers have been much simplified, and this post has been superseded by a new script in a new post Chemdoodle web components tricks #4: showing atom numbers with the altLabel property

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).

One thing missing from the API is atom numbers (i.e. numbering from 1,2...10 for all atoms). Here I'll show how to display atom numbers using a viewercanvas.

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

I have played around a bit with chemdoodle web compontents. Very nice GPL licensed javascript library for chemical 2D (and 3D if you have a webGL supporting browser).

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.