Abstract
The Fourier Transform is ubiquitous, but it has singular standing in signal processing because of the way sampling imposes a bandwidth-centric view of the world. The Discrete-Time Fourier Transform (DFT) is the primary analysis tool for exploring this perspective. Our development unconventionally starts with a matrix/vector representation of the DFT because that facilitates our visual approach which in turn is designed to develop intuition about the operation and usage of the DFT in practice.
Access this chapter
Tax calculation will be finalised at checkout
Purchases are for personal use only
Notes
- 1.
The H superscript indicates the conjugate transpose.
Author information
Authors and Affiliations
Appendix
Appendix
Listing 3.1: Listing corresponding to Fig. 3.1. The yaxis.set_label_position function places the y-label on the right side of the figure instead of on the default left side. Using set_xticks to set the tick labels list to the empty list ([]) removes all the tick marks on the x-axis. The set_xticklabels functions sets the labels on the tickmarks to the specified list of LaTeX formatted strings. Matplotlib’s gridspec is a generalization of subplot that allows more precise control of the layout of nested plots. The art3d module holds the codes for converting 2D elements into 3D elements that can be added to 3D axes. The Poly3DCollection object is a container for 3D elements.
1 # must start notebook with --pylab flag
2
3 from matplotlib.patches import FancyArrow
4 import mpl_toolkits.mplot3d.art3d as art3d
5 from mpl_toolkits.mplot3d.art3d import Poly3DCollection
6 import matplotlib.gridspec as gridspec
7
8 def dftmatrix(Nfft=32,N=None):
9     ’construct DFT matrix’
10 Â Â Â Â k=Â np.arange(Nfft)
11     if N is None: N = Nfft
12     n = arange(N)
13     U = matrix(exp(1j* 2*pi/Nfft *k*n[:,None])) # use numpy broadcasting to
14     create matrix return U/sqrt(Nfft)
15
16 Nfft=16
17 v = ones((16,1))
18 UÂ =Â dftmatrix(Nfft=Nfft,N=16)
19 #Â ---
20 # hardcoded constants to format complicated figure
21
22 gs = gridspec.GridSpec(8,12)
23 gs.update( wspace=1, left=0.01)
24
25 fig =figure(figsize=(10,5))
26 ax0Â =Â subplot(gs[:,:3])
27 fig.add_subplot(ax0)
28
29 ax0.set_aspect(1)
30 a=2*pi/Nfft*arange(Nfft)
31
32 colors = [’k’,’b’,’r’,’m’,’g’,’Brown’,’DarkBlue’,’Tomato’,’Violet’, ’Tan’,
33           ’Salmon’,’Pink’,’SaddleBrown’, ’SpringGreen’, ’RosyBrown’,’Silver’,]
34 for j,i in enumerate(a):
35 Â Â ax0.add_patch(FancyArrow(0,0,cos(i),sin(i),width=0.02,
36 Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â length_includes_head=True,edgecolor=colors[j]))
37
38 ax0.text(1,0.1,’0’,fontsize=16)
39 ax0.text(0.1,1,r’\(\frac{\pi}{2}\)’,fontsize=22)
40 ax0.text(-1,0.1,r’$\pi$’,fontsize=18)
41 ax0.text(0.1,-1.2,r’\(\frac{3\pi}{2}\)’,fontsize=22)
42 ax0.axis(array([-1,1,-1,1])*1.45)
43 ax0.set_title(’Radial Frequency’,fontsize=18)
44 ax0.set_xlabel(’Real’)
45 ax0.set_ylabel(’Imaginary’)
46 # plots in the far right column
47 for i in range(8):
48 Â Â ax=subplot(gs[i,8:])
49 Â Â ax.set_xticks([]);Â Â ax.set_yticks([])
50   ax.set_ylabel(r’\(\omega_{%d}=%d\times\frac{2\pi}{16}\)’%(i+8,i+8),fontsize=16,
51                 rotation=’horizontal’)
52   ax.plot(U.real[:,i+8],’-o’,color=colors[i+8])
53   ax.plot(U.imag[:,i+8],’--o’,color=colors[i+8],alpha=0.2)
54 Â Â ax.axis(ymax=4/Nfft*1.1,ymin=-4/Nfft*1.1)
55   ax.yaxis.set_label_position(’right’)
56 ax.set_xticks(arange(16))
57 ax.set_xlabel(’n’)
Listing 3.2: Listing corresponding to Fig. 3.2. The set_xticklabels function changes the labeling of the tick marks to the given string, here with extra LaTeX formatting.
1 UÂ =Â dftmatrix(64,16)
2 x = ones((16,1))
3 XÂ =Â U.H*x
4
5 fig,ax=subplots()
6 fig.set_size_inches((8,4))
7 ax.set_aspect(0.8)
8 ax.grid()
9 ax.plot(arange(0,64)*2*pi/64.,abs(X),’o-’)
10 ax.set_ylabel(r’$|X(\omega)|$’,fontsize=18)
11 ax.set_xticks([0, pi/2., pi, 3*pi/2,2*pi])
12 ax.set_xlabel(r’$\omega$’,fontsize=16)
13 ax.axis([0, 2*pi,0,2.1])
14 ax.set_xticklabels([’0’,r’\(\frac{\pi}{2}\)’, r’$\pi$’,r’\(\frac{3\pi}{2}\)’,
15                     r’$2\pi$’], fontsize=18);
Listing 3.3: Listing corresponding to Fig. 3.3.
1 UÂ =Â dftmatrix(64,16)
2 x = ones((16,1))
3 XÂ =Â U.H*x
4
5 fig,ax=subplots()
6 fig.set_size_inches((8,4))
7
8 ax.set_aspect(0.8) # aspect ratio
9 ax.plot(arange(0,64)*2*pi/64.,abs(X),’o-’,label=’zero padded’)
10 ax.stem(arange(0,16)*2*pi/16.,abs(dftmatrix(16).H*x),
11         markerfmt=’gs’, basefmt=’g-’,linefmt=’g-’,
12         label=’no padding’)
13 ax.set_xlabel(r’$\omega$’,fontsize=18)
14 ax.set_ylabel(r’$|X(\omega)|$’,fontsize=18)
15 ax.set_xticks([0, pi/2., pi, 3*pi/2,2*pi])
16 ax.axis([-.1, 2*pi,-.1,4.1])
17 ax.legend(loc=0,fontsize=18)
18 ax.set_xticklabels([’0’,r’\(\frac{\pi}{2}\)’, r’$\pi$’,r’\(\frac{3\pi}{2}\)’,
19                    r’$2\pi$’], fontsize=18);
20 ax.set_title(’Zero padding samples more frequencies’);
Listing 3.4: Listing corresponding to Fig. 3.5.
1 v = U[:,6].real
2 ax1,ax2=drawInOut(U.H*v,v,return_axes=1)
3 ax1.set_title(r’\(\omega=\frac{2\pi 5}{16}\)’)
Listing 3.5: Listing corresponding to Fig. 3.7.
1 v = matrix(cos(pi*arange(0,16))).T
2 ax1,ax2=drawInOut(U.H*v,v,return_axes=1)
3 ax1.set_title(’Highest Frequency’)
4 v = ones((16,1))
5 ax1,ax2=drawInOut(U.H*v,v,return_axes=1)
6 ax1.set_title(’Lowest Frequency’)
Listing 3.6: Listing corresponding to Fig. 3.4.
1 a=2*pi/64.*arange(64)
2 d=vstack([cos(a),sin(a),array(abs(X)).flatten()]).T
3
4 fig = plt.figure()
5 fig.set_size_inches(6,6)
6 ax = fig.add_subplot(1, 1, 1, projection=’3d’)
7 ax.axis([-1,1,-1,1])
8 ax.set_zlim([0,d[:,2].max()])
9 ax.set_aspect(1)
10 ax.view_init(azim=-30)
11
12 ax.set_xlabel(’real’)
13 ax.set_ylabel(’imag’)
14 ax.set_zlabel(’Abs’)
15 ax.set_title(’64-Point DFT Magnitude’)
16
17 def facet_filled(x,alpha=0.5,color=’b’):
18     ’construct 3D facet from adjacent points filled to zero’
19 Â Â Â Â a,b=x
20 Â Â Â Â a0=Â a*array([1,1,0])
21 Â Â Â Â b0=Â b*array([1,1,0])
22     ve = vstack([a,a0,b0,b])      # create closed polygon facet
23     poly = Poly3DCollection([ve]) # create facet
24 Â Â Â Â poly.set_alpha(alpha)
25 Â Â Â Â poly.set_color(color)
26     return poly
27
28 sl=[slice(i,i+2) for i in range(d.shape[0]-2)] # collect neighboring points
29 for s in sl:
30 Â Â poly=facet_filled(d[s,:])
31 Â Â ax.add_collection3d(poly)
32
33 # edge polygons
34 ax.add_collection3d(facet_filled(d[[-1,0],:]))
35 ax.add_collection3d(facet_filled(d[[-2,-1],:]))
36
37 # add 0 and pi/2 arrows for reference
38 a=FancyArrow(0,0,1,0,width=0.02,length_includes_head=True)
39 ax.add_patch(a)
40 b=FancyArrow(0,0,0,1,width=0.02,length_includes_head=True)
41 ax.add_patch(b)
42 art3d.patch_2d_to_3d(a)
43 art3d.patch_2d_to_3d(b)
44 plt.show()
Rights and permissions
Copyright information
© 2014 Springer International Publishing Switzerland
About this chapter
Cite this chapter
Unpingco, J. (2014). Discrete-Time Fourier Transform. In: Python for Signal Processing. Springer, Cham. https://doi.org/10.1007/978-3-319-01342-8_3
Download citation
DOI: https://doi.org/10.1007/978-3-319-01342-8_3
Published:
Publisher Name: Springer, Cham
Print ISBN: 978-3-319-01341-1
Online ISBN: 978-3-319-01342-8
eBook Packages: EngineeringEngineering (R0)