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 }