index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>W-PCA Scatterplot Chart</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="description" content="WPCA scatter plot">
<meta name="author" content="Michal Škop">
<script src="//d3js.org/d3.v3.min.js"></script>
<script src="./d3.scatterplot.js"></script>
<script src="./d3.tips.js"></script>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootswatch/3.3.5/united/bootstrap.min.css">
<style type="text/css">
.tick {
fill-opacity: 0;
stroke: #000000;
stroke-width: 1;
}
.domain {
fill: none;
fill-opacity: 0;
stroke: black;
stroke-width: 1;
}
.axis line {
fill: none;
fill-opacity: 0;
stroke: black;
stroke-width: 1;
shape-rendering: crispEdges;
}
.axis text {
font-family: sans-serif;
font-size: 11px;
stroke: gray;
}
circle:hover {
fill-opacity: 1;
}
.label {
font-family: sans-serif;
font-size: 15px;
}
.d3-tip {
line-height: 1;
font-weight: bold;
padding: 12px;
background: rgba(0, 0, 0, 0.8);
color: #fff;
border-radius: 2px;
pointer-events: none;
max-width: 400px;
}
.d3-tip:after {
box-sizing: border-box;
display: inline;
font-size: 10px;
width: 100%;
line-height: 1;
color: rgba(0, 0, 0, 0.8);
position: absolute;
pointer-events: none;
}
.d3-tip:after {
content: "\25BC";
margin: -1px 0 0 0;
top: 100%;
left: 0;
text-align: center;
}
line {
stroke:gray;
stroke-width:0;
opacity: .3;
}
.perfect {
stroke: gray;
stroke-width:0;
opacity: 0.7;
}
#chart {
padding-top:30px;
}
</style>
</head>
<body>
<nav class="navbar navbar-default">
<div class="container">
<div class="navbar-header">
<h2>Spatial distribution of MEPs based on their votes in the 1st year of the 8th term (2014-2015)</h2>
</div>
</div>
</nav>
<div id="chart"></div>
<div class="alert alert-info">
<p>Each bubble represents one MEP.
<p><a href="//bl.ocks.org/michalskop/8514867">W-PCA</a> model is used.
<p>Another file: c2.html (with cutting lines)
<script type="text/javascript">
d3.csv("chart_data.csv", function(voters) {
spdata = [];
voters.forEach(function(d) {
spdata.push({"x":d["wpca:d1"],"y":d["wpca:d2"],"r":d["r"],"color":d["color"],"name":d["name"],"opacity":d["opacity"], "party": d["party"], "country": d["country"]})
});
var scatterplotwithlineplot = [{
"data": spdata,
"margin": {top: 10, right: 10, bottom: 30, left: 30},
"axes": {"labels":{"x":"DIM 1", "y":"DIM 2"}},
"minmax":{"x":{'min':-1,'max':1},"y":{'min':-1,'max':1},"r":{'min':0,'max':1},"rrange":{'min':0,'max':100}},
"size":{"width":500,"height":500}
}];
var svg = d3.select("#chart")
.append("svg")
.attr("width",scatterplotwithlineplot[0]['size']['width'])
.attr("height",scatterplotwithlineplot[0]['size']['height']);
tip = d3.tip().attr('class', 'd3-tip').html(function(d) {
return "<span class=\'stronger\'>" + d["name"] + "</span><br>" + d["party"] + "<br>" + d["country"];
});
svg.call(tip)
var sp = d3.scatterplotwithlineplot()
.data(function(d) {return d.data})
.margin(function(d) {return d.margin})
.axes(function(d) {return d.axes})
.minmax(function(d) {return d.minmax})
.size(function(d) {return d.size})
var scatter = svg.selectAll(".scatterplot")
.data(scatterplotwithlineplot)
.enter()
.append("svg:g")
.attr("transform", "translate(" + scatterplotwithlineplot[0].margin.left + "," + scatterplotwithlineplot[0].margin.top + ")")
.call(sp);
})
</script>
</body>
</html>
c2.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>W-PCA Scatterplot Chart</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="description" content="WPCA scatter plot">
<meta name="author" content="Michal Škop">
<script src="//d3js.org/d3.v3.min.js"></script>
<script src="./d3.scatterplotwithlineplot.js"></script>
<script src="./d3.tips.js"></script>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootswatch/3.3.5/united/bootstrap.min.css">
<style type="text/css">
.tick {
fill-opacity: 0;
stroke: #000000;
stroke-width: 1;
}
.domain {
fill: none;
fill-opacity: 0;
stroke: black;
stroke-width: 1;
}
.axis line {
fill: none;
fill-opacity: 0;
stroke: black;
stroke-width: 1;
shape-rendering: crispEdges;
}
.axis text {
font-family: sans-serif;
font-size: 11px;
stroke: gray;
}
circle:hover {
fill-opacity: 1;
}
.label {
font-family: sans-serif;
font-size: 15px;
}
.d3-tip {
line-height: 1;
font-weight: bold;
padding: 12px;
background: rgba(0, 0, 0, 0.8);
color: #fff;
border-radius: 2px;
pointer-events: none;
max-width: 400px;
}
.d3-tip:after {
box-sizing: border-box;
display: inline;
font-size: 10px;
width: 100%;
line-height: 1;
color: rgba(0, 0, 0, 0.8);
position: absolute;
pointer-events: none;
}
.d3-tip:after {
content: "\25BC";
margin: -1px 0 0 0;
top: 100%;
left: 0;
text-align: center;
}
line {
stroke:gray;
stroke-width:1;
opacity: .3;
}
.perfect {
stroke: gray;
stroke-width:2;
opacity: 0.7;
}
#chart {
padding-top:30px;
}
</style>
</head>
<body>
<nav class="navbar navbar-default">
<div class="container">
<div class="navbar-header">
<h2>Spatial distribution of MEPs based on their votes in the 1st year of the 8th term (2014-2015)</h2>
</div>
</div>
</nav>
<div id="chart"></div>
<div class="alert alert-info">
<p>Each bubble represents one MEP.
<p><a href="//bl.ocks.org/michalskop/8514867">W-PCA</a> model is used.
<script type="text/javascript">
d3.csv("chart_data.csv", function(voters) {
d3.csv("cutting_lines.csv", function(lines) {
linesselected = [];
for (k in lines) {
if ((parseFloat(lines[k]['loss']) < 33) && (parseFloat(lines[k]['cl_beta0']) < 50)) {
beta = [lines[k]['normal_x'],lines[k]['normal_y']];
beta0 = lines[k]['cl_beta0'];
if (beta[1] != 0) {
lines[k]['a'] = -beta0/beta[1];
lines[k]['b'] = -beta[0]/beta[1];
} else {
lines[k]['a'] = 0;
lines[k]['b'] = 0;
}
if (lines[k]['loss'] == 0) {
lines[k]['class'] = 'perfect';
} else {
lines[k]['class'] = 'non-perfect';
}
lines[k]['name'] = lines[k]["motion:name"];
linesselected.push(lines[k]);
}
}
spdata = [];
voters.forEach(function(d) {
spdata.push({"x":d["wpca:d1"],"y":d["wpca:d2"],"r":d["r"],"color":d["color"],"name":d["name"],"opacity":d["opacity"], "party": d["party"], "country": d["country"]})
});
var scatterplotwithlineplot = [{
"data": spdata,
"margin": {top: 10, right: 10, bottom: 30, left: 30},
"axes": {"labels":{"x":"DIM 1", "y":"DIM 2"}},
"minmax":{"x":{'min':-1,'max':1},"y":{'min':-1,'max':1},"r":{'min':0,'max':1},"rrange":{'min':0,'max':100}},
"size":{"width":500,"height":500},
"lines": linesselected
}];
var svg = d3.select("#chart")
.append("svg")
.attr("width",scatterplotwithlineplot[0]['size']['width'])
.attr("height",scatterplotwithlineplot[0]['size']['height']);
tip = d3.tip().attr('class', 'd3-tip').html(function(d) {
return "<span class=\'stronger\'>" + d["name"] + "</span><br>" + d["party"] + "<br>" + d["country"];
});
svg.call(tip)
var sp = d3.scatterplotwithlineplot()
.data(function(d) {return d.data})
.margin(function(d) {return d.margin})
.axes(function(d) {return d.axes})
.minmax(function(d) {return d.minmax})
.size(function(d) {return d.size})
.lines(function(d) {return d.lines})
var scatter = svg.selectAll(".scatterplot")
.data(scatterplotwithlineplot)
.enter()
.append("svg:g")
.attr("transform", "translate(" + scatterplotwithlineplot[0].margin.left + "," + scatterplotwithlineplot[0].margin.top + ")")
.call(sp);
})
})
</script>
</body>
</html>
chart_data.py
import csv
import json
import slugify
g2c = {
'Europe of Freedom and Direct Democracy Group':"#47cbd7",
'Group of the Alliance of Liberals and Democrats for Europe':'gold',
'Non-attached Members':'gray',
'European Conservatives and Reformists Group':'darkblue',
'Group of the Progressive Alliance of Socialists and Democrats in the European Parliament':'red',
'Group of the Greens/European Free Alliance':'darkgreen',
'Europe of Nations and Freedom Group':'#030E40',
'Confederal Group of the European United Left - Nordic Green Left':'darkred',
"Group of the European People's Party (Christian Democrats)":'blue'
}
meps = []
data = {}
files = ["meps_current","meps_ins","meps_outs"]
for f in files:
with open("../" + f + ".json") as fin:
meps = meps + json.load(fin)
ms = {}
for mep in meps:
ms[mep['id']] = mep
with open("chart_data.csv","w") as fout:
csvw = csv.writer(fout)
csvw.writerow(["voter_id","wpca:d1","wpca:d2","name", "party", "political_group", "country", "country_code", "color"])
with open("proj_unit.csv") as fin:
csvd = csv.DictReader(fin)
for row in csvd:
m = ms[row["V1"]]
r = [row["V1"],row["V2"],row["V3"],m['name'],m['party'],m['political_group'],m['country'],m['country_code'],g2c[m['political_group']]]
csvw.writerow(r)
d3.scatterplot.js
d3.scatterplotwithlineplot = function() {
unit_circle = true;
function scatterplotwithlineplot(selection) {
selection.each(function(d, i) {
var data = (typeof(data) === "function" ? data(d) : d.data),
margin = (typeof(margin) === "function" ? margin(d) : d.margin),
axes = (typeof(axes) === "function" ? axes(d) : d.axes),
minmax = (typeof(minmax) === "function" ? minmax(d) : d.minmax),
size = (typeof(size) === "function" ? size(d) : d.size),
unit_circle_val = (typeof(unit_circle) === "function" ? unit_circle(d) : unit_circle);
var width = size['width'] - margin.left - margin.right,
height = size['height'] - margin.top - margin.bottom;
var xScale = d3.scale.linear()
.domain([minmax['x']['min'], minmax['x']['max']])
.range([0, width])
var yScale = d3.scale.linear()
.domain([minmax['y']['min'], minmax['y']['max']])
.range([height, 0])
var rScale = d3.scale.linear()
.domain([minmax['r']['min'],minmax['r']['max']])
.range([minmax['rrange']['min'],minmax['rrange']['max']]);
var xAxis = d3.svg.axis()
.scale(xScale)
.orient("bottom");
var yAxis = d3.svg.axis()
.scale(yScale)
.orient("left");
var element = d3.select(this);
element.append("g")
.attr("class", "axis x-axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis);
element.append("g")
.attr("class", "axis y-axis")
.call(yAxis);
limits = {"x":[minmax["x"]["min"],minmax["x"]["max"]],"y":[minmax["y"]["min"],minmax["y"]["max"]]}
if (unit_circle_val) {
element.selectAll(".ellipse")
.data([0])
.enter()
.append("ellipse")
.attr("cx", xScale(0))
.attr("cy", yScale(0))
.attr("rx", Math.abs(xScale(1)-xScale(0)))
.attr("ry", Math.abs(yScale(1)-yScale(0)))
.attr("fill-opacity",0)
.attr("stroke","red")
.style("stroke-dasharray", ("10,3"));
}
element.selectAll(".circle")
.data(data)
.enter()
.append("circle")
.attr("cx", function(d) {
return xScale(d.x);
})
.attr("cy", function(d) {
return yScale(d.y);
})
.attr("r", function(d) {
if ((typeof(d['r']) != 'undefined') && (d['r'] != ''))
return rScale(d.r);
else return rScale(0.05);
})
.attr("class", function(d) {
if ((typeof(d['class']) != 'undefined') && (d['class'] != ''))
return d['class'];
else return 'circle';
})
.attr("fill",function(d) {
if ((typeof(d['color']) != 'undefined') && (d['color'] != ''))
return d.color;
else
return "#eee";
})
.attr("stroke",function(d) {
if ((typeof(d['color']) != 'undefined') && (d['color'] != ''))
return d.color;
else
return "#bbb";
})
.attr("stroke-width",function(d) {
if ((typeof(d['r']) != 'undefined') && (d['r'] != ''))
return Math.max(d.r*5,1);
else return 1;
})
.attr("fill-opacity",function(d) {
if ((typeof(d['opacity']) != 'undefined') && (d['opacity'] != ''))
return d.opacity;
else
return 0.5;
})
.on('mouseover', tip.show)
.on('mouseout', tip.hide);
element.append("text")
.attr("class", "x-label label")
.attr("text-anchor", "end")
.attr("x", width)
.attr("y", height-5)
.text(axes['labels']['x']);
element.append("text")
.attr("class", "y label")
.attr("text-anchor", "end")
.attr("y", 5)
.attr("x", 0)
.attr("dy", ".75em")
.attr("transform", "rotate(-90)")
.text(axes['labels']['y']);
element.selectAll(".domain")
.attr("fill","none")
.attr("fill-opacity",0)
.attr("stroke","black")
.attr("stroke-width",1);
element.selectAll(".tick")
.attr("fill-opacity",0)
.attr("stroke","#000")
.attr("stroke-width",1);
element.selectAll("text")
.attr("font-family","sans-serif")
.attr("font-size",11)
element.selectAll(".label")
.attr("font-size",15)
.attr("font-weight","bold")
element.selectAll("text")
.attr("dy",function(d) {
if (d3.select(this).attr("dy")) {
em = parseFloat(d3.select(this).attr("dy").replace("em",""));
if (d3.select(this).attr("font-size"))
px = parseFloat(d3.select(this).attr("font-size"));
else
px = 11;
return em*px + "px";
} else {
return 0;
}
})
});
}
scatterplotwithlineplot.data = function(value) {
if (!arguments.length) return value;
data = value;
return scatterplotwithlineplot;
};
scatterplotwithlineplot.margin = function(value) {
if (!arguments.length) return value;
margin = value;
return scatterplotwithlineplot;
};
scatterplotwithlineplot.axes = function(value) {
if (!arguments.length) return value;
axes = value;
return scatterplotwithlineplot;
};
scatterplotwithlineplot.minmax = function(value) {
if (!arguments.length) return value;
minmax = value;
return scatterplotwithlineplot;
};
scatterplotwithlineplot.size = function(value) {
if (!arguments.length) return value;
size = value;
return scatterplotwithlineplot;
};
scatterplotwithlineplot.unit_circle = function(value) {
if (!arguments.length) return value;
unit_circle = value;
return scatterplotwithlineplot;
};
return scatterplotwithlineplot;
function corners(l,e,o) {
outp = linecross (l,e);
out = [];
for (i=0;i<=1;i++){
for (j=0;j<=1;j++){
if (o*(l.a+l.b*e.x[i]-e.y[j]) > 0)
outp.push([e.x[i],e.y[j]]);
}
}
if (outp.length > 0) {
mid = [0,0];
for (i in outp) {
mid[0] += outp[i][0];
mid[1] += outp[i][1];
}
mid[0] = mid[0] / outp.length;
mid[1] = mid[1] / outp.length;
for (i in outp) {
p = outp[i][1] - mid[1];
q = outp[i][0] - mid[0];
if (q != 0)
outp[i][2] = Math.atan(p/q) + (q<0 ? Math.PI : 0);
else
outp[i][2] = Math.PI/2 + Math.PI*sign(p);
}
outp = outp.sort(function(w,z) {
return w[2] > z[2];
});
for (i in outp) {
outp[i].splice(2,1);
out.push({"x":outp[i][0],"y":outp[i][1]});
}
}
return out;
}
function linecross (l,e) {
out = [];
for (i=0;i<=1;i++){
Y = l.a + l.b*e.x[i];
if ((Y > e.y[0]) && (Y < e.y[1]))
out.push([e.x[i],Y]);
}
for (j=0;j<=1;j++){
if (l.b != 0) {
X = (e.y[j] - l.a)/l.b;
if ((X > e.x[0]) && (X < e.x[1]))
out.push([X,e.y[j]]);
}
}
return out;
}
function get_sign(b,d1,d2) {
t = b*d1-d2;
if (t > 0) return 1;
if (t < 0) return -1;
return 0;
}
}
d3.scatterplotwithlineplot.js
d3.scatterplotwithlineplot = function() {
unit_circle = true;
function scatterplotwithlineplot(selection) {
selection.each(function(d, i) {
var data = (typeof(data) === "function" ? data(d) : d.data),
lines = (typeof(lines) === "function" ? lines(d) : d.lines),
margin = (typeof(margin) === "function" ? margin(d) : d.margin),
axes = (typeof(axes) === "function" ? axes(d) : d.axes),
minmax = (typeof(minmax) === "function" ? minmax(d) : d.minmax),
size = (typeof(size) === "function" ? size(d) : d.size),
unit_circle_val = (typeof(unit_circle) === "function" ? unit_circle(d) : unit_circle);
var width = size['width'] - margin.left - margin.right,
height = size['height'] - margin.top - margin.bottom;
var xScale = d3.scale.linear()
.domain([minmax['x']['min'], minmax['x']['max']])
.range([0, width])
var yScale = d3.scale.linear()
.domain([minmax['y']['min'], minmax['y']['max']])
.range([height, 0])
var rScale = d3.scale.linear()
.domain([minmax['r']['min'],minmax['r']['max']])
.range([minmax['rrange']['min'],minmax['rrange']['max']]);
var xAxis = d3.svg.axis()
.scale(xScale)
.orient("bottom");
var yAxis = d3.svg.axis()
.scale(yScale)
.orient("left");
var element = d3.select(this);
element.append("g")
.attr("class", "axis x-axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis);
element.append("g")
.attr("class", "axis y-axis")
.call(yAxis);
limits = {"x":[minmax["x"]["min"],minmax["x"]["max"]],"y":[minmax["y"]["min"],minmax["y"]["max"]]}
for (k in lines) {
ps = linecross(lines[k],limits);
if (ps.length == 2) {
lines[k].x1 = ps[0][0];
lines[k].y1 = ps[0][1];
lines[k].x2 = ps[1][0];
lines[k].y2 = ps[1][1];
}
way = get_sign(lines[k].b,lines[k].n1,lines[k].n2);
lines[k].path =[corners(lines[k],limits,way),corners(lines[k],limits,-1*way)];
}
if (unit_circle_val) {
element.selectAll(".ellipse")
.data([0])
.enter()
.append("ellipse")
.attr("cx", xScale(0))
.attr("cy", yScale(0))
.attr("rx", Math.abs(xScale(1)-xScale(0)))
.attr("ry", Math.abs(yScale(1)-yScale(0)))
.attr("fill-opacity",0)
.attr("stroke","red")
.style("stroke-dasharray", ("10,3"));
}
var line = element.selectAll ('.line')
.data(lines)
.enter()
.append("line")
.attr("x1",function(d) {return xScale(d.x1)})
.attr("y1",function(d) {return yScale(d.y1)})
.attr("x2",function(d) {return xScale(d.x2)})
.attr("y2",function(d) {return yScale(d.y2)})
.attr("id", function (d, i) {return "q-" + i;})
.attr("class", function(d) {
if (typeof(d['class'] != 'undefined')) return d['class'];
else return 'line';
})
.attr("stroke","gray")
.attr("stroke-width","1")
.attr("opacity", 0.15)
.on('mouseover', tip.show)
.on('mouseout', tip.hide);
element.selectAll(".circle")
.data(data)
.enter()
.append("circle")
.attr("cx", function(d) {
return xScale(d.x);
})
.attr("cy", function(d) {
return yScale(d.y);
})
.attr("r", function(d) {
if ((typeof(d['r']) != 'undefined') && (d['r'] != ''))
return rScale(d.r);
else return rScale(0.075);
})
.attr("class", function(d) {
if ((typeof(d['class']) != 'undefined') && (d['class'] != ''))
return d['class'];
else return 'circle';
})
.attr("fill",function(d) {
if ((typeof(d['color']) != 'undefined') && (d['color'] != ''))
return d.color;
else
return "#eee";
})
.attr("stroke",function(d) {
if ((typeof(d['color']) != 'undefined') && (d['color'] != ''))
return d.color;
else
return "#bbb";
})
.attr("stroke-width",function(d) {
if ((typeof(d['r']) != 'undefined') && (d['r'] != ''))
return Math.max(d.r*5,1);
else return 1;
})
.attr("fill-opacity",function(d) {
if ((typeof(d['opacity']) != 'undefined') && (d['opacity'] != ''))
return d.opacity;
else
return 1;
})
.on('mouseover', tip.show)
.on('mouseout', tip.hide);
element.append("text")
.attr("class", "x-label label")
.attr("text-anchor", "end")
.attr("x", width)
.attr("y", height-5)
.text(axes['labels']['x']);
element.append("text")
.attr("class", "y label")
.attr("text-anchor", "end")
.attr("y", 5)
.attr("x", 0)
.attr("dy", ".75em")
.attr("transform", "rotate(-90)")
.text(axes['labels']['y']);
element.selectAll(".domain")
.attr("fill","none")
.attr("fill-opacity",0)
.attr("stroke","black")
.attr("stroke-width",1);
element.selectAll(".tick")
.attr("fill-opacity",0)
.attr("stroke","#000")
.attr("stroke-width",1);
element.selectAll("text")
.attr("font-family","sans-serif")
.attr("font-size",11)
element.selectAll(".label")
.attr("font-size",15)
.attr("font-weight","bold")
element.selectAll("text")
.attr("dy",function(d) {
if (d3.select(this).attr("dy")) {
em = parseFloat(d3.select(this).attr("dy").replace("em",""));
if (d3.select(this).attr("font-size"))
px = parseFloat(d3.select(this).attr("font-size"));
else
px = 11;
return em*px + "px";
} else {
return 0;
}
})
});
}
scatterplotwithlineplot.data = function(value) {
if (!arguments.length) return value;
data = value;
return scatterplotwithlineplot;
};
scatterplotwithlineplot.lines = function(value) {
if (!arguments.length) return value;
lines = value;
return scatterplotwithlineplot;
};
scatterplotwithlineplot.margin = function(value) {
if (!arguments.length) return value;
margin = value;
return scatterplotwithlineplot;
};
scatterplotwithlineplot.axes = function(value) {
if (!arguments.length) return value;
axes = value;
return scatterplotwithlineplot;
};
scatterplotwithlineplot.minmax = function(value) {
if (!arguments.length) return value;
minmax = value;
return scatterplotwithlineplot;
};
scatterplotwithlineplot.size = function(value) {
if (!arguments.length) return value;
size = value;
return scatterplotwithlineplot;
};
scatterplotwithlineplot.unit_circle = function(value) {
if (!arguments.length) return value;
unit_circle = value;
return scatterplotwithlineplot;
};
return scatterplotwithlineplot;
function corners(l,e,o) {
outp = linecross (l,e);
out = [];
for (i=0;i<=1;i++){
for (j=0;j<=1;j++){
if (o*(l.a+l.b*e.x[i]-e.y[j]) > 0)
outp.push([e.x[i],e.y[j]]);
}
}
if (outp.length > 0) {
mid = [0,0];
for (i in outp) {
mid[0] += outp[i][0];
mid[1] += outp[i][1];
}
mid[0] = mid[0] / outp.length;
mid[1] = mid[1] / outp.length;
for (i in outp) {
p = outp[i][1] - mid[1];
q = outp[i][0] - mid[0];
if (q != 0)
outp[i][2] = Math.atan(p/q) + (q<0 ? Math.PI : 0);
else
outp[i][2] = Math.PI/2 + Math.PI*sign(p);
}
outp = outp.sort(function(w,z) {
return w[2] > z[2];
});
for (i in outp) {
outp[i].splice(2,1);
out.push({"x":outp[i][0],"y":outp[i][1]});
}
}
return out;
}
function linecross (l,e) {
out = [];
for (i=0;i<=1;i++){
Y = l.a + l.b*e.x[i];
if ((Y > e.y[0]) && (Y < e.y[1]))
out.push([e.x[i],Y]);
}
for (j=0;j<=1;j++){
if (l.b != 0) {
X = (e.y[j] - l.a)/l.b;
if ((X > e.x[0]) && (X < e.x[1]))
out.push([X,e.y[j]]);
}
}
return out;
}
function get_sign(b,d1,d2) {
t = b*d1-d2;
if (t > 0) return 1;
if (t < 0) return -1;
return 0;
}
}
d3.tips.js
(function (root, factory) {
if (typeof define === 'function' && define.amd) {
define(['d3'], factory)
} else if (typeof module === 'object' && module.exports) {
module.exports = function(d3) {
d3.tip = factory(d3)
return d3.tip
}
} else {
root.d3.tip = factory(root.d3)
}
}(this, function (d3) {
return function() {
var direction = d3_tip_direction,
offset = d3_tip_offset,
html = d3_tip_html,
node = initNode(),
svg = null,
point = null,
target = null
function tip(vis) {
svg = getSVGNode(vis)
point = svg.createSVGPoint()
document.body.appendChild(node)
}
tip.show = function() {
var args = Array.prototype.slice.call(arguments)
if(args[args.length - 1] instanceof SVGElement) target = args.pop()
var content = html.apply(this, args),
poffset = offset.apply(this, args),
dir = direction.apply(this, args),
nodel = d3.select(node),
i = directions.length,
coords,
scrollTop = document.documentElement.scrollTop || document.body.scrollTop,
scrollLeft = document.documentElement.scrollLeft || document.body.scrollLeft
nodel.html(content)
.style({ opacity: 1, 'pointer-events': 'all' })
while(i--) nodel.classed(directions[i], false)
coords = direction_callbacks.get(dir).apply(this)
nodel.classed(dir, true).style({
top: (coords.top + poffset[0]) + scrollTop + 'px',
left: (coords.left + poffset[1]) + scrollLeft + 'px'
})
return tip
}
tip.hide = function() {
var nodel = d3.select(node)
nodel.style({ opacity: 0, 'pointer-events': 'none' })
return tip
}
tip.attr = function(n, v) {
if (arguments.length < 2 && typeof n === 'string') {
return d3.select(node).attr(n)
} else {
var args = Array.prototype.slice.call(arguments)
d3.selection.prototype.attr.apply(d3.select(node), args)
}
return tip
}
tip.style = function(n, v) {
if (arguments.length < 2 && typeof n === 'string') {
return d3.select(node).style(n)
} else {
var args = Array.prototype.slice.call(arguments)
d3.selection.prototype.style.apply(d3.select(node), args)
}
return tip
}
tip.direction = function(v) {
if (!arguments.length) return direction
direction = v == null ? v : d3.functor(v)
return tip
}
tip.offset = function(v) {
if (!arguments.length) return offset
offset = v == null ? v : d3.functor(v)
return tip
}
tip.html = function(v) {
if (!arguments.length) return html
html = v == null ? v : d3.functor(v)
return tip
}
function d3_tip_direction() { return 'n' }
function d3_tip_offset() { return [0, 0] }
function d3_tip_html() { return ' ' }
var direction_callbacks = d3.map({
n: direction_n,
s: direction_s,
e: direction_e,
w: direction_w,
nw: direction_nw,
ne: direction_ne,
sw: direction_sw,
se: direction_se
}),
directions = direction_callbacks.keys()
function direction_n() {
var bbox = getScreenBBox()
return {
top: bbox.n.y - node.offsetHeight,
left: bbox.n.x - node.offsetWidth / 2
}
}
function direction_s() {
var bbox = getScreenBBox()
return {
top: bbox.s.y,
left: bbox.s.x - node.offsetWidth / 2
}
}
function direction_e() {
var bbox = getScreenBBox()
return {
top: bbox.e.y - node.offsetHeight / 2,
left: bbox.e.x
}
}
function direction_w() {
var bbox = getScreenBBox()
return {
top: bbox.w.y - node.offsetHeight / 2,
left: bbox.w.x - node.offsetWidth
}
}
function direction_nw() {
var bbox = getScreenBBox()
return {
top: bbox.nw.y - node.offsetHeight,
left: bbox.nw.x - node.offsetWidth
}
}
function direction_ne() {
var bbox = getScreenBBox()
return {
top: bbox.ne.y - node.offsetHeight,
left: bbox.ne.x
}
}
function direction_sw() {
var bbox = getScreenBBox()
return {
top: bbox.sw.y,
left: bbox.sw.x - node.offsetWidth
}
}
function direction_se() {
var bbox = getScreenBBox()
return {
top: bbox.se.y,
left: bbox.e.x
}
}
function initNode() {
var node = d3.select(document.createElement('div'))
node.style({
position: 'absolute',
top: 0,
opacity: 0,
'pointer-events': 'none',
'box-sizing': 'border-box'
})
return node.node()
}
function getSVGNode(el) {
el = el.node()
if(el.tagName.toLowerCase() === 'svg')
return el
return el.ownerSVGElement
}
function getScreenBBox() {
var targetel = target || d3.event.target;
while ('undefined' === typeof targetel.getScreenCTM && 'undefined' === targetel.parentNode) {
targetel = targetel.parentNode;
}
var bbox = {},
matrix = targetel.getScreenCTM(),
tbbox = targetel.getBBox(),
width = tbbox.width,
height = tbbox.height,
x = tbbox.x,
y = tbbox.y
point.x = x
point.y = y
bbox.nw = point.matrixTransform(matrix)
point.x += width
bbox.ne = point.matrixTransform(matrix)
point.y += height
bbox.se = point.matrixTransform(matrix)
point.x -= width
bbox.sw = point.matrixTransform(matrix)
point.y -= height / 2
bbox.w = point.matrixTransform(matrix)
point.x += width
bbox.e = point.matrixTransform(matrix)
point.x -= width / 2
point.y -= height / 2
bbox.n = point.matrixTransform(matrix)
point.y += height
bbox.s = point.matrixTransform(matrix)
return bbox
}
return tip
};
}));
data.py
import json
import slugify
import csv
countries = []
with open("../member_states.csv") as fin:
csvd = csv.DictReader(fin)
for row in csvd:
countries.append(row['code'])
meps = []
data = {}
files = ["meps_current","meps_ins","meps_outs"]
for f in files:
with open("../" + f + ".json") as fin:
meps = meps + json.load(fin)
name2id = {}
for mep in meps:
name2id[slugify.slugify(mep['name'])] = mep['id']
g2g = {
'Europe of Freedom and Direct Democracy Group':"group_icon_efd",
'Group of the Alliance of Liberals and Democrats for Europe':'group_icon_aldeadle',
'Non-attached Members':'group_icon_ni',
'European Conservatives and Reformists Group':'group_icon_ecr',
'Group of the Progressive Alliance of Socialists and Democrats in the European Parliament':'group_icon_sd',
'Group of the Greens/European Free Alliance':'group_icon_greensefa',
'Europe of Nations and Freedom Group':'group_icon_enf',
'Confederal Group of the European United Left - Nordic Green Left':'group_icon_guengl',
"Group of the European People's Party (Christian Democrats)":'group_icon_epp'
}
o2o = {
'N': 'not voting',
'-': 'no',
'+': 'yes',
'0': 'abstain',
'A': 'absent',
'M': 'absent'
}
def n4(n):
if n > 999:
return str(n)
if n > 99:
return "0" + str(n)
if n > 9:
return "00" + str(n)
return "000" + str(n)
with open("x_source.csv","w") as fout:
csvw = csv.writer(fout)
csvw.writerow(["voter_id","vote_event_id","option"])
for i in range(1,1309):
print(i)
path = "/home/michal/project/vaa2012-2/dev/ep2015/votes_votewatch/" + "vote_event_" + n4(i) + ".json"
with open(path) as fin:
votes = json.load(fin)
for m in votes['all_votes']:
option = o2o[m['euro_vot_valoare_sign']]
voter_id = name2id[slugify.slugify(m['mep_name_name'])]
vote_event_id = i
csvw.writerow([voter_id,vote_event_id,option])