Skip to content

Instantly share code, notes, and snippets.

@kleem
Last active November 9, 2016 13:24
Show Gist options
  • Save kleem/c6533e3e1a2002c901765e68ee3ddc85 to your computer and use it in GitHub Desktop.
Save kleem/c6533e3e1a2002c901765e68ee3ddc85 to your computer and use it in GitHub Desktop.
Rectangular adjacency matrix IV
# DATA
links = [
{a: 'Italy', b: 'Italian', w: 1},
{a: 'Germany', b: 'German', w: 5},
{a: 'France', b: 'French', w: 2},
{a: 'Spain', b: 'Spanish', w: 2},
{a: 'Switzerland', b: 'Italian', w: 2},
{a: 'Switzerland', b: 'German', w: 1},
{a: 'Switzerland', b: 'French', w: 1}
]
a_ids = (d3.set (links.map (d) -> d.a)).values()
b_ids = (d3.set (links.map (d) -> d.b)).values()
max_weight = d3.max links, (d) -> d.w
# LAYOUT
# try to fit this rectangle with the matrix
matrix_w = 400
matrix_h = 400
a_n = a_ids.length
b_n = b_ids.length
cellsize = Math.min matrix_w/b_n, matrix_h/a_n # beware! a is y and b is x!
a_ids.sort()
b_ids.sort()
x = d3.scaleBand()
.domain b_ids # beware! a is y and b is x!
.range [-cellsize*b_n/2, cellsize*b_n/2] # centered in (0,0)
y = d3.scaleBand()
.domain a_ids
.range [-cellsize*a_n/2, cellsize*a_n/2]
weight2radius = d3.scaleSqrt()
.domain [0, max_weight]
.range [0, x.bandwidth()/2] # x.bw == y.bw
# VIS
svg = d3.select 'svg'
width = svg.node().getBoundingClientRect().width
height = svg.node().getBoundingClientRect().height
# center the vis on (0,0)
vis = svg.append 'g'
.attrs
transform: "translate(#{width/2},#{height/2})"
# draw background lines
hlines = vis.selectAll '.hline'
.data a_ids, (d) -> d
en_hlines = hlines.enter().append 'line'
.attrs
class: 'hline line'
all_hlines = en_hlines.merge hlines
all_hlines
.attrs
x1: x.range()[0]
y1: (d) -> y(d) + y.bandwidth()/2
x2: x.range()[1]
y2: (d) -> y(d) + y.bandwidth()/2
hlines.exit().remove()
vlines = vis.selectAll '.vline'
.data b_ids, (d) -> d
en_vlines = vlines.enter().append 'line'
.attrs
class: 'vline line'
all_vlines = en_vlines.merge vlines
all_vlines
.attrs
x1: (d) -> x(d) + x.bandwidth()/2
y1: y.range()[0]
x2: (d) -> x(d) + x.bandwidth()/2
y2: y.range()[1]
vlines.exit().remove()
# draw cells
cells = vis.selectAll '.cell'
.data links, (d) -> "#{d.a}--#{d.b}"
en_cells = cells.enter().append 'circle'
.attrs
class: 'cell'
all_cells = en_cells.merge cells
all_cells
.attrs
cx: (d) -> x(d.b) + x.bandwidth()/2
cy: (d) -> y(d.a) + y.bandwidth()/2
r: (d) -> weight2radius(d.w)
cells.exit().remove()
# draw row labels
a_labels = vis.selectAll '.a_label'
.data a_ids
en_a_labels = a_labels.enter().append 'text'
.attrs
class: 'a_label'
all_a_labels = en_a_labels.merge a_labels
all_a_labels
.text (d) -> d
.attrs
dy: '0.35em'
x: x.range()[0] - 8
y: (d) -> y(d) + y.bandwidth()/2
a_labels.exit().remove()
# draw column labels
b_labels = vis.selectAll '.b_label'
.data b_ids
en_b_labels = b_labels.enter().append 'text'
.attrs
class: 'b_label'
all_b_labels = en_b_labels.merge b_labels
all_b_labels
.text (d) -> d
.attrs
x: (d) -> x(d) + x.bandwidth()/2
y: y.range()[0] - 8
b_labels.exit().remove()
body, html {
padding: 0;
margin: 0;
height: 100%;
}
svg {
width: 100%;
height: 100%;
background: white;
}
.line {
stroke: #EEE;
}
.cell {
fill: teal;
}
.a_label, .b_label {
font-family: sans-serif;
font-size: 14px;
}
.a_label {
text-anchor: end;
}
.b_label {
text-anchor: middle;
}
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Rectangular adjacency matrix IV</title>
<link type="text/css" href="index.css" rel="stylesheet"/>
<script src="https://d3js.org/d3.v4.min.js"></script>
<script src="https://d3js.org/d3-selection-multi.v0.4.min.js"></script>
</head>
<body>
<svg></svg>
<script src="index.js"></script>
</body>
</html>
// Generated by CoffeeScript 1.10.0
(function() {
var a_ids, a_labels, a_n, all_a_labels, all_b_labels, all_cells, all_hlines, all_vlines, b_ids, b_labels, b_n, cells, cellsize, en_a_labels, en_b_labels, en_cells, en_hlines, en_vlines, height, hlines, links, matrix_h, matrix_w, max_weight, svg, vis, vlines, weight2radius, width, x, y;
links = [
{
a: 'Italy',
b: 'Italian',
w: 1
}, {
a: 'Germany',
b: 'German',
w: 5
}, {
a: 'France',
b: 'French',
w: 2
}, {
a: 'Spain',
b: 'Spanish',
w: 2
}, {
a: 'Switzerland',
b: 'Italian',
w: 2
}, {
a: 'Switzerland',
b: 'German',
w: 1
}, {
a: 'Switzerland',
b: 'French',
w: 1
}
];
a_ids = (d3.set(links.map(function(d) {
return d.a;
}))).values();
b_ids = (d3.set(links.map(function(d) {
return d.b;
}))).values();
max_weight = d3.max(links, function(d) {
return d.w;
});
matrix_w = 400;
matrix_h = 400;
a_n = a_ids.length;
b_n = b_ids.length;
cellsize = Math.min(matrix_w / b_n, matrix_h / a_n);
a_ids.sort();
b_ids.sort();
x = d3.scaleBand().domain(b_ids).range([-cellsize * b_n / 2, cellsize * b_n / 2]);
y = d3.scaleBand().domain(a_ids).range([-cellsize * a_n / 2, cellsize * a_n / 2]);
weight2radius = d3.scaleSqrt().domain([0, max_weight]).range([0, x.bandwidth() / 2]);
svg = d3.select('svg');
width = svg.node().getBoundingClientRect().width;
height = svg.node().getBoundingClientRect().height;
vis = svg.append('g').attrs({
transform: "translate(" + (width / 2) + "," + (height / 2) + ")"
});
hlines = vis.selectAll('.hline').data(a_ids, function(d) {
return d;
});
en_hlines = hlines.enter().append('line').attrs({
"class": 'hline line'
});
all_hlines = en_hlines.merge(hlines);
all_hlines.attrs({
x1: x.range()[0],
y1: function(d) {
return y(d) + y.bandwidth() / 2;
},
x2: x.range()[1],
y2: function(d) {
return y(d) + y.bandwidth() / 2;
}
});
hlines.exit().remove();
vlines = vis.selectAll('.vline').data(b_ids, function(d) {
return d;
});
en_vlines = vlines.enter().append('line').attrs({
"class": 'vline line'
});
all_vlines = en_vlines.merge(vlines);
all_vlines.attrs({
x1: function(d) {
return x(d) + x.bandwidth() / 2;
},
y1: y.range()[0],
x2: function(d) {
return x(d) + x.bandwidth() / 2;
},
y2: y.range()[1]
});
vlines.exit().remove();
cells = vis.selectAll('.cell').data(links, function(d) {
return d.a + "--" + d.b;
});
en_cells = cells.enter().append('circle').attrs({
"class": 'cell'
});
all_cells = en_cells.merge(cells);
all_cells.attrs({
cx: function(d) {
return x(d.b) + x.bandwidth() / 2;
},
cy: function(d) {
return y(d.a) + y.bandwidth() / 2;
},
r: function(d) {
return weight2radius(d.w);
}
});
cells.exit().remove();
a_labels = vis.selectAll('.a_label').data(a_ids);
en_a_labels = a_labels.enter().append('text').attrs({
"class": 'a_label'
});
all_a_labels = en_a_labels.merge(a_labels);
all_a_labels.text(function(d) {
return d;
}).attrs({
dy: '0.35em',
x: x.range()[0] - 8,
y: function(d) {
return y(d) + y.bandwidth() / 2;
}
});
a_labels.exit().remove();
b_labels = vis.selectAll('.b_label').data(b_ids);
en_b_labels = b_labels.enter().append('text').attrs({
"class": 'b_label'
});
all_b_labels = en_b_labels.merge(b_labels);
all_b_labels.text(function(d) {
return d;
}).attrs({
x: function(d) {
return x(d) + x.bandwidth() / 2;
},
y: y.range()[0] - 8
});
b_labels.exit().remove();
}).call(this);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment