Guest User

Untitled

a guest
Sep 25th, 2018
107
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 4.49 KB | None | 0 0
  1. #!/usr/bin/python3
  2.  
  3. import math
  4.  
  5. try:
  6. import matplotlib.pyplot as plt
  7. has_matplotlib = True
  8. except:
  9. has_matplotlib = False
  10.  
  11. import argparse
  12.  
  13. defaultParameters = {
  14. 'window_size': 1,
  15. 'num_points': 1024,
  16. }
  17.  
  18. class Complex:
  19. def __init__(self, real, im):
  20. self.real = real
  21. self.im = im
  22.  
  23. def __add__(self, n):
  24. if type(n) is Complex:
  25. return Complex(self.real+n.real, self.im+n.im)
  26. else:
  27. return Complex(self.real+n, self.im)
  28.  
  29. def __mul__(self, n):
  30. if type(n) is Complex:
  31. return Complex(self.real*n.real - self.im*n.im, self.real*n.im + self.im*n.real)
  32. else:
  33. return Complex(self.real*n, self.im*n)
  34.  
  35. def __truediv__(self, n):
  36. if type(n) is Complex:
  37. m2 = n.real*n.real + n.im*n.im
  38. return self*Complex(n.real/m2, -n.im/m2)
  39. else:
  40. return Complex(self.real/n, self.im/n)
  41.  
  42. def __str__(self):
  43. return "("+str(self.real)+","+str(self.im)+")"
  44.  
  45. def mod(self):
  46. return math.sqrt(self.real*self.real + self.im*self.im)
  47.  
  48. def e(v):
  49. return Complex(math.cos(v), math.sin(v))
  50.  
  51. def create_samples(window, n_samples, function):
  52. offset = window/n_samples
  53. samples = list()
  54. for i in range(0, n_samples):
  55. v = i*offset
  56. samples.append(function(v))
  57. return samples
  58.  
  59. def perform_dft(t_samples):
  60. n_samples = len(t_samples)
  61. f_samples = [Complex(0, 0)]*n_samples
  62. for k in range(0, n_samples):
  63. for n in range(0, n_samples):
  64. v = -2*math.pi*k*n/n_samples
  65. f_samples[k] += (Complex.e(v)*t_samples[n])
  66. return f_samples
  67.  
  68. sines = lambda x: 3+2*math.sin(50*x)+math.cos(90*x)
  69. def ramp(x):
  70. if x < math.pi/2:
  71. return x*2/math.pi
  72. if x < 3*math.pi/2:
  73. return 2-x*2/math.pi
  74. if x < 2*math.pi:
  75. return -4+x*2/math.pi
  76.  
  77. def parseArgs():
  78. parser = argparse.ArgumentParser(description='Playing with DFT')
  79. parser.add_argument('-w', '--window', help='Window size (default = %.2f)' % defaultParameters['window_size'], default=defaultParameters['window_size'], type=float)
  80. parser.add_argument('-n', '--num_points', help='Number of points (default = %d)' % defaultParameters['num_points'], default=defaultParameters['num_points'], type=int)
  81. parser.add_argument('-p', '--plot', help='Plot time and frequency series', action='store_true')
  82. args = parser.parse_args()
  83. return args
  84.  
  85. def plot(args, t_samples, f_samples):
  86. # Drop all samples for frequencies higher than Fsampling/2
  87. m = [round(v.mod(), 3) for v in f_samples[0:int(args.num_points/2)]]
  88.  
  89. f, axa = plt.subplots(2)
  90.  
  91. # Get current axes
  92. axa[0].set_title('DFT example')
  93.  
  94. axa[0].set_xlim([-0.5, args.window + 0.5])
  95. axa[0].set_xlabel('Time')
  96. axa[0].plot([x*args.window/args.num_points for x in list(range(0, args.num_points))], t_samples, color = 'b')
  97. axa[0].grid()
  98.  
  99. delta_freq = 2*math.pi/args.window_size
  100. x = [v*delta_freq for v in list(range(0, int(args.num_points/2)))]
  101. axa[1].set_xlim([-0.5, x[-1]+0.5])
  102. axa[1].set_ylabel('Power Spectral Density')
  103. axa[1].set_xlabel('Frequency')
  104. axa[1].stem(x, m, 'r-')
  105. axa[1].grid()
  106.  
  107. plt.show()
  108.  
  109. def show_dft(args, f_samples):
  110. delta_freq = 2*math.pi/args.window
  111. print("+---------+---------+")
  112. print("| %-7s | %-7s |" % ("Freq", "PSD"))
  113. print("+---------+---------+")
  114.  
  115. for i, v in enumerate(f_samples[0:int(args.num_points/2)]):
  116. print("| %7.3f | %7.3f |" %(round(i*delta_freq,3), round(v.mod(),3)))
  117.  
  118. print("+---------+---------+")
  119.  
  120. # Main program !
  121. f=sines
  122. args = parseArgs()
  123. t_samples = create_samples(args.window, args.num_points, f)
  124. f_samples = perform_dft(t_samples)
  125.  
  126. # Normalize value, then take only half the spectrum
  127. for i,v in enumerate(f_samples):
  128. f_samples[i] = f_samples[i]*(2/args.num_points)
  129. f_samples[0] = f_samples[0]/2
  130.  
  131. if args.plot:
  132. if has_matplotlib:
  133. plot(args, t_samples, f_samples)
  134. else:
  135. print("Plotting is not possible. Please install matplotlib.")
  136. else:
  137. show_dft(args, f_samples)
Add Comment
Please, Sign In to add comment