14a4f2fe02baf385f6c24fc98c6e17bf6ac5e0724Dan SinclairHeatmap.prototype.draw = function() { 24a4f2fe02baf385f6c24fc98c6e17bf6ac5e0724Dan Sinclair this.drawHeatmap(); 34a4f2fe02baf385f6c24fc98c6e17bf6ac5e0724Dan Sinclair for (var i = 0; i < this.drawTraces.length; ++i) 44a4f2fe02baf385f6c24fc98c6e17bf6ac5e0724Dan Sinclair if (this.drawTraces[i]) 54a4f2fe02baf385f6c24fc98c6e17bf6ac5e0724Dan Sinclair this.drawTrace(i, 1); 64a4f2fe02baf385f6c24fc98c6e17bf6ac5e0724Dan Sinclair}; 74a4f2fe02baf385f6c24fc98c6e17bf6ac5e0724Dan Sinclair 84a4f2fe02baf385f6c24fc98c6e17bf6ac5e0724Dan SinclairHeatmap.prototype.drawHeatmap = function() { 94a4f2fe02baf385f6c24fc98c6e17bf6ac5e0724Dan Sinclair this.context.clearRect(0, 0, this.w, this.h); 104a4f2fe02baf385f6c24fc98c6e17bf6ac5e0724Dan Sinclair 114a4f2fe02baf385f6c24fc98c6e17bf6ac5e0724Dan Sinclair this.context.save(); 124a4f2fe02baf385f6c24fc98c6e17bf6ac5e0724Dan Sinclair this.context.scale(this.w / this.revisions.length, this.h / this.resolution); 134a4f2fe02baf385f6c24fc98c6e17bf6ac5e0724Dan Sinclair 144a4f2fe02baf385f6c24fc98c6e17bf6ac5e0724Dan Sinclair var counts = []; 154a4f2fe02baf385f6c24fc98c6e17bf6ac5e0724Dan Sinclair for (var time = 0; time < this.revisions.length; ++time) { 164a4f2fe02baf385f6c24fc98c6e17bf6ac5e0724Dan Sinclair var revision = this.revisions[time]; 174a4f2fe02baf385f6c24fc98c6e17bf6ac5e0724Dan Sinclair for (var bucket in this.data[revision]) { 184a4f2fe02baf385f6c24fc98c6e17bf6ac5e0724Dan Sinclair counts.push(this.data[revision][bucket].length); 194a4f2fe02baf385f6c24fc98c6e17bf6ac5e0724Dan Sinclair } 204a4f2fe02baf385f6c24fc98c6e17bf6ac5e0724Dan Sinclair } 214a4f2fe02baf385f6c24fc98c6e17bf6ac5e0724Dan Sinclair counts.sort(function(a, b) {return a - b}); 224a4f2fe02baf385f6c24fc98c6e17bf6ac5e0724Dan Sinclair var cutoff = percentile(counts, 0.9); 234a4f2fe02baf385f6c24fc98c6e17bf6ac5e0724Dan Sinclair if (cutoff < 2) 244a4f2fe02baf385f6c24fc98c6e17bf6ac5e0724Dan Sinclair cutoff = 2; 254a4f2fe02baf385f6c24fc98c6e17bf6ac5e0724Dan Sinclair 264a4f2fe02baf385f6c24fc98c6e17bf6ac5e0724Dan Sinclair for (var time = 0; time < this.revisions.length; ++time) { 274a4f2fe02baf385f6c24fc98c6e17bf6ac5e0724Dan Sinclair var revision = this.revisions[time]; 284a4f2fe02baf385f6c24fc98c6e17bf6ac5e0724Dan Sinclair for (var bucket in this.data[revision]) { 294a4f2fe02baf385f6c24fc98c6e17bf6ac5e0724Dan Sinclair var count = this.data[revision][bucket].length; 304a4f2fe02baf385f6c24fc98c6e17bf6ac5e0724Dan Sinclair 314a4f2fe02baf385f6c24fc98c6e17bf6ac5e0724Dan Sinclair // Calculate average color across all traces in bucket. 324a4f2fe02baf385f6c24fc98c6e17bf6ac5e0724Dan Sinclair var r = 0, g = 0, b = 0; 334a4f2fe02baf385f6c24fc98c6e17bf6ac5e0724Dan Sinclair for (var i = 0; i < this.data[revision][bucket].length; ++i) { 344a4f2fe02baf385f6c24fc98c6e17bf6ac5e0724Dan Sinclair var trace = this.data[revision][bucket][i]; 354a4f2fe02baf385f6c24fc98c6e17bf6ac5e0724Dan Sinclair r += nthColor(trace)[0]; 364a4f2fe02baf385f6c24fc98c6e17bf6ac5e0724Dan Sinclair g += nthColor(trace)[1]; 374a4f2fe02baf385f6c24fc98c6e17bf6ac5e0724Dan Sinclair b += nthColor(trace)[2]; 384a4f2fe02baf385f6c24fc98c6e17bf6ac5e0724Dan Sinclair } 394a4f2fe02baf385f6c24fc98c6e17bf6ac5e0724Dan Sinclair r /= count, g /= count, b /= count; 404a4f2fe02baf385f6c24fc98c6e17bf6ac5e0724Dan Sinclair var brightness = mapRange(count / cutoff, 0, 1, 2, 0.5); 414a4f2fe02baf385f6c24fc98c6e17bf6ac5e0724Dan Sinclair 424a4f2fe02baf385f6c24fc98c6e17bf6ac5e0724Dan Sinclair // Draw! 434a4f2fe02baf385f6c24fc98c6e17bf6ac5e0724Dan Sinclair this.context.fillStyle = calculateColor(r, g, b, 1, brightness); 444a4f2fe02baf385f6c24fc98c6e17bf6ac5e0724Dan Sinclair this.context.fillRect(time, bucket, 1, 1); 454a4f2fe02baf385f6c24fc98c6e17bf6ac5e0724Dan Sinclair } 464a4f2fe02baf385f6c24fc98c6e17bf6ac5e0724Dan Sinclair } 474a4f2fe02baf385f6c24fc98c6e17bf6ac5e0724Dan Sinclair 484a4f2fe02baf385f6c24fc98c6e17bf6ac5e0724Dan Sinclair this.context.restore(); 494a4f2fe02baf385f6c24fc98c6e17bf6ac5e0724Dan Sinclair}; 504a4f2fe02baf385f6c24fc98c6e17bf6ac5e0724Dan Sinclair 514a4f2fe02baf385f6c24fc98c6e17bf6ac5e0724Dan SinclairHeatmap.prototype.drawTrace = function(trace, opacity) { 524a4f2fe02baf385f6c24fc98c6e17bf6ac5e0724Dan Sinclair this.drawTraceLine(trace, 4, calculateColor(255, 255, 255, opacity, 1)); 534a4f2fe02baf385f6c24fc98c6e17bf6ac5e0724Dan Sinclair var color = calculateColor(nthColor(trace)[0], nthColor(trace)[1], nthColor(trace)[2], opacity, 1); 544a4f2fe02baf385f6c24fc98c6e17bf6ac5e0724Dan Sinclair this.drawTraceLine(trace, 2, color); 554a4f2fe02baf385f6c24fc98c6e17bf6ac5e0724Dan Sinclair}; 564a4f2fe02baf385f6c24fc98c6e17bf6ac5e0724Dan Sinclair 574a4f2fe02baf385f6c24fc98c6e17bf6ac5e0724Dan SinclairHeatmap.prototype.drawTraceLine = function(trace, width, color) { 584a4f2fe02baf385f6c24fc98c6e17bf6ac5e0724Dan Sinclair var revisionWidth = this.w / this.revisions.length; 594a4f2fe02baf385f6c24fc98c6e17bf6ac5e0724Dan Sinclair 604a4f2fe02baf385f6c24fc98c6e17bf6ac5e0724Dan Sinclair this.context.save(); 614a4f2fe02baf385f6c24fc98c6e17bf6ac5e0724Dan Sinclair this.context.lineJoin = 'round'; 624a4f2fe02baf385f6c24fc98c6e17bf6ac5e0724Dan Sinclair this.context.lineWidth = width; 634a4f2fe02baf385f6c24fc98c6e17bf6ac5e0724Dan Sinclair this.context.strokeStyle = color; 644a4f2fe02baf385f6c24fc98c6e17bf6ac5e0724Dan Sinclair this.context.translate(revisionWidth / 2, 0); 654a4f2fe02baf385f6c24fc98c6e17bf6ac5e0724Dan Sinclair this.context.beginPath(); 664a4f2fe02baf385f6c24fc98c6e17bf6ac5e0724Dan Sinclair 674a4f2fe02baf385f6c24fc98c6e17bf6ac5e0724Dan Sinclair var started = false; 684a4f2fe02baf385f6c24fc98c6e17bf6ac5e0724Dan Sinclair for (var time = 0; time < this.revisions.length; ++time) { 694a4f2fe02baf385f6c24fc98c6e17bf6ac5e0724Dan Sinclair var values = this.traces[this.revisions[time]][trace]; 704a4f2fe02baf385f6c24fc98c6e17bf6ac5e0724Dan Sinclair var sum = 0; 714a4f2fe02baf385f6c24fc98c6e17bf6ac5e0724Dan Sinclair for (var value of values) 724a4f2fe02baf385f6c24fc98c6e17bf6ac5e0724Dan Sinclair sum += value; 734a4f2fe02baf385f6c24fc98c6e17bf6ac5e0724Dan Sinclair var value = sum / values.length; 744a4f2fe02baf385f6c24fc98c6e17bf6ac5e0724Dan Sinclair 754a4f2fe02baf385f6c24fc98c6e17bf6ac5e0724Dan Sinclair var bucket = mapRange(value, this.min, this.max, 0, this.h); 764a4f2fe02baf385f6c24fc98c6e17bf6ac5e0724Dan Sinclair if (started) { 774a4f2fe02baf385f6c24fc98c6e17bf6ac5e0724Dan Sinclair this.context.lineTo(revisionWidth * time, bucket); 784a4f2fe02baf385f6c24fc98c6e17bf6ac5e0724Dan Sinclair } else { 794a4f2fe02baf385f6c24fc98c6e17bf6ac5e0724Dan Sinclair this.context.moveTo(revisionWidth * time, bucket); 804a4f2fe02baf385f6c24fc98c6e17bf6ac5e0724Dan Sinclair started = true; 814a4f2fe02baf385f6c24fc98c6e17bf6ac5e0724Dan Sinclair } 824a4f2fe02baf385f6c24fc98c6e17bf6ac5e0724Dan Sinclair } 834a4f2fe02baf385f6c24fc98c6e17bf6ac5e0724Dan Sinclair 844a4f2fe02baf385f6c24fc98c6e17bf6ac5e0724Dan Sinclair this.context.stroke(); 854a4f2fe02baf385f6c24fc98c6e17bf6ac5e0724Dan Sinclair this.context.restore(); 864a4f2fe02baf385f6c24fc98c6e17bf6ac5e0724Dan Sinclair} 874a4f2fe02baf385f6c24fc98c6e17bf6ac5e0724Dan Sinclair 884a4f2fe02baf385f6c24fc98c6e17bf6ac5e0724Dan SinclairHeatmap.prototype.scaleCanvas = function() { 894a4f2fe02baf385f6c24fc98c6e17bf6ac5e0724Dan Sinclair this.canvas.width = this.canvas.clientWidth * window.devicePixelRatio; 904a4f2fe02baf385f6c24fc98c6e17bf6ac5e0724Dan Sinclair this.canvas.height = this.canvas.clientHeight * window.devicePixelRatio; 914a4f2fe02baf385f6c24fc98c6e17bf6ac5e0724Dan Sinclair this.context.scale(window.devicePixelRatio, window.devicePixelRatio); 924a4f2fe02baf385f6c24fc98c6e17bf6ac5e0724Dan Sinclair 934a4f2fe02baf385f6c24fc98c6e17bf6ac5e0724Dan Sinclair this.w = this.canvas.clientWidth, this.h = this.canvas.clientHeight; 944a4f2fe02baf385f6c24fc98c6e17bf6ac5e0724Dan Sinclair 954a4f2fe02baf385f6c24fc98c6e17bf6ac5e0724Dan Sinclair // Flip canvas. 964a4f2fe02baf385f6c24fc98c6e17bf6ac5e0724Dan Sinclair this.context.scale(1, -1); 974a4f2fe02baf385f6c24fc98c6e17bf6ac5e0724Dan Sinclair this.context.translate(0, -this.h); 984a4f2fe02baf385f6c24fc98c6e17bf6ac5e0724Dan Sinclair}; 99