Prelab2

pdf

School

University of California, Berkeley *

*We aren’t endorsed by this school

Course

3

Subject

Electrical Engineering

Date

Apr 3, 2024

Type

pdf

Pages

13

Uploaded by DrSnakePerson912

Report
1/21/24, 5:20 PM FFT_Tutorial.ipynb - Colaboratory https://colab.research.google.com/drive/1mJ1ml4dvUtvHacrhS4PiAEDS9woLiNFJ?authuser=2#scrollTo=7mqlyvvjnItS&printMode=true 1/7 developed by Pauline Arriaga Fourier transforms tutorial A Fourier transform is a way of converting between looking at a signal in time vs some quantity to frequency vs some quantity. Let's look at what this looks like for some signals. We will be using the scipy fft function. Let's say that we have some mechanism that outputs a signal that's shaped like a sin wave. In our lab we will be using an Arduino to produce a sound wave such that the intensity of the sound as a function of time is a sin wave. Our output signal will then be: For the following, let's assume that f = sound_frequency = 440 Hz and A = 4. Let's measure the sound for t = 0 to 2 seconds Our laptop speakers will be taking measurements of the sound volume at a rate of sampling_rate = 44100Hz meaning that it will take a signal every seconds, de±ned below as time_between_samples. Note that we declare all of our variables at the top of the code, which makes it easy to re-run our code if we make any changes. Let's ±rst plot what the intensity looks like as a function of time. Take some time to understand the code below and ask a TA if there is anything you don't understand Text(0, 0.5, 'Intensity') import matplotlib.pyplot as plt import numpy as np from scipy.fftpack import fft # Generate our variables sound_frequency = 10. # Frequency in Hz of the sound a = 4. # Amplitude of our sound in arbitrary units sampling_rate = 44100. # Sampling rate in Hz time_between_samples = 1. / sampling_rate # Interval between samples length_of_sample = 2. # We are measuring the sound for 2 seconds number_of_samples = sampling_rate * length_of_sample # Total number of samples # Generate an array with 44100 * 2 seconds with spacing of time_between_samples seconds time = np.arange(number_of_samples) * length_of_sample / number_of_samples measured_signal = a * np.sin(2. * np.pi * sound_frequency * time) plt.plot(time, measured_signal) plt.xlabel('Time (s)') plt.ylabel('Intensity') Now, let's see what the Fourier transform looks like. The maximum frequency that the signal above can measure is sampling_rate. You can convince yourself of this by imagining what a signal with sound_frequency = sampling_rate would look like.
1/21/24, 5:20 PM FFT_Tutorial.ipynb - Colaboratory https://colab.research.google.com/drive/1mJ1ml4dvUtvHacrhS4PiAEDS9woLiNFJ?authuser=2#scrollTo=7mqlyvvjnItS&printMode=true 2/7 Text(0, 0.5, 'Intensity') # We create an array that goes from 0 to the sampling_rate frequencies = np.arange(number_of_samples) * sampling_rate / number_of_samples # Hz fourier_intensity = np.fft.fft(measured_signal) # The fourier transform has a real and imaginary part. We only want to look at the real part. plt.plot(frequencies, np.abs(fourier_intensity)) #Let's focus on just the earlier frequencies plt.xlim([0,30]) plt.xlabel('Frequency (Hz)') plt.ylabel('Intensity') As you can see from the Fourier plot, all of the intensity is now focused on a frequency of 10 Hz, the frequency of the sin wave. We can use the np.where function to ±nd the position where the peak is. The where function will return the indices of the array where some condition is true. The peak is the location where the data point is the maximum intensity. # Now we only want to use the real part of the fourier transform (ignore the imaginary) abs_fourier_int = np.abs(fourier_intensity) # Find the maximum value of the Fourier transform max_value = np.max(abs_fourier_int) # Find the index where the max location is max_location = np.where(abs_fourier_int == max_value)[0] # Now we find the frequency where this happens peak_location = frequencies[max_location] print('Signal peak at ' + str(peak_location) + 'Hz') Signal peak at [1.000e+01 4.409e+04]Hz Now let's look at a superposition of two sin waves. If we have two speakers each playing a sin wave, then we'll hear two frequencies at once and our microphone will receive both signals. We'll use the same sampling frequency as we did above so we don't have to remake our time and frequency axes. One sin wave will have an intensity A of 4 and a frequency of 10, while the second will have an intensity of 2 and a frequency of 5.
1/21/24, 5:20 PM FFT_Tutorial.ipynb - Colaboratory https://colab.research.google.com/drive/1mJ1ml4dvUtvHacrhS4PiAEDS9woLiNFJ?authuser=2#scrollTo=7mqlyvvjnItS&printMode=true 3/7 Text(0, 0.5, 'Intensity') a1 = 4. a2 = 2. f1 = 10. f2 = 5. sin1 = a1 * np.sin(2 * np.pi * f1 * time) sin2 = a2 * np.sin(2 * np.pi * f2 * time) superpos_signal = sin1 + sin2 plt.plot(time, superpos_signal) plt.xlabel('Time(s)') plt.ylabel('Intensity') While this signal looks fairly chaotic in the time domain, we can do a Fourier transform to look at the signal in the frequency domain. Text(0, 0.5, 'Intensity') fourier_intensity = np.fft.fft(superpos_signal) # The fourier transform has a real and imaginary part. We only want to look at the real part. plt.plot(frequencies, np.abs(fourier_intensity)) plt.xlim([0, 30]) plt.xlabel('Frequency (Hz)') plt.ylabel('Intensity')
Your preview ends here
Eager to read complete document? Join bartleby learn and gain access to the full version
  • Access to all documents
  • Unlimited textbook solutions
  • 24/7 expert homework help
1/21/24, 5:20 PM FFT_Tutorial.ipynb - Colaboratory https://colab.research.google.com/drive/1mJ1ml4dvUtvHacrhS4PiAEDS9woLiNFJ?authuser=2#scrollTo=7mqlyvvjnItS&printMode=true 4/7 What is a chaotic signal in the time domain is now a coherent signal in the frequency domain. We clearly see all of the characteristics of the input parameters. The 5 Hz signal has half of the intensity of the 10 Hz signal Fourier Transforms of Sound waves # Run this cell to mount your Google Drive. from google.colab import drive drive.mount('drive') Drive already mounted at drive; to attempt to forcibly remount, call drive.mount("drive", force_remount=True). We will now use the module wav±le to read in our data. From the example sounds directory, read in the sin_a440_3.wav ±le. In the wav±le.read command, change the path to the path on your own drive. from scipy.io import wavfile rate, data = wavfile.read('/content/drive/My Drive/Prelab2/sin_a440_3.wav') Now let's look at the intensity as a function of time. Sampling Rate: 44100 Text(0, 0.5, 'Intensity') import matplotlib.pyplot as plt samp_period = 1. / rate num_data_points = len(data) print('Sampling Rate: ' + str(rate)) xaxis = np.arange(len(data)) * samp_period # Make our axis go from 0 to the length of our recording plt.plot(xaxis, data) plt.xlabel('Time (s)') plt.ylabel('Intensity') Again, the data is very chaotic in the time domain, but we can look at the frequency domain. In these labs, all of the signals we'll need will be somewhere from 0 to 1000. Set the x lmits to make it easier to see the signal. Even though it is di²cult to make out features from the time vs intensity plot because of all of the background noise, we can clearly see what frequency the pitch of the recording is.
1/21/24, 5:20 PM FFT_Tutorial.ipynb - Colaboratory https://colab.research.google.com/drive/1mJ1ml4dvUtvHacrhS4PiAEDS9woLiNFJ?authuser=2#scrollTo=7mqlyvvjnItS&printMode=true 5/7 (400.0, 700.0) from scipy.fftpack import fft import numpy as np fft_out = fft(data) # Create an array that goes from 0 to the 44100 Hz frequencies = np.linspace(0,1,num_data_points) * rate plt.plot(frequencies,np.abs(fft_out)) plt.xlim([400, 700]) FFT of a Square Wave Run the following code block to produce a square wave signal. Once you have that signal, we will perform an FFT on it # Import packages from scipy.fftpack import fft from scipy import signal import numpy as np import numpy.ma as ma import matplotlib.pyplot as plt # Define time with a sampling rate of 10,000 Hz tstart = -1 tstop = 1 sample_time = 0.0001 t = np.arange(tstart, tstop, sample_time) #define a 50 Hz squarewave squareWave = signal.square(2 * np.pi * 50 * t) Run the following code block to see we have made many periods of a 50 Hz Square wave. We will need a large chunk of data (many periods) to produce a good clean FFT. #plot the wave plt.plot(t, squareWave) plt.xlim(-1, 1)
1/21/24, 5:20 PM FFT_Tutorial.ipynb - Colaboratory https://colab.research.google.com/drive/1mJ1ml4dvUtvHacrhS4PiAEDS9woLiNFJ?authuser=2#scrollTo=7mqlyvvjnItS&printMode=true 6/7 (-1.0, 1.0) Run the following code block to zoom in on the x-axis and note that we do indeed have a 50 Hz square wave. (-0.0105, 0.0105) #plot the wave plt.plot(t, squareWave) plt.xlim(-0.0105, 0.0105) Next ±ll in the code below to complete your FFT. Where is the ±rst spike? Does it make sense given the results of your forier series of a square wave? #Setup and Run the fft num_data_points_SW = len(squareWave) #Your code here rate_SW = 1/sample_time #Your code here fft_squareWave = np.fft.fft(squareWave)#Your code here # Create a frequency array that goes from 0 to the 10,000 Hz frequencies_SW = np.linspace(0,1,num_data_points_SW) * rate_SW #Your code here #Plot the FFT #Your code here plt.plot(frequencies_SW,np.abs(fft_squareWave)) # Plot Settings plt.xlim(0, 400) #Shows from 0 to 400 Hz plt.title("Square Wave FFT")
Your preview ends here
Eager to read complete document? Join bartleby learn and gain access to the full version
  • Access to all documents
  • Unlimited textbook solutions
  • 24/7 expert homework help
1/21/24, 5:20 PM FFT_Tutorial.ipynb - Colaboratory https://colab.research.google.com/drive/1mJ1ml4dvUtvHacrhS4PiAEDS9woLiNFJ?authuser=2#scrollTo=7mqlyvvjnItS&printMode=true 7/7 Text(0, 0.5, 'Intensity') plt.xlabel("Freq (Hz)") plt.ylabel("Intensity")
1/21/24, 9:27 PM Loops.ipynb - Colaboratory https://colab.research.google.com/drive/16aFHxdSCKI7jZGd1OdG4O8FT1Gv0MW2x?authuser=2#printMode=true 1/5 Loop tutorial A loop, like its name suggests, is a coding technique that runs the same snippet of code over and over again. Many loops have pre-determined break conditions where the loop will end and the program will move onto the next segment of code. These conditions may be after the loop has run a speci±fed amount of times or when some external condtion is met (such as a certain time has passed or the program got input from a user or other program). There are also times when loops will never end running, such as the main function of an Arduino code [the "void loop()"]. Loops are extremely powerful in coding and can save you a lot of time. For example let's say we have a 5 sets data from an experiment saved in an array where each row represents a different set of data. #Importing plt and np import matplotlib.pyplot as plt import numpy as np #Time values time = [1,2,3,4] #Mock Data where each row is a differnt data set (ie dataSet1 = [1,2,5,7], dataSet2=[2,4,6,8], ect...) data = np.array([np.array([1,2,5,7]),np.array([2,4,6,8]),np.array([1.5,3.5,5.5,7.5]),np.array([2.5,3,4.5,5.5]),np.array([5,7,9,11])]) print("The Data Array is") print(data) The Data Array is [[ 1. 2. 5. 7. ] [ 2. 4. 6. 8. ] [ 1.5 3.5 5.5 7.5] [ 2.5 3. 4.5 5.5] [ 5. 7. 9. 11. ]] #Mock Constant modifers Cn (C1 is the first value (3), C2 is the second value(2), ect...) Cn = np.array([3,2,1,1.5,0.5]) print("The Constant Array is") print(Cn) The Constant Array is [3. 2. 1. 1.5 0.5] Let's say for analysis we need to multiply each data set by it's speci±c constant value (Cn) and then plot it vs time. Without a loop our code might look something like this: # Allocating memory on the computer for the new data dataSetnew=np.zeros((5,4)) # Multiplying the Data Sets by the constant C dataSetnew[0,:] = data[0,:]*Cn[0] #Recall that the first index of an array is 0 so C1 is actually at index C[0] dataSetnew[1,:] = data[1,:]*Cn[1] dataSetnew[2,:] = data[2,:]*Cn[2] dataSetnew[3,:] = data[3,:]*Cn[3] dataSetnew[4,:] = data[4,:]*Cn[4] # Plotting the data sets vs time plt.scatter(time,dataSetnew[0,:]) plt.scatter(time,dataSetnew[1,:]) plt.scatter(time,dataSetnew[2,:]) plt.scatter(time,dataSetnew[3,:]) plt.scatter(time,dataSetnew[4,:]) #Setting plot parameters plt.xlim([0,5]) plt.xlabel('Time (Sec)') plt.ylabel('Data (Units)') plt.title('No Loop Plot')
Your preview ends here
Eager to read complete document? Join bartleby learn and gain access to the full version
  • Access to all documents
  • Unlimited textbook solutions
  • 24/7 expert homework help
1/21/24, 9:27 PM Loops.ipynb - Colaboratory https://colab.research.google.com/drive/16aFHxdSCKI7jZGd1OdG4O8FT1Gv0MW2x?authuser=2#printMode=true 2/5 Text(0.5, 1.0, 'No Loop Plot') While it is not di²cult to copy, paste, and slightly modify simple bits code with ±ve data sets, imagine if you had thousands of data sets. Luckily loops can do this for us with very little code. There are several types of loops, but the main two are For loops and While loops. Let's look at a For loop ±rst. For loops typically run using a counter variables to keep track of how many times the loop is run. When the counter goes beyond the total amount of loops desired, the loop ends. Here is an example of how we can turn the above code into a For loop. Text(0.5, 1.0, 'For Loop Plot') # Allocating memory on the computer for the new data dataSetnew=np.zeros((5,4)) NumOfDataSets = 5 #The amount of data sets we have # For Loop - NOTE THAT INDENTATIONS ARE IMPORTANT - Only code that is indented under the for will be part of the loop for i in range(0, NumOfDataSets): # i is the counter which will start at 0 and loop dataSetnew[i,:] = data[i,:]*Cn[i] # Every loop i changes allowing us to use it inside the loop to call different variables plt.scatter(time,dataSetnew[i,:]) # i increases by 1 after this line is completed and the loop goes back to the start # Setting plot parameters plt.xlim([0,5]) plt.xlabel('Time (Sec)') plt.ylabel('Data (Units)') plt.title('For Loop Plot')
1/21/24, 9:27 PM Loops.ipynb - Colaboratory https://colab.research.google.com/drive/16aFHxdSCKI7jZGd1OdG4O8FT1Gv0MW2x?authuser=2#printMode=true 3/5 The most general syntax structure of a for loop is as follows. You can modify it from here to ±t your coding needs. Start is the number i will begin at, stop is the number that when i exceeds that value the loop will end, and stepSize is how much i increases after the Looped code is executed. #for i in range(start, stop, stepSize): #Looped code goes here Another useful type of loop is the While loop. The while loop makes it easier to have code loop until an outside condition is met as opposed to looping a speci±ed number of times. That being said, while loops and for loops can be used to achieve the same tasks, so it is up to you to ±gure out what you think is the best practice for your application. Here is what our above For loop would look like as a While loop with the 5 data sets. Text(0.5, 1.0, 'While Loop Plot') NumOfDataSets = 5 i = 0 #initialize our counter. For loops do this within the for statement while i < NumOfDataSets: dataSetnew[i,:] = data[i,:]*Cn[i] # Every loop i changes allowing us to use it inside the loop to call different variables plt.scatter(time,dataSetnew[i,:]) i += 1 # This is the same as count = count + 1. Note that For loops do this automatically. While loops do not # Setting plot parameters plt.xlim([0,5]) plt.xlabel('Time (Sec)') plt.ylabel('Data (Units)') plt.title('While Loop Plot') The most general syntax structure of a for while is as follows. Again you can modify it from here to ±t your coding needs. Some condition statements may use >, <, operators or just be 1 for an in±nite loop. #while condition: #The condition is any statement that evaulates as true (1) or false (0) #Looped code goes here These are just the basics of loops. More advanced loop techniques exist, and if you are interested in coding there are many great resources online! Fourier Series Square Wave Loop Now that you have a basic grasp on loops, let's apply it to a Fourier Series. Recall that a square wave can be broken down into a Fourier Series. Using the Fourier Series equation for a square wave, write a loop to plot the series for n = 1...3, n = 1...9, and n = 1...49. Does the higher n value
1/21/24, 9:27 PM Loops.ipynb - Colaboratory https://colab.research.google.com/drive/16aFHxdSCKI7jZGd1OdG4O8FT1Gv0MW2x?authuser=2#printMode=true 4/5 make the wave look more square? Assume L = 0.01 (half the period). Hint: if you initialize your function f(x) to zero before the loop, you can increase it as a running sum using f(x) = f(x) + new term Text(0, 0.5, 'Intensity') import numpy.ma as ma # x data x = np.linspace(-0.01,0.01,1000) L = 0.01 # half the period # Initial Sums f3 = 0 # n=1..3 f9 = 0 # n=1..9 f49 = 0 # n=1..49 f1 = (4/np.pi)*(1/1)*(np.sin((1*np.pi*x)/L)) #Fill in code here for n in range(1, 4): #edit these values f3 += (4/np.pi)*(1/n)*(np.sin((n*np.pi*x)/L))#Fill in code here for n in range(1, 10): #edit these values f9 += (4/np.pi)*(1/n)*(np.sin((n*np.pi*x)/L))#Fill in code here for n in range(1,50): #edit these values f49 += (4/np.pi)*(1/n)*(np.sin((n*np.pi*x)/L))#Fill in code here # Make the plots plt.plot(x, f1, label="n=1") plt.plot(x, f3, label="n=1..3") plt.plot(x, f9, label="n=1..9") plt.plot(x, f49, label="n=1..49") # Plot settings plt.title("Square Wave Fourier Series") plt.legend() plt.xlim([-0.01,0.01]) plt.xlabel("Time (sec)") plt.ylabel("Intensity") Developed by E. Kramer
Your preview ends here
Eager to read complete document? Join bartleby learn and gain access to the full version
  • Access to all documents
  • Unlimited textbook solutions
  • 24/7 expert homework help
1/21/24, 9:27 PM Loops.ipynb - Colaboratory https://colab.research.google.com/drive/16aFHxdSCKI7jZGd1OdG4O8FT1Gv0MW2x?authuser=2#printMode=true 5/5 © Regents of the University of California