Skip to content

Instantly share code, notes, and snippets.

@jonahwilliams
Last active August 29, 2015 14:19
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 jonahwilliams/d7620abc1f0329c0901e to your computer and use it in GitHub Desktop.
Save jonahwilliams/d7620abc1f0329c0901e to your computer and use it in GitHub Desktop.
Gaussian Smoother
<!DOCTYPE html>
<meta charset="utf-8">
<head>
<style>
.axis {
font: 10px sans-serif;
}
path {
stroke: steelblue;
stroke-width: 2;
fill: none;
}
.axis path,
.axis line {
fill: none;
stroke: #000;
shape-rendering: crispEdges;
}
</style>
</head>
<body>
<div id="BandSelect" align=center></div>
<script src="http://d3js.org/d3.v3.min.js"></script>
<script>
var data = []
for (var i = 0; i < 20; i++){
var a = 6 * Math.random();
data.push({'x': a,'y': 0.9 * Math.sin(a) + (0.25 * Math.random()) - 0.125});
}
var sliderLabel = d3.select("#BandSelect")
.append("label")
.attr("for", "fader")
.text("theta");
var slider = d3.select("#BandSelect").append("input")
.attr("id","slider2").attr("type","range")
.attr("min","0.01").attr("max","6")
.attr("step","0.01").attr("value","1")
.attr("oninput","outputUpdate(value)");
var sliderOutput = d3.select("#BandSelect")
.append("output").attr("for","fader")
.attr("id","band")
.text("1");
var margin = {top: 80, right: 180, bottom: 80, left: 180},
width = 960 - margin.left - margin.right,
height = 500 - margin.top - margin.bottom;
var svg = d3.select("body").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 + ")");
var y = d3.scale.linear()
.domain([-1, 1])
.range([height, 0]);
var x = d3.scale.linear()
.domain([0, 6])
.range([0, width])
var xAxis = d3.svg.axis()
.scale(x)
.orient("bottom");
var yAxis = d3.svg.axis()
.scale(y)
.orient("left");
var line = d3.svg.line()
.x(function(d) { return x(d.x); })
.y(function(d) { return y(d.y); });
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis)
svg.append("g")
.attr("class", "y axis")
.call(yAxis);
svg.selectAll(".dot")
.data(data)
.enter().append("circle")
.attr("class", "dot")
.attr("r", 3.5)
.attr("cx", function(d){
return x(d.x);
})
.attr("cy", function(d){
return y(d.y)
})
.style("fill", "black");
var smoothed = gaussianSmoother(data, 1, 0, 6, 1000);
svg.append("path")
.datum(smoothed)
.attr("class", "line")
.attr("d", line);
slider.on("change", function(d){
band = ChangeReg();
var smoothed = gaussianSmoother(data, band, 0, 6, 1000);
svg.selectAll(".line")
.datum(smoothed)
.transition()
.attr("class", "line")
.attr("d", line);
});
function gaussianSmoother(data, variance, rangeMin, rangeMax, samples){
var smoothData = [];
var step = (rangeMax - rangeMin) / samples;
//generate support set for given resolution
for (var i = 0; i < samples; i++){
var total_weight = Number.MIN_VALUE;
var individual_weight = [];
var y = Number.MIN_VALUE;
for (var j = 0; j < data.length; j++){
var d = Gaussian(i * step, data[j].x, variance);
total_weight += d;
individual_weight.push(d);
}
for (var j = 0; j < data.length; j++){
y += (individual_weight[j] * data[j].y) / total_weight;
}
smoothData.push({'x': i * step, 'y': y});
}
return smoothData;
}
function Gaussian(x1, x2, h){
var a = 1 / (h * Math.sqrt(Math.PI * 2))
var b = -Math.pow(x1 - x2,2) / (2 * Math.pow(h, 2))
return a * Math.pow(Math.E, b);
}
function ChangeReg() {
var e = document.getElementById("band");
var selection = +e.value;
return selection;
}
function outputUpdate(vol) {
document.querySelector('#band').value = vol;
}
</script>
</body>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment