Anonymous (owner)

Revisions

  • ed802d Tue Jan 06 03:33:06 -0800 2009
gist: 43774 Download_button fork
public
Public Clone URL: git://gist.github.com/43774.git
Embed All Files: show embed
jme2canvas.html #
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
<html>
<head>
<script language=javascript>
//
// molecular depictions in a canvas element, by Richard Hall, Jan 2009
//
// when I've finished reading Crockford's Javascript - The Good Parts, I should tidy this up...
//
 
//a really simple atom class
function Atom(type, x, y){
        this.type = type;
        this.crd = new Array(x, y);
}
 
//an atom representation string
Atom.prototype.repr = function(){
        return('atom '+this.type+':'+this.crd[0]+' '+this.crd[1]);
}
 
//scale 2d atom coordinates to coordinates that will fit in the canvas context, leaving some border
Atom.prototype.context = function(border, xscale, yscale, xr, yr){
        var x = border + (this.crd[0]-xr[0])/(xr[1]-xr[0]) * xscale;
        var y = border + (1.0 - (this.crd[1]-yr[0])/(yr[1]-yr[0])) * yscale;
        return new Array(x, y);
}
 
//a really simple bond class
function Bond(a, b, type){
        this.a = a;
        this.b = b;
        this.type = type;
}
 
//a bond representation string
Bond.prototype.repr = function(){
        var atype = new Array('x', '-', '=', '#');
        return('bond '+this.a+atype[this.type]+this.b);
}
 
//a really simple molecule class, built from a jme string...
function Molecule(str){
        var i;
 
        this.atoms = new Array;
        this.bonds = new Array;
 
        var tok = str.split(" ");
 
        this.natoms = parseInt(tok[0]);
        this.nbonds = parseInt(tok[1]);
 
        for(i=2; i<2+3*this.natoms; i+=3){
                var type = tok[i];
                var xcrd = parseFloat(tok[i+1]);
                var ycrd = parseFloat(tok[i+2]);
                this.atoms[this.atoms.length] = new Atom(type, xcrd, ycrd);
        }
 
        var start = 2+3*this.natoms;
        for(var i=start; i<tok.length; i+=3){
                var a = parseInt(tok[i])-1;
                var b = parseInt(tok[i+1])-1;
                var type = parseInt(tok[i+2]);
                this.bonds[this.bonds.length] = new Bond(a, b, type);
        }
}
 
//a molecular representation string
Molecule.prototype.repr = function(){
        var i;
        var s = '';
        for(i=0; i<this.atoms.length; i++){
                s += this.atoms[i].repr()+'\n';
        }
        for(i=0; i<this.bonds.length; i++){
                s += this.bonds[i].repr()+'\n';
        }
        return(s);
}
 
//return the min max extent in a given dimension (0:x, 1:y)
Molecule.prototype.minmax = function(dim){
        var minv = 99999.9;
        var maxv = -99999.9;
        for(var i=0; i<this.atoms.length;i++){
                minv = this.atoms[i].crd[dim] < minv ? this.atoms[i].crd[dim] : minv;
                maxv = this.atoms[i].crd[dim] > maxv ? this.atoms[i].crd[dim] : maxv;
        }
        return Array(minv, maxv);
}
 
//draw a molecule to the canvas element named id
Molecule.prototype.depict = function(id){
        var cnv = document.getElementById(id);
 
        var border=20; //the amount of whitespace around the depiction in pixels
 
//scaling to make the molecule fit the element dimensions
        var xreg = this.minmax(0);
        var yreg = this.minmax(1);
        var xyratio = (xreg[1]-xreg[0])/(yreg[1]-yreg[0]);
//additional scaling if the canvas is not square...
        var canvasratio = (cnv.width-2*border)/(cnv.height-2*border);
        var xyratio = xyratio/canvasratio;
 
        var xscale, yscale;
        if(xyratio > 1){
                xscale = (cnv.width-2*border);
                yscale = (cnv.height-2*border)/xyratio;
        }
        else{
                xscale = (cnv.width-2*border)*xyratio;
                yscale = (cnv.height-2*border);
        }
 
        var ctx = cnv.getContext('2d');
//clear the context
        ctx.clearRect(0, 0, cnv.width, cnv.height)
//draw the bonds
        for(var i=0; i<this.bonds.length;i++){
                var a = this.atoms[this.bonds[i].a];
                var b = this.atoms[this.bonds[i].b];
                var actx = a.context(border, xscale, yscale, xreg, yreg);
                var bctx = b.context(border, xscale, yscale, xreg, yreg);
                ctx.moveTo(actx[0], actx[1]);
                ctx.lineTo(bctx[0], bctx[1]);
        }
        ctx.stroke();
}
 
//this function is called when the button is pressed - it copies the jme string from the applet and uses it to build a new molecule
function depict(){
        var jmestr = document.getElementById('jme').jmeFile();
        if(jmestr.length()){
                document.getElementById('jmestr').value = jmestr;
        }
        var m = new Molecule(document.getElementById('jmestr').value);
//draw the molecule onto the element with id 'mycanvas'
        m.depict('mycanvas')
}
</script>
</head>
</head>
<body>
<p>
this is an example of using the canvas widget to depict molecules in 2D - to make life a bit easier, I'm starting with the JME string, so I use their coordinates etc for rendering...wouldn't it would be nice to be able to use a molfile or a smiles string though ;)
</p>
<p>
You'll need a copy of the <a href="http://www.molinspiration.com/jme/index.html">JME Editor</a>, <a href="http://www.mozilla-europe.org/en/firefox/">firefox</a> is the only browser I've tested it in and <a href="http://getfirebug.com/">firebug</a> was used during development.
</p>
 
<table>
        <tr>
                <td>
                        <applet id='jme' code='JME.class' archive='JME.jar' codebase='./' width=300 height=300>
                                        <param name='options' value='nohydrogens,query,multipart'>
                        </applet>
</br>
<font face="arial,helvetica,sans-serif"><small><a href="http://www.molinspiration.com/jme/index.html">JME Editor</a> courtesy of Peter Ertl, Novartis</small></font>
                </td>
                <td>
                        <canvas id=mycanvas width=300 height=300>
                        </canvas>
                </td>
        </tr>
</table>
</br>
paste a jme string into the textbox (or draw onto the applet) and click depict - you should see a depiction in the canvas element
</br>
there is a sample string below if you don't have a JME applet to hand - you may need to hack the depict function to get it to work
</br>
<input id=jmestr type=text value="12 13 C 7.32 -7.53 C 7.32 -6.13 C 6.10 -5.43 C 4.89 -6.13 C 4.89 -7.53 C 6.10 -8.23 C 8.53 -8.23 C 9.74 -7.53 C 9.74 -6.13 C 8.53 -5.43 C 6.10 -4.03 C 3.68 -8.23 1 2 1 2 3 2 3 4 1 4 5 2 5 6 1 6 1 2 7 8 2 8 9 1 9 10 2 2 10 1 1 7 1 3 11 1 5 12 1" />
<input onClick=depict() type=button value='depict' />
</body>
</html>