The properties of Fermions drawn as a radar plot. The radar plot is achieved by mapping the angle and value along the axis to by converting polar co-ordinates to svg (x, y) co-ordinates.
Last active
February 29, 2016 08:19
-
-
Save starcalibre/a0a0449817b71eddc7f3 to your computer and use it in GitHub Desktop.
Radar Plot of Fermion Properties
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
.idea/ | |
*.iml |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var fermions = [ | |
{ | |
name: 'Up Quark', | |
mass: 2.4, | |
charge: 0.666, | |
spin: 0.5 | |
}, | |
{ | |
name: 'Down Quark', | |
mass: 4.8, | |
charge: -0.333, | |
spin: 0.5 | |
}, | |
{ | |
name: 'e Nutrino', | |
mass: 2.2, | |
charge: 0, | |
spin: 0.5 | |
}, | |
{ | |
name: 'Electron', | |
mass: 0.511, | |
charge: -1, | |
spin: 0.5 | |
} | |
]; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<html lang="en"> | |
<head> | |
<meta charset="UTF-8"> | |
<title></title> | |
<style> | |
circle, polygon { | |
fill: none; | |
stroke-width: 1px; | |
stroke: black; | |
} | |
.axis path, | |
.axis line { | |
fill: none; | |
stroke: #000000; | |
stroke-width: 1px; | |
shape-rendering: optimizeQuality; | |
} | |
.axis text { | |
font-family: monospace; | |
font-size: 12px; | |
} | |
.label { | |
font-family: monospace; | |
} | |
</style> | |
</head> | |
<body> | |
</body> | |
<script src="./fermions.js"></script> | |
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.14/d3.min.js"></script> | |
<script> | |
var width = 500; | |
var height = 500; | |
var axisLength = 275; | |
var axisOffset = (height/2 - axisLength); | |
var massScale = d3.scale.linear() | |
.domain([0, 5]) | |
.range([0, axisLength]); | |
var chargeScale = d3.scale.linear() | |
.domain([-1.2, 0.8]) | |
.range([0, axisLength]); | |
var spinScale = d3.scale.linear() | |
.domain([0, 0.5]) | |
.range([0, axisLength]); | |
var svg = d3.select('body').append('svg') | |
.attr('width', width) | |
.attr('height', height) | |
.append("g") | |
.attr("transform", translateString(0, 50)); | |
var colourScale = ['#66c2a5', '#fc8d62', '#8da0cb', '#e78ac3']; | |
// create polygon for each datapoint | |
var delta = (2 * Math.PI) / 3; | |
fermions.forEach(function(d) { | |
var polygon = []; | |
var mass = polarToCartestian(massScale(d.mass), -Math.PI / 2); | |
polygon.push([width/2 + mass[0], height/2 + mass[1]]); | |
var charge = polarToCartestian(chargeScale(d.charge), -Math.PI / 2 + delta); | |
polygon.push([width/2 + charge[0], height/2 + charge[1]]); | |
var spin = polarToCartestian(spinScale(d.spin), -Math.PI / 2 + 2 * delta); | |
polygon.push([width/2 + spin[0], height/2 + spin[1]]); | |
d.polygon = polygon.map(function(d) { | |
return d.join(","); | |
}).join(" ") | |
}); | |
// attach the polygons to the svg with a data-bind | |
svg.selectAll('polygon') | |
.data(fermions) | |
.enter() | |
.append('polygon') | |
.attr("id", function(d, i) { | |
return "polygon-" + i; | |
}) | |
.attr("points", function(d) { | |
return d.polygon; | |
}) | |
.style("fill", function(d, i) { | |
return colourScale[i]; | |
}) | |
.style("opacity", 0.4) | |
.on("mouseover", function(d, i) { | |
onMouseOver(i); | |
}) | |
.on("mouseout", function() { | |
onMouseOut(); | |
}); | |
// create and attach the axes | |
var massAxis = d3.svg.axis() | |
.scale(massScale) | |
.orient("left") | |
.ticks(3) | |
.tickFormat(function(d) { return d.toPrecision(2) }); | |
svg.append("g") | |
.attr("class", "mass axis") | |
.attr("transform", translateString(width/2, axisOffset + axisLength) + | |
rotateString(Math.PI)) | |
.call(massAxis) | |
.selectAll("text") | |
.attr("transform", translateString(-40, 0) + rotateString(Math.PI)); | |
var chargeAxis = d3.svg.axis() | |
.scale(chargeScale) | |
.orient("left") | |
.ticks(3); | |
svg.append("g") | |
.attr("class", "axis") | |
.attr("transform", translateString(width/2, axisOffset + axisLength) + | |
rotateString(-Math.PI / 3)) | |
.call(chargeAxis); | |
var spinAxis = d3.svg.axis() | |
.scale(spinScale) | |
.orient("left") | |
.ticks(3); | |
svg.append("g") | |
.attr("class", "axis") | |
.attr("transform", translateString(width/2, axisOffset + axisLength) + | |
rotateString(Math.PI / 3)) | |
.call(spinAxis); | |
// add axis labels | |
svg.append("text") | |
.attr("class", "label") | |
.attr("x", 279) | |
.attr("y", 0) | |
.text("Mass (MeV)"); | |
svg.append("text") | |
.attr("class", "label") | |
.attr("x", 398) | |
.attr("y", 413) | |
.text("Charge"); | |
svg.append("text") | |
.attr("class", "label") | |
.attr("x", 30) | |
.attr("y", 413) | |
.text("Spin"); | |
// add plot legend | |
var legendX = 370; | |
var legendY = 50; | |
var legendDy = 30; | |
var names = fermions.map(function(d) { return d.name }); | |
names.forEach(function(d, i) { | |
svg.append("rect") | |
.attr("id", "legend-rect-" + i) | |
.attr("class", "legend-rect") | |
.attr("x", 370) | |
.attr("y", legendY + legendDy * i) | |
.attr("width", 25) | |
.attr("height", 25) | |
.attr("fill", colourScale[i]) | |
.style("opacity", 0.4) | |
.on("mouseover", function() { | |
onMouseOver(i); | |
}) | |
.on("mouseout", function() { | |
onMouseOut(); | |
}); | |
svg.append("text") | |
.attr("id", "legend-text-" + i) | |
.text(d) | |
.attr("class", "label legend-text") | |
.attr("x", 402) | |
.attr("y", legendY + legendDy * i + 17) | |
.on("mouseover", function() { | |
onMouseOver(i); | |
}) | |
.on("mouseout", function() { | |
onMouseOut(); | |
}); | |
}); | |
function onMouseOver(i) { | |
d3.select("#legend-rect-" + i) | |
.style("opacity", 1); | |
d3.select("#legend-text-" + i) | |
.style("font-weight", "bold"); | |
d3.select("#polygon-" + i) | |
.style("opacity", 1); | |
} | |
function onMouseOut() { | |
d3.selectAll(".legend-rect") | |
.style("opacity", 0.4); | |
d3.selectAll(".legend-text") | |
.style("font-weight", "normal"); | |
d3.selectAll("polygon") | |
.style("opacity", 0.4) | |
} | |
function rotateString(r, cx, cy) { | |
if(!cx || !cy) { | |
cx = 0; | |
cy = 0; | |
} | |
var deg = r * (180 / Math.PI); | |
var out = ["rotate("]; | |
out.push(deg); | |
out.push(" "); | |
out.push(cx); | |
out.push(" "); | |
out.push(cy); | |
out.push(")"); | |
return out.join(""); | |
} | |
function translateString(x, y) { | |
var out = ["translate("]; | |
out.push(x); | |
out.push(" "); | |
out.push(y); | |
out.push(")"); | |
return out.join("") | |
} | |
function polarToCartestian(r, theta) { | |
var x = r * Math.cos(theta); | |
var y = r * Math.sin(theta); | |
return [x, y]; | |
} | |
</script> | |
</html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment