Skip to content

Commit

Permalink
Fix documentation to adhere to Python style
Browse files Browse the repository at this point in the history
  • Loading branch information
ange1a-j14 committed Jul 29, 2024
1 parent aaa4825 commit 8408e9f
Show file tree
Hide file tree
Showing 2 changed files with 81 additions and 48 deletions.
20 changes: 11 additions & 9 deletions acquire_automatic.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,16 @@
rp_s = scpi.scpi(IP)
print('Connected to ' + IP)

'''
Runs one shot of driving the speaker with a waveform and collecting the relevant data.
@param store_data: whether to save time, measured speaker & PD voltage,
and expected speaker velocity data to h5py
@param plot_data: whether to plot data after acquisition
'''
def run_one_shot(start_freq=1, end_freq=1000, decimation=8192, store_data=False, plot_data=False):
"""Runs one shot of driving the speaker with a waveform and collecting the relevant data.
Args:
start_freq (int, optional): the lower bound of the valid frequency range. Defaults to 1.
end_freq (int, optional): the upper bound of the valid frequency range. Defaults to 1000.
decimation (int, optional): Decimation that determines sample rate, should be power of 2. Defaults to 8192.
store_data (bool, optional): Whether to store data in h5py file. Defaults to False.
plot_data (bool, optional): Whether to plot data after acquisition. Defaults to False.
"""
##### Create Waveform #####

N = 16384 # Number of samples in buffer
Expand Down Expand Up @@ -129,6 +131,6 @@ def run_one_shot(start_freq=1, end_freq=1000, decimation=8192, store_data=False,
rp_s.tx_txt('ACQ:RST')


num_shots = 1e3
num_shots = 1
for i in range(num_shots):
run_one_shot(store_data=False, plot_data=False)
run_one_shot(store_data=False, plot_data=True)
109 changes: 70 additions & 39 deletions util.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,18 @@
from scipy.fftpack import fft, ifft, fftfreq
import h5py

'''
Generates a random waveform within the given frequency range of a given length.
'''
def bounded_frequency_waveform(start_frequency, end_frequency, length=1000, sample_rate=1000):
def bounded_frequency_waveform(start_frequency, end_frequency, length, sample_rate):
"""Generates a random waveform within the given frequency range of a given length.
Args:
start_frequency (float): the lower bound of the valid frequency range
end_frequency (float): the upper bound of the valid frequency range
length (int): the number of values to generate
sample_rate (float): the rate at which to sample values
Returns:
[1darr, 1darr]: the array of time points and amplitude points in time domain
"""
# Create an evenly spaced time array
t = np.linspace(0, 1.0, length, False) # 1 second
# Generate a random frequency spectrum between the start and end frequencies
Expand All @@ -23,26 +31,30 @@ def bounded_frequency_waveform(start_frequency, end_frequency, length=1000, samp
y = np.fft.fftshift(y)
return t, y

'''
Linearly scales data to a new range.
@param data: assumed to be 1D array
'''
def linear_convert(data, new_min=-1, new_max=1):
"""Linearly scales data to a new range. Default is [-1, 1].
Args:
data (1darr): data to scale
new_min (float, optional): new minimum value for data. Defaults to -1.
new_max (float, optional): new maximum value for data. Defaults to 1.
Returns:
1darr: the newly scaled data
"""
old_min = np.min(data)
old_max = np.max(data)
old_range = old_max - old_min
new_range = new_max - new_min
return new_min + new_range * (data - old_min) / old_range

def write_data(file_path, entries):
'''Add data to a given dataset in 'file'. Creates dataset if it doesn't exist; otherwise,
appends.
Keyword arguments:
file_path (string) - the name of the output HDF5 file to which to append data
entries (dict) - dictionary of column name & corresponding data
'''
"""Add data to a given dataset in 'file'. Creates dataset if it doesn't exist;
otherwise, appends.
Args:
file_path (string): the name of the output HDF5 file to which to append data
entries (dict<str, 1darr>): dictionary of column name & corresponding data
"""
with h5py.File(file_path, 'a') as f:
for col_name, col_data in entries.items():
if col_name in f.keys():
Expand All @@ -61,31 +73,43 @@ def write_data(file_path, entries):
k = 33.42493417407945
c = -3.208233068626455

'''
Calculates the expected displacement of the speaker at an inputted drive amplitude 'ampl'
for a given frequency 'f', based on the calibration fit at 0.2Vpp.
@param f: frequencies at which to calculate expected displacement
@return: expected displacement in microns
'''
def A(f):
return (k * f0**2) / np.sqrt((f0**2 - f**2)**2 + f0**2*f**2/Q**2)
"""Calculates the expected displacement of the speaker at an inputted drive amplitude 'ampl' for a given frequency 'f',
based on the calibration fit at 0.2Vpp.
Args:
f (1darr): frequencies at which to calculate expected displacement
'''
Calculates the phase delay between the speaker voltage waveform and the photodiode response
at a given frequency 'f'.
Returns:
1darr: expected displacement/V_ampl in microns/V
"""
return (k * f0**2) / np.sqrt((f0**2 - f**2)**2 + f0**2*f**2/Q**2)

@param f: optimal range 20Hz-1kHz
@return: phase in radians
'''
def phase(f):
"""Calculates the phase delay between the speaker voltage waveform and the photodiode response
at a given frequency 'f'.
Args:
f (1darr): frequencies at which to calculate expected displacement
Returns:
1darr: phase in radians
"""
return np.arctan2(f0/Q*f, f**2 - f0**2) + c

'''
Calculates the corresponding displacement waveform based on the given voltage waveform
using calibration.
'''
def displacement_waveform(speaker_data, sample_rate):
"""Calculates the corresponding displacement waveform based on the given voltage waveform
using calibration.
Args:
speaker_data (1darr): voltage waveform for speaker
sample_rate (float): sample rate used to generate voltage waveform
Returns:
[1darr, 1darr, 1darr]: converted displacement waveform (microns) in time domain,
converted displacement waveform in frequency domain,
frequency array (Hz)
"""
speaker_spectrum = fft(speaker_data)
n = speaker_data.size
sample_spacing = 1/sample_rate
Expand All @@ -97,11 +121,19 @@ def displacement_waveform(speaker_data, sample_rate):

return y, converted_signal, freq

'''
Calculates the corresponding velocity waveform based on the given voltage waveform
using calibration.
'''
def velocity_waveform(speaker_data, sample_rate):
"""Calculates the corresponding velocity waveform based on the given voltage waveform
using calibration.
Args:
speaker_data (1darr): voltage waveform for speaker
sample_rate (float): sample rate used to generate voltage waveform
Returns:
[1darr, 1darr, 1darr]: converted velocity waveform (microns/s) in time domain,
converted velocity waveform in frequency domain,
frequency array (Hz)
"""
speaker_spectrum = fft(speaker_data)
n = speaker_data.size
sample_spacing = 1/sample_rate
Expand All @@ -110,6 +142,5 @@ def velocity_waveform(speaker_data, sample_rate):
# Multiply signal by transfer func in freq domain, then return to time domain
converted_signal = 1j*freq * speaker_spectrum * A(freq) * np.where(freq < 0, np.exp(-1j*phase(-freq)), np.exp(1j*phase(freq)))
v = np.real(ifft(converted_signal))
# y = np.fft.fftshift(y)

return v, converted_signal, freq

0 comments on commit 8408e9f

Please sign in to comment.