Skip to content

Instantly share code, notes, and snippets.

@Fil

Fil/.block Secret

Last active April 25, 2017 08:28
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 Fil/6e83bb512f22ec579f6226b7692530fb to your computer and use it in GitHub Desktop.
Save Fil/6e83bb512f22ec579f6226b7692530fb to your computer and use it in GitHub Desktop.
Fourier interpolation
license: mit

Join points with a Fourier interpolator, for Chris Henrick.

We resample by adding zeros to the FFT and calling the inverse, there is probably a better way???

Two difficulties here:

  1. you must filter out the zeros if you want something that follows the main rythm
  2. the timestamps are not on fixed interval, which FFT expects, so we have to map everything to fixed intervals, do the FFT (on the filtered data), then remap to the original timeline.

See the sinusoidal version.

Built with blockbuilder.org

forked from Fil's block: Parabolic interpolation

<!DOCTYPE html>
<head>
<meta charset="utf-8">
<script src="https://d3js.org/d3.v4.min.js"></script>
<script src="https://unpkg.com/fourier@0.2.1/fourier.js"></script>
<style>
body { margin:0;position:fixed;top:0;right:0;bottom:0;left:0; }
</style>
</head>
<body>
<script>
var svg = d3.select("body").append("svg")
.attr("width", 960)
.attr("height", 500)
.append('g')
.attr('transform', 'translate(10,10)');
var width = 940, height = 480
var parset = d3.timeParse('%m/%d/%y %H:%M');
var data = d3.csvParse(`Date_Time,Event,Speed
3/31/17 0:24,flood,1.59
3/31/17 3:42,slack,0
3/31/17 7:12,ebb,-1.86
3/31/17 10:30,slack,0
3/31/17 13:12,flood,1.43
3/31/17 17:00,slack,0
3/31/17 20:00,ebb,-1.45
3/31/17 22:42,slack,0
4/1/17 1:12,flood,1.48
4/1/17 4:24,slack,0
4/1/17 8:06,ebb,-1.74
4/1/17 11:30,slack,0
4/1/17 14:06,flood,1.23
4/1/17 18:06,slack,0
4/1/17 21:00,ebb,-1.25
4/1/17 23:36,slack,0
`)
.map((d,i) => {
d.time = +parset(d.Date_Time);
d.speed = +d.Speed;
return d;
});
const x = d3.scaleLinear()
.domain(d3.extent(data.map(d => d.time)))
.range([0,width]);
const y = d3.scaleLinear()
.domain(d3.extent(data.map(d => d.speed)))
.range([height,0]);
// compute the Fast Fourier transform
const a = data.filter(d => d.Event != 'slack'),
points = 256,
c = points / a.length,
d = points / data.length,
f = fourier.dft(a.map((d,i) => d.speed), a.map((d,i) => 0)),
zeros = d3.range(points - f[0].length).map(d => 0),
h = [ [...zeros,...f[0]], [...zeros,...f[1]]],
g = fourier.idft(...h)
// interpolate the values
function inter(i) {
return c * (g[0][i] || 0)
}
// interpolate the time
t = d3.scaleLinear()
.domain(d3.range(data.length))
.range(data.map(d => d.time));
var line = d3.line().x(i => x(t(i / d))).y(i => y(inter(i)));
svg.append('path')
.attr('fill', 'none')
.attr('stroke', 'lightblue')
.attr('d', line(d3.range(points)))
svg.selectAll('circle')
.data(data)
.enter()
.append('circle')
.attr('r', 4)
.attr('cx', d => x(d.time))
.attr('cy', d => y(d.speed))
</script>
</body>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment