Skip to content

Instantly share code, notes, and snippets.

@spiermar
Last active February 28, 2018 01:53
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save spiermar/76dc64a7716205df91e51b485a2445e8 to your computer and use it in GitHub Desktop.
Save spiermar/76dc64a7716205df91e51b485a2445e8 to your computer and use it in GitHub Desktop.
d3-heatmap
.columnLabel, .rowLabel {
font-size: 1.0rem;
fill: #AAAAAA;
font-weight: 300;
}
.title {
font-size: 2.8rem;
fill: #4F4F4F;
font-weight: 300;
}
.subtitle {
font-size: 1.4rem;
fill: #AAAAAA;
font-weight: 300;
}
.axis path, .axis tick, .axis line {
fill: none;
stroke: none;
}
text {
font-size: 1.2rem;
fill: #AAAAAA;
font-weight: 400;
}
.legendTitle {
font-size: 1.3rem;
fill: #4F4F4F;
font-weight: 400;
}
(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
typeof define === 'function' && define.amd ? define(['exports'], factory) :
(factory((global.d3 = global.d3 || {})));
}(this, (function (exports) { 'use strict';
/* global d3 */
function cantorPair (x, y) {
var z = ((x + y) * (x + y + 1)) / 2 + y;
return z
}
var heatmap = function () {
var svg = null;
var columns = 0;
var rows = 0;
var title = '';
var subtitle = '';
var legendLabel = '';
var width = 960;
var margin = {
top: 20,
right: 0,
bottom: 0,
left: 0
};
var gridSize = null;
var colorScale = null;
var xAxisScale = null;
var yAxisScale = null;
var xAxisTickFormat = d3.format('.0f');
var yAxisTickFormat = d3.format('.2s');
var xAxisLabels = null;
var yAxisLabels = null;
var xAxisLabelFormat = function (d) { return d };
var yAxisLabelFormat = function (d) { return d };
var hideLegend = false;
var clickHandler = null;
var mouseOverHandler = null;
var highlight = [];
var highlightColor = '#936EB5';
var highlightOpacity = '0.4';
function click (d, i, j) {
if (typeof clickHandler === 'function') {
clickHandler(d, i, j);
}
}
function mouseOver (d, i, j) {
if (typeof mouseOverHandler === 'function') {
mouseOverHandler(d, i, j);
}
}
function getHighlightFrames () {
var highlightFrames = [];
for (var k in highlight) { // all highlights
if (highlight[k].start[0] <= highlight[k].end[0]) { // no reverse column range highlight
for (var i = highlight[k].start[0]; i <= highlight[k].end[0]; i++) {
var j = null;
if (i > highlight[k].start[0] && i < highlight[k].end[0]) { // middle columns
for (j = 0; j < rows; j++) {
highlightFrames.push([i, j]);
}
} else if (i === highlight[k].start[0]) { // start column, or start and end are the same
if (i === highlight[k].end[0]) { // ends in the same column
if (highlight[k].start[1] <= highlight[k].end[1]) { // no reverse row range highlight
for (j = highlight[k].start[1]; j <= highlight[k].end[1]; j++) {
highlightFrames.push([i, j]);
}
} else {
console.log('Error: Start row is higher than end row. No reverse range highlight.');
}
} else { // doesn't end in the same column
for (j = highlight[k].start[1]; j < rows; j++) {
highlightFrames.push([i, j]);
}
}
} else { // end column, when different than start column
for (j = highlight[k].end[1]; j >= 0; j--) {
highlightFrames.push([i, j]);
}
}
}
} else {
console.log('Error: Start column is higher than end column. No reverse range highlight.');
}
}
return highlightFrames
}
function updateHighlight () {
if (highlight && highlight.length > 0 && svg && rows && gridSize) {
var highlightFrames = getHighlightFrames();
var frames = svg.selectAll('g.highlight')
.data(highlightFrames, function (d) { return cantorPair(d[0], d[1]) });
frames.exit().remove();
frames.enter().append('g')
.attr('class', 'highlight')
.append('rect')
.attr('x', function (d) { return d[0] * gridSize })
.attr('y', function (d) { return d[1] * gridSize })
.attr('width', gridSize)
.attr('height', gridSize)
.style('fill', highlightColor)
.style('fill-opacity', highlightOpacity)
.style('pointer-events', 'none');
} else {
console.log("Error: Can't update highlight. Heatmap was not initialized yet or highlight was not defined.");
}
}
function heatmap (selection) {
var data = selection.datum();
columns = data.length;
rows = data[0].length;
gridSize = width / columns;
var height = gridSize * (rows + 2);
if (title) {
margin.top = margin.top + 50;
}
if (subtitle) {
margin.top = margin.top + 20;
}
if (!hideLegend) {
margin.bottom = margin.bottom + 50;
}
if (yAxisScale || yAxisLabels) {
margin.left = margin.left + 50;
}
var max = 0;
for (let i = 0; i < data.length; i++) {
for (let j = 0; j < data[i].length; j++) {
if (data[i][j] > max) { max = data[i][j]; }
}
}
if (!colorScale) {
colorScale = d3.scaleLinear()
.domain([0, max / 2, max])
.range(['#FFFFDD', '#3E9583', '#1F2D86']);
// .interpolate(d3.interpolateHcl);
}
svg = selection
.append('svg')
.attr('width', width + margin.left + margin.right)
.attr('height', height + margin.top + margin.bottom)
.append('g')
.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');
if (yAxisScale || yAxisLabels) {
if (yAxisScale) {
var y = d3.scaleLinear()
.domain(yAxisScale)
.range([height, 0]);
svg.append('g')
.attr('transform', 'translate(3,-12)')
.attr('class', 'rowLabel axis')
.call(d3.axisLeft(y)
.ticks(20)
.tickFormat(yAxisTickFormat));
} else {
svg.selectAll('.rowLabel')
.data(yAxisLabels)
.enter().append('text')
.text(yAxisLabelFormat)
.attr('x', 0)
.attr('y', function (d, i) { return i * gridSize })
.style('text-anchor', 'end')
.attr('transform', 'translate(-6,' + gridSize / 1.2 + ')')
.attr('class', 'rowLabel mono axis');
}
}
if (xAxisScale || xAxisLabels) {
if (xAxisScale) {
var x = d3.scaleLinear()
.domain(xAxisScale)
// .range([0, width - margin.left - margin.right - 40])
.range([0, width - margin.left - margin.right]);
svg.append('g')
.attr('transform', 'translate(5,3)')
.attr('class', 'columnLabel axis')
.call(d3.axisTop(x)
.ticks(20)
.tickFormat(xAxisTickFormat));
} else {
svg.selectAll('.columnLabel')
.data(xAxisLabels)
.enter().append('text')
.text(xAxisLabelFormat)
.attr('y', function (d, i) { return i * gridSize })
.attr('x', 0)
.style('text-anchor', 'beginning')
.attr('transform', 'translate(' + gridSize / 1.4 + ', -6) rotate(270)')
.attr('class', 'columnLabel mono axis');
}
}
svg.selectAll('g.column')
.data(data)
.enter().append('g')
.each(function (d, i) { // function (d, i, j) might replace .each.
d3.select(this).selectAll('rect')
.data(d)
.enter().append('rect')
.attr('x', function (d) { return i * gridSize }) // column
.attr('y', function (d, j) { return j * gridSize }) // row
.attr('class', 'bordered')
.attr('width', gridSize)
.attr('height', gridSize)
.style('stroke', 'white')
.style('stroke-opacity', 0.6)
.style('fill', function (d) { return colorScale(d) })
.style('pointer-events', 'all')
.on('mouseover', function (d, j) { return mouseOver(d, i, j) })
.on('click', function (d, j) { return click(d, i, j) });
});
if (highlight && highlight.length > 0) {
updateHighlight();
}
// Append title to the top
if (title) {
svg.append('text')
.attr('class', 'title')
.attr('x', width / 2)
.attr('y', -60)
.style('text-anchor', 'middle')
.text(title);
}
if (subtitle) {
svg.append('text')
.attr('class', 'subtitle')
.attr('x', width / 2)
.attr('y', -40)
.style('text-anchor', 'middle')
.text(subtitle);
}
if (!hideLegend) {
// Extra scale since the color scale is interpolated
var countScale = d3.scaleLinear()
.domain([0, max])
.range([0, width]);
// Calculate the variables for the temp gradient
var numStops = 10;
var countRange = countScale.domain();
var countPoint = [];
countRange[2] = countRange[1] - countRange[0];
for (var i = 0; i < numStops; i++) {
countPoint.push(i * countRange[2] / (numStops - 1) + countRange[0]);
}// for i
// Create the gradient
svg.append('defs')
.append('linearGradient')
.attr('id', 'legend-traffic')
.attr('x1', '0%').attr('y1', '0%')
.attr('x2', '100%').attr('y2', '0%')
.selectAll('stop')
.data(d3.range(numStops))
.enter().append('stop')
.attr('offset', function (d, i) {
return countScale(countPoint[i]) / width
})
.attr('stop-color', function (d, i) {
return colorScale(countPoint[i])
});
var legendWidth = Math.min(width * 0.8, 400);
// Color Legend container
var legendsvg = svg.append('g')
.attr('class', 'legendWrapper')
.attr('transform', 'translate(' + (width / 2) + ',' + (gridSize * rows + 40) + ')');
// Draw the Rectangle
legendsvg.append('rect')
.attr('class', 'legendRect')
.attr('x', -legendWidth / 2)
.attr('y', 0)
// .attr("rx", hexRadius*1.25/2)
.attr('width', legendWidth)
.attr('height', 10)
.style('fill', 'url(#legend-traffic)');
// Append title
legendsvg.append('text')
.attr('class', 'legendTitle')
.attr('x', 0)
.attr('y', -10)
.style('text-anchor', 'middle')
.text(legendLabel);
// Set scale for x-axis
var xScale = d3.scaleLinear()
.range([-legendWidth / 2, legendWidth / 2])
.domain([0, max]);
// Define x-axis
var xAxis = d3.axisBottom()
.ticks(5)
// .tickFormat(formatPercent)
.scale(xScale);
// Set up X axis
legendsvg.append('g')
.attr('class', 'axis')
.attr('transform', 'translate(0,' + (10) + ')')
.call(xAxis);
}
}
heatmap.title = function (_) {
if (!arguments.length) { return title }
title = _;
return heatmap
};
heatmap.subtitle = function (_) {
if (!arguments.length) { return subtitle }
subtitle = _;
return heatmap
};
heatmap.legendLabel = function (_) {
if (!arguments.length) { return legendLabel }
legendLabel = _;
return heatmap
};
heatmap.width = function (_) {
if (!arguments.length) { return width }
width = _;
return heatmap
};
heatmap.margin = function (_) {
if (!arguments.length) { return margin }
margin = _;
return heatmap
};
heatmap.colorScale = function (_) {
if (!arguments.length) { return colorScale }
colorScale = _;
return heatmap
};
heatmap.xAxisScale = function (_) {
if (!arguments.length) { return xAxisScale }
xAxisScale = _;
return heatmap
};
heatmap.yAxisScale = function (_) {
if (!arguments.length) { return yAxisScale }
yAxisScale = _;
return heatmap
};
heatmap.xAxisLabelFormat = function (_) {
if (!arguments.length) { return xAxisLabelFormat }
xAxisLabelFormat = _;
return heatmap
};
heatmap.yAxisLabelFormat = function (_) {
if (!arguments.length) { return yAxisLabelFormat }
yAxisLabelFormat = _;
return heatmap
};
heatmap.xAxisTickFormat = function (_) {
if (!arguments.length) { return xAxisTickFormat }
xAxisTickFormat = _;
return heatmap
};
heatmap.yAxisTickFormat = function (_) {
if (!arguments.length) { return yAxisTickFormat }
yAxisTickFormat = _;
return heatmap
};
heatmap.hideLegend = function (_) {
if (!arguments.length) { return hideLegend }
hideLegend = _;
return heatmap
};
heatmap.onClick = function (_) {
if (!arguments.length) { return clickHandler }
clickHandler = _;
return heatmap
};
heatmap.onMouseOver = function (_) {
if (!arguments.length) { return mouseOverHandler }
mouseOverHandler = _;
return heatmap
};
heatmap.xAxisLabels = function (_) {
if (!arguments.length) { return xAxisLabels }
xAxisLabels = _;
return heatmap
};
heatmap.yAxisLabels = function (_) {
if (!arguments.length) { return yAxisLabels }
yAxisLabels = _;
return heatmap
};
heatmap.highlightColor = function (_) {
if (!arguments.length) { return highlightColor }
highlightColor = _;
return heatmap
};
heatmap.highlightOpacity = function (_) {
if (!arguments.length) { return highlightOpacity }
highlightOpacity = _;
return heatmap
};
heatmap.setHighlight = function (_) {
if (!arguments.length) { return highlight }
highlight = _;
return heatmap
};
heatmap.updateHighlight = updateHighlight;
return heatmap
};
exports.heatmap = heatmap;
Object.defineProperty(exports, '__esModule', { value: true });
})));
{
"rows": [
1962,
1924,
1886,
1848,
1810,
1772,
1734,
1696,
1659,
1621,
1583,
1545,
1507,
1469,
1431,
1393,
1356,
1318,
1280,
1242,
1204,
1166,
1128,
1090,
1053,
1015,
977,
939,
901,
863,
825,
787,
749,
712,
674,
636,
598,
560,
522,
484,
446,
409,
371,
333,
295,
257,
219,
181,
143,
106
],
"columns": [
1,
2,
3,
4,
5,
6,
7,
8,
9,
10,
11,
12,
13,
14,
15,
16,
17,
18,
19,
20,
21,
22,
23,
24,
25,
26,
27,
28,
29,
30,
31,
32,
33,
34,
35,
36,
37,
38,
39,
40,
41,
42,
43,
44,
45,
46,
47,
48,
49,
50,
51,
52,
53,
54,
55,
56,
57,
58,
59,
60,
61,
62,
63,
64,
65,
66,
67,
68,
69,
70,
71,
72,
73,
74,
75,
76,
77,
78,
79,
80,
81,
82,
83,
84,
85,
86,
87,
88,
89,
90,
91,
92,
93,
94,
95,
96,
97,
98,
99,
100,
101,
102,
103,
104,
105,
106,
107,
108,
109,
110,
111,
112,
113,
114,
115,
116,
117,
118,
119,
120,
121,
122
],
"values": [
[
4,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
1,
0,
0,
0,
0,
0,
3,
4,
0,
1,
4,
2,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0
],
[
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
2,
1,
0,
2,
6,
2,
1,
14,
9,
11,
0,
0,
0,
0,
0,
4,
3,
1,
29,
14,
10,
0,
0,
0,
1,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0
],
[
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
1,
1,
0,
0,
0,
1,
1,
1,
4,
3,
14,
14,
4,
0,
0,
0,
0,
0,
7,
2,
2,
30,
16,
5,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0
],
[
1,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
1,
1,
0,
1,
6,
3,
10,
5,
9,
1,
0,
0,
0,
0,
16,
1,
2,
20,
25,
8,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0
],
[
27,
0,
0,
0,
0,
1,
0,
0,
0,
0,
0,
0,
0,
1,
1,
1,
1,
0,
2,
2,
4,
2,
12,
7,
8,
0,
1,
0,
2,
7,
6,
4,
13,
15,
15,
2,
1,
4,
0,
1,
1,
1,
2,
1,
1,
0,
0,
0,
0,
0
],
[
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
1,
0,
0,
6,
5,
1,
22,
4,
2,
0,
0,
0,
1,
11,
8,
7,
32,
21,
1,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0
],
[
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
8,
35,
14,
3,
0,
0,
0,
0,
1,
2,
15,
29,
17,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0
],
[
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
6,
40,
12,
7,
0,
0,
0,
0,
0,
1,
21,
25,
16,
2,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0
],
[
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
8,
35,
21,
2,
0,
0,
0,
0,
0,
0,
13,
37,
13,
3,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0
],
[
53,
2,
2,
0,
1,
0,
0,
0,
0,
0,
0,
2,
1,
2,
1,
2,
2,
1,
0,
1,
1,
2,
9,
24,
5,
1,
0,
0,
2,
0,
1,
1,
10,
23,
2,
0,
3,
3,
0,
4,
3,
0,
3,
1,
0,
1,
0,
1,
0,
1
],
[
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
1,
35,
18,
10,
0,
0,
0,
0,
0,
0,
9,
36,
17,
2,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0
],
[
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
14,
35,
16,
1,
0,
0,
0,
0,
0,
0,
18,
35,
12,
0,
0,
0,
0,
0,
1,
0,
0,
0,
0,
0,
0,
0,
0,
0
],
[
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
1,
31,
24,
11,
0,
0,
0,
0,
0,
0,
0,
9,
43,
11,
4,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0
],
[
2,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
1,
0,
0,
0,
2,
17,
26,
14,
1,
0,
0,
1,
0,
0,
1,
0,
12,
31,
14,
2,
0,
0,
2,
0,
1,
0,
0,
0,
0,
0,
0,
0,
0,
0
],
[
65,
1,
0,
2,
0,
1,
0,
1,
0,
0,
1,
0,
2,
3,
0,
0,
2,
2,
3,
1,
11,
18,
1,
1,
0,
2,
1,
2,
1,
2,
2,
2,
6,
19,
9,
1,
1,
1,
1,
1,
1,
1,
1,
2,
0,
2,
0,
0,
0,
1
],
[
7,
0,
0,
0,
0,
0,
0,
0,
1,
0,
0,
3,
1,
1,
0,
0,
0,
0,
1,
7,
14,
11,
8,
0,
0,
0,
0,
0,
0,
0,
0,
2,
15,
28,
9,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0
],
[
4,
0,
0,
0,
0,
0,
1,
2,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
3,
10,
25,
8,
5,
1,
0,
0,
0,
0,
0,
0,
0,
6,
17,
23,
12,
1,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0
],
[
4,
0,
0,
1,
2,
0,
1,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
8,
20,
12,
10,
4,
0,
0,
0,
0,
0,
0,
0,
1,
5,
19,
23,
11,
3,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0
],
[
29,
0,
1,
3,
0,
1,
0,
3,
0,
0,
1,
0,
0,
1,
1,
0,
2,
2,
8,
19,
10,
6,
0,
0,
0,
0,
0,
1,
1,
1,
1,
4,
22,
14,
8,
5,
0,
1,
0,
1,
0,
1,
0,
0,
0,
0,
0,
0,
0,
0
],
[
66,
0,
0,
1,
1,
2,
1,
2,
1,
0,
1,
1,
0,
0,
0,
3,
2,
1,
8,
12,
12,
10,
3,
0,
0,
1,
2,
0,
1,
1,
2,
7,
25,
8,
3,
0,
0,
1,
1,
2,
2,
1,
1,
0,
0,
0,
0,
0,
0,
0
],
[
3,
0,
1,
0,
0,
1,
0,
1,
0,
0,
0,
0,
0,
0,
0,
0,
1,
0,
0,
3,
16,
25,
13,
6,
0,
0,
0,
1,
0,
1,
1,
2,
29,
20,
11,
2,
0,
0,
1,
0,
0,
0,
1,
0,
0,
0,
0,
0,
0,
0
],
[
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
1,
9,
38,
8,
8,
0,
0,
0,
0,
0,
2,
2,
13,
40,
11,
2,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0
],
[
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
5,
9,
11,
6,
0,
0,
1,
4,
32,
10,
9,
31,
21,
1,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0
],
[
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
5,
9,
0,
0,
1,
4,
47,
14,
1,
34,
18,
0,
1,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0
],
[
52,
0,
2,
1,
2,
2,
1,
0,
2,
0,
2,
2,
0,
1,
1,
2,
0,
0,
1,
1,
2,
0,
0,
0,
0,
1,
1,
0,
0,
4,
25,
9,
0,
20,
17,
2,
0,
2,
1,
1,
4,
0,
3,
0,
2,
0,
1,
1,
1,
0
],
[
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
1,
0,
0,
0,
0,
0,
5,
39,
16,
0,
32,
27,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0
],
[
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
1,
2,
2,
1,
1,
12,
5,
2,
0,
0,
0,
4,
24,
11,
4,
36,
20,
1,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0
],
[
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
1,
0,
2,
7,
4,
6,
17,
3,
0,
0,
0,
0,
3,
14,
1,
20,
27,
11,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0
],
[
1,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
2,
2,
5,
5,
20,
9,
1,
0,
1,
0,
0,
11,
4,
3,
34,
19,
2,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0
],
[
37,
2,
0,
2,
4,
2,
0,
3,
0,
0,
1,
0,
1,
0,
1,
1,
0,
2,
4,
4,
3,
4,
11,
1,
6,
0,
0,
0,
3,
4,
1,
10,
11,
10,
6,
0,
2,
1,
0,
2,
4,
1,
3,
1,
1,
0,
1,
1,
0,
1
],
[
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
1,
1,
8,
2,
6,
15,
6,
2,
0,
0,
0,
0,
14,
4,
0,
31,
24,
4,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0
],
[
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
1,
1,
5,
3,
9,
21,
5,
3,
0,
0,
0,
0,
8,
4,
4,
34,
11,
11,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0
],
[
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
1,
1,
5,
2,
5,
19,
4,
0,
0,
0,
0,
0,
12,
10,
2,
29,
19,
9,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0
],
[
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
1,
1,
2,
6,
35,
10,
0,
0,
0,
0,
0,
0,
4,
0,
45,
11,
2,
0,
0,
1,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0
],
[
40,
2,
1,
0,
2,
1,
2,
1,
4,
0,
2,
0,
1,
2,
1,
0,
0,
1,
0,
0,
0,
17,
15,
4,
1,
1,
0,
0,
1,
0,
1,
6,
26,
1,
5,
1,
0,
2,
0,
1,
2,
2,
2,
1,
1,
0,
0,
0,
0,
0
],
[
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
9,
33,
9,
8,
0,
0,
0,
0,
0,
0,
4,
37,
4,
14,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0
],
[
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
5,
36,
17,
0,
0,
0,
0,
0,
0,
0,
0,
43,
10,
5,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0
],
[
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
7,
33,
19,
0,
0,
0,
0,
0,
0,
0,
7,
32,
19,
1,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0
],
[
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
11,
27,
18,
0,
0,
0,
0,
0,
0,
0,
4,
39,
9,
4,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0
],
[
31,
0,
2,
1,
1,
2,
1,
1,
1,
3,
0,
0,
3,
1,
2,
0,
0,
0,
1,
0,
2,
19,
11,
6,
1,
0,
0,
0,
0,
1,
0,
1,
26,
7,
1,
0,
1,
1,
0,
0,
4,
0,
3,
1,
1,
0,
0,
0,
2,
0
],
[
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
1,
38,
17,
2,
0,
0,
0,
0,
0,
0,
0,
1,
40,
13,
4,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0
],
[
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
5,
43,
8,
1,
0,
0,
0,
0,
0,
0,
0,
0,
42,
7,
8,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0
],
[
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
14,
32,
11,
1,
0,
0,
0,
0,
0,
0,
0,
0,
1,
37,
13,
6,
0,
0,
0,
0,
1,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0
],
[
10,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
1,
0,
0,
0,
1,
0,
2,
13,
13,
6,
3,
0,
0,
0,
0,
0,
1,
0,
0,
5,
27,
8,
7,
0,
0,
0,
0,
0,
1,
0,
0,
0,
0,
0,
0,
0,
0,
0
],
[
31,
0,
0,
0,
0,
0,
0,
0,
1,
0,
0,
0,
1,
1,
0,
2,
3,
5,
5,
15,
2,
2,
1,
0,
1,
2,
3,
5,
2,
5,
2,
11,
15,
7,
5,
1,
1,
2,
2,
2,
0,
2,
0,
0,
0,
0,
0,
0,
0,
0
],
[
5,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
10,
22,
13,
4,
0,
0,
0,
0,
0,
0,
0,
1,
2,
12,
28,
9,
1,
0,
0,
0,
1,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0
],
[
18,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
1,
7,
20,
12,
0,
0,
0,
0,
0,
0,
0,
0,
0,
2,
9,
24,
9,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0
],
[
3,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
1,
0,
0,
1,
0,
9,
24,
17,
1,
0,
0,
0,
0,
0,
0,
0,
0,
0,
3,
31,
20,
2,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0
],
[
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
1,
4,
29,
18,
4,
0,
0,
0,
0,
0,
0,
0,
0,
2,
30,
11,
13,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0
],
[
50,
2,
0,
0,
1,
1,
1,
1,
0,
1,
0,
0,
1,
1,
0,
2,
1,
1,
1,
4,
14,
5,
8,
0,
0,
2,
1,
1,
1,
0,
1,
3,
14,
12,
4,
2,
2,
3,
1,
3,
2,
3,
1,
1,
0,
1,
0,
0,
0,
1
],
[
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
1,
0,
1,
0,
0,
19,
19,
13,
3,
0,
0,
0,
0,
0,
1,
1,
1,
36,
9,
8,
0,
0,
1,
0,
1,
1,
1,
0,
0,
0,
0,
0,
0,
0,
0
],
[
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
2,
15,
20,
2,
0,
0,
0,
0,
0,
6,
12,
3,
34,
12,
8,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0
],
[
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
7,
8,
0,
0,
0,
0,
0,
33,
19,
3,
2,
36,
4,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0
],
[
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
11,
1,
0,
0,
0,
0,
34,
23,
0,
1,
39,
7,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0
],
[
56,
0,
1,
1,
0,
1,
0,
0,
1,
0,
0,
2,
0,
0,
0,
2,
0,
0,
1,
2,
0,
3,
0,
1,
2,
3,
2,
0,
5,
20,
5,
3,
5,
19,
4,
2,
0,
2,
0,
2,
2,
1,
1,
2,
1,
1,
0,
1,
0,
1
],
[
8,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
1,
0,
0,
0,
0,
0,
0,
31,
18,
0,
0,
41,
7,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0
],
[
1,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
1,
2,
5,
5,
1,
0,
0,
0,
0,
0,
30,
13,
0,
11,
36,
7,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0
],
[
3,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
2,
4,
6,
3,
11,
10,
2,
0,
0,
0,
0,
0,
12,
4,
2,
26,
26,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0
],
[
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
2,
7,
4,
8,
12,
4,
0,
0,
0,
0,
0,
13,
6,
0,
27,
23,
6,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0
],
[
35,
0,
1,
0,
1,
0,
0,
1,
0,
0,
0,
1,
2,
0,
2,
0,
1,
6,
6,
2,
5,
12,
7,
4,
1,
3,
0,
1,
3,
2,
6,
6,
22,
9,
2,
1,
0,
1,
1,
1,
1,
1,
0,
1,
0,
0,
0,
1,
1,
0
],
[
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
3,
2,
3,
4,
18,
13,
4,
0,
0,
0,
0,
1,
6,
4,
2,
37,
12,
7,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0
],
[
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
1,
4,
6,
2,
15,
10,
1,
0,
0,
0,
0,
0,
12,
5,
2,
31,
18,
5,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0
],
[
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
1,
0,
8,
6,
15,
12,
2,
0,
0,
0,
0,
0,
8,
6,
2,
36,
15,
5,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0
],
[
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
1,
2,
2,
2,
12,
15,
4,
0,
0,
0,
0,
0,
11,
7,
4,
25,
21,
6,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0
],
[
29,
0,
0,
0,
0,
0,
0,
0,
0,
1,
0,
0,
0,
1,
1,
1,
0,
0,
2,
1,
1,
18,
15,
5,
0,
2,
2,
2,
2,
3,
4,
4,
27,
4,
5,
0,
2,
2,
0,
1,
0,
1,
0,
1,
0,
0,
0,
0,
0,
0
],
[
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
1,
10,
36,
9,
1,
0,
0,
0,
0,
0,
0,
5,
37,
12,
3,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0
],
[
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
3,
26,
18,
10,
0,
0,
0,
0,
0,
0,
0,
5,
38,
6,
8,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0
],
[
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
3,
15,
29,
10,
0,
0,
0,
0,
0,
0,
0,
4,
35,
12,
6,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0
],
[
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
1,
22,
25,
9,
0,
0,
0,
0,
0,
0,
0,
6,
35,
8,
7,
0,
0,
0,
1,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0
],
[
36,
0,
2,
2,
0,
2,
2,
0,
1,
1,
1,
0,
2,
0,
1,
1,
1,
2,
1,
0,
0,
9,
22,
3,
1,
1,
0,
0,
2,
0,
1,
3,
23,
6,
0,
1,
0,
3,
4,
0,
3,
1,
3,
1,
1,
0,
0,
0,
0,
1
],
[
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
3,
15,
27,
11,
0,
0,
0,
0,
0,
0,
0,
4,
33,
17,
2,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0
],
[
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
2,
10,
35,
6,
2,
0,
0,
0,
0,
0,
0,
0,
6,
35,
11,
3,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0
],
[
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
11,
36,
11,
1,
0,
0,
0,
0,
0,
0,
0,
2,
46,
6,
5,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0
],
[
4,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
1,
0,
0,
0,
0,
1,
2,
10,
21,
15,
3,
1,
0,
0,
0,
0,
0,
1,
1,
8,
31,
8,
7,
0,
0,
0,
0,
0,
1,
0,
0,
0,
0,
0,
0,
0,
0,
0
],
[
41,
0,
0,
0,
0,
0,
0,
0,
0,
0,
1,
0,
0,
0,
1,
0,
1,
1,
4,
7,
9,
8,
0,
2,
1,
0,
3,
0,
1,
2,
1,
12,
14,
7,
2,
1,
2,
2,
0,
0,
2,
1,
0,
2,
0,
1,
0,
1,
1,
0
],
[
5,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
6,
9,
15,
13,
8,
0,
0,
0,
0,
0,
0,
0,
0,
11,
21,
17,
7,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0
],
[
4,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
8,
24,
9,
7,
3,
0,
0,
0,
0,
0,
0,
0,
8,
22,
19,
6,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0
],
[
5,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
1,
0,
0,
1,
0,
0,
2,
28,
15,
9,
0,
0,
0,
0,
0,
0,
0,
0,
3,
18,
30,
9,
1,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0
],
[
20,
0,
1,
0,
0,
0,
1,
0,
0,
0,
1,
0,
0,
0,
1,
0,
0,
0,
0,
0,
8,
29,
13,
7,
1,
0,
0,
0,
0,
0,
0,
0,
20,
28,
9,
1,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0
],
[
55,
2,
2,
3,
4,
0,
3,
3,
3,
2,
0,
4,
2,
1,
3,
1,
0,
1,
1,
0,
2,
11,
8,
7,
1,
0,
1,
2,
1,
1,
0,
2,
6,
10,
9,
0,
0,
0,
0,
0,
0,
0,
1,
0,
0,
0,
0,
0,
0,
0
],
[
18,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
1,
0,
0,
0,
0,
0,
0,
2,
34,
10,
10,
0,
0,
0,
0,
0,
1,
0,
14,
29,
9,
4,
0,
0,
0,
0,
1,
0,
0,
0,
0,
0,
0,
0,
0,
0
],
[
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
10,
30,
12,
0,
0,
0,
0,
0,
10,
2,
13,
35,
16,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0
],
[
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
3,
8,
6,
0,
0,
0,
3,
43,
9,
5,
31,
18,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0
],
[
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
5,
7,
0,
0,
0,
2,
44,
16,
0,
24,
26,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0
],
[
28,
1,
1,
1,
1,
2,
1,
2,
3,
0,
2,
2,
1,
1,
1,
2,
0,
1,
3,
1,
1,
1,
1,
2,
3,
0,
1,
1,
0,
3,
27,
8,
0,
18,
19,
0,
0,
0,
0,
0,
0,
1,
0,
2,
1,
1,
0,
1,
1,
0
],
[
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
1,
0,
0,
0,
3,
46,
15,
1,
31,
34,
0,
1,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0
],
[
1,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
1,
2,
3,
4,
5,
12,
13,
1,
0,
0,
0,
1,
18,
7,
9,
33,
19,
1,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0
],
[
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
9,
4,
7,
20,
3,
1,
0,
0,
0,
3,
18,
4,
11,
36,
19,
3,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0
],
[
1,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
2,
1,
7,
6,
8,
28,
5,
0,
1,
0,
0,
1,
6,
0,
16,
37,
10,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0
],
[
32,
1,
1,
0,
2,
1,
1,
1,
1,
0,
1,
2,
1,
0,
2,
0,
0,
0,
4,
2,
6,
1,
8,
9,
8,
1,
0,
0,
1,
1,
8,
2,
10,
17,
14,
0,
0,
1,
0,
1,
3,
0,
3,
2,
1,
2,
1,
0,
1,
0
],
[
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
1,
1,
12,
6,
16,
19,
2,
0,
0,
0,
0,
0,
7,
7,
15,
39,
16,
1,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0
],
[
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
2,
3,
5,
3,
9,
22,
4,
0,
0,
0,
1,
3,
16,
8,
15,
39,
20,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0
],
[
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
1,
1,
19,
34,
15,
1,
0,
0,
0,
0,
3,
0,
19,
38,
14,
3,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0
],
[
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
2,
43,
14,
7,
0,
0,
0,
0,
0,
0,
18,
36,
9,
3,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0
],
[
38,
1,
0,
0,
0,
0,
0,
0,
2,
0,
0,
0,
0,
1,
0,
1,
1,
1,
3,
1,
1,
1,
5,
25,
6,
5,
3,
1,
2,
2,
4,
0,
11,
23,
9,
4,
0,
4,
1,
2,
1,
1,
0,
1,
0,
0,
0,
0,
0,
0
],
[
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
7,
32,
8,
16,
0,
0,
0,
0,
0,
0,
16,
28,
16,
3,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0
],
[
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
4,
46,
16,
0,
0,
0,
0,
0,
0,
1,
13,
46,
6,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0
],
[
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
10,
33,
16,
5,
0,
0,
0,
0,
0,
0,
10,
36,
15,
4,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0
],
[
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
1,
30,
20,
13,
0,
0,
0,
0,
0,
0,
0,
6,
35,
17,
4,
0,
0,
1,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0
],
[
70,
1,
1,
0,
1,
2,
2,
0,
2,
0,
1,
2,
1,
2,
2,
0,
1,
4,
3,
1,
1,
2,
11,
6,
0,
0,
1,
6,
3,
2,
3,
3,
2,
10,
7,
2,
2,
4,
0,
1,
2,
3,
0,
1,
0,
0,
0,
0,
0,
0
],
[
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
12,
26,
21,
3,
1,
0,
0,
0,
0,
0,
0,
0,
26,
29,
7,
1,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0
],
[
9,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
1,
0,
0,
0,
0,
1,
1,
11,
18,
12,
2,
0,
0,
0,
0,
0,
0,
0,
1,
15,
23,
13,
3,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0
],
[
5,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
4,
23,
19,
5,
2,
0,
0,
0,
0,
0,
0,
0,
1,
21,
28,
8,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0
],
[
5,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
3,
17,
12,
12,
6,
0,
0,
0,
0,
0,
1,
0,
3,
14,
21,
15,
1,
0,
0,
0,
1,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0
],
[
59,
2,
0,
2,
2,
5,
2,
1,
3,
1,
2,
3,
0,
0,
4,
5,
2,
2,
1,
1,
7,
3,
3,
1,
0,
1,
1,
2,
2,
3,
3,
4,
4,
10,
1,
0,
4,
0,
0,
2,
0,
1,
0,
0,
0,
0,
0,
0,
0,
0
],
[
3,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
1,
0,
0,
0,
1,
2,
22,
25,
5,
0,
0,
0,
0,
0,
0,
0,
0,
1,
17,
30,
10,
0,
0,
0,
1,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0
],
[
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
2,
21,
27,
7,
2,
0,
0,
0,
0,
1,
0,
0,
10,
35,
12,
2,
0,
0,
0,
1,
0,
0,
0,
0,
1,
0,
0,
0,
0,
0
],
[
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
7,
29,
19,
6,
0,
0,
0,
0,
0,
0,
0,
8,
39,
14,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0
],
[
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
1,
19,
20,
3,
7,
0,
0,
0,
0,
4,
5,
12,
33,
12,
2,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0
],
[
26,
1,
2,
4,
1,
0,
1,
1,
1,
0,
2,
0,
1,
0,
0,
0,
1,
0,
1,
1,
2,
1,
0,
4,
9,
2,
1,
0,
1,
5,
18,
6,
2,
21,
14,
0,
1,
1,
0,
2,
0,
1,
0,
2,
1,
1,
0,
1,
0,
1
],
[
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
1,
0,
0,
0,
0,
0,
1,
0,
1,
0,
0,
1,
1,
10,
10,
1,
0,
1,
2,
32,
19,
3,
20,
17,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0
],
[
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
1,
3,
0,
0,
0,
4,
45,
11,
0,
22,
34,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0
],
[
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
1,
0,
0,
0,
0,
6,
41,
15,
0,
35,
26,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0
],
[
1,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
1,
1,
7,
3,
0,
0,
0,
0,
2,
33,
12,
2,
29,
25,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0
],
[
35,
1,
1,
0,
1,
3,
0,
0,
1,
1,
1,
0,
1,
0,
3,
1,
0,
1,
2,
2,
1,
4,
4,
4,
7,
3,
1,
0,
1,
1,
9,
3,
5,
12,
17,
2,
2,
0,
2,
2,
3,
0,
3,
1,
1,
0,
0,
0,
0,
1
],
[
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
2,
3,
6,
3,
16,
9,
0,
0,
0,
0,
1,
15,
4,
2,
33,
24,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0
],
[
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
2,
1,
7,
2,
7,
18,
9,
5,
0,
0,
0,
1,
4,
4,
19,
18,
19,
2,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0
],
[
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
2,
0,
2,
5,
7,
14,
11,
5,
0,
0,
0,
1,
7,
5,
3,
24,
25,
7,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0
],
[
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
5,
9,
3,
11,
14,
2,
0,
0,
0,
0,
11,
4,
1,
33,
19,
6,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0
],
[
46,
1,
0,
3,
2,
1,
2,
3,
1,
2,
3,
0,
2,
0,
2,
2,
1,
0,
1,
4,
7,
3,
10,
9,
0,
3,
1,
0,
0,
7,
0,
3,
18,
8,
1,
0,
0,
0,
0,
0,
1,
1,
1,
4,
0,
0,
0,
0,
1,
1
],
[
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
4,
7,
2,
15,
10,
4,
0,
0,
0,
0,
11,
7,
1,
32,
20,
8,
1,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0
],
[
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
2,
6,
0,
0,
0,
0,
0,
0,
2,
0,
7,
3,
1,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0
]
]
}
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>d3-heatmap2</title>
<!-- Bootstrap -->
<link href='https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css' rel='stylesheet' type='text/css'>
<!-- d3-heatmap2 -->
<link href='d3-heatmap2.css' rel='stylesheet' type='text/css'>
<style>
/* Space out content a bit */
body {
padding-top: 20px;
padding-bottom: 20px;
}
/* Custom page header */
.header {
padding-bottom: 20px;
padding-right: 15px;
padding-left: 15px;
border-bottom: 1px solid #e5e5e5;
}
/* Make the masthead heading the same height as the navigation */
.header h3 {
margin-top: 0;
margin-bottom: 0;
line-height: 40px;
}
/* Customize container */
.container {
max-width: 960px;
}
</style>
<!-- HTML5 shim and Respond.js for IE8 support of HTML5 elements and media queries -->
<!--[if lt IE 9]>
<script src="https://oss.maxcdn.com/html5shiv/3.7.2/html5shiv.min.js"></script>
<script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script>
<![endif]-->
</head>
<body>
<div class="container">
<div class="header clearfix">
<h3 class="text-muted">d3-heatmap2</h3>
</div>
<div id="chart"></div>
<hr>
<div id="details"></div>
</div>
<!-- D3.js -->
<script src="https://d3js.org/d3.v4.min.js" charset="utf-8"></script>
<!-- d3-heatmap2 -->
<script src="d3-heatmap2.js"></script>
<script>
var chart = null
var selectStart = null
var selectEnd = null
function select(cell) {
if (!selectStart) {
selectStart = cell
chart.setHighlight([{"start": selectStart, "end": selectStart}])
chart.updateHighlight()
} else if (!selectEnd) {
selectEnd = cell
chart.setHighlight([{"start": selectStart, "end": selectEnd}])
chart.updateHighlight()
} else {
selectStart = cell
selectEnd = null
chart.setHighlight([{"start": selectStart, "end": selectStart}])
chart.updateHighlight()
}
}
function hover(cell) {
if (selectStart && !selectEnd) {
if (cell[0] > selectStart[0]) { // column is higher
chart.setHighlight([{"start": selectStart, "end": cell}])
chart.updateHighlight()
} else if (cell[0] = selectStart[0]) { // same column
if (cell[1] >= selectStart[1]) { // row is higher or equal
chart.setHighlight([{"start": selectStart, "end": cell}])
chart.updateHighlight()
} else {
chart.setHighlight([{"start": selectStart, "end": selectStart}])
chart.updateHighlight()
}
} else {
chart.setHighlight([{"start": selectStart, "end": selectStart}])
chart.updateHighlight()
}
}
}
d3.json("data.json", function(error, data) {
if (error) return console.warn(error)
function onClick(d, i, j) {
console.info("Clicked on range " + data.rows[j] + ", time " + data.columns[i] + ", count " + d)
select([i, j])
}
function onMouseOver(d, i, j) {
document.getElementById("details").innerHTML = "time: " + data.columns[i] + ", range: " + data.rows[j] + ", count: " + d
hover([i, j])
}
chart = d3.heatmap()
.title("")
.subtitle("")
.legendLabel("Count")
.width(900)
.xAxisScale([0,121])
.yAxisScale([106,1999])
// .xAxisLabels(data.columns)
// .yAxisLabels(data.rows)
.highlightColor('#936EB5')
.highlightOpacity('0.4')
.onClick(onClick)
.onMouseOver(onMouseOver)
.colorScale(d3.scaleLinear()
.domain([0, 65 / 2, 65])
.range(['#F5F5DC', '#FF5032', '#E50914'])
)
.margin({
top: 40,
right: 0,
bottom: 10,
left: -20
})
d3.select("#chart")
.datum(data.values)
.call(chart)
})
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment