TeX - LaTeX Stack Exchange is a question and answer site for users of TeX, LaTeX, ConTeXt, and related typesetting systems. Join them; it only takes a minute:

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

The following time-frequency correspondence illustration is in the wikipedia entry of the Fourier transform.


Also a gif animation version (if the animation doesn't show, please open the following image in a new window):


This picture has so much explanatory power, and I would like to replicate it in TikZ for future use.

Here is what I came up with:


\draw[->,thick,blue!90] (0,6.5,0) -- (6.2,6.5,0) node[right] {Frequency};
\draw[->,thick,red!90] (0,0,0) -- (0,6.5,0) node[below] {Time};
\draw[->,thick] (0,0,0) -- (0,0,2) node[above] {Magnitude};
\foreach \x in {0.5,1.5,2.5,3.5,4.5,5.5}{
  \draw[blue!50] (\x,0,0)
  \foreach \y in {0,0.02,...,6.28}{ 
   -- ({\x},{\y},{sin(\x*\y*(157))/sqrt(2*\x)})
  \draw[blue!90, thick] (\x,6.5,0) -- (\x,6.5,1/\x);


This is the output so far.


I have two questions:

  • How to produce that red superposed sine wave of all the blue sine waves? I don't know if there is a sum function or I have to use loop yet again?

  • How to make the camera projection in TikZ more similar to the perspective in that wikipedia illustration?

Any suggestion and tweaking of the parameters I used in the sample drawing are welcome as well.

Thanks in advance!

Update 1: Here is a new version using tikz, more readable than the first one. Yet the superposition of the sine waves are done manually...I still don't know how to use foreach to produce a sum.

\draw[->,thick,black!70] (0,6.5,0) -- (6.2,6.5,0) node[right] {Frequency};
\draw[->,thick,black!70] (0,0,0) -- (0,6.5,0) node[below right] {Time};
\draw[->,thick] (0,0,0) -- (0,0,2) node[above] {Magnitude};
\foreach \y in {0.5,1.5,...,5.5}{
\draw [cyan!50, domain=0:2*pi,samples=200,smooth] 
 plot (\y,\x, {sin(4*\y*\x r)/\y });
\draw[blue, ultra thick] (\y,6.5,0) -- (\y,6.5,1/\y);
\draw [red, thick, domain=0:2*pi,samples=200,smooth] 
plot (0,\x, {sin(4*0.5*\x r)/0.5 + sin(4*1.5*\x r)/1.5 + sin(4*2.5*\x r)/2.5 + sin(4*3.5*\x r)/3.5 + sin(4*4.5*\x r)/4.5 + sin(4*5.5*\x r)/5.5} );

The result is as follows:fourier2

share|improve this question
up vote 28 down vote accepted

Here's a way of plotting this using PGFPlots. You can collect the expression for the red curve while you're looping over the individual components using an \xdef.

Unfortunately, PGFPlots can't use a perspective projection (and even in plain TikZ I think you'll have to jump through a lot of hoops to simulate it).


    set layers=standard,
    samples y=1,
    hide axis,
    unit vector ratio*=1 2 1,
    xtick=\empty, ytick=\empty, ztick=\empty,
    \draw [on layer=background, gray!20] (axis cs:0,#1,0) -- (axis cs:10,#1,0);
    \addplot3 [on layer=main, blue!30, smooth, samples=101] (x,#1,{sin(#1*x*(157))/(#1*2)});

    \addplot3 [on layer=axis foreground, very thick, blue,ycomb, samples=2] (10.5,#1,{1/(#1*2)});
    \xdef\sumcurve{\sumcurve + sin(#1*x*(157))/(#1*2)}
\addplot3 [red, samples=200] (x,0,{\sumcurve});

\draw [on layer=axis foreground]  (axis cs:0,0,0) -- (axis cs:10,0,0);
\draw (axis cs:10.5,0.25,0) -- (axis cs:10.5,5.5,0);
share|improve this answer
Sweet! I wonder if we can use view={}{} for animation :) – percusse Aug 9 '13 at 5:32

An (animatable) ePiX version is below. (I wasn't able to view the original animation, but have extrapolated from the wave equation.)

Use, e.g.,

flix --frames 120 -o fourier.gif fourier.flx

to compile.

Fourier spectrum

/* -*-flix-*- */
#include "epix.h"
using namespace ePiX;

// n treated throughout as an integer
double freq(double n) { return 2*n - 1; }
double ampl(double n) { return 1.0/freq(n); }

const unsigned int N(6); // number of harmonics
const unsigned int num_pts(120);

double MAX(2*M_PI), // max spatial coordinate
  dX(1), dY(0.5); // offsets for spectrum/frequency screens

P sw1(-MAX, 0, -2), // "waveform screen" corners
  ne1( MAX, 0,  2),
  sw2(MAX + dX,           dY, -2), // "spectrum screen" corners
  ne2(MAX + dX, freq(N) + dY,  2);

// standing sine waves of specified frequency, amplitude
P waves(double x, double n)
  return P(x, freq(n), ampl(n)*Sin(freq(n)*x)*Cos(freq(n)*full_turn()*tix()));

// sum of waves, in (x, y)-plane
P waveform(double x)
  double val(0);
  for (int i=1; i <= N; ++i)
    val += waves(x, i).x3();

  return P(x, 0, val);

domain R(P(-MAX, 1), P(MAX, N), mesh(num_pts, N - 1));

int main(int argc, char* argv[])
  if (argc == 3)
      char* arg;
      double temp1(strtod(argv[1], &arg)), temp2(strtod(argv[2], &arg));

  picture(P(-6,-3), P(12, 3), "6 x 2in");

  camera.at(P(12, -8, 4)).look_at(P(0, 0.5*N, 0)).range(25);

  // frequancy components
  plot(waves, R.slices2());

  // "screens"
  rect(sw2, ne2); // spectrum
  rect(sw1, ne1); // waveform

  // frequency components
  plot(waves, R.slices2());
  for (int i=1; i <= N; ++i)
    line(P(-MAX, freq(i), 0), P(MAX, freq(i), 0));

  // spectrum
  line(P(MAX + dX, dY, 0), P(MAX + dX, freq(N) + dY, 0));
  for (int i=1; i <= N; ++i)
      P loc(MAX + dX, freq(i), 0);
      line(loc, loc + ampl(i)*E_3);

  // waveform
  plot(waveform, -MAX, MAX, 2*num_pts);

share|improve this answer
Hi, Andrew, is the perspective projection automatic in ePiX? It is pretty amazing. – Shuhao Cao Aug 15 '13 at 1:32
@Shuhao Cao: In a word, "yes", the ePiX camera does finite-distance point projection by default. :) – user86418 Aug 15 '13 at 11:17

Here is something I have just made using this post to show constructive interferences in the time domain.

enter image description here



        \draw[->] (0,-pi,0) --++ (6,0,0) node[above right] {Frequency};
        \draw[->] (0,-pi,0) --++ (0,6.5,0) node[right] {Time};
        \draw[->] (0,-pi,0) --++ (0,0,1.5) node[above] {Magnitude};

        \draw [dashed] (1,0,0.2) --++ (4,0,0);          
        \foreach \y in {1,2,...,5}{
            \draw[blue] plot[domain = -pi:+pi, samples = 300] 
            (\y,\x,{0.2*cos(10*\y/2*(\x) r)});
            \draw[blue] (\y,-pi-0.15,0) node [left]{$f_{\y}$};
            \draw[red] (\y,0,{0.2*cos(10*\y/2*(0) r)}) node {\textbf{.}};

        \draw[red, thick] plot[domain = -pi:+pi, samples = 2000] 
        (0,\x,{0.02*sin(50*(\x) r)/(\x))});

share|improve this answer

Your Answer


By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.