// change to any of the .CSV files (latency, duration, etc) // e.g. blocked, connected, duration, latency, req_body, res_body, rx, service, tx var filename = "latency.csv"; var containerSelection = d3.select('.heatmap-container') var container = containerSelection.node() var cw = container.clientWidth, ch = container.clientHeight var margin = {top: 25, right: 100, bottom: 25, left: 50}, width = cw - margin.left - margin.right, height = ch - margin.top - margin.bottom; var parseDate = d3.timeParse("%Y-%m-%d-%H"), formatDate = d3.timeFormat("%m/%d @ %H"), tickFormat = function(d, i) { return d3.format(".1s")(d) }, coerceTypes = function(d) { d.date = parseDate(d.date); d.bucket = +d.bucket; d.count = +d.count; } ; var pluck = function (key) { return function (obj) { return obj[key]; } }; var pipe = function () { var args = [].slice.call(arguments).reverse(), f = args.shift(), g = args.shift(), fog = g ? function() { return f(g.apply(this, arguments)); } : f; return args.length ? compose.apply(this, [fog].concat(args)) : fog; }; var x = d3.scaleTime().range([0, width]), y = d3.scaleBand().rangeRound([height, 0]), z = d3.scaleLinear().range(["white", "steelblue"]); var xAxis = d3.axisBottom() .scale(x) .ticks() .tickFormat(formatDate); var yAxis = d3.axisLeft() .scale(y) .tickFormat(tickFormat) // The size of the buckets in the CSV data file. // This could be inferred from the data if it weren't sparse. var dayMs = 864e5, xStep = dayMs/24; var svg = containerSelection.append("svg") .attr("width", width + margin.left + margin.right) .attr("height", height + margin.top + (3*margin.bottom)) .append("g") .attr("transform", "translate(" + margin.left + "," + margin.top + ")"); var tooltip = d3.select('.histogram-container') var barChart = BarChart() barChart .margin(margin) .height(height) .width(width) d3.csv(filename, function(error, rows) { if (error) throw error; drawHeatmap(rows) }); function drawHeatmap(rows) { window.rows = rows; // Coerce the CSV data to the appropriate types. rows.forEach(coerceTypes); var keys = { bucket: pluck('bucket'), date: pipe(pluck('date'), formatDate) }; var nest = { byBucket: d3.nest().key(keys.bucket), byDate: d3.nest().key(keys.date) }; var map = { byBucket: nest.byBucket.map(rows, d3.map), byDate: nest.byDate.map(rows, d3.map) }; // Compute the scale domains. x.domain(d3.extent(rows, pluck('date'))); y.domain(map.byBucket.keys()) z.domain(d3.extent(rows, function(d) { return d.count * d.bucket; })); // Extend the x-domain to fit the last bucket. x.domain([x.domain()[0], +x.domain()[1] + xStep]); // Display the tiles for each non-zero bucket. svg.selectAll(".tile") .data(rows) .enter().append("rect") .attr("class", "tile") .attr("x", function(d) { return x(d.date); }) .attr("y", function(d) { return y(d.bucket)-y.bandwidth()/2; }) .attr("width", x(xStep) - x(0)) .attr("height", y.bandwidth()) .style("fill", function(d) { return z(d.count * d.bucket); }) .on('mouseover', function (d, i, all) { var histogram = map.byDate.get(keys.date(d)) var data = d3.range(20).map(function(d){return {"x":d,"y":Math.floor(Math.random() * 100)}}); var data2 = histogram.map(d => ({x: d.bucket, y: d.count })) console.log(data2) tooltip .datum(data2) .call(barChart); var message = d.count + ' @ ' + d.bucket +' = ' + d.count * d.bucket }) // .on('mouseout', function (d) { tooltip.text('') }) ; // Add a legend for the color values. var legend = svg.selectAll(".legend") .data(z.ticks(6).slice(1).reverse()) .enter().append("g") .attr("class", "legend") .attr("transform", function(d, i) { return "translate(" + (width + 20) + "," + (20 + i * 20) + ")"; }); legend.append("rect") .attr("width", 20) .attr("height", 20) .style("fill", z); legend.append("text") .attr("x", 26) .attr("y", 10) .attr("dy", ".35em") .text(tickFormat); svg.append("text") .attr("class", "label") .attr("x", width + 20) .attr("y", 10) .attr("dy", ".35em") .text("Count * Value"); // Add an x-axis with label. svg.append("g") .attr("class", "x axis") .attr("transform", "translate(0," + height + ")") .call(xAxis) .append("text") .attr("class", "label") .attr("x", width) .attr("y", -6) .attr("text-anchor", "end") .text("Date"); // Add a y-axis with label. svg.append("g") .attr("class", "y axis") .call(yAxis) .append("text") .attr("class", "label") .attr("y", 6) .attr("dy", ".71em") .attr("text-anchor", "end") .attr("transform", "rotate(-90)") .text("Value") ; }