Mercurial > repos > pieterlukasse > nist_wrapper
comparison templates/spectrum_gen.js @ 0:cce6989ed423
new NIST wrapper demo tools
author | pieter.lukasse@wur.nl |
---|---|
date | Thu, 22 Jan 2015 16:14:57 +0100 |
parents | |
children | 82368bd06e1d |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:cce6989ed423 |
---|---|
1 function getMax(values) | |
2 { | |
3 var result = 0; | |
4 for (var i = 0; i < values.length; i++) | |
5 { | |
6 if (values[i] > result) | |
7 result = values[i]; | |
8 } | |
9 return result; | |
10 } | |
11 | |
12 /** | |
13 * This function will first convert the spectrum mass and intensities list in MSP format | |
14 * to the internal lists needed by renderSpectrum function. | |
15 * | |
16 * @param spectrumMSPString : list of masses and intensities in the following format: | |
17 * e.g. : "14 8; 15 15; 27 18; 28 15; 29 15; 30 11; 32 19; 39 32; 40 12; 41 68;" | |
18 */ | |
19 function renderSpectrumFromMSPString(spectrumMSPString, targetElement) | |
20 { | |
21 var spectrum1 = getSpectrumObjectFromMSPString(spectrumMSPString); | |
22 renderSpectrum(spectrum1, null,targetElement); | |
23 } | |
24 | |
25 function endsWith(str, suffix) { | |
26 return str.indexOf(suffix, str.length - suffix.length) !== -1; | |
27 } | |
28 | |
29 function getSpectrumObjectFromCouplesString(spectrumCouplesString, couplesSeparator, massAndIntensitySeparator) | |
30 { | |
31 var couples = spectrumCouplesString.split(couplesSeparator); | |
32 var masses = new Array(); | |
33 var intensities = new Array(); | |
34 for (var i = 0; i < couples.length; i++) | |
35 { | |
36 var couple = couples[i].trim().split(massAndIntensitySeparator) | |
37 var mass = parseInt(couple[0]) | |
38 var intensity = parseInt(couple[1]) | |
39 masses.push(mass); | |
40 intensities.push(intensity); | |
41 } | |
42 var spectrum1 = new Object(); | |
43 spectrum1.masses = masses; | |
44 spectrum1.intensities = intensities; | |
45 return spectrum1; | |
46 } | |
47 | |
48 function getSpectrumObjectFromMSPString(spectrumMSPString) | |
49 { | |
50 spectrumMSPString = spectrumMSPString.trim(); | |
51 if (endsWith(spectrumMSPString, ";")) | |
52 spectrumMSPString = spectrumMSPString.substring(0, spectrumMSPString.length - 1); | |
53 return getSpectrumObjectFromCouplesString(spectrumMSPString, ';', ' '); | |
54 } | |
55 | |
56 | |
57 function getSpectrumObjectFromJCAMPString(spectrumJCAMPString) | |
58 { | |
59 var spectrum = getSpectrumObjectFromCouplesString(spectrumJCAMPString, ' ', ','); | |
60 for (var i = 0; i < spectrum.intensities.length; i++) | |
61 spectrum.intensities[i] = spectrum.intensities[i]/10; | |
62 return spectrum; | |
63 } | |
64 | |
65 /** | |
66 * This function will render a comparison spectrum comparable to | |
67 * the NIST "head to tail" visualization to compare the measured spectrum | |
68 * with the matched library spectrum. | |
69 * | |
70 * NB: One important detail in this function | |
71 * is that the library spectrum is not available in NIST output, so | |
72 * its representative is retrieved from NIST's webbook website in this case. | |
73 * (e.g. http://webbook.nist.gov/cgi/cbook.cgi?JCAMP=C537268&Index=0&Type=Mass | |
74 * for casNr = "C537268" ) | |
75 * | |
76 * | |
77 * @param spectrumMSPString | |
78 * @param casNr | |
79 * @param targetElement | |
80 */ | |
81 function renderComparisonSpectrum(spectrumMSPString, casNr, targetElement) | |
82 { | |
83 var peakTable; | |
84 try | |
85 { | |
86 //remove dashes: | |
87 casNr = casNr.replace("-", ""); | |
88 peakTable = httpGet2("/nist_controller/get_nistdata?casnr="+casNr); | |
89 | |
90 } | |
91 catch(e) | |
92 { | |
93 //assume running locally: | |
94 alert("Error while trying to get data from NIST. Rendering library spectrum with dummy data."); | |
95 peakTable = "55,290 56,240 57,100 58,80"+ | |
96 " 63,30 65,150 66,50 67,1271"+ | |
97 " 68,370 69,100 70,210 71,10"+ | |
98 " 74,50 75,60 76,120 77,2312"+ | |
99 " 78,220 79,120 80,190 81,630"+ | |
100 " 82,4884 83,2702 84,240 85,20"+ | |
101 " 91,180 92,50 93,210 94,3353"+ | |
102 " 95,1371 96,1261 97,370 98,120"+ | |
103 " 105,1621 106,160 107,70 108,220"+ | |
104 " 109,80 110,60 111,30 112,40"+ | |
105 " 121,30 122,460 123,940 124,9999"; | |
106 //note that the intensities in jcamp response are 10x when compared to MSP format | |
107 } | |
108 var spectrum1 = getSpectrumObjectFromMSPString(spectrumMSPString); | |
109 var spectrum2 = getSpectrumObjectFromJCAMPString(peakTable); | |
110 renderSpectrum(spectrum1, spectrum2,targetElement); | |
111 } | |
112 | |
113 function httpGet2(theUrl) | |
114 { | |
115 //Tried many options: the solution was to add a new service to our | |
116 //Galaxy server to act as a proxy to the NIST site and then retrieve the data. | |
117 | |
118 //way of working: added a new controller to | |
119 // /home/lukas007/galaxy-dist/lib/galaxy/webapps/galaxy/controllers | |
120 // which gives the service "/nist_controller/get_nistdata?casnr=<casnr>" | |
121 | |
122 var xmlHttp = null; | |
123 | |
124 xmlHttp = new XMLHttpRequest(); | |
125 xmlHttp.open( "GET", theUrl, false ); | |
126 xmlHttp.send( null ); | |
127 return xmlHttp.responseText; | |
128 } | |
129 | |
130 | |
131 | |
132 /** | |
133 * This function will ensure only the local highest peaks get a label | |
134 * to make the spectrum more readable and avoid all the overlapping labels | |
135 * of minor peaks. | |
136 * | |
137 * @param spectrum | |
138 */ | |
139 function getSpectrumLabels(spectrum) | |
140 { | |
141 //TODO - improve logic to include more labels when area of peaks is sparse enough. | |
142 //for now we let all labels, keep only the ones where intensity > 100: | |
143 //and leave the largest/last mass as well: | |
144 var result = new Array(); | |
145 for (var i = 0; i < spectrum.masses.length; i++) | |
146 { | |
147 if (spectrum.intensities[i] > 100 || i == spectrum.masses.length-1) | |
148 result.push(spectrum.masses[i]); | |
149 else | |
150 result.push(""); | |
151 } | |
152 return result; | |
153 } | |
154 | |
155 function renderSpectrum(spectrum1, spectrum2, targetElement) | |
156 { | |
157 var maxMassSpectrum1 = getMax(spectrum1.masses); | |
158 var maxX = maxMassSpectrum1; | |
159 spectrum1.labels = getSpectrumLabels(spectrum1) | |
160 var maxMassSpectrum2 = 0; | |
161 if (spectrum2 != null) | |
162 { | |
163 maxMassSpectrum2 = getMax(spectrum2.masses); | |
164 if (maxMassSpectrum2 > maxMassSpectrum1) | |
165 maxX = maxMassSpectrum2; | |
166 spectrum2.labels = getSpectrumLabels(spectrum2) | |
167 } | |
168 maxX += 20; | |
169 | |
170 var margin = {top: 80, right: 80, bottom: 80, left: 80}; | |
171 //var width = maxX*2 - margin.left - margin.right; | |
172 //fixed width is better: | |
173 var width = 600 - margin.left - margin.right; | |
174 var zoomFactor = 1; | |
175 | |
176 var height; | |
177 //if (spectrum2 != null) | |
178 //height = 800 - margin.top - margin.bottom; | |
179 //else | |
180 height = 400 - margin.top - margin.bottom; | |
181 | |
182 //var x = d3.scale.ordinal() | |
183 // .rangeRoundBands([0, width], .1); | |
184 | |
185 var x = d3.scale.linear().domain([0, maxX]).range([0, width]); | |
186 | |
187 var y0 = d3.scale.linear().domain([300, 1100]).range([height, 0]); | |
188 | |
189 var xAxis = d3.svg.axis() | |
190 .scale(x) | |
191 .orient("center"); | |
192 | |
193 // create left yAxis | |
194 var yAxisLeft = d3.svg.axis().scale(y0).ticks(4).orient("left"); | |
195 | |
196 | |
197 var svg = d3.select(targetElement).append("svg") | |
198 .attr("width", width + margin.left + margin.right) | |
199 .attr("height", height + margin.top + margin.bottom) | |
200 .append("g") | |
201 .attr("class", "graph") | |
202 .attr("transform", "translate(" + margin.left + "," + margin.top + ")"); | |
203 | |
204 | |
205 //x.domain([0,10,500]); | |
206 if (spectrum2 != null) | |
207 { | |
208 y0.domain([-999, 999]); | |
209 } | |
210 else | |
211 { | |
212 y0.domain([0, 999]); | |
213 } | |
214 svg.append("g") | |
215 .attr("class", "x axis") | |
216 .append("line") | |
217 .attr("y1", y0(0)) | |
218 .attr("y2", y0(0)) | |
219 .attr("x2", width); | |
220 | |
221 svg.append("g") | |
222 .attr("class", "y axis axisLeft") | |
223 .attr("transform", "translate(0,0)") | |
224 .call(yAxisLeft) | |
225 .append("text") | |
226 .attr("y", 6) | |
227 .attr("dy", "-2em") | |
228 .style("text-anchor", "end") | |
229 .text("Relative Intensity"); | |
230 | |
231 | |
232 | |
233 //for each mass in spectrum 1, generate bar: | |
234 for (var i = 0; i < spectrum1.masses.length; i++) | |
235 { | |
236 var heightFactor = 1; | |
237 if (spectrum2 != null) | |
238 heightFactor = 2; | |
239 | |
240 svg.append("rect") | |
241 .attr("class", "bar1") | |
242 .attr("x", x(spectrum1.masses[i]*zoomFactor)) | |
243 .attr("width", 1) | |
244 .attr("y", y0(spectrum1.intensities[i])) | |
245 .attr("height", height/heightFactor - y0(spectrum1.intensities[i])); | |
246 svg.append("text") | |
247 .attr("x", x(spectrum1.masses[i]*zoomFactor)) | |
248 .attr("y", y0(spectrum1.intensities[i])) | |
249 .attr("dy", "-1em") | |
250 .attr("dx", "-1em") | |
251 .style("text-anchor", "start") | |
252 .text(spectrum1.labels[i]); | |
253 } | |
254 | |
255 if (spectrum2 != null) | |
256 { | |
257 for (var i = 0; i < spectrum2.masses.length; i++) | |
258 { | |
259 heightFactor = 2; | |
260 | |
261 svg.append("rect") | |
262 .attr("class", "bar2") | |
263 .attr("x", x(spectrum2.masses[i]*zoomFactor)) | |
264 .attr("width", 1) | |
265 .attr("y", y0(0)) | |
266 .attr("height", height/heightFactor - y0(spectrum2.intensities[i])); | |
267 svg.append("text") | |
268 .attr("x", x(spectrum2.masses[i]*zoomFactor)) | |
269 .attr("y", y0(-spectrum2.intensities[i])) | |
270 .attr("dy", "1.5em") | |
271 .attr("dx", "-1em") | |
272 .style("text-anchor", "start") | |
273 .text(spectrum2.labels[i]); | |
274 } | |
275 } | |
276 | |
277 } |