Mercurial > repos > immport-devteam > flow_overview
comparison js/boxplotsFlow.js @ 1:b5453d07f740 draft default tip
"planemo upload for repository https://github.com/ImmPortDB/immport-galaxy-tools/tree/master/flowtools/flow_overview commit 65373effef15809f3db0e5f9603ef808f4110aa3"
author | azomics |
---|---|
date | Wed, 29 Jul 2020 17:03:53 -0400 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
0:8283ff163ba6 | 1:b5453d07f740 |
---|---|
1 // Copyright (c) 2016 Northrop Grumman. | |
2 // All rights reserved. | |
3 var updateBPmfi = function(plotconfig){ | |
4 plotconfig.selectedPopulations = []; | |
5 $(plotconfig.popSelectj).each(function() { | |
6 if (this.checked) { | |
7 plotconfig.selectedPopulations.push(parseInt(this.value)); | |
8 } | |
9 }); | |
10 // Update selected markers? | |
11 plotconfig.selectedMarkers = []; | |
12 $(plotconfig.mrkrSelectj).each(function() { | |
13 if (this.checked) { | |
14 plotconfig.selectedMarkers.push(parseInt(this.value)); | |
15 } | |
16 }); | |
17 // update plot | |
18 updateBoxplotMFI(plotconfig); | |
19 }; | |
20 | |
21 var displayPopulationLegend = function(plotconfig) { | |
22 $(plotconfig.table).empty(); | |
23 plotconfig.allPopulations.map(function(value,index) { | |
24 $(plotconfig.table).append('<tr><td align="center">' | |
25 + '<input type="checkbox" checked class=' + plotconfig.popSelect | |
26 + ' value=' + value + '/></td><td title="' + newNames[value] + '">' | |
27 + newNames[value] + '</td><td><span style="background-color:' | |
28 + color_palette[0][value][0] + '"> </span></td></tr>'); | |
29 }); | |
30 | |
31 $(plotconfig.popSelectAll).click(function() { | |
32 var checkAll = $(plotconfig.popSelectAll).prop('checked'); | |
33 if (checkAll) { | |
34 $(plotconfig.popSelectj).prop("checked", true); | |
35 } else { | |
36 $(plotconfig.popSelectj).prop("checked", false); | |
37 } | |
38 updateBPmfi(plotconfig); | |
39 }); | |
40 | |
41 $(plotconfig.popSelectj).click(function() { | |
42 if ($(plotconfig.popSelectj).length == $(plotconfig.popSelectCheck).length) { | |
43 $(plotconfig.popSelectAll).prop("checked",true); | |
44 } else { | |
45 $(plotconfig.popSelectAll).prop("checked",false); | |
46 } | |
47 updateBPmfi(plotconfig); | |
48 }); | |
49 | |
50 $(plotconfig.popSelectj).each(function() { | |
51 var selectedpopn = parseInt(this.value); | |
52 if ($.inArray(selectedpopn,plotconfig.selectedPopulations) > -1) { | |
53 this.checked = true; | |
54 } else { | |
55 this.checked = false; | |
56 } | |
57 }); | |
58 }; | |
59 | |
60 var displayToolbar = function(plotconfig){ | |
61 $(plotconfig.displaybutton).on("click",function() { | |
62 $(plotconfig.popSelectAll).prop("checked",true); | |
63 $(plotconfig.popSelectj).prop("checked", true); | |
64 $(plotconfig.mrkrSelectj).prop("checked", true); | |
65 $(plotconfig.mrkrSelectAll).prop("checked",true); | |
66 $(plotconfig.displayMFI).prop("checked", false); | |
67 $(plotconfig.displayvalues).prop("checked", false); | |
68 updateBPmfi(plotconfig); | |
69 }); | |
70 | |
71 $(plotconfig.toggledisplayj).on("click",function() { | |
72 var text = document.getElementById(plotconfig.toggledisplay).firstChild; | |
73 text.data = text.data == "View per marker" ? "View per population" : "View per marker"; | |
74 plotconfig.view = plotconfig.view == "p" ? "m" : "p"; | |
75 updateBPmfi(plotconfig); | |
76 }); | |
77 | |
78 $(plotconfig.displayMFI).on("click", function(){ | |
79 updateBPmfi(plotconfig); | |
80 }); | |
81 | |
82 $(plotconfig.displayvalues).on("click", function(){ | |
83 updateBPmfi(plotconfig); | |
84 }); | |
85 | |
86 displayPlot(plotconfig); | |
87 }; | |
88 | |
89 var displayPlot = function(plotconfig) { | |
90 var h = $(window).height() - 200, | |
91 nbPop = Object.keys(plotconfig.csdata.mfi[plotconfig.mrkrNames[0]]).length + 2; | |
92 | |
93 $(plotconfig.plotdivj).empty(); | |
94 $(plotconfig.plotdivj).height(h); | |
95 | |
96 // Get Markers too | |
97 for (var i = 0, nbMarkers = plotconfig.mrkrNames.length; i < nbMarkers; i++){ | |
98 plotconfig.allMarkers.push(i); | |
99 plotconfig.selectedMarkers.push(i); | |
100 } | |
101 for (var i = 2; i < nbPop; i++) { | |
102 plotconfig.allPopulations.push(i - 1); | |
103 plotconfig.selectedPopulations.push(i - 1); | |
104 } | |
105 | |
106 $(window).on('resize',function() { | |
107 waitForFinalEvent(function() { | |
108 updateBoxplotMFI(plotconfig); | |
109 }, 500, "resizePlot"); | |
110 }); | |
111 | |
112 displayPopulationLegend(plotconfig); | |
113 displayMarkerTable(plotconfig); | |
114 updateBoxplotMFI(plotconfig); | |
115 }; | |
116 | |
117 var displayMarkerTable = function(plotconfig){ | |
118 var nbm = plotconfig.mrkrNames.length + 1; | |
119 $(plotconfig.mtable).empty(); | |
120 plotconfig.allMarkers.map(function(v) { | |
121 $(plotconfig.mtable).append('<tr>' | |
122 + '<td><span style="background-color:rgba(0,0,0,' + (v + 1 )/ nbm + ')' | |
123 + '"> </span></td>' | |
124 + '<td title="' + plotconfig.mrkrNames[v] + '">' | |
125 + plotconfig.mrkrNames[v] + '</td>' | |
126 + '<td align="center"><input type="checkbox" checked class=' | |
127 + plotconfig.mrkrSelect + ' value=' + v + '/></td></tr>'); | |
128 }); | |
129 | |
130 if (nbm > 5) { | |
131 $(plotconfig.mrkrSelectAll).prop('checked', false); | |
132 $(plotconfig.mrkrSelectAll).prop('disabled', true); | |
133 $('#markerWarning').show(); | |
134 $(plotconfig.mrkrSelectj).each(function() { | |
135 var selectedMrkr = parseInt(this.value); | |
136 if (selectedMrkr > 4){ | |
137 this.checked = false; | |
138 this.disabled = true; | |
139 } else { | |
140 this.checked = true; | |
141 } | |
142 }); | |
143 } | |
144 | |
145 $(plotconfig.mrkrSelectAll).click(function() { | |
146 var checkAll = $(plotconfig.mrkrSelectAll).prop('checked'); | |
147 if (checkAll) { | |
148 $(plotconfig.mrkrSelectj).prop("checked", true); | |
149 } else { | |
150 $(plotconfig.mrkrSelectj).prop("checked", false); | |
151 } | |
152 updateBPmfi(plotconfig); | |
153 }); | |
154 | |
155 $(plotconfig.mrkrSelectj).click(function() { | |
156 if (nbm < 6){ | |
157 if ($(plotconfig.mrkrSelectj).length == $(plotconfig.mrkrSelectCheck).length) { | |
158 $(plotconfig.mrkrSelectAll).prop("checked",true); | |
159 } else { | |
160 $(plotconfig.mrkrSelectAll).prop("checked",false); | |
161 } | |
162 } else { | |
163 var nbSelected = 0; | |
164 $(plotconfig.mrkrSelectj).each(function() { | |
165 if (this.checked) {nbSelected++} | |
166 }); | |
167 if (nbSelected < 5) { | |
168 $(plotconfig.mrkrSelectj).prop('disabled', false); | |
169 } else { | |
170 $(plotconfig.mrkrSelectj).each(function() { | |
171 if (!this.checked) { | |
172 this.disabled = true; | |
173 } | |
174 }); | |
175 } | |
176 } | |
177 updateBPmfi(plotconfig); | |
178 }); | |
179 }; | |
180 | |
181 var updateBoxplotMFI = function(plotconfig){ | |
182 var margin = {top: 30, right: 10, bottom: 50, left: 60}, | |
183 h = 0, | |
184 w = 0, | |
185 width = 0, | |
186 height = 0, | |
187 labels = false, // show the text labels beside individual boxplots? | |
188 mfi_option = false, | |
189 checkLabels = $(plotconfig.displayvalues).prop("checked"), | |
190 checkMFI = $(plotconfig.displayMFI).prop("checked"), | |
191 dataToPlot = [], | |
192 tmp = [], | |
193 nbm = plotconfig.mrkrNames.length + 1, | |
194 maxRange = 0, | |
195 minRange = 0, | |
196 domainx = [], | |
197 domainx1 = [], | |
198 min = Infinity, | |
199 max = -Infinity; | |
200 | |
201 $(plotconfig.plotdivj).empty(); | |
202 h = $(window).height() - 200; | |
203 $(plotconfig.plotdivj).height(h); | |
204 w = $(plotconfig.plotdivj).width(); | |
205 width = w - margin.left - margin.right; | |
206 height = h - margin.top - margin.bottom; | |
207 | |
208 var svg = d3.select(plotconfig.plotdivj).append("svg") | |
209 .attr("width", width + margin.left + margin.right) | |
210 .attr("height", height + margin.top + margin.bottom) | |
211 .attr("class", "box") | |
212 .append("g") | |
213 .attr("transform", "translate(" + margin.left + "," + margin.top + ")"); | |
214 | |
215 if (checkLabels) { | |
216 labels = true; | |
217 }; | |
218 if (checkMFI) { | |
219 mfi_option = true; | |
220 }; | |
221 | |
222 /* Get the data in proper shape to feed to the boxplot function | |
223 want [Object, Object, ..., Object] where Object: | |
224 'population': pop | |
225 'Data' : [Object, Object, ..., Object] where Object: | |
226 'Marker' : marker name | |
227 'outliers' : outliers | |
228 */ | |
229 | |
230 if (plotconfig.view == 'p') { | |
231 plotconfig.selectedPopulations.forEach(function(p) { | |
232 tmpPlot = []; | |
233 plotconfig.selectedMarkers.forEach(function(m) { | |
234 var markernm = plotconfig.mrkrNames[m], | |
235 qtmp = [ | |
236 +plotconfig.csdata.q1[markernm][p], | |
237 +plotconfig.csdata.q2[markernm][p], | |
238 +plotconfig.csdata.q3[markernm][p] | |
239 ], | |
240 wtmp = [ | |
241 +plotconfig.csdata.lower[markernm][p], | |
242 +plotconfig.csdata.upper[markernm][p] | |
243 ]; | |
244 tmp = []; | |
245 // Get min and max while we're here | |
246 plotconfig.csdata.outliers[markernm][p].forEach(function(outl) { | |
247 tmp.push(+outl); | |
248 if (+outl > max) {max = +outl}; | |
249 if (+outl < min) {min = +outl}; | |
250 }); | |
251 if (+plotconfig.csdata.upper[markernm][p] > max) { | |
252 max = +plotconfig.csdata.upper[markernm][p]; | |
253 } | |
254 if (+plotconfig.csdata.lower[markernm][p] < min) { | |
255 min = +plotconfig.csdata.lower[markernm][p]; | |
256 } | |
257 tmpPlot.push({ | |
258 marker: markernm, | |
259 outliers: tmp, | |
260 quartiles: qtmp, | |
261 whiskers: wtmp, | |
262 config: [m,p, nbm], | |
263 mfi: +plotconfig.csdata.mfi[markernm][p] | |
264 }); | |
265 }); | |
266 dataToPlot.push({population:p, popdata: tmpPlot}); | |
267 }); | |
268 } else { | |
269 plotconfig.selectedMarkers.forEach(function(m) { | |
270 var markernm = plotconfig.mrkrNames[m]; | |
271 tmpPlot = []; | |
272 plotconfig.selectedPopulations.forEach(function(p) { | |
273 var qtmp = [ | |
274 +plotconfig.csdata.q1[markernm][p], | |
275 +plotconfig.csdata.q2[markernm][p], | |
276 +plotconfig.csdata.q3[markernm][p] | |
277 ], | |
278 wtmp = [ | |
279 +plotconfig.csdata.lower[markernm][p], | |
280 +plotconfig.csdata.upper[markernm][p] | |
281 ]; | |
282 // Get min and max while we're here | |
283 tmp = []; | |
284 plotconfig.csdata.outliers[markernm][p].forEach(function(outl) { | |
285 tmp.push(+outl); | |
286 if (+outl > max) {max = +outl}; | |
287 if (+outl < min) {min = +outl}; | |
288 }); | |
289 if (+plotconfig.csdata.upper[markernm][p] > max) { | |
290 max = +plotconfig.csdata.upper[markernm][p]; | |
291 } | |
292 if (+plotconfig.csdata.lower[markernm][p] < min) { | |
293 min = +plotconfig.csdata.lower[markernm][p]; | |
294 } | |
295 tmpPlot.push({ | |
296 population:p, | |
297 outliers: tmp, | |
298 quartiles: qtmp, | |
299 whiskers: wtmp, | |
300 config: [m,p, nbm], | |
301 mfi: +plotconfig.csdata.mfi[markernm][p] | |
302 }); | |
303 }); | |
304 dataToPlot.push({marker: markernm, popdata: tmpPlot}); | |
305 }); | |
306 }; | |
307 maxRange = max + 30; | |
308 minRange = min - 30; | |
309 | |
310 if (plotconfig.view == 'p') { | |
311 domainx = plotconfig.selectedPopulations; | |
312 domainx1 = plotconfig.selectedMarkers.map(function(d){ | |
313 return plotconfig.mrkrNames[d] | |
314 }); | |
315 } else { | |
316 domainx1 = plotconfig.selectedPopulations; | |
317 domainx = plotconfig.selectedMarkers.map(function(d){ | |
318 return plotconfig.mrkrNames[d] | |
319 }); | |
320 } | |
321 // axes | |
322 var xScale = d3.scale.ordinal() | |
323 .domain(domainx) | |
324 .rangeRoundBands([0 , width], 0.2, 0.02); | |
325 | |
326 var x1Scale = d3.scale.ordinal() | |
327 .domain(domainx1) | |
328 .rangeRoundBands([0, xScale.rangeBand()], 0.1); | |
329 | |
330 var xAxis = d3.svg.axis() | |
331 .scale(xScale) | |
332 .orient("bottom"); | |
333 | |
334 // the y-axis | |
335 var yScale = d3.scale.linear() | |
336 .domain([minRange, maxRange]) | |
337 .range([height + margin.top, 0 + margin.top]); | |
338 | |
339 var yAxis = d3.svg.axis() | |
340 .scale(yScale) | |
341 .orient("left") | |
342 .tickFormat(d3.format("d")); | |
343 | |
344 svg.append("g") | |
345 .attr("class", "x axisbp") | |
346 .attr("transform", "translate(0," + (height + margin.top) + ")") | |
347 .call(xAxis); | |
348 | |
349 svg.append("g") | |
350 .attr("class", "y axisbp") | |
351 .call(yAxis) | |
352 .append("text") | |
353 .attr("class", "ylabel") | |
354 .attr("transform", "rotate(-90)") | |
355 .attr("y", 0 - margin.left) | |
356 .attr("x", 0 - (height / 2)) | |
357 .attr("dy", "1em") | |
358 .style("text-anchor", "middle") | |
359 .text("MFI values"); | |
360 | |
361 var boxplot = d3.box() | |
362 .width(x1Scale.rangeBand()) | |
363 .height(height + margin.top) | |
364 .domain([minRange, maxRange]) | |
365 .showLabels(labels) | |
366 .showMFI(mfi_option); | |
367 | |
368 if (plotconfig.view == 'p'){ | |
369 var group = svg.selectAll(".groups") | |
370 .data(dataToPlot) | |
371 .enter().append("g") | |
372 .attr("class", "group") | |
373 .attr("transform", function(d) { | |
374 return "translate(" + xScale(d.population) + ",0)"; | |
375 }); | |
376 | |
377 group.selectAll(".box") | |
378 .data(function(d) { return d.popdata; }) | |
379 .enter().append("g") | |
380 .attr("transform", function(d) { return "translate(" + x1Scale(d.marker) + ",0)"; }) | |
381 .call(boxplot); | |
382 } else { | |
383 var group = svg.selectAll(".groups") | |
384 .data(dataToPlot) | |
385 .enter().append("g") | |
386 .attr("class", "group") | |
387 .attr("transform", function(d) { | |
388 return "translate(" + xScale(d.marker) + ",0)"; | |
389 }); | |
390 | |
391 group.selectAll(".box") | |
392 .data(function(d) { return d.popdata; }) | |
393 .enter().append("g") | |
394 .attr("transform", function(d) { return "translate(" + x1Scale(d.population) + ",0)"; }) | |
395 .call(boxplot); | |
396 } | |
397 }; | |
398 | |
399 (function() { | |
400 // Inspired by http://informationandvisualization.de/blog/box-plot | |
401 // Modified to fit our data structure. | |
402 d3.box = function() { | |
403 var width = 1, | |
404 height = 1, | |
405 duration = 0, | |
406 domain = null, | |
407 value = Number, | |
408 showLabels = true, // whether or not to show text labels | |
409 numBars = 4, | |
410 curBar = 1, | |
411 showMFI = true, // display MFI ? | |
412 tickFormat = null; | |
413 var margin = {top: 30, right: 10, bottom: 50, left: 60}; | |
414 | |
415 // For each small multiple… | |
416 function box(g) { | |
417 g.each(function(data, i) { | |
418 var d = data.outliers.sort(d3.ascending); | |
419 var g = d3.select(this), | |
420 n = d.length, | |
421 min = Infinity, | |
422 max = -Infinity; | |
423 if (n > 0){ | |
424 min = d[0], | |
425 max = d[n - 1]; | |
426 } | |
427 // Readjust min and max with upper and lower values | |
428 if (data.whiskers[0] < min) {min = data.whiskers[0]} | |
429 if (data.whiskers[1] > max) {max = data.whiskers[1]} | |
430 // Compute quartiles. Must return exactly 3 elements. | |
431 var quartileData = data.quartiles; | |
432 // Compute whiskers. Must return exactly 2 elements, or null. | |
433 var whiskerData = data.whiskers; | |
434 // Compute outliers. here all data in d is an outlier. | |
435 // We compute the outliers as indices, so that we can join across transitions! | |
436 var outlierIndices = d3.range(n); | |
437 var mfiData = data.mfi; | |
438 // this is the scale for ONE SET of values | |
439 // Compute the new x-scale. | |
440 var x1 = d3.scale.linear() | |
441 .domain(domain && domain.call(this, d, i) || [min, max]) | |
442 .range([height , 0 + margin.top ]); | |
443 // Retrieve the old x-scale, if this is an update. | |
444 var x0 = this.__chart__ || d3.scale.linear() | |
445 .domain([0, Infinity]) | |
446 .range(x1.range()); | |
447 | |
448 // Stash the new scale. | |
449 this.__chart__ = x1; | |
450 // Note: the box, median, and box tick elements are fixed in number, | |
451 // so we only have to handle enter and update. In contrast, the outliers | |
452 // and other elements are variable, so we need to exit them! Variable | |
453 // elements also fade in and out. | |
454 // Update center line: the vertical line spanning the whiskers. | |
455 var center = g.selectAll("line.center") | |
456 .data(whiskerData ? [whiskerData] : []); | |
457 | |
458 //vertical line | |
459 center.enter().insert("line", "rect") | |
460 .attr("class", "center") | |
461 .attr("x1", width / 2) | |
462 .attr("y1", function(d) { return x0(d[0]); }) | |
463 .attr("x2", width / 2) | |
464 .attr("y2", function(d) { return x0(d[1]); }) | |
465 .style("opacity", 1e-6) | |
466 .style("stroke", function(d) { return color_palette[0][data.config[1]][3]; }) | |
467 .transition() | |
468 .duration(duration) | |
469 .style("opacity", 1) | |
470 .attr("y1", function(d) { return x1(d[0]); }) | |
471 .attr("y2", function(d) { return x1(d[1]); }); | |
472 | |
473 center.transition() | |
474 .duration(duration) | |
475 .style("opacity", 1) | |
476 .attr("y1", function(d) { return x1(d[0]); }) | |
477 .attr("y2", function(d) { return x1(d[1]); }); | |
478 | |
479 center.exit().transition() | |
480 .duration(duration) | |
481 .style("opacity", 1e-6) | |
482 .attr("y1", function(d) { return x1(d[0]); }) | |
483 .attr("y2", function(d) { return x1(d[1]); }) | |
484 .remove(); | |
485 | |
486 // Update innerquartile box. | |
487 var box = g.selectAll("rect.box") | |
488 .data([quartileData]); | |
489 | |
490 box.enter().append("rect") | |
491 .attr("class", "box") | |
492 .style("fill", function(d) { | |
493 var nbm = data.config[2], | |
494 pop = data.config[1], | |
495 mrkr = data.config[0]; | |
496 var color = color_palette[0][pop][1] + (mrkr + 1 )/ nbm + ')'; | |
497 return color }) | |
498 .style("stroke", function(d) { return color_palette[0][data.config[1]][3]; }) | |
499 .attr("x", 0) | |
500 .attr("y", function(d) { return x0(d[2]); }) | |
501 .attr("width", width) | |
502 .attr("height", function(d) { return x0(d[0]) - x0(d[2]); }) | |
503 .transition() | |
504 .duration(duration) | |
505 .attr("y", function(d) { return x1(d[2]); }) | |
506 .attr("height", function(d) { return x1(d[0]) - x1(d[2]); }); | |
507 | |
508 box.transition() | |
509 .duration(duration) | |
510 .attr("y", function(d) { return x1(d[2]); }) | |
511 .attr("height", function(d) { return x1(d[0]) - x1(d[2]); }); | |
512 | |
513 // Update median line. | |
514 var medianLine = g.selectAll("line.median") | |
515 .data([quartileData[1]]); | |
516 | |
517 medianLine.enter().append("line") | |
518 .attr("class", "median") | |
519 .attr("x1", 0) | |
520 .attr("y1", x0) | |
521 .attr("x2", width) | |
522 .attr("y2", x0) | |
523 .style("stroke", function(d) { return color_palette[0][data.config[1]][3]; }) | |
524 .transition() | |
525 .duration(duration) | |
526 .attr("y1", x1) | |
527 .attr("y2", x1); | |
528 | |
529 medianLine.transition() | |
530 .duration(duration) | |
531 .attr("y1", x1) | |
532 .attr("y2", x1); | |
533 | |
534 // Update MFI line. | |
535 var MFILine = g.selectAll("line.mfi") | |
536 .data([mfiData]); | |
537 if (showMFI == true) { | |
538 MFILine.enter().append("line") | |
539 .attr("class", "mfi") | |
540 .style("stroke", function(d){ return color_palette[0][data.config[1]][2]; }) | |
541 .attr("x1", 0) | |
542 .attr("y1", x0) | |
543 .attr("x2", width) | |
544 .attr("y2", x0) | |
545 .transition() | |
546 .duration(duration) | |
547 .attr("y1", x1) | |
548 .attr("y2", x1); | |
549 | |
550 MFILine.transition() | |
551 .duration(duration) | |
552 .attr("y1", x1) | |
553 .attr("y2", x1); | |
554 } | |
555 | |
556 // Update whiskers. | |
557 var whisker = g.selectAll("line.whisker") | |
558 .data(whiskerData || []); | |
559 | |
560 whisker.enter().insert("line", "circle, text") | |
561 .attr("class", "whisker") | |
562 .attr("x1", 0) | |
563 .attr("y1", x0) | |
564 .attr("x2", 0 + width) | |
565 .attr("y2", x0) | |
566 .style("opacity", 1e-6) | |
567 .style("stroke", function(d) { return color_palette[0][data.config[1]][3]; }) | |
568 .transition() | |
569 .duration(duration) | |
570 .attr("y1", x1) | |
571 .attr("y2", x1) | |
572 .style("opacity", 1); | |
573 | |
574 whisker.transition() | |
575 .duration(duration) | |
576 .attr("y1", x1) | |
577 .attr("y2", x1) | |
578 .style("opacity", 1); | |
579 | |
580 whisker.exit().transition() | |
581 .duration(duration) | |
582 .attr("y1", x1) | |
583 .attr("y2", x1) | |
584 .style("opacity", 1e-6) | |
585 .remove(); | |
586 | |
587 // Update outliers. | |
588 var outlier = g.selectAll("circle.outlier") | |
589 .data(outlierIndices, Number); | |
590 | |
591 outlier.enter().insert("circle", "text") | |
592 .attr("class", "outlier") | |
593 .attr("r", 3) | |
594 .attr("cx", function(d){ | |
595 return Math.floor(Math.random() * width); | |
596 }) | |
597 .attr("cy", function(i) { return x0(d[i]); }) | |
598 .style("opacity", 1e-6) | |
599 .style("fill", function(d) { | |
600 var nbm = data.config[2], | |
601 pop = data.config[1], | |
602 mrkr = data.config[0]; | |
603 var color = color_palette[0][pop][1] + (mrkr + 1 )/ nbm + ')'; | |
604 return color; }) | |
605 .style("stroke", function(d) { return color_palette[0][data.config[1]][3]; }) | |
606 .transition() | |
607 .duration(duration) | |
608 .attr("cy", function(i) { return x1(d[i]); }) | |
609 .style("opacity", 1); | |
610 | |
611 outlier.transition() | |
612 .duration(duration) | |
613 .attr("cy", function(i) { return x1(d[i]); }) | |
614 .style("opacity", 1); | |
615 | |
616 outlier.exit().transition() | |
617 .duration(duration) | |
618 .attr("cy", function(i) { return x1(d[i]); }) | |
619 .style("opacity", 1e-6) | |
620 .remove(); | |
621 | |
622 // Compute the tick format. | |
623 var format = tickFormat || x1.tickFormat(8); | |
624 // Update box ticks. | |
625 var boxTick = g.selectAll("text.box") | |
626 .data(quartileData); | |
627 | |
628 if(showLabels == true) { | |
629 boxTick.enter().append("text") | |
630 .attr("class", "box") | |
631 .attr("dy", ".3em") | |
632 .attr("dx", function(d, i) { return i & 1 ? 6 : -6 }) | |
633 .attr("x", function(d, i) { return i & 1 ? + width : 0 }) | |
634 .attr("y", x0) | |
635 .attr("text-anchor", function(d, i) { return i & 1 ? "start" : "end"; }) | |
636 .text(format) | |
637 .transition() | |
638 .duration(duration) | |
639 .attr("y", x1); | |
640 } | |
641 | |
642 boxTick.transition() | |
643 .duration(duration) | |
644 .text(format) | |
645 .attr("y", x1); | |
646 | |
647 // Update whisker ticks. These are handled separately from the box | |
648 // ticks because they may or may not exist, and we want don't want | |
649 // to join box ticks pre-transition with whisker ticks post-. | |
650 var whiskerTick = g.selectAll("text.whisker") | |
651 .data(whiskerData || []); | |
652 if(showLabels == true) { | |
653 whiskerTick.enter().append("text") | |
654 .attr("class", "whisker") | |
655 .attr("dy", ".3em") | |
656 .attr("dx", 6) | |
657 .attr("x", width) | |
658 .attr("y", x0) | |
659 .text(format) | |
660 .style("opacity", 1e-6) | |
661 .style("stroke", function(d) { return color_palette[0][data.config[1]][3]; }) | |
662 .transition() | |
663 .duration(duration) | |
664 .attr("y", x1) | |
665 .style("opacity", 1); | |
666 } | |
667 whiskerTick.transition() | |
668 .duration(duration) | |
669 .text(format) | |
670 .attr("y", x1) | |
671 .style("opacity", 1); | |
672 | |
673 whiskerTick.exit().transition() | |
674 .duration(duration) | |
675 .attr("y", x1) | |
676 .style("opacity", 1e-6) | |
677 .remove(); | |
678 }); | |
679 d3.timer.flush(); | |
680 } | |
681 | |
682 box.width = function(x) { | |
683 if (!arguments.length) return width; | |
684 width = x; | |
685 return box; | |
686 }; | |
687 box.height = function(x) { | |
688 if (!arguments.length) return height; | |
689 height = x; | |
690 return box; | |
691 }; | |
692 box.tickFormat = function(x) { | |
693 if (!arguments.length) return tickFormat; | |
694 tickFormat = x; | |
695 return box; | |
696 }; | |
697 box.duration = function(x) { | |
698 if (!arguments.length) return duration; | |
699 duration = x; | |
700 return box; | |
701 }; | |
702 box.domain = function(x) { | |
703 if (!arguments.length) return domain; | |
704 domain = x == null ? x : d3.functor(x); | |
705 return box; | |
706 }; | |
707 box.value = function(x) { | |
708 if (!arguments.length) return value; | |
709 value = x; | |
710 return box; | |
711 }; | |
712 box.showLabels = function(x) { | |
713 if (!arguments.length) return showLabels; | |
714 showLabels = x; | |
715 return box; | |
716 }; | |
717 box.showMFI = function(x) { | |
718 if (!arguments.length) return showMFI; | |
719 showMFI = x; | |
720 return box; | |
721 }; | |
722 return box; | |
723 }; | |
724 })(); |