The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.
#!perl
use strict;
use warnings;
use lib 'lib';
use Math::FFTW;

# You need a gnuplot to run this example.
# Multiple instances of gnuplot will be spawned to display data.
# Enter 'q' in the gnuplot shell to exit an instance. Execution will
# continue afterwards.

# Leave as 'gnuplot' if it's in PATH, otherwise set to full
# gnuplot path:
my $gp = 'gnuplot';

use File::Temp qw/tempfile/;

# This is a sine with some randomness. Sampled at 10000 points from
# 1/100 to 100.
my @x   = (1..10000);
my @y   = map {
    my $y = sin($_/100);
    $y-=0.25*$y;$y+=rand($y*0.5);
    $y
} @x;

# Plot the input data.
print "Plotting input data...\n";
plot(\@x, \@y);

print "Computing Discrete Fourier Transform...\n";
my $res = Math::FFTW::fftw_dft_real2complex_1d(\@y);

print "Plotting coefficients (real, imaginary, real, ...)...\n";
plot(\@x, $res);

print "Setting all coefficients beyond 25 to 0 for smoothing...\n";
for (50..$#$res) {
    $res->[$_] = 0;
}

print "Computing inverse DFT...\n";
my $res2 = Math::FFTW::fftw_idft_complex2real_1d($res);

print "Plotting smoothed data...\n";
plot(\@x, $res2);

sub plot {
    my $xdata = shift;
    my $ydata = shift;
    my ($fh, $fname) = tempfile(UNLINK => 1);
    foreach my $i (0..$#$xdata) {
        print $fh $xdata->[$i], ' ', $ydata->[$i], "\n";
    }
    if (@$ydata > @$xdata) {
        foreach my $i (@$xdata..$#$ydata) {
            print $fh "$i $ydata->[$i]\n";
        }
    }
    close $fh;
    
    my ($dh, $dname) = tempfile(UNLINK => 1);
    print $dh <<"HERE";
plot '$fname'
HERE
    close $dh;
    system($gp, $dname, '-');
}