{"id":336,"date":"2010-07-16T18:20:22","date_gmt":"2010-07-16T22:20:22","guid":{"rendered":"https:\/\/blogs.mathworks.com\/steve\/2010\/07\/16\/complex-surprises-from-fft\/"},"modified":"2019-10-29T13:31:18","modified_gmt":"2019-10-29T17:31:18","slug":"complex-surprises-from-fft","status":"publish","type":"post","link":"https:\/\/blogs.mathworks.com\/steve\/2010\/07\/16\/complex-surprises-from-fft\/","title":{"rendered":"Complex surprises from fft"},"content":{"rendered":"<div xmlns:mwsh=\"https:\/\/www.mathworks.com\/namespace\/mcode\/v1\/syntaxhighlight.dtd\" class=\"content\">\r\n   <p>One of the discrete-time Fourier transform properties that many people learn is that if a sequence is conjugate symmetric,\r\n      <img decoding=\"async\" vspace=\"5\" hspace=\"5\" src=\"https:\/\/blogs.mathworks.com\/images\/steve\/2010\/fft_symmetry_eq79904.png\"> , then the Fourier transform is real.\r\n   <\/p>\r\n   <p>Therefore it surprises people sometimes when the output of <tt>fft<\/tt> is unexpectedly complex. For example:\r\n   <\/p><pre style=\"background: #F9F7F3; padding: 10px; border: 1px solid rgb(200,200,200)\">x = [1 2 3 2 1]<\/pre><pre style=\"font-style:oblique\">\r\nx =\r\n\r\n     1     2     3     2     1\r\n\r\n<\/pre><p>The sequence above appears to be symmetric, but the output of <tt>fft(x)<\/tt> is complex:\r\n   <\/p><pre style=\"background: #F9F7F3; padding: 10px; border: 1px solid rgb(200,200,200)\">fft(x)<\/pre><pre style=\"font-style:oblique\">\r\nans =\r\n\r\n   9.0000            -2.1180 - 1.5388i   0.1180 + 0.3633i   0.1180 - 0.3633i  -2.1180 + 1.5388i\r\n\r\n<\/pre><p>So what's going on? Well, the <tt>fft<\/tt> function is computing the discrete Fourier transform of a sequence <img decoding=\"async\" vspace=\"5\" hspace=\"5\" src=\"https:\/\/blogs.mathworks.com\/images\/steve\/2010\/fft_symmetry_eq17606.png\">  that is nonzero over the interval <img decoding=\"async\" vspace=\"5\" hspace=\"5\" src=\"https:\/\/blogs.mathworks.com\/images\/steve\/2010\/fft_symmetry_eq84656.png\"> . Here's a plot:\r\n   <\/p>\r\n   <p><img decoding=\"async\" vspace=\"5\" hspace=\"5\" src=\"https:\/\/blogs.mathworks.com\/images\/steve\/2010\/tri[n].png\"> <\/p>\r\n   <p>You can see that in fact <img decoding=\"async\" vspace=\"5\" hspace=\"5\" src=\"https:\/\/blogs.mathworks.com\/images\/steve\/2010\/fft_symmetry_eq17606.png\">  isn't actually symmetric about the origin: <img decoding=\"async\" vspace=\"5\" hspace=\"5\" src=\"https:\/\/blogs.mathworks.com\/images\/steve\/2010\/fft_symmetry_eq48915.png\"> . <img decoding=\"async\" vspace=\"5\" hspace=\"5\" src=\"https:\/\/blogs.mathworks.com\/images\/steve\/2010\/fft_symmetry_eq17606.png\">  is a shifted version of a symmetric sequence, and that shift causes the output of <tt>fft<\/tt> to be complex.\r\n   <\/p>\r\n   <p><b>This<\/b> is the symmetric sequence that has a real-valued Fourier transform:\r\n   <\/p>\r\n   <p><img decoding=\"async\" vspace=\"5\" hspace=\"5\" src=\"https:\/\/blogs.mathworks.com\/images\/steve\/2010\/tri_centered[n].png\"> <\/p>\r\n   <p>So how do we compute the real-valued Fourier transform of that sequence using the <tt>fft<\/tt> function? If you'll allow me to be a bit hand-wavy here, I'll just say that the discrete Fourier transform has an implicit\r\n      periodicity in both the time domain and in the frequency domain.  Related to this periodicity, many of the discrete Fourier\r\n      transform analogs to the more familiar Fourier transform properties involve circular shifts, or modulo indexing.\r\n   <\/p>\r\n   <p>For example, the conjugate symmetry property for the discrete Fourier transform looks like this: if <img decoding=\"async\" vspace=\"5\" hspace=\"5\" src=\"https:\/\/blogs.mathworks.com\/images\/steve\/2010\/fft_symmetry_eq27040.png\"> , then the DFT is real. What we want to do, then, is circularly shift <tt>x<\/tt> so that the center element moves to the left of the vector, like this:\r\n   <\/p><pre style=\"background: #F9F7F3; padding: 10px; border: 1px solid rgb(200,200,200)\">xs = circshift(x,[0 -2])<\/pre><pre style=\"font-style:oblique\">\r\nxs =\r\n\r\n     3     2     1     1     2\r\n\r\n<\/pre><p>Now take the DFT of <tt>xs<\/tt>:\r\n   <\/p><pre style=\"background: #F9F7F3; padding: 10px; border: 1px solid rgb(200,200,200)\">fft(xs)<\/pre><pre style=\"font-style:oblique\">\r\nans =\r\n\r\n    9.0000    2.6180    0.3820    0.3820    2.6180\r\n\r\n<\/pre><p>Now the output is real, as expected.<\/p>\r\n   <p>If you're going to zero-pad, do that first and then apply the circular shift.<\/p><pre style=\"background: #F9F7F3; padding: 10px; border: 1px solid rgb(200,200,200)\">x128 = x;\r\nx128(128) = 0;\r\nx128s = circshift(x128,[0 -2]);\r\nX128 = fft(x128s);\r\nisreal(X128)<\/pre><pre style=\"font-style:oblique\">\r\nans =\r\n\r\n     0\r\n\r\n<\/pre><p>Whoops. Was I wrong about using this procedure to produce a real result? Not really, it's just our old friend floating-point\r\n      round-off error. Look how small the imaginary part is:\r\n   <\/p><pre style=\"background: #F9F7F3; padding: 10px; border: 1px solid rgb(200,200,200)\">max(abs(imag(X128(:))))<\/pre><pre style=\"font-style:oblique\">\r\nans =\r\n\r\n  4.4409e-016\r\n\r\n<\/pre><p>You can get rid of the negligible imaginary part by using <tt>real<\/tt>. Let's plot the real-valued Fourier transform. I'll use the frequency axis labeling technique I showed in my <a href=\"https:\/\/blogs.mathworks.com\/steve\/2010\/06\/25\/plotting-the-dtft-using-the-output-of-fft\/\">June 25 blog post<\/a>.\r\n   <\/p><pre style=\"background: #F9F7F3; padding: 10px; border: 1px solid rgb(200,200,200)\">w = unwrap(fftshift(2*pi * (0:(128-1)) \/ 128) - 2*pi);\r\nplot(w\/pi, fftshift(real(X128)))\r\nxlabel(<span style=\"color: #A020F0\">'radians \/ \\pi'<\/span>)<\/pre><img decoding=\"async\" vspace=\"5\" hspace=\"5\" src=\"https:\/\/blogs.mathworks.com\/images\/steve\/2010\/fft_symmetry_01.png\"> <script language=\"JavaScript\">\r\n<!--\r\n\r\n    function grabCode_7b47b83514fd4d3695d5803fb3af4e30() {\r\n        \/\/ Remember the title so we can use it in the new page\r\n        title = document.title;\r\n\r\n        \/\/ Break up these strings so that their presence\r\n        \/\/ in the Javascript doesn't mess up the search for\r\n        \/\/ the MATLAB code.\r\n        t1='7b47b83514fd4d3695d5803fb3af4e30 ' + '##### ' + 'SOURCE BEGIN' + ' #####';\r\n        t2='##### ' + 'SOURCE END' + ' #####' + ' 7b47b83514fd4d3695d5803fb3af4e30';\r\n    \r\n        b=document.getElementsByTagName('body')[0];\r\n        i1=b.innerHTML.indexOf(t1)+t1.length;\r\n        i2=b.innerHTML.indexOf(t2);\r\n \r\n        code_string = b.innerHTML.substring(i1, i2);\r\n        code_string = code_string.replace(\/REPLACE_WITH_DASH_DASH\/g,'--');\r\n\r\n        \/\/ Use \/x3C\/g instead of the less-than character to avoid errors \r\n        \/\/ in the XML parser.\r\n        \/\/ Use '\\x26#60;' instead of '<' so that the XML parser\r\n        \/\/ doesn't go ahead and substitute the less-than character. \r\n        code_string = code_string.replace(\/\\x3C\/g, '\\x26#60;');\r\n\r\n        author = 'Steve Eddins';\r\n        copyright = 'Copyright 2010 The MathWorks, Inc.';\r\n\r\n        w = window.open();\r\n        d = w.document;\r\n        d.write('<pre>\\n');\r\n        d.write(code_string);\r\n\r\n        \/\/ Add author and copyright lines at the bottom if specified.\r\n        if ((author.length > 0) || (copyright.length > 0)) {\r\n            d.writeln('');\r\n            d.writeln('%%');\r\n            if (author.length > 0) {\r\n                d.writeln('% _' + author + '_');\r\n            }\r\n            if (copyright.length > 0) {\r\n                d.writeln('% _' + copyright + '_');\r\n            }\r\n        }\r\n\r\n        d.write('<\/pre>\\n');\r\n      \r\n      d.title = title + ' (MATLAB code)';\r\n      d.close();\r\n      }   \r\n      \r\n-->\r\n<\/script><p style=\"text-align: right; font-size: xx-small; font-weight:lighter;   font-style: italic; color: gray\"><br><a href=\"javascript:grabCode_7b47b83514fd4d3695d5803fb3af4e30()\"><span style=\"font-size: x-small;        font-style: italic;\">Get \r\n            the MATLAB code \r\n            <noscript>(requires JavaScript)<\/noscript><\/span><\/a><br><br>\r\n      Published with MATLAB&reg; 7.10<br><\/p>\r\n<\/div>\r\n<!--\r\n7b47b83514fd4d3695d5803fb3af4e30 ##### SOURCE BEGIN #####\r\n%%\r\n% One of the discrete-time Fourier transform properties that many people learn\r\n% is that if a sequence is conjugate symmetric, $x[n] = x^*[-n]$, then the\r\n% Fourier transform is real.\r\n%\r\n% Therefore it surprises people sometimes when the output of |fft| is\r\n% unexpectedly complex. For example:\r\n\r\nx = [1 2 3 2 1]\r\n\r\n%%\r\n% The sequence above appears to be symmetric, but the output of |fft(x)| is\r\n% complex:\r\n\r\nfft(x)\r\n\r\n%%\r\n% So what's going on? Well, the |fft| function is computing the discrete Fourier\r\n% transform of a sequence $x[n]$ that is nonzero over the interval $0 \\leq n < N$.\r\n% Here's a plot:\r\n%\r\n% <<https:\/\/blogs.mathworks.com\/images\/steve\/2010\/tri[n].png>>\r\n%\r\n% You can see that in fact $x[n]$ isn't actually symmetric about the origin:\r\n% $x[n] \\neq x[-n]$. $x[n]$ is a shifted version of a symmetric sequence, and\r\n% that shift causes the output of |fft| to be complex.\r\n%\r\n% *This* is the symmetric sequence that has a real-valued Fourier transform:\r\n%\r\n% <<https:\/\/blogs.mathworks.com\/images\/steve\/2010\/tri_centered[n].png>>\r\n%\r\n% So how do we compute the real-valued Fourier transform of that sequence using\r\n% the |fft| function? If you'll allow me to be a bit hand-wavy here, I'll just\r\n% say that the discrete Fourier transform has an implicit periodicity in both\r\n% the time domain and in the frequency domain.  Related to this periodicity,\r\n% many of the discrete Fourier transform analogs to the more familiar Fourier\r\n% transform properties involve circular shifts, or modulo indexing.\r\n%\r\n% For example, the conjugate symmetry property for the discrete Fourier\r\n% transform looks like this: if $x[n] = x^*[((-n))_N]$, then the DFT is real.\r\n% What we want to do, then, is circularly shift |x| so that the center element\r\n% moves to the left of the vector, like this:\r\n\r\nxs = circshift(x,[0 -2])\r\n\r\n%%\r\n% Now take the DFT of |xs|:\r\n\r\nfft(xs)\r\n\r\n%%\r\n% Now the output is real, as expected.\r\n%\r\n% If you're going to zero-pad, do that first and then apply the circular shift.\r\n\r\nx128 = x;\r\nx128(128) = 0;\r\nx128s = circshift(x128,[0 -2]);\r\nX128 = fft(x128s);\r\nisreal(X128)\r\n\r\n%%\r\n% Whoops. Was I wrong about using this procedure to produce a real result? Not\r\n% really, it's just our old friend floating-point round-off error. Look how\r\n% small the imaginary part is:\r\n\r\nmax(abs(imag(X128(:))))\r\n\r\n%%\r\n% You can get rid of the negligible imaginary part by using |real|. Let's plot\r\n% the real-valued Fourier transform. I'll use the frequency axis labeling\r\n% technique I showed in my \r\n% <https:\/\/blogs.mathworks.com\/steve\/2010\/06\/25\/plotting-the-dtft-using-the-output-of-fft\/ \r\n% June 25 blog post>.\r\n\r\nw = unwrap(fftshift(2*pi * (0:(128-1)) \/ 128) - 2*pi);\r\nplot(w\/pi, fftshift(real(X128)))\r\nxlabel('radians \/ \\pi')\r\n\r\n##### SOURCE END ##### 7b47b83514fd4d3695d5803fb3af4e30\r\n-->","protected":false},"excerpt":{"rendered":"<p>\r\n   One of the discrete-time Fourier transform properties that many people learn is that if a sequence is conjugate symmetric,\r\n       , then the Fourier transform is real.\r\n   \r\n   Therefore it... <a class=\"read-more\" href=\"https:\/\/blogs.mathworks.com\/steve\/2010\/07\/16\/complex-surprises-from-fft\/\">read more >><\/a><\/p>","protected":false},"author":42,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":[],"categories":[20],"tags":[208,434,426,400,202,703,122,532,68,200,701,94],"_links":{"self":[{"href":"https:\/\/blogs.mathworks.com\/steve\/wp-json\/wp\/v2\/posts\/336"}],"collection":[{"href":"https:\/\/blogs.mathworks.com\/steve\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blogs.mathworks.com\/steve\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blogs.mathworks.com\/steve\/wp-json\/wp\/v2\/users\/42"}],"replies":[{"embeddable":true,"href":"https:\/\/blogs.mathworks.com\/steve\/wp-json\/wp\/v2\/comments?post=336"}],"version-history":[{"count":1,"href":"https:\/\/blogs.mathworks.com\/steve\/wp-json\/wp\/v2\/posts\/336\/revisions"}],"predecessor-version":[{"id":3689,"href":"https:\/\/blogs.mathworks.com\/steve\/wp-json\/wp\/v2\/posts\/336\/revisions\/3689"}],"wp:attachment":[{"href":"https:\/\/blogs.mathworks.com\/steve\/wp-json\/wp\/v2\/media?parent=336"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blogs.mathworks.com\/steve\/wp-json\/wp\/v2\/categories?post=336"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blogs.mathworks.com\/steve\/wp-json\/wp\/v2\/tags?post=336"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}