Skip to content

Instantly share code, notes, and snippets.

@jmfernandez
Last active April 17, 2020 22:24
Show Gist options
  • Save jmfernandez/84e9fd5a4f8992f6081da77318a7acf6 to your computer and use it in GitHub Desktop.
Save jmfernandez/84e9fd5a4f8992f6081da77318a7acf6 to your computer and use it in GitHub Desktop.
Plotting functions with D3 (v3, v4 and v5)
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8"/>
<!-- Based on http://bl.ocks.org/enthal/1726550 -->
<title>D3 - Line Chart - continuous function</title>
<!-- script type="text/javascript" src="https://raw.github.com/jquery/sizzle/master/sizzle.js"></script -->
<script type="text/javascript" src="https://d3js.org/d3.v3.min.js"></script>
<script type="text/javascript" src="https://d3js.org/d3-time.v1.min.js"></script>
<style type="text/css">
body {
font: 12px sans-serif;
}
.mouse_area {
opacity: 0;
}
.guides {
stroke-width: 1px;
}
.guides line {
stroke: #BBF;
shape-rendering: crispEdges;
}
.guides circle {
fill: #BBF;
stroke: #348;
opacity: 0.2;
}
.rules line, .rules path {
shape-rendering: crispEdges;
stroke: #000;
}
.rules .tick {
}
.rules .minor {
stroke: #BBB;
}
.rules .domain {
fill: none;
}
.grid .tick {
stroke: #CCC;
}
.series path {
fill: none;
stroke: #348;
stroke-width: 3px;
}
</style>
<script type="text/javascript">
function onload() {
var w = 760;
var h = 400;
var pad = 50;
genGaussianPlot("#left",w,h,pad,[-5,5],[0,1],100);
genF1Plot("#right",w,h,pad,[0,1],[0,1],1000);
}
function genF1Plot(selector, w, h, pad, xRange, yRange, numTicks) {
var x = d3.scale.linear().domain(xRange).range([0,w]);
var y = d3.scale.linear().domain(yRange).range([h,0]);
var svg = d3.select(selector)
.append("svg:svg")
.attr("height", h + pad)
.attr("width", w + pad)
var vis = svg.append("svg:g")
.attr("transform", "translate(40,20)")
var legend = d3.select(selector).append("div")
.classed("legend", true)
//var continuous = make_gaussian_func(-2, .7);
make_rules(vis,x,y,w,h);
var beta = 1;
for(var f=0.1;f<1;f += 0.1) {
var continuous = make_f_contour_func(beta,f);
chart_line(x,y,vis,continuous,numTicks,yRange);
make_mouseover_guides(x,y,w,h,vis,legend,continuous);
}
//var f = 0.5;
//var continuous = make_f_contour_func(beta,f);
//chart_line(x,y,yRange,vis,continuous);
//make_mouseover_guides(x,y,w,h,vis,legend,continuous);
return vis;
}
function genGaussianPlot(selector, w, h, pad, xRange, yRange, numTicks) {
var x = d3.scale.linear().domain(xRange).range([0,w]);
var y = d3.scale.linear().domain(yRange).range([h,0]);
var svg = d3.select(selector)
.append("svg:svg")
.attr("height", h + pad)
.attr("width", w + pad)
var vis = svg.append("svg:g")
.attr("transform", "translate(40,20)")
var legend = d3.select(selector).append("div")
.classed("legend", true)
make_rules(vis,x,y,w,h);
var mu = -2;
var sigma_squared = 0.7;
var continuous = make_gaussian_func(mu, sigma_squared);
chart_line(x,y,vis,continuous,numTicks);
make_mouseover_guides(x,y,w,h,vis,legend,continuous);
return vis;
}
function make_f_contour_func(beta,f) {
// For F contour drawing I have rewritten the F-β function
// defined at https://en.wikipedia.org/wiki/F1_score#Definition
//
// precision * recall
// F-β = (1 + β²) * ---------------------------
// (β² * precision) + recall
//
// clearing precision , supposing that beta and F-beta
// are constant, computing it from the recall
var f_beta = f;
var beta2 = Math.pow(beta,2);
var onebeta2 = 1.0 + beta2;
return (function(recall) {
return (f_beta*recall) / (onebeta2 * recall - f_beta*beta2);
});
}
function make_gaussian_func(mu, sigma_squared) {
// per: http://en.wikipedia.org/wiki/Gaussian_function
// and: http://mathworld.wolfram.com/GaussianFunction.html
var sqrt = Math.sqrt, pow = Math.pow, e = Math.E, pi = Math.PI;
var sigma = sqrt(sigma_squared);
var a = 1 / (sigma * sqrt(2 * pi));
return (function(xi) {
return pow( a * e, - pow(xi - mu, 2) / (2 * pow(sigma, 2)) )
});
}
function chart_line(x,y,vis,continuous,numTicks,/*optional*/yRange) {
var g = vis.append("svg:g")
.classed("series", true)
var points = x.ticks(numTicks).map(function(xi) {
var yi = continuous(xi);
return [xi, yi];
});
if(Array.isArray(yRange)) {
var cutPoint = undefined;
var minYRange = yRange[0];
var maxYRange = yRange[1];
points.forEach(function(pair_i,iPos) {
if(!isFinite(pair_i[1]) || pair_i[1]<minYRange || pair_i[1]>maxYRange) {
cutPoint=iPos+1;
}
});
}
if(cutPoint===undefined || cutPoint<points.length) {
if(cutPoint!==undefined) {
points = points.slice(cutPoint);
}
g.append("svg:path")
.attr("d", function(d) { return d3.svg.line()(
points.map(function(pair_i) {
return [ x(pair_i[0]), y(pair_i[1]) ];
})
)
});
}
}
function make_mouseover_guides(x,y,w,h,vis,legend,continuous) {
var guides = vis.append("svg:g")
.classed("guides", true)
var y_guides = guides.append("svg:g")
guides.append("svg:line")
.attr("y1",h)
y_guides.append("svg:circle")
.attr("r",7)
y_guides.append("svg:line")
.attr("x1",-20)
.attr("x2",+20)
vis.append("svg:rect")
.classed("mouse_area", true)
.attr("width", w)
.attr("height", h)
.on("mousemove", update_legend_values)
.on("mouseout", blank_legend_values)
blank_legend_values();
var format_5f = d3.format(".5f");
function update_legend_values() {
var xi = x.invert(d3.mouse(this)[0]);
legend
.text("x: "+format_5f(xi)+ " | y: "+format_5f(continuous(xi)));
guides
.attr("transform", "translate("+(x(xi))+",0)")
.attr("visibility", "visible")
y_guides
.attr("transform", "translate(0,"+y(continuous(xi))+")")
}
function blank_legend_values() {
legend
.text("Mouse over the graph...")
guides
.attr("visibility", "hidden")
}
}
function make_rules(vis,x,y,w,h) {
var rules = vis.append("svg:g").classed("rules", true)
function make_x_axis() {
return d3.svg.axis()
.scale(x)
.orient("bottom")
.ticks(10)
}
function make_y_axis() {
return d3.svg.axis()
.scale(y)
.orient("left")
.ticks(10)
}
rules.append("svg:g").classed("grid x_grid", true)
.attr("transform", "translate(0,"+h+")")
.call(make_x_axis()
.tickSize(-h,0,0)
.tickFormat("")
)
rules.append("svg:g").classed("grid y_grid", true)
.call(make_y_axis()
.tickSize(-w,0,0)
.tickFormat("")
)
rules.append("svg:g").classed("labels x_labels", true)
.attr("transform", "translate(0,"+h+")")
.call(make_x_axis()
.tickSize(5)
// .tickFormat(d3.time.format("%Y/%m"))
)
rules.append("svg:g").classed("labels y_labels", true)
.call(make_y_axis()
.tickSubdivide(1)
.tickSize(10, 5, 0)
)
}
</script>
</head>
<body onload="onload()">
<div id="left" style="float:left;clear:left;width:50%;"></div>
<div id="right" style="float:right;clear:right;width:50%;"></div>
</body>
</html>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8"/>
<!-- Based on http://bl.ocks.org/enthal/1726550 -->
<title>D3 - Line Chart - continuous function</title>
<!-- script type="text/javascript" src="https://raw.github.com/jquery/sizzle/master/sizzle.js"></script -->
<script type="text/javascript" src="https://d3js.org/d3.v4.min.js"></script>
<script type="text/javascript" src="https://d3js.org/d3-time.v1.min.js"></script>
<style type="text/css">
body {
font: 12px sans-serif;
}
.mouse_area {
opacity: 0;
}
.guides {
stroke-width: 1px;
}
.guides line {
stroke: #BBF;
shape-rendering: crispEdges;
}
.guides circle {
fill: #BBF;
stroke: #348;
opacity: 0.2;
}
.rules line, .rules path {
shape-rendering: crispEdges;
stroke: #000;
}
.rules .tick {
}
.rules .minor {
stroke: #BBB;
}
.rules .domain {
fill: none;
}
.grid .tick {
stroke: #CCC;
}
.series path {
fill: none;
stroke: #348;
stroke-width: 3px;
}
</style>
<script type="text/javascript">
function onload() {
var w = 760;
var h = 400;
var pad = 50;
genGaussianPlot("#left",w,h,pad,[-5,5],[0,1],100);
genF1Plot("#right",w,h,pad,[0,1],[0,1],1000);
}
function genF1Plot(selector, w, h, pad, xRange, yRange, numTicks) {
var x = d3.scaleLinear().domain(xRange).range([0,w]);
var y = d3.scaleLinear().domain(yRange).range([h,0]);
var svg = d3.select(selector)
.append("svg:svg")
.attr("height", h + pad)
.attr("width", w + pad)
var vis = svg.append("svg:g")
.attr("transform", "translate(40,20)")
var legend = d3.select(selector).append("div")
.classed("legend", true)
//var continuous = make_gaussian_func(-2, .7);
make_rules(vis,x,y,w,h);
var beta = 1;
for(var f=0.1;f<1;f += 0.1) {
var continuous = make_f_contour_func(beta,f);
chart_line(x,y,vis,continuous,numTicks,yRange);
make_mouseover_guides(x,y,w,h,vis,legend,continuous);
}
//var f = 0.5;
//var continuous = make_f_contour_func(beta,f);
//chart_line(x,y,yRange,vis,continuous);
//make_mouseover_guides(x,y,w,h,vis,legend,continuous);
return vis;
}
function genGaussianPlot(selector, w, h, pad, xRange, yRange, numTicks) {
var x = d3.scaleLinear().domain(xRange).range([0,w]);
var y = d3.scaleLinear().domain(yRange).range([h,0]);
var svg = d3.select(selector)
.append("svg:svg")
.attr("height", h + pad)
.attr("width", w + pad)
var vis = svg.append("svg:g")
.attr("transform", "translate(40,20)")
var legend = d3.select(selector).append("div")
.classed("legend", true)
make_rules(vis,x,y,w,h);
var mu = -2;
var sigma_squared = 0.7;
var continuous = make_gaussian_func(mu, sigma_squared);
chart_line(x,y,vis,continuous,numTicks);
make_mouseover_guides(x,y,w,h,vis,legend,continuous);
return vis;
}
function make_f_contour_func(beta,f) {
// For F contour drawing I have rewritten the F-β function
// defined at https://en.wikipedia.org/wiki/F1_score#Definition
//
// precision * recall
// F-β = (1 + β²) * ---------------------------
// (β² * precision) + recall
//
// clearing precision , supposing that beta and F-beta
// are constant, computing it from the recall
var f_beta = f;
var beta2 = Math.pow(beta,2);
var onebeta2 = 1.0 + beta2;
return (function(recall) {
return (f_beta*recall) / (onebeta2 * recall - f_beta*beta2);
});
}
function make_gaussian_func(mu, sigma_squared) {
// per: http://en.wikipedia.org/wiki/Gaussian_function
// and: http://mathworld.wolfram.com/GaussianFunction.html
var sqrt = Math.sqrt, pow = Math.pow, e = Math.E, pi = Math.PI;
var sigma = sqrt(sigma_squared);
var a = 1 / (sigma * sqrt(2 * pi));
return (function(xi) {
return pow( a * e, - pow(xi - mu, 2) / (2 * pow(sigma, 2)) )
});
}
function chart_line(x,y,vis,continuous,numTicks,/*optional*/yRange) {
var g = vis.append("svg:g")
.classed("series", true)
var points = x.ticks(numTicks).map(function(xi) {
var yi = continuous(xi);
return [xi, yi];
});
if(Array.isArray(yRange)) {
var cutPoint = undefined;
var minYRange = yRange[0];
var maxYRange = yRange[1];
points.forEach(function(pair_i,iPos) {
if(!isFinite(pair_i[1]) || pair_i[1]<minYRange || pair_i[1]>maxYRange) {
cutPoint=iPos+1;
}
});
}
if(cutPoint===undefined || cutPoint<points.length) {
if(cutPoint!==undefined) {
points = points.slice(cutPoint);
}
g.append("svg:path")
.attr("d", function(d) { return d3.line()(
points.map(function(pair_i) {
return [ x(pair_i[0]), y(pair_i[1]) ];
})
)
});
}
}
function make_mouseover_guides(x,y,w,h,vis,legend,continuous) {
var guides = vis.append("svg:g")
.classed("guides", true)
var y_guides = guides.append("svg:g")
guides.append("svg:line")
.attr("y1",h)
y_guides.append("svg:circle")
.attr("r",7)
y_guides.append("svg:line")
.attr("x1",-20)
.attr("x2",+20)
vis.append("svg:rect")
.classed("mouse_area", true)
.attr("width", w)
.attr("height", h)
.on("mousemove", update_legend_values)
.on("mouseout", blank_legend_values)
blank_legend_values();
var format_5f = d3.format(".5f");
function update_legend_values() {
var xi = x.invert(d3.mouse(this)[0]);
legend
.text("x: "+format_5f(xi)+ " | y: "+format_5f(continuous(xi)));
guides
.attr("transform", "translate("+(x(xi))+",0)")
.attr("visibility", "visible")
y_guides
.attr("transform", "translate(0,"+y(continuous(xi))+")")
}
function blank_legend_values() {
legend
.text("Mouse over the graph...")
guides
.attr("visibility", "hidden")
}
}
function make_rules(vis,x,y,w,h) {
var rules = vis.append("svg:g").classed("rules", true)
function make_x_axis() {
return d3.axisBottom(x)
.ticks(10)
}
function make_y_axis() {
return d3.axisLeft(y)
.ticks(10)
}
rules.append("svg:g").classed("grid x_grid", true)
.attr("transform", "translate(0,"+h+")")
.call(make_x_axis()
.tickSize(-h,0,0)
.tickFormat("")
)
rules.append("svg:g").classed("grid y_grid", true)
.call(make_y_axis()
.tickSize(-w,0,0)
.tickFormat("")
)
rules.append("svg:g").classed("labels x_labels", true)
.attr("transform", "translate(0,"+h+")")
.call(make_x_axis()
.tickSize(5)
// .tickFormat(d3.time.format("%Y/%m"))
)
rules.append("svg:g").classed("labels y_labels", true)
.call(make_y_axis()
//.tickSubdivide(1)
.tickSize(10, 5, 0)
)
}
</script>
</head>
<body onload="onload()">
<div id="left" style="float:left;clear:left;width:50%;"></div>
<div id="right" style="float:right;clear:right;width:50%;"></div>
</body>
</html>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8"/>
<!-- Based on http://bl.ocks.org/enthal/1726550 -->
<title>D3 - Line Chart - continuous function</title>
<!-- script type="text/javascript" src="https://raw.github.com/jquery/sizzle/master/sizzle.js"></script -->
<script type="text/javascript" src="https://d3js.org/d3.v5.min.js"></script>
<script type="text/javascript" src="https://d3js.org/d3-time.v1.min.js"></script>
<style type="text/css">
body {
font: 12px sans-serif;
}
.mouse_area {
opacity: 0;
}
.guides {
stroke-width: 1px;
}
.guides line {
stroke: #BBF;
shape-rendering: crispEdges;
}
.guides circle {
fill: #BBF;
stroke: #348;
opacity: 0.2;
}
.rules line, .rules path {
shape-rendering: crispEdges;
stroke: #000;
}
.rules .tick {
}
.rules .minor {
stroke: #BBB;
}
.rules .domain {
fill: none;
}
.grid .tick {
stroke: #CCC;
}
.series path {
fill: none;
stroke: #348;
stroke-width: 3px;
}
</style>
<script type="text/javascript">
function onload() {
var w = 760;
var h = 400;
var pad = 50;
genGaussianPlot("#left",w,h,pad,[-5,5],[0,1],100);
genF1Plot("#right",w,h,pad,[0,1],[0,1],1000);
}
function genF1Plot(selector, w, h, pad, xRange, yRange, numTicks) {
var x = d3.scaleLinear().domain(xRange).range([0,w]);
var y = d3.scaleLinear().domain(yRange).range([h,0]);
var svg = d3.select(selector)
.append("svg:svg")
.attr("height", h + pad)
.attr("width", w + pad)
var vis = svg.append("svg:g")
.attr("transform", "translate(40,20)")
var legend = d3.select(selector).append("div")
.classed("legend", true)
//var continuous = make_gaussian_func(-2, .7);
make_rules(vis,x,y,w,h);
var beta = 1;
for(var f=0.1;f<1;f += 0.1) {
var continuous = make_f_contour_func(beta,f);
chart_line(x,y,vis,continuous,numTicks,yRange);
make_mouseover_guides(x,y,w,h,vis,legend,continuous);
}
//var f = 0.5;
//var continuous = make_f_contour_func(beta,f);
//chart_line(x,y,yRange,vis,continuous);
//make_mouseover_guides(x,y,w,h,vis,legend,continuous);
return vis;
}
function genGaussianPlot(selector, w, h, pad, xRange, yRange, numTicks) {
var x = d3.scaleLinear().domain(xRange).range([0,w]);
var y = d3.scaleLinear().domain(yRange).range([h,0]);
var svg = d3.select(selector)
.append("svg:svg")
.attr("height", h + pad)
.attr("width", w + pad)
var vis = svg.append("svg:g")
.attr("transform", "translate(40,20)")
var legend = d3.select(selector).append("div")
.classed("legend", true)
make_rules(vis,x,y,w,h);
var mu = -2;
var sigma_squared = 0.7;
var continuous = make_gaussian_func(mu, sigma_squared);
chart_line(x,y,vis,continuous,numTicks);
make_mouseover_guides(x,y,w,h,vis,legend,continuous);
return vis;
}
function make_f_contour_func(beta,f) {
// For F contour drawing I have rewritten the F-β function
// defined at https://en.wikipedia.org/wiki/F1_score#Definition
//
// precision * recall
// F-β = (1 + β²) * ---------------------------
// (β² * precision) + recall
//
// clearing precision , supposing that beta and F-beta
// are constant, computing it from the recall
var f_beta = f;
var beta2 = Math.pow(beta,2);
var onebeta2 = 1.0 + beta2;
return (function(recall) {
return (f_beta*recall) / (onebeta2 * recall - f_beta*beta2);
});
}
function make_gaussian_func(mu, sigma_squared) {
// per: http://en.wikipedia.org/wiki/Gaussian_function
// and: http://mathworld.wolfram.com/GaussianFunction.html
var sqrt = Math.sqrt, pow = Math.pow, e = Math.E, pi = Math.PI;
var sigma = sqrt(sigma_squared);
var a = 1 / (sigma * sqrt(2 * pi));
return (function(xi) {
return pow( a * e, - pow(xi - mu, 2) / (2 * pow(sigma, 2)) )
});
}
function chart_line(x,y,vis,continuous,numTicks,/*optional*/yRange) {
var g = vis.append("svg:g")
.classed("series", true)
var points = x.ticks(numTicks).map(function(xi) {
var yi = continuous(xi);
return [xi, yi];
});
if(Array.isArray(yRange)) {
var cutPoint = undefined;
var minYRange = yRange[0];
var maxYRange = yRange[1];
points.forEach(function(pair_i,iPos) {
if(!isFinite(pair_i[1]) || pair_i[1]<minYRange || pair_i[1]>maxYRange) {
cutPoint=iPos+1;
}
});
}
if(cutPoint===undefined || cutPoint<points.length) {
if(cutPoint!==undefined) {
points = points.slice(cutPoint);
}
g.append("svg:path")
.attr("d", function(d) { return d3.line()(
points.map(function(pair_i) {
return [ x(pair_i[0]), y(pair_i[1]) ];
})
)
});
}
}
function make_mouseover_guides(x,y,w,h,vis,legend,continuous) {
var guides = vis.append("svg:g")
.classed("guides", true)
var y_guides = guides.append("svg:g")
guides.append("svg:line")
.attr("y1",h)
y_guides.append("svg:circle")
.attr("r",7)
y_guides.append("svg:line")
.attr("x1",-20)
.attr("x2",+20)
vis.append("svg:rect")
.classed("mouse_area", true)
.attr("width", w)
.attr("height", h)
.on("mousemove", update_legend_values)
.on("mouseout", blank_legend_values)
blank_legend_values();
var format_5f = d3.format(".5f");
function update_legend_values() {
var xi = x.invert(d3.mouse(this)[0]);
legend
.text("x: "+format_5f(xi)+ " | y: "+format_5f(continuous(xi)));
guides
.attr("transform", "translate("+(x(xi))+",0)")
.attr("visibility", "visible")
y_guides
.attr("transform", "translate(0,"+y(continuous(xi))+")")
}
function blank_legend_values() {
legend
.text("Mouse over the graph...")
guides
.attr("visibility", "hidden")
}
}
function make_rules(vis,x,y,w,h) {
var rules = vis.append("svg:g").classed("rules", true)
function make_x_axis() {
return d3.axisBottom(x)
.ticks(10)
}
function make_y_axis() {
return d3.axisLeft(y)
.ticks(10)
}
rules.append("svg:g").classed("grid x_grid", true)
.attr("transform", "translate(0,"+h+")")
.call(make_x_axis()
.tickSize(-h,0,0)
.tickFormat("")
)
rules.append("svg:g").classed("grid y_grid", true)
.call(make_y_axis()
.tickSize(-w,0,0)
.tickFormat("")
)
rules.append("svg:g").classed("labels x_labels", true)
.attr("transform", "translate(0,"+h+")")
.call(make_x_axis()
.tickSize(5)
// .tickFormat(d3.time.format("%Y/%m"))
)
rules.append("svg:g").classed("labels y_labels", true)
.call(make_y_axis()
//.tickSubdivide(1)
.tickSize(10, 5, 0)
)
}
</script>
</head>
<body onload="onload()">
<div id="left" style="float:left;clear:left;width:50%;"></div>
<div id="right" style="float:right;clear:right;width:50%;"></div>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment