def proc_file(file): fobj = hsDat(file) vperp = fobj.dat[:, 0] elec3 = fobj.dat[:, 1] vperp_filt = signal.filtfilt(b1, a1, vperp) elec3_filt = signal.filtfilt(b2, a2, elec3) vperp_fft = np.fft.rfft(vperp_filt) elec3_fft = np.fft.rfft(elec3_filt) if plot_raw_dat: plt.plot(time_vec[:10000], vperp_filt[:10000]) plt.figure() plt.loglog(freqs, np.abs(np.fft.rfft(vperp))) plt.loglog(freqs, np.abs(np.fft.rfft(vperp_filt))) plt.figure() plt.loglog(freqs, np.abs(np.fft.rfft(elec3))) plt.loglog(freqs, np.abs(np.fft.rfft(elec3_filt))) plt.show() fc = freqs[np.argmax(np.abs(vperp_fft))] #print fc inds1 = np.abs(freqs - fc) < 0.5 * bandwidth inds2 = np.abs(freqs - 0.5 * fc) < 0.25 * bandwidth dat_phase = np.angle(np.sum(vperp_fft[inds1])) drive_phase = np.angle(np.sum(elec3_fft[inds2])) drive_amp = np.abs(np.sum(elec3_fft[inds2])) * bu.fft_norm( nsamp, fsamp) p01 = [np.std(vperp_filt), fc, dat_phase, 0] popt1, pcov1 = opti.curve_fit(sine, time_vec, vperp_filt, p0=p01, maxfev=10000) #print popt1 p02 = [np.std(elec3_filt), 0.5 * fc, drive_phase, 0] popt2, pcov2 = opti.curve_fit(sine, time_vec, elec3_filt, p0=p02, maxfev=10000) #print popt2 drive_amp2 = np.abs(popt2[0]) drive_phase2 = popt2[2] dat_phase2 = popt1[2] print(drive_amp / drive_amp2) if plot_raw_dat: plot_x = time_vec[:10000] plt.plot(plot_x, vperp_filt[:10000]) plt.figure() plt.loglog(freqs, np.abs(np.fft.rfft(vperp))) plt.loglog(freqs, np.abs(np.fft.rfft(vperp_filt))) plt.figure() plt.loglog(freqs, np.abs(np.fft.rfft(elec3))) plt.loglog(freqs, np.abs(np.fft.rfft(elec3_filt))) plt.show() if plot_fit: plot_x = time_vec[:10000] plt.figure() plt.plot(plot_x, vperp_filt[:10000]) plt.plot(plot_x, sine(plot_x, *p01)) plt.plot(plot_x, sine(plot_x, *popt1)) plt.figure() plt.plot(plot_x, elec3_filt[:10000]) plt.plot(plot_x, sine(plot_x, *p02)) plt.plot(plot_x, sine(plot_x, *popt2)) plt.show() return [ drive_amp, drive_phase, dat_phase, drive_amp2, drive_phase2, dat_phase2 ]
def proc_file(file): fobj = bu.hsDat(file, load=True) vperp = fobj.dat[:, 0] elec3 = fobj.dat[:, 1] elec3_filt = signal.filtfilt(b2, a2, elec3) if plot_raw_dat: fac = bu.fft_norm(nsamp, fsamp) plt.plot(time_vec[:10000], elec3[:10000]) plt.figure() plt.plot(time_vec[:10000], vperp[:10000]) plt.figure() plt.loglog(freqs, fac * np.abs(np.fft.rfft(vperp))) plt.figure() plt.loglog(freqs, fac * np.abs(np.fft.rfft(elec3))) plt.loglog(freqs, fac * np.abs(np.fft.rfft(elec3_filt))) plt.show() input() inds = np.abs(freqs - fspin) < 200.0 elec3_fft = np.fft.rfft(elec3) true_fspin = freqs[np.argmax(np.abs(elec3_fft))] amp, phase_mod = bu.demod(vperp, true_fspin, fsamp, plot=plot_demod, \ filt=True, bandwidth=bandwidth, \ notch_freqs=notch_freqs, notch_qs=notch_qs, \ tukey=True, tukey_alpha=5.0e-4, \ detrend=detrend, detrend_order=1, harmind=2.0, \ force_2pi_wrap=force_2pi_wrap) phase_mod_filt = signal.filtfilt(b3, a3, phase_mod) #phase_mod_filt = phase_mod amp_asd = np.abs(np.fft.rfft(amp)) phase_asd = np.abs(np.fft.rfft(phase_mod)) phase_asd_filt = np.abs(np.fft.rfft(phase_mod_filt)) # popt_n, pcov_n = opti.curve_fit(gauss, freqs[notch_fit_inds], \ # phase_asd_filt[notch_fit_inds], \ # p0=[10000, notch_init, 2, 0]) if apply_notch: notch = freqs[np.argmax(phase_asd_filt * notch_fit_inds)] notch_digital = (2.0 / fsamp) * (notch) for i in range(notch_nharm): bn, an = signal.iirnotch(notch_digital * (i + 1), notch_q) phase_mod_filt = signal.lfilter(bn, an, phase_mod_filt) phase_asd_filt_2 = np.abs(np.fft.rfft(phase_mod_filt)) if correct_noise_color: phase_asd = phase_asd * freqs**noise_color_power phase_asd_filt = phase_asd_filt * freqs**noise_color_power phase_asd_filt_2 = phase_asd_filt_2 * freqs**noise_color_power if plot_phase: plt.plot(freqs, phase_mod) plt.xlabel('Frequency [Hz]') plt.ylabel('Phase [rad]') plt.tight_layout() plt.figure() plt.loglog(freqs, phase_asd) plt.loglog(freqs, phase_asd_filt) plt.loglog(freqs, phase_asd_filt_2) plt.xlabel('Frequency [Hz]') plt.ylabel('Phase ASD [arb]') plt.tight_layout() plt.show() input() freq_mask = (freqs > allowed_freqs[0]) * (freqs < allowed_freqs[1]) max_ind = np.argmax(phase_asd_filt_2 * freq_mask) max_freq = freqs[max_ind] p0 = [10000, max_freq, 5.0, 0] try: popt, pcov = opti.curve_fit(lorentzian, freqs[max_ind-30:max_ind+30], \ phase_asd_filt_2[max_ind-30:max_ind+30], p0=p0, \ maxfev=10000) fit_max = popt[1] fit_std = np.abs(popt[2]) except: print('bad fit...') fit_max = max_freq fit_std = 5.0 * (freqs[1] - freqs[0]) popt = p0 if plot_sideband_fit: plot_freqs = np.linspace(freqs[max_ind - 30], freqs[max_ind + 30], 100) plt.loglog(freqs, phase_asd_filt_2) plt.loglog(plot_freqs, lorentzian(plot_freqs, *popt)) print(fit_max, fit_std) plt.show() input() # if fit_max < 10: # return # if len(wobble_freq): # if (np.abs(fit_max - wobble_freq[-1]) / wobble_freq[-1]) > 0.1: # # plt.loglog(freqs, phase_asd) # # plt.loglog(freqs, phase_asd_filt) # # plt.loglog(freqs, phase_asd_filt_2) # # plt.show() # return elec3_filt_fft = np.fft.rfft(elec3_filt) fit_ind = 100000 short_freqs = np.fft.rfftfreq(fit_ind, d=1.0 / fsamp) zeros = np.zeros(fit_ind) voltage = np.array([zeros, zeros, zeros, elec3_filt[:fit_ind], \ zeros, zeros, zeros, zeros]) efield = bu.trap_efield(voltage * tabor_mon_fac, only_x=True) #efield_mag = np.linalg.norm(efield, axis=0) efield_asd = bu.fft_norm(fit_ind, fsamp) * np.abs( np.fft.rfft(efield[0])) # max_ind = np.argmax(np.abs(elec3_filt_fft)) short_max_ind = np.argmax(efield_asd) # freq_guess = freqs[max_ind] # phase_guess = np.mean(np.angle(elec3_filt_fft[max_ind-2:max_ind+2])) # amp_guess = np.sqrt(2) * np.std(efield[0]) # p0 = [amp_guess, freq_guess, phase_guess, 0] # popt_l, pcov_l = opti.curve_fit(lorentzian, short_freqs[short_max_ind-100:short_max_ind+100], \ # efield_asd[short_max_ind-100:short_max_ind+100], \ # p0=[amp_guess, freq_guess, 100, 0], maxfev=10000) # start_sine = time.time() # popt, pcov = opti.curve_fit(sine, time_vec[:fit_ind], efield[0], \ # sigma=0.01*efield[0], p0=p0) # print popt[0], popt_l[0] * (fsamp / fit_ind) #print popt[0], np.sqrt(pcov[0,0]) # amp_fit = efield_asd[short_max_ind] * np.sqrt(2.0 * fsamp / fit_ind) amp_fit = np.sqrt(2) * np.std(efield[0]) # plt.plot(efield[0]) # plt.show() err_val = np.mean(np.array([efield_asd[short_max_ind-10:short_max_ind], \ efield_asd[short_max_ind+1:short_max_ind+11]]).flatten()) amp_err = np.sqrt( (err_val * fsamp / fit_ind)**2) # + (0.01*amp_fit)**2) # print amp_fit, amp_err # stop_sine = time.time() # print "Field sampling: ", stop_sine - start_sine return [2.0 * amp_fit, np.sqrt(2) * amp_err, fit_max, fit_std]
avg_asd = [] for fileind, filname in enumerate(files): bu.progress_bar(fileind, nfiles) df = bu.DataFile() df.load(filname) df.diagonalize(plot=False) drive = df.electrode_data[elec_ind] resp = df.pos_data[pos_ind] diag_resp = df.diag_pos_data[pos_ind] normfac = bu.fft_norm(df.nsamp, df.fsamp) if len(resp) != len(drive): continue freqs = np.fft.rfftfreq(len(resp), d=1.0 / df.fsamp) fft = np.fft.rfft(resp) diag_fft = np.fft.rfft(diag_resp) dfft = np.fft.rfft(drive) #plt.figure() #plt.loglog(freqs, np.abs(dfft)) #plt.loglog(freqs, np.abs(fft)) #plt.show() amp = np.abs(fft)
files, _ = bu.find_all_fnames(dir_name, ext='.h5', sort_time=False, skip_subdirectories=False) files = files[file_inds[0]:file_inds[1]:file_step] nfiles = len(files) Ibead = bu.get_Ibead(date=date) fobj = bu.hsDat(files[0], load=False, load_attribs=True) nsamp = fobj.nsamp fsamp = fobj.fsamp fac = bu.fft_norm(nsamp, fsamp) time_vec = np.arange(nsamp) * (1.0 / fsamp) full_freqs = np.fft.rfftfreq(nsamp, 1.0 / fsamp) out_inds = (full_freqs > output_band[0]) * (full_freqs < output_band[1]) out_freqs = full_freqs[out_inds] times = [] for file in files: fobj = bu.hsDat(file, load=False, load_attribs=True) times.append(fobj.time) times = np.array(times) * 1e-9 times -= times[0]
def build_uncalibrated_H(fobjs, average_first=True, dpsd_thresh = 8e-1, mfreq = 1., \ skip_qpd=False, plot_response=False, drop_bad_bins=True, \ new_trap=False, lines_to_remove=[60.0], zero_drive_phase=False): '''Generates a transfer function from a list of DataFile objects INPUTS: fobjs, list of file objects average_first, boolean specifying whether to average responses for a given drive before computing H dpsd_thresh, threshold above which to compute H mfreq, minimum frequency to consider fix_HF, boolean to specify whether to try fixing spectral leakage at high frequency due to drift in a timebase OUTPUTS: Hout, dictionary with 3x3 complex valued matrices as values and frequencies as keys''' print("BUILDING H...") sys.stdout.flush() Hout = {} Hout_noise = {} Hout_amp = {} Hout_phase = {} Hout_fb = {} Hout_counts = {} avg_drive_fft = {} avg_data_fft = {} avg_fb_fft = {} if not skip_qpd: avg_side_fft = {} avg_amp_fft = {} avg_phase_fft = {} counts = {} if plot_response: fbfig, fb_axarr = plt.subplots(3,3,sharex=True,sharey=True,figsize=(9,8)) posfig, pos_axarr = plt.subplots(3,3,sharex=True,sharey='row',figsize=(9,8)) drivefig, drive_axarr = plt.subplots(3,3,sharex=True,sharey=True,figsize=(9,8)) if not skip_qpd: ampfig, amp_axarr = plt.subplots(5,3,sharex=True,sharey=True,figsize=(9,10)) phasefig, phase_axarr = plt.subplots(5,3,sharex=True,sharey=True,figsize=(9,10)) sidefig, side_axarr = plt.subplots(4,3,sharex=True,sharey=True,figsize=(9,9)) filind = 0 for fobj in fobjs: N = np.shape(fobj.pos_data)[1]#number of samples fsamp = fobj.fsamp fft_fac = bu.fft_norm(N, fsamp) drive = bu.trap_efield(fobj.electrode_data) #* constants.elementary_charge #drive = np.roll(drive, -10, axis=-1) # dfft = np.fft.rfft(fobj.electrode_data) #fft of electrode drive in daxis. dfft = np.fft.rfft( drive ) * fft_fac if new_trap: data_fft = np.fft.rfft(fobj.pos_data_3) * fft_fac else: data_fft = np.fft.rfft(fobj.pos_data) * fft_fac fb_fft = np.fft.rfft(fobj.pos_fb) * fft_fac if not skip_qpd: amp_fft = np.fft.rfft(fobj.amp) * fft_fac phase_fft = np.fft.rfft(fobj.phase) * fft_fac left = fobj.amp[2] + fobj.amp[3] right = fobj.amp[0] + fobj.amp[1] top = fobj.amp[2] + fobj.amp[0] bot = fobj.amp[3] + fobj.amp[1] side_fft = np.fft.rfft(np.array([right, left, top, bot])) * fft_fac fft_freqs = np.fft.rfftfreq(N, d=1.0/fsamp) # for i in range(len(dfft)): # plt.loglog(fft_freqs, np.abs(dfft[i])) # # plt.loglog(fft_freqs, np.abs(dfft[4])) # # plt.loglog(fft_freqs, np.abs(data_fft[0])) # plt.show() dpsd = np.abs(dfft)**2 #psd for all electrode drives dpsd_thresh = 0.1 * np.max(dpsd.flatten()) inds = np.where(dpsd>dpsd_thresh)#Where the dpsd is over the threshold for being used. eind = np.unique(inds[0])[0] # print(eind) if eind not in avg_drive_fft: avg_drive_fft[eind] = np.zeros(dfft.shape, dtype=np.complex128) avg_data_fft[eind] = np.zeros(data_fft.shape, dtype=np.complex128) avg_fb_fft[eind] = np.zeros(fb_fft.shape, dtype=np.complex128) if not skip_qpd: avg_amp_fft[eind] = np.zeros(amp_fft.shape, dtype=np.complex128) avg_phase_fft[eind] = np.zeros(phase_fft.shape, dtype=np.complex128) avg_side_fft[eind] = np.zeros(side_fft.shape, dtype=np.complex128) counts[eind] = 0. # try: avg_drive_fft[eind] += dfft avg_data_fft[eind] += data_fft avg_fb_fft[eind] += fb_fft if not skip_qpd: avg_amp_fft[eind] += amp_fft avg_phase_fft[eind] += phase_fft avg_side_fft[eind] += side_fft # except: # traceback.print_exc() # print() # print(fobj.fname) # derpfig, derpax = plt.subplots(1,1) # for i in [0,1,2,3,4]: # derpax.loglog(np.abs(amp_fft[i]) * 10**i, label=str(i)) # derpax.legend() # plt.show() # input() counts[eind] += 1. for eind in list(counts.keys()): print(eind, counts[eind]) avg_drive_fft[eind] = avg_drive_fft[eind] / counts[eind] avg_data_fft[eind] = avg_data_fft[eind] / counts[eind] avg_fb_fft[eind] = avg_fb_fft[eind] / counts[eind] if not skip_qpd: avg_amp_fft[eind] = avg_amp_fft[eind] / counts[eind] avg_phase_fft[eind] = avg_phase_fft[eind] / counts[eind] avg_side_fft[eind] = avg_side_fft[eind] / counts[eind] poslabs = {0: 'X', 1: 'Y', 2: 'Z'} sidelabs = {0: 'Right', 1: 'Left', 2: 'Top', 3: 'Bottom'} quadlabs = {0: 'Top Right', 1: 'Bottom Right', 2: 'Top Left', \ 3: 'Bottom Left', 4: 'Backscatter'} for eind in list(avg_drive_fft.keys()): # First find drive-frequency bins above a fixed threshold dpsd = np.abs(avg_drive_fft[eind])**2 inds = np.where(dpsd > dpsd_thresh) # Extract the frequency indices finds = inds[1] # Ignore DC and super low frequencies mfreq = 1.0 b = finds > np.argmin(np.abs(fft_freqs - mfreq)) tf_inds = finds[b] for linefreq in lines_to_remove: print('Ignoring response at line frequency: {:0.1f}'.format(linefreq)) line_freq_ind = np.argmin(np.abs(fft_freqs - linefreq)) tf_inds = tf_inds[tf_inds != line_freq_ind] freqs = fft_freqs[tf_inds] xlim = (np.min(fft_freqs[1:]), np.max(fft_freqs)) # xlim = (45.0, 130.0) # plt.plot(freqs, np.angle(avg_drive_fft[eind][eind,tf_inds]) / np.pi) # plt.title('Raw Phase From Drive FFT') # plt.ylabel('Apparent Phase [$\\pi \\, rad$]') # plt.xlabel('Drive Frequency [Hz]') # plt.tight_layout() # plt.figure() # plt.plot(freqs, np.unwrap(np.angle(avg_drive_fft[eind][eind,tf_inds])) / np.pi) # plt.title('Unwrapped Phase From Drive FFT') # plt.ylabel('Apparent Phase [$\\pi \\, rad$]') # plt.xlabel('Drive Frequency [Hz]') # plt.tight_layout() # plt.show() # outind = config.elec_map[eind] outind = eind if plot_response: for elec in [0,1,2]: #,3,4,5,6,7]: drive_axarr[elec,outind].loglog(fft_freqs, \ np.abs(avg_drive_fft[eind][elec]), alpha=1.0) drive_axarr[elec,outind].loglog(fft_freqs[tf_inds], \ np.abs(avg_drive_fft[eind][elec])[tf_inds], alpha=1.0) if outind == 0: drive_axarr[elec,outind].set_ylabel('Efield axis ' + str(elec) \ + '\n[(V/m)/$\\sqrt{\\rm Hz}$]') if elec == 2: #7: drive_axarr[elec,outind].set_xlabel('Frequency [Hz]') for resp in [0,1,2,3,4]: if not skip_qpd: amp_axarr[resp,outind].loglog(fft_freqs[tf_inds], \ np.abs(avg_amp_fft[eind][resp])[tf_inds], alpha=1.0) phase_axarr[resp,outind].loglog(fft_freqs[tf_inds], \ np.abs(avg_phase_fft[eind][resp])[tf_inds], alpha=1.0) if outind == 0: amp_axarr[resp,outind].set_ylabel(quadlabs[resp]) phase_axarr[resp,outind].set_ylabel(quadlabs[resp]) if resp == 4: amp_axarr[resp,outind].set_xlabel('Frequency [Hz]') phase_axarr[resp,outind].set_xlabel('Frequency [Hz]') if resp in [0,1,2,3]: side_axarr[resp,outind].loglog(fft_freqs[tf_inds], \ np.abs(avg_side_fft[eind][resp])[tf_inds], alpha=1.0) if outind == 0: side_axarr[resp,outind].set_ylabel(sidelabs[resp]) if resp == 3: side_axarr[resp,outind].set_xlabel('Frequency [Hz]') if resp in [0,1,2]: # if resp == 2: # fac = 1000.0 # else: # fac = 1.0 pos_axarr[resp,outind].loglog(fft_freqs, np.abs(avg_data_fft[eind][resp]), alpha=1.0) pos_axarr[resp,outind].loglog(fft_freqs[tf_inds], \ np.abs(avg_data_fft[eind][resp])[tf_inds], alpha=1.0) fb_axarr[resp,outind].loglog(fft_freqs, np.abs(avg_fb_fft[eind][resp]), alpha=1.0) fb_axarr[resp,outind].loglog(fft_freqs[tf_inds], \ np.abs(avg_fb_fft[eind][resp])[tf_inds], alpha=1.0) if outind == 0: pos_axarr[resp,outind].set_ylabel(poslabs[resp] + ' [arb]') fb_axarr[resp,outind].set_ylabel(poslabs[resp] + ' FB\n[bits/$\\sqrt{\\rm Hz}$]') if resp == 2: pos_axarr[resp,outind].set_xlabel('Frequency [Hz]') fb_axarr[resp,outind].set_xlabel('Frequency [Hz]') drivefig.suptitle('Drive Amplitude vs. Frequency', fontsize=16) posfig.suptitle('ASD of XYZ vs. Frequency', fontsize=16) fbfig.suptitle('ASD of XYZ Feedback vs. Frequency', fontsize=16) if not skip_qpd: ampfig.suptitle('ASD of Demod. Carrier Amp vs. Frequency', fontsize=16) phasefig.suptitle('ASD of Demod. Carrier Phase vs. Frequency', fontsize=16) sidefig.suptitle('ASD of Sum of Neighboring QPD Carrier Amplitudes', fontsize=16) figlist = [posfig, fbfig, drivefig, ampfig, phasefig, sidefig] axlist = [pos_axarr, fb_axarr, drive_axarr, amp_axarr, phase_axarr, side_axarr] else: figlist = [posfig, fbfig, drivefig] axlist = [pos_axarr, fb_axarr, drive_axarr] for axind, axarr in enumerate(axlist): # axarr[0,0].set_xlim(*xlim) axarr[0,0].set_xlim(34, 107) for drive in [0,1,2]: axarr[0,drive].set_title(poslabs[drive] + ' Drive') for resp in [0,1,2]: if (axind != 0) and (resp != 0): continue mag_major_locator = LogLocator(base=10.0, numticks=30) mag_minor_locator = LogLocator(base=1.0, numticks=300) axarr[resp,0].yaxis.set_major_locator(mag_major_locator) axarr[resp,0].yaxis.set_minor_locator(mag_minor_locator) axarr[resp,0].yaxis.set_minor_formatter(NullFormatter()) for d in [0,1,2]: for r in [0,1,2]: axarr[r,d].grid(which='both') ### Compute FFT of each response divided by FFT of each drive. ### This is way more information than we need for a single drive freq ### and electrode pair, but it allows a nice vectorization Hmat = np.einsum('ij, kj -> ikj', \ avg_data_fft[eind][:,tf_inds], 1. / avg_drive_fft[eind][:,tf_inds]) Hmat_fb = np.einsum('ij, kj -> ikj', \ avg_fb_fft[eind][:,tf_inds], 1. / avg_drive_fft[eind][:,tf_inds]) if not skip_qpd: Hmat_amp = np.einsum('ij, kj -> ikj', \ avg_amp_fft[eind][:,tf_inds], 1. / avg_drive_fft[eind][:,tf_inds]) Hmat_phase = np.einsum('ij, kj -> ikj', \ avg_phase_fft[eind][:,tf_inds], 1. / avg_drive_fft[eind][:,tf_inds]) # Generate an integer by which to roll the data_fft to compute the noise # limit of the TF measurement if len(tf_inds) > 1: shift = int(0.5 * (tf_inds[1] - tf_inds[0])) else: shift = int(0.5 * tf_inds[0]) randadd = np.random.choice(np.arange(-int(0.1*shift), \ int(0.1*shift)+1, 1)) shift = shift + randadd rolled_data_fft = np.roll(avg_data_fft[eind], shift, axis=-1) # Compute the Noise TF Hmat_noise = np.einsum('ij, kj -> ikj', \ rolled_data_fft[:,tf_inds], 1. / avg_drive_fft[eind][:,tf_inds]) # Map the 3x7xNfreq arrays to dictionaries with keys given by the drive # frequencies and values given by 3x3 complex-values TF matrices #outind = config.elec_map[eind] outind = eind for i, freq in enumerate(freqs): if freq not in Hout: if i != 0 and drop_bad_bins: sep = freq - freqs[i-1] # Clause to ignore this particular frequency response if an # above threshold response is found not on a drive bin. Sometimes # random noise components pop up or some power leaks to a # neighboring bin if sep < 0.8 * (freqs[1] - freqs[0]): continue Hout[freq] = np.zeros((3,3), dtype=np.complex128) Hout_noise[freq] = np.zeros((3,3), dtype=np.complex128) Hout_amp[freq] = np.zeros((5,3), dtype=np.complex128) Hout_phase[freq] = np.zeros((5,3), dtype=np.complex128) # Add the response from this drive freq/electrode pair to the TF matrix Hout[freq][:,outind] += Hmat[:,eind,i] Hout_noise[freq][:,outind] += Hmat_noise[:,eind,i] if not skip_qpd: Hout_amp[freq][:,outind] += Hmat_amp[:,eind,i] Hout_phase[freq][:,outind] += Hmat_phase[:,eind,i] if plot_response: for fig in figlist: fig.tight_layout() fig.subplots_adjust(top=0.90) plt.show() # first_mats = [] freqs = list(Hout.keys()) freqs.sort() if zero_drive_phase: # init_phases = np.angle(Hout[freqs[0]]) first_mats = [] for freq in freqs[1:3]: first_mats.append(Hout[freq]) first_mats = np.array(first_mats) init_phases = np.mean(np.unwrap(np.angle(first_mats), axis=0), axis=0) # print(init_phases) # input() for drive in [0,1,2]: if np.abs(init_phases[drive,drive]) > 1.5: ### Check the second frequency to make sure the first isn't crazy if np.abs(np.angle(Hout[freqs[1]][drive,drive])) > 1.5: print("Correcting phase shift for drive channel", drive) sys.stdout.flush() for freq in freqs: Hout[freq][drive,:] = Hout[freq][drive,:] * (-1) # Hout[freq][:,drive] = Hout[freq][:,drive] * (-1) else: Hout[freqs[0]][drive,:] = Hout[freqs[0]][drive,:] * (-1) out_dict = {'Hout': Hout, 'Hout_amp': Hout_amp, 'Hout_phase': Hout_phase, \ 'Hout_noise': Hout_noise} return out_dict
def plot_many_spectra(files, data_axes=[0,1,2], cant_axes=[], elec_axes=[], other_axes=[], \ fb_axes=[], plot_power=False, diag=True, colormap='plasma', \ sort='time', file_inds=(0,10000)): '''Loops over a list of file names, loads each file, diagonalizes, then plots the amplitude spectral density of any number of data or cantilever/electrode drive signals INPUTS: files, list of files names to extract data data_axes, list of pos_data axes to plot cant_axes, list of cant_data axes to plot elec_axes, list of electrode_data axes to plot diag, boolean specifying whether to diagonalize OUTPUTS: none, plots stuff ''' if diag: dfig, daxarr = plt.subplots(len(data_axes),2,sharex=True,sharey=True, \ figsize=figsize) else: dfig, daxarr = plt.subplots(len(data_axes),1,sharex=True,sharey=True, \ figsize=figsize) dfig.suptitle('XYZ Data', fontsize=18) if len(cant_axes): cfig, caxarr = plt.subplots(len(data_axes), 1, sharex=True, sharey=True) if len(cant_axes) == 1: caxarr = [caxarr] cfig.suptitle('Attractor Data', fontsize=18) if len(elec_axes): efig, eaxarr = plt.subplots(len(elec_axes), 1, sharex=True, sharey=True) if len(elec_axes) == 1: eaxarr = [eaxarr] efig.suptitle('Electrode Data', fontsize=18) if len(other_axes): ofig, oaxarr = plt.subplots(len(other_axes), 1, sharex=True, sharey=True) if len(other_axes) == 1: oaxarr = [oaxarr] ofig.suptitle('Other Data', fontsize=18) if len(fb_axes): fbfig, fbaxarr = plt.subplots(len(fb_axes),1,sharex=True,sharey=True, \ figsize=figsize) if len(fb_axes) == 1: fbaxarr = [fbaxarr] fbfig.suptitle('Feedback Data', fontsize=18) if plot_power: pfig, paxarr = plt.subplots(2, 1, sharex=True, figsize=(6, 6)) pfig.suptitle('Power/Power Feedback Data', fontsize=18) kludge_fig, kludge_ax = plt.subplots(1, 1) files = files[file_inds[0]:file_inds[1]] if step10: files = files[::10] if invert_order: files = files[::-1] colors = bu.get_color_map(len(files), cmap=colormap) #colors = ['C0', 'C1', 'C2'] old_per = 0 print("Processing %i files..." % len(files)) for fil_ind, fil in enumerate(files): color = colors[fil_ind] # Display percent completion bu.progress_bar(fil_ind, len(files)) # Load data df = bu.DataFile() if new_trap: df.load_new(fil) else: df.load(fil) if len(other_axes): df.load_other_data() df.calibrate_stage_position() #df.high_pass_filter(fc=1) #df.detrend_poly() #plt.figure() #plt.plot(df.pos_data[0]) #plt.show() if cascade: cascade_scale = (cascade_fac)**fil_ind else: cascade_scale = 1.0 freqs = np.fft.rfftfreq(len(df.pos_data[0]), d=1.0 / df.fsamp) if diag: df.diagonalize(maxfreq=lpf, date=tfdate, plot=tf_plot) if fil_ind == 0 and len(cant_axes): drivepsd = np.abs(np.fft.rfft(df.cant_data[drive_ax])) driveind = np.argmax(drivepsd[1:]) + 1 drive_freq = freqs[driveind] for axind, ax in enumerate(data_axes): try: fac = cascade_scale * df.conv_facs[ax] # * (1.0 / 0.12e-12) except: fac = cascade_scale if fullNFFT: NFFT = len(df.pos_data[ax]) else: NFFT = userNFFT psd, freqs = mlab.psd(df.pos_data[ax], Fs=df.fsamp, \ NFFT=NFFT, window=window) norm = bu.fft_norm(df.nsamp, df.fsamp) new_freqs = np.fft.rfftfreq(df.nsamp, d=1.0 / df.fsamp) #fac = 1.0 kludge_fac = 1.0 #kludge_fac = 1.0 / np.sqrt(10) if diag: dpsd, dfreqs = mlab.psd(df.diag_pos_data[ax], Fs=df.fsamp, \ NFFT=NFFT, window=window) kludge_ax.loglog(freqs, np.sqrt(dpsd) *kludge_fac, color='C'+str(axind), \ label=posdic[axind]) kludge_ax.set_ylabel( '$\sqrt{\mathrm{PSD}}$ $[\mathrm{N}/\sqrt{\mathrm{Hz}}]$') kludge_ax.set_xlabel('Frequency [Hz]') # daxarr[axind,0].loglog(new_freqs, fac*norm*np.abs(np.fft.rfft(df.pos_data[ax]))*kludge_fac, color='k', label='np.fft with manual normalization') daxarr[axind, 0].loglog(freqs, np.sqrt(psd) * fac * kludge_fac, color=color, label=df.fname) #'mlab.psd') daxarr[axind, 0].grid(alpha=0.5) daxarr[axind, 1].loglog( new_freqs, norm * np.abs(np.fft.rfft(df.diag_pos_data[ax])) * kludge_fac, color='k') daxarr[axind, 1].loglog(freqs, np.sqrt(dpsd) * kludge_fac, color=color) daxarr[axind, 1].grid(alpha=0.5) daxarr[axind, 0].set_ylabel( '$\sqrt{\mathrm{PSD}}$ $[\mathrm{N}/\sqrt{\mathrm{Hz}}]$') if ax == data_axes[-1]: daxarr[axind, 0].set_xlabel('Frequency [Hz]') daxarr[axind, 1].set_xlabel('Frequency [Hz]') else: # daxarr[axind].loglog(new_freqs, norm*np.abs(np.fft.rfft(df.pos_data[ax])), color='k', label='np.fft with manual normalization') daxarr[axind].loglog(freqs, np.sqrt(psd) * fac, color=color, label=df.fname) #'mlab.psd') daxarr[axind].grid(alpha=0.5) daxarr[axind].set_ylabel( '$\\sqrt{\mathrm{PSD}}$ $[\\mathrm{Arb}/\\sqrt{\mathrm{Hz}}]$' ) #daxarr[axind].set_ylabel('$\sqrt{\mathrm{PSD}}$ $[\mathrm{N}/\sqrt{\mathrm{Hz}}]$') if ax == data_axes[-1]: daxarr[axind].set_xlabel('Frequency [Hz]') if len(fb_axes): for axind, ax in enumerate(fb_axes): fb_psd, freqs = mlab.psd(df.pos_fb[ax], Fs=df.fsamp, \ NFFT=NFFT, window=window) fbaxarr[axind].loglog(freqs, np.sqrt(fb_psd) * fac, color=color) fbaxarr[axind].set_ylabel('$\\sqrt{\\mathrm{PSD}}$') if len(cant_axes): for axind, ax in enumerate(cant_axes): psd, freqs = mlab.psd(df.cant_data[ax], Fs=df.fsamp, \ NFFT=NFFT, window=window) caxarr[axind].loglog(freqs, np.sqrt(psd), color=color) caxarr[axind].set_ylabel('$\\sqrt{\\mathrm{PSD}}$') if len(elec_axes): for axind, ax in enumerate(elec_axes): psd, freqs = mlab.psd(df.electrode_data[ax], Fs=df.fsamp, \ NFFT=NFFT, window=window) eaxarr[axind].loglog(freqs, np.sqrt(psd), color=color) eaxarr[axind].set_ylabel('$\\sqrt{\\mathrm{PSD}}$') if len(other_axes): for axind, ax in enumerate(other_axes): #ax = ax - 3 psd, freqs = mlab.psd(df.other_data[ax], Fs=df.fsamp, \ NFFT=NFFT, window=window) oaxarr[axind].loglog(freqs, np.sqrt(psd), color=color) oaxarr[axind].set_ylabel('$\\sqrt{\\mathrm{PSD}}$') if plot_power: psd, freqs = mlab.psd(df.power, Fs=df.fsamp, \ NFFT=NFFT, window=window) psd_fb, freqs_fb = mlab.psd(df.power_fb, Fs=df.fsamp, \ NFFT=NFFT, window=window) paxarr[0].loglog(freqs, np.sqrt(psd), color=color) paxarr[1].loglog(freqs_fb, np.sqrt(psd_fb), color=color) for axind in [0, 1]: paxarr[axind].set_ylabel('$\\sqrt{\\mathrm{PSD}}$') if filename_labels: daxarr[0].legend(fontsize=10) if len(fb_axes): fbaxarr[0].legend(fontsize=10) #daxarr[0].set_xlim(0.5, 25000) if diag: derp_ax = daxarr[0, 0] else: derp_ax = daxarr[0] # derp_ax.legend(fontsize=10) if len(ylim): derp_ax.set_ylim(*ylim) kludge_ax.set_ylim(*ylim) if len(xlim): derp_ax.set_xlim(*xlim) kludge_ax.set_xlim(1, 500) dfig.tight_layout() dfig.subplots_adjust(top=0.91) kludge_ax.grid() kludge_ax.legend() kludge_fig.tight_layout() if plot_power: paxarr[-1].set_xlabel('Frequency [Hz]') pfig.tight_layout() pfig.subplots_adjust(top=0.91) if len(cant_axes): caxarr[-1].set_xlabel('Frequency [Hz]') cfig.tight_layout() cfig.subplots_adjust(top=0.91) if len(elec_axes): eaxarr[-1].set_xlabel('Frequency [Hz]') efig.tight_layout() efig.subplots_adjust(top=0.91) if len(other_axes): oaxarr[-1].set_xlabel('Frequency [Hz]') ofig.tight_layout() ofig.subplots_adjust(top=0.91) if len(fb_axes): fbaxarr[-1].set_xlabel('Frequency [Hz]') fbfig.tight_layout() fbfig.subplots_adjust(top=0.91) if savefigs: plt.savefig(title_pre + '.png') daxarr[0].set_xlim(2000, 25000) plt.tight_layout() plt.savefig(title_pre + '_zoomhf.png') daxarr[0].set_xlim(1, 80) plt.tight_layout() plt.savefig(title_pre + '_zoomlf.png') daxarr[0].set_xlim(0.5, 25000) if not savefigs: plt.show()
def weigh_bead(files, pcol=0, colormap='plasma', sort='time', file_inds=(0, 10000)): '''Loops over a list of file names, loads each file, diagonalizes, then plots the amplitude spectral density of any number of data or cantilever/electrode drive signals INPUTS: files, list of files names to extract data data_axes, list of pos_data axes to plot cant_axes, list of cant_data axes to plot elec_axes, list of electrode_data axes to plot diag, boolean specifying whether to diagonalize OUTPUTS: none, plots stuff ''' files = [(os.stat(path), path) for path in files] files = [(stat.st_ctime, path) for stat, path in files] files.sort(key=lambda x: (x[0])) files = [obj[1] for obj in files] files = files[file_inds[0]:file_inds[1]] if step10: files = files[::10] if invert_order: files = files[::-1] date = re.search(r"\d{8,}", files[0])[0] charge_dat = np.load( open('/calibrations/charges/' + date + '.charge', 'rb')) q_bead = -1.0 * charge_dat[0] * constants.elementary_charge # q_bead = -25.0 * 1.602e-19 nfiles = len(files) colors = bu.get_color_map(nfiles, cmap=colormap) avg_fft = [] print("Processing %i files..." % nfiles) for fil_ind, fil in enumerate(files): color = colors[fil_ind] bu.progress_bar(fil_ind, nfiles) # Load data df = bu.DataFile() df.load(fil) df.calibrate_stage_position() df.calibrate_phase() #plt.hist( df.zcal / df.phase[4] ) #plt.show() #print np.mean(df.zcal / df.phase[4]), np.std(df.zcal / df.phase[4]) freqs = np.fft.rfftfreq(df.nsamp, d=1.0 / df.fsamp) fft = np.fft.rfft(df.zcal) * bu.fft_norm(df.nsamp, df.fsamp) \ * np.sqrt(freqs[1] - freqs[0]) fft2 = np.fft.rfft(df.phase[4]) * bu.fft_norm(df.nsamp, df.fsamp) \ * np.sqrt(freqs[1] - freqs[0]) fftd = np.fft.rfft(df.zcal - np.pi*df.phase[4]) * bu.fft_norm(df.nsamp, df.fsamp) \ * np.sqrt(freqs[1] - freqs[0]) #plt.plot(np.pi * df.phase[4]) #plt.plot(df.zcal) #plt.figure() #plt.loglog(freqs, np.abs(fft)) #plt.loglog(freqs, np.pi * np.abs(fft2)) #plt.loglog(freqs, np.abs(fftd)) #plt.show() drive_fft = np.fft.rfft(df.electrode_data[1]) #plt.figure() #plt.loglog(freqs, np.abs(drive_fft)) #plt.show() inds = np.abs(drive_fft) > 1e4 inds *= (freqs > 2.0) * (freqs < 300.0) inds = np.arange(len(inds))[inds] ninds = inds + 5 drive_amp = np.abs( drive_fft[inds][0] * bu.fft_norm(df.nsamp, df.fsamp) \ * np.sqrt(freqs[1] - freqs[0]) ) if not len(avg_fft): avg_fft = fft avg_drive_fft = drive_fft ratio = fft[inds] / drive_fft[inds] else: avg_fft += fft avg_drive_fft += drive_fft ratio += fft[inds] / drive_fft[inds] fac = bu.fft_norm(df.nsamp, df.fsamp) * np.sqrt(freqs[1] - freqs[0]) avg_fft *= (1.0 / nfiles) avg_drive_fft *= (1.0 / nfiles) resp = fft[inds] * (1064.0e-9 / 2.0) * (1.0 / (2.0 * np.pi)) noise = fft[ninds] * (1064.0e-9 / 2.0) * (1.0 / (2.0 * np.pi)) drive_noise = np.abs(np.median(avg_drive_fft[ninds] * fac)) #plt.loglog(freqs[inds], np.abs(resp)) #plt.loglog(freqs[ninds], np.abs(noise)) #plt.show() resp_sc = resp * 1e9 # put resp in units of nm noise_sc = noise * 1e9 def amp_sc(f, d_accel, f0, g): return np.abs(harmonic_osc(f, d_accel, f0, g)) * 1e9 def phase_sc(f, d_accel, f0, g): return np.angle(harmonic_osc(f, d_accel, f0, g)) #plt.loglog(freqs[inds], np.abs(resp_sc)) #plt.loglog(freqs[inds], np.abs(harmonic_osc(freqs[inds], 1e-3, 160, 75e1))*1e9) #plt.show() #plt.loglog(freqs[inds], np.abs(resp_sc)) #plt.loglog(freqs, amp_sc(freqs, 1e-3, 160, 750)) #plt.show() popt, pcov = opti.curve_fit(amp_sc, freqs[inds], np.abs(resp_sc), sigma=np.abs(noise_sc), \ absolute_sigma=True, p0=[1e-3, 160, 750], maxfev=10000) #popt2, pcov2 = opti.curve_fit(phase_sc, freqs[inds], np.angle(resp_sc), p0=[1e-3, 160, 750]) print(popt) print(pcov) plt.figure() plt.errorbar(freqs[inds], np.abs(resp), np.abs(noise), fmt='.', ms=10, lw=2) #plt.loglog(freqs[inds], np.abs(noise)) plt.loglog(freqs, np.abs(harmonic_osc(freqs, *popt))) plt.xlabel('Frequency [Hz]', fontsize=16) plt.ylabel('Z Amplitude [m]', fontsize=16) force = (drive_amp / (4.0e-3)) * q_bead mass = np.abs(popt[0]**(-1) * force) * 10**12 fit_err = np.sqrt(pcov[0, 0] / popt[0]) charge_err = 0.1 drive_err = drive_noise / drive_amp print(drive_err) mass_err = np.sqrt((fit_err)**2 + (charge_err)**2 + (drive_err)**2) * mass #print "IMPLIED MASS [ng]: ", mass print('%0.3f ng, %0.2f e^-, %0.1f V' % (mass, q_bead * (1.602e-19)**(-1), drive_amp)) print('%0.6f ng' % (mass_err)) plt.tight_layout() plt.show()
def analyze_background(self, data_axes=[0,1,2], lpf=2500, \ diag=False, colormap='jet', \ file_inds=(0,10000), unwrap=False, \ harms_to_track = [1, 2, 3], \ ext_cant_drive=False, ext_cant_ind=0, \ plot_first_drive=False, sub_cant_phase=True, \ progstr=''): '''Loops over a list of file names, loads each file, diagonalizes, then plots the amplitude spectral density of any number of data or cantilever/electrode drive signals INPUTS: files, list of files names to extract data data_axes, list of pos_data axes to plot ax_labs, dict with labels for plotted axes diag, bool specifying whether to diagonalize unwrap, bool to unwrap phase of background harms, harmonics to label in ASD OUTPUTS: none, generates class attributes ''' files = bu.sort_files_by_timestamp(self.relevant_files) files = files[file_inds[0]:file_inds[1]] nfreq = len(harms_to_track) nax = len(data_axes) nfiles = len(files) colors = bu.get_color_map(nfiles, cmap=colormap) avg_asd = [[]] * nax diag_avg_asd = [[]] * nax Nasds = [[]] * nax amps = np.zeros((nax, nfreq, nfiles)) amp_errs = np.zeros((nax, nfreq, nfiles)) phases = np.zeros((nax, nfreq, nfiles)) phase_errs = np.zeros((nax, nfreq, nfiles)) temps = np.zeros((2, nfiles)) times = np.zeros(nfiles) print("Processing %i files..." % nfiles) for fil_ind, fil in enumerate(files): color = colors[fil_ind] # Display percent completion bu.progress_bar(fil_ind, nfiles, suffix=progstr) # Load data df = bu.DataFile() df.load(fil) try: temps[0, fil_ind] = df.temps[0] temps[1, fil_ind] = df.temps[1] except: temps[:, fil_ind] = 0.0 if fil_ind == 0: self.fsamp = df.fsamp init_time = df.time times[0] = 0.0 else: times[fil_ind] = (df.time - init_time).total_seconds() df.calibrate_stage_position() #df.high_pass_filter(fc=1) #df.detrend_poly() df.diagonalize(maxfreq=lpf, interpolate=False) Nsamp = len(df.pos_data[0]) if len(harms_to_track): harms = harms_to_track else: harms = [1] ginds, driveind, drive_freq, drive_ax = \ df.get_boolean_cantfilt(ext_cant_drive=ext_cant_drive, \ ext_cant_ind=ext_cant_ind, \ nharmonics=10, harms=harms) if fil_ind == 0: if plot_first_drive: df.plot_cant_asd(drive_ax) freqs = np.fft.rfftfreq(Nsamp, d=1.0 / df.fsamp) bin_sp = freqs[1] - freqs[0] datfft, diagdatfft, daterr, diagdaterr = \ df.get_datffts_and_errs(ginds, drive_freq, plot=False) harm_freqs = freqs[ginds] for axind, ax in enumerate(data_axes): print(ax, df.conv_facs[ax]) asd = np.abs( np.fft.rfft(df.pos_data[ax]) ) * \ bu.fft_norm(Nsamp, df.fsamp) * df.conv_facs[ax] diag_asd = np.abs( np.fft.rfft(df.diag_pos_data[ax]) ) * \ bu.fft_norm(Nsamp, df.fsamp) if not len(avg_asd[axind]): avg_asd[axind] = asd diag_avg_asd[axind] = diag_asd Nasds[axind] = 1 else: avg_asd[axind] += asd diag_avg_asd[axind] += diag_asd Nasds[axind] += 1 for freqind, freq in enumerate(harm_freqs): phase = np.angle(datfft[axind][freqind]) if sub_cant_phase: cantfft = np.fft.rfft(df.cant_data[drive_ax]) cantphase = np.angle(cantfft[driveind]) phases[axind][freqind][fil_ind] = phase - cantphase else: phases[axind][freqind][fil_ind] = phase sig_re = daterr[axind][freqind] / np.sqrt(2) sig_im = np.copy(sig_re) im = np.imag(datfft[axind][freqind]) re = np.real(datfft[axind][freqind]) phase_var = np.mean((im**2 * sig_re**2 + re**2 * sig_im**2) / \ (re**2 + im**2)**2) phase_errs[axind][freqind][fil_ind] = np.sqrt(phase_var) amps[axind][freqind][fil_ind] = np.abs(datfft[axind][freqind] * \ np.sqrt(bin_sp) * \ bu.fft_norm(Nsamp, df.fsamp)) amp_errs[axind][freqind][fil_ind] = daterr[axind][freqind] * \ np.sqrt(bin_sp) * \ bu.fft_norm(Nsamp, df.fsamp) for axind, ax in enumerate(data_axes): avg_asd[axind] *= (1.0 / Nasds[axind]) diag_avg_asd[axind] *= (1.0 / Nasds[axind]) self.freqs = freqs self.ginds = ginds self.avg_asd = avg_asd self.diag_avg_asd = diag_avg_asd self.amps = amps self.phases = phases self.amp_errs = amp_errs self.phase_errs = phase_errs self.temps = temps self.times = times
def weigh_bead(files, colormap='jet', sort='time', file_inds=(0, 10000)): '''Loops over a list of file names, loads each file, diagonalizes, then plots the amplitude spectral density of any number of data or cantilever/electrode drive signals INPUTS: files, list of files names to extract data data_axes, list of pos_data axes to plot cant_axes, list of cant_data axes to plot elec_axes, list of electrode_data axes to plot diag, boolean specifying whether to diagonalize OUTPUTS: none, plots stuff ''' files = [(os.stat(path), path) for path in files] files = [(stat.st_ctime, path) for stat, path in files] files.sort(key=lambda x: (x[0])) files = [obj[1] for obj in files] #files = files[file_inds[0]:file_inds[1]] #files = [files[0], files[-1]] #files = files[::10] date = files[0].split('/')[2] charge_dat = np.load( open('/calibrations/charges/' + date + '.charge', 'rb')) #q_bead = -1.0 * charge_dat[0] * 1.602e-19 q_bead = 25.0 * 1.602e-19 nfiles = len(files) colors = bu.get_color_map(nfiles, cmap=colormap) avg_fft = [] mass_arr = [] times = [] q_arr = [] print("Processing %i files..." % nfiles) for fil_ind, fil in enumerate(files): date = fil.split('/')[2] charge_dat = np.load( open('/calibrations/charges/' + date + '.charge', 'rb')) q_bead = -1.0 * charge_dat[0] * 1.602e-19 color = colors[fil_ind] bu.progress_bar(fil_ind, nfiles) # Load data df = bu.DataFile() try: df.load(fil) except: continue df.calibrate_stage_position() df.calibrate_phase() #df.diagonalize() if fil_ind == 0: init_phi = np.mean(df.zcal) #plt.hist( df.zcal / df.phase[4] ) #plt.show() #print np.mean(df.zcal / df.phase[4]), np.std(df.zcal / df.phase[4]) freqs = np.fft.rfftfreq(df.nsamp, d=1.0 / df.fsamp) fac = bu.fft_norm(df.nsamp, df.fsamp) * np.sqrt(freqs[1] - freqs[0]) fft = np.fft.rfft(df.zcal) * fac fft2 = np.fft.rfft(df.phase[4]) * fac fftd = np.fft.rfft(df.zcal - np.pi * df.phase[4]) * fac #plt.plot(np.pi * df.phase[4]) #plt.plot((df.zcal-np.mean(df.zcal))*(0.532 / (2*np.pi))) #plt.figure() #plt.loglog(freqs, np.abs(fft)) #plt.loglog(freqs, np.pi * np.abs(fft2)) #plt.loglog(freqs, np.abs(fftd)) #plt.show() drive_fft = np.fft.rfft(df.electrode_data[1]) #plt.figure() #plt.loglog(freqs, np.abs(drive_fft)) #plt.show() inds = np.abs(drive_fft) > 1e4 inds *= (freqs > 2.0) * (freqs < 300.0) inds = np.arange(len(inds))[inds] ninds = inds + 5 drive_amp = np.abs(drive_fft[inds][0] * fac) resp = fft[inds] * (1064.0e-9 / 2.0) * (1.0 / (2.0 * np.pi)) noise = fft[ninds] * (1064.0e-9 / 2.0) * (1.0 / (2.0 * np.pi)) drive_noise = np.abs(np.median(drive_fft[ninds] * fac)) #plt.loglog(freqs[inds], np.abs(resp)) #plt.loglog(freqs[ninds], np.abs(noise)) #plt.show() resp_sc = resp * 1e9 # put resp in units of nm noise_sc = noise * 1e9 def amp_sc(f, d_accel, f0, g): return np.abs(harmonic_osc(f, d_accel, f0, g)) * 1e9 def phase_sc(f, d_accel, f0, g): return np.angle(harmonic_osc(f, d_accel, f0, g)) popt, pcov = opti.curve_fit(amp_sc, freqs[inds], np.abs(resp_sc), \ sigma=np.abs(noise_sc), absolute_sigma=True, p0=[1e-3, 160, 750], maxfev=10000) #plt.figure() #plt.errorbar(freqs[inds], np.abs(resp), np.abs(noise), fmt='.', ms=10, lw=2) #plt.loglog(freqs[inds], np.abs(noise)) #plt.loglog(freqs, np.abs(harmonic_osc(freqs, *popt))) #plt.xlabel('Frequency [Hz]', fontsize=16) #plt.ylabel('Z Amplitude [m]', fontsize=16) #plt.show() if fil_ind == 0: q_bead = 25.0 * 1.602e-19 resps = [resp] N = 1 elif fil_ind < 100: q_bead = 25.0 * 1.602e-19 resps.append(resp) else: mean_resp = np.mean(np.array(resps), axis=0) inner_prod = np.abs(np.vdot(resp, mean_resp)) proj = inner_prod / np.abs(np.vdot(mean_resp, mean_resp)) q_bead = (proj * 25.0) * 1.602e-19 q_arr.append(q_bead / (1.602e-19)) force = (drive_amp / (4.0e-3)) * q_bead mass = np.abs(popt[0]**(-1) * force) * 10**12 # in ng #if mass > 0.2: # continue #print mass #print df.xy_tf_res_freqs if fil_ind == 0: delta_phi = [0.0] else: delta_phi.append(np.mean(df.zcal) - init_phi) mass_arr.append(mass) times.append(df.time) #fit_err = np.sqrt(pcov[0,0] / popt[0]) #charge_err = 0.1 #drive_err = drive_noise / drive_amp #mass_err = np.sqrt( (fit_err)**2 + (charge_err)**2 + (drive_err)**2 ) * mass plt.plot((times - times[0]) * 1e-9, q_arr) plt.grid(axis='y') plt.xlabel('Time') plt.ylabel('Charge [e]') err_bars = 0.002 * np.ones(len(delta_phi)) fig, axarr = plt.subplots(2, 1, sharey=True) #plt.plot((times - times[0])*1e-9, mass_arr) axarr[0].errorbar((times - times[0]) * 1e-9, mass_arr, err_bars, fmt='-o', markersize=5) axarr[0].set_xlabel('Time [s]', fontsize=14) axarr[0].set_ylabel('Measured Mass [ng]', fontsize=14) plt.tight_layout() plt.figure(2) n, bin_edge, patch = plt.hist(mass_arr, bins=20, \ color='w', edgecolor='k', linewidth=2) real_bins = bin_edge[:-1] + 0.5 * (bin_edge[1] - bin_edge[0]) popt, pcov = opti.curve_fit(gauss, real_bins, n, p0=[100, 0.08, 0.01], maxfev=10000) lab = r'$\mu=%0.3f~\rm{ng}$, $\sigma=%0.3f~\rm{ng}$' % (popt[1], popt[2]) test_vals = np.linspace(np.min(mass_arr), np.max(mass_arr), 100) plt.plot(test_vals, gauss(test_vals, *popt), color='r', linewidth=2, \ label=lab) plt.legend() plt.xlabel('Measured Mass [ng]', fontsize=14) plt.ylabel('Arb', fontsize=14) plt.tight_layout() #plt.figure() #plt.scatter(np.array(delta_phi) * (1.0 / (2 * np.pi)) * (1064.0e-9 / 2) * 1e6, mass_arr) axarr[1].errorbar(np.array(delta_phi) * (1.0 / (2 * np.pi)) * (1064.0e-9 / 2) * 1e6, mass_arr, err_bars, fmt='o', markersize=5) axarr[1].set_xlabel('Mean z-position (arb. offset) [um]', fontsize=14) axarr[1].set_ylabel('Measured Mass [ng]', fontsize=14) plt.tight_layout() plt.show()
def proc_mc(i): cdir = os.path.join(dirname, 'mc_{:d}'.format(i)) param_path = os.path.join(cdir, 'params.p') params = pickle.load( open(param_path, 'rb') ) pressure = params['pressure'] drive_amp = params['drive_amp'] drive_amp_noise = params['drive_amp_noise'] drive_phase_noise = params['drive_phase_noise'] discretized_phase = params['discretized_phase'] drive_freq = params['drive_freq'] fsig = params['drive_freq'] p0 = params['p0'] Ibead = params['Ibead'] t_therm = params['t_therm'] beta_rot = params['beta_rot'] try: init_angle = params['init_angle'] except Exception: init_angle = np.pi / 2.0 try: fsamp = params['fsamp'] except Exception: fsamp = 1.0e6 beta_rot = pressure * np.sqrt(m0) / kappa phieq = -1.0 * np.arcsin(2.0 * np.pi * drive_freq * beta_rot / (drive_amp * p0)) # print(phieq) offset_phi = 2.0 * np.pi * drive_freq * t_therm + init_angle # print(pressure, time_constant) def Ephi(t, t_therm=0.0): return 2.0 * np.pi * drive_freq * (t + t_therm) def energy(xi, t, ndim=3): omega = xi[ndim:] omega_frame = 2.0 * np.pi * drive_freq omega[1] -= omega_frame kinetic_term = 0.5 * Ibead * np.sum(omega**2, axis=0) potential_term = -1.0 * p0 * drive_amp * (np.sin(xi[0]) * np.cos(Ephi(t) - xi[1])) return kinetic_term + potential_term datfiles, lengths = bu.find_all_fnames(cdir, ext=ext, verbose=False, \ sort_time=True, use_origin_timestamp=True) nfiles = lengths[0] integrated_energy = [] all_energy = np.array([]) all_t_energy = np.array([]) all_amp = np.array([]) all_t_amp = np.array([]) plot = False for fileind, file in enumerate(datfiles): if fileind >= maxfile: break if plot_first_file: plot = not fileind try: if hdf5: fobj = h5py.File(file, 'r') dat = np.copy(fobj['sim_data']) fobj.close() else: dat = np.load(file) except Exception: print('Bad File!') print(file) continue nsamp = dat.shape[1] ndim = int((dat.shape[0] - 1) / 2) if plot_raw_dat: fig1, axarr1 = plt.subplots(2,1,sharex=True) axarr1[0].set_title('$\\theta$ - Azimuthal Coordinate (Locked)') axarr1[0].plot(dat[0], dat[1], zorder=2) axarr1[0].axhline(np.pi/2, color='k', alpha=0.7, ls='--', zorder=1, \ label='Equatorial plane') axarr1[0].set_ylabel('$\\theta$ [rad]') axarr1[1].plot(dat[0], dat[1+ndim]) axarr1[1].set_xlabel('Time [s]') axarr1[1].set_ylabel('$\\omega_{\\theta}$ [rad/s]') if plot_thermalization_window: xlims = axarr1[0].get_xlim() ylims0 = axarr1[0].get_ylim() ylims1 = axarr1[1].get_ylim() xvec = np.linspace(xlims[0], t_therm, 10) top0 = np.ones_like(xvec) * ylims0[1] bot0 = np.ones_like(xvec) * ylims0[0] top1 = np.ones_like(xvec) * ylims1[1] bot1 = np.ones_like(xvec) * ylims1[0] axarr1[0].fill_between(xvec, bot0, top0, color='k', alpha=0.3, \ label='Thermalization time') axarr1[1].fill_between(xvec, bot1, top1, color='k', alpha=0.3, \ label='Thermalization time') axarr1[0].set_xlim(*xlims) axarr1[0].set_ylim(*ylims0) axarr1[1].set_ylim(*ylims1) axarr1[0].legend(fontsize=10, loc='lower right') fig1.tight_layout() fig2a, axarr2a = plt.subplots(2,1,sharex=True) axarr2a[0].set_title('$\\phi$ - Rotating Coordinate') axarr2a[0].plot(dat[0], dat[2]) axarr2a[0].set_ylabel('$\\phi$ [rad]') axarr2a[1].plot(dat[0], dat[2+ndim]) axarr2a[1].set_xlabel('Time [s]') axarr2a[1].set_ylabel('$\\omega_{\\phi}$ [rad/s]') if plot_thermalization_window: xlims = axarr2a[0].get_xlim() ylims0 = axarr2a[0].get_ylim() ylims1 = axarr2a[1].get_ylim() xvec = np.linspace(xlims[0], t_therm, 10) top0 = np.ones_like(xvec) * ylims0[1] bot0 = np.ones_like(xvec) * ylims0[0] top1 = np.ones_like(xvec) * ylims1[1] bot1 = np.ones_like(xvec) * ylims1[0] axarr2a[0].fill_between(xvec, bot0, top0, color='k', alpha=0.3, \ label='Thermalization time') axarr2a[1].fill_between(xvec, bot1, top1, color='k', alpha=0.3, \ label='Thermalization time') axarr2a[0].set_xlim(*xlims) axarr2a[0].set_ylim(*ylims0) axarr2a[1].set_ylim(*ylims1) axarr2a[0].legend(fontsize=10, loc='lower right') fig2a.tight_layout() fig2b, axarr2b = plt.subplots(2,1,sharex=True) axarr2b[0].set_title("$\\phi'$ - In Rotating Frame") axarr2b[0].plot(dat[0], dat[2] - 2.0*np.pi*drive_freq*dat[0] - offset_phi, zorder=2) axarr2b[0].axhline(phieq, color='k', alpha=0.7, ls='--', zorder=1, \ label='Expected Equilibrium value') axarr2b[0].set_ylabel('$\\phi$ [rad]') axarr2b[1].plot(dat[0], dat[2+ndim]-2.0*np.pi*drive_freq) axarr2b[1].set_xlabel('Time [s]') axarr2b[1].set_ylabel('$\\omega_{\\phi}$ [rad/s]') if plot_thermalization_window: xlims = axarr2b[0].get_xlim() ylims0 = axarr2b[0].get_ylim() ylims1 = axarr2b[1].get_ylim() xvec = np.linspace(xlims[0], t_therm, 10) top0 = np.ones_like(xvec) * ylims0[1] bot0 = np.ones_like(xvec) * ylims0[0] top1 = np.ones_like(xvec) * ylims1[1] bot1 = np.ones_like(xvec) * ylims1[0] axarr2b[0].fill_between(xvec, bot0, top0, color='k', alpha=0.3, \ label='Thermalization time') axarr2b[1].fill_between(xvec, bot1, top1, color='k', alpha=0.3, \ label='Thermalization time') axarr2b[0].set_xlim(*xlims) axarr2b[0].set_ylim(*ylims0) axarr2b[1].set_ylim(*ylims1) axarr2b[0].legend(fontsize=10, loc='lower right') fig2b.tight_layout() if ndim == 3: fig3, axarr3 = plt.subplots(2,1,sharex=True) axarr3[0].set_title('$\\psi$ - Roll About Dipole (Free)') axarr3[0].plot(dat[0], dat[3]) axarr3[0].set_ylabel('$\\psi$ [rad]') axarr3[1].plot(dat[0], dat[3+ndim]) axarr3[1].set_xlabel('Time [s]') axarr3[1].set_ylabel('$\\omega_{\\psi}$ [rad/s]') if plot_thermalization_window: xlims = axarr3[0].get_xlim() ylims0 = axarr3[0].get_ylim() ylims1 = axarr3[1].get_ylim() xvec = np.linspace(xlims[0], t_therm, 10) top0 = np.ones_like(xvec) * ylims0[1] bot0 = np.ones_like(xvec) * ylims0[0] top1 = np.ones_like(xvec) * ylims1[1] bot1 = np.ones_like(xvec) * ylims1[0] axarr3[0].fill_between(xvec, bot0, top0, color='k', alpha=0.3, \ label='Thermalization time') axarr3[1].fill_between(xvec, bot1, top1, color='k', alpha=0.3, \ label='Thermalization time') axarr3[0].set_xlim(*xlims) axarr3[0].set_ylim(*ylims0) axarr3[1].set_ylim(*ylims1) axarr3[0].legend(fontsize=10, loc='lower right') fig3.tight_layout() plt.show() input() tvec = dat[0] theta = dat[1] phi = dat[2] energy_vec = energy(dat[1:], tvec, ndim=ndim) freqs = np.fft.rfftfreq(nsamp, d=1.0/fsamp) energy_psd = np.abs( np.fft.rfft(energy_vec-np.mean(energy_vec)) )**2 * bu.fft_norm(nsamp, fsamp)**2 energy_asd = np.sqrt(energy_psd) # plt.loglog(freqs, energy_asd*freqs) # plt.show() integrated_energy.append(np.sqrt(np.sum(energy_psd) * (freqs[1] - freqs[0]))) crossp = np.sin(phi)**2 carrier_amp, carrier_phase \ = bu.demod(crossp, fsig, fsamp, harmind=2.0, filt=True, \ bandwidth=4000.0, plot=plot, tukey=True, \ tukey_alpha=1e-3) params, cov = bu.fit_damped_osc_amp(carrier_phase, fsamp, plot=plot) libration_amp, libration_phase \ = bu.demod(carrier_phase, params[1], fsamp, harmind=1.0, \ filt=True, filt_band=[100, 2000], plot=plot, \ tukey=True, tukey_alpha=1e-3) amp_ds, tvec_ds = signal.resample(libration_amp, 500, t=tvec, window=None) amp_ds_cut = amp_ds[5:-5] tvec_ds_cut = tvec_ds[5:-5] energy_ds, tvec_ds_2 = signal.resample(energy_vec, 100, t=tvec, window=None) energy_ds_cut = energy_ds[5:-5] tvec_ds_cut_2 = tvec_ds_2[5:-5] all_amp = np.concatenate( (all_amp, amp_ds_cut) ) all_t_amp = np.concatenate( (all_t_amp, tvec_ds_cut) ) all_energy = np.concatenate( (all_energy, energy_ds_cut)) all_t_energy = np.concatenate( (all_t_energy, tvec_ds_cut_2) ) return [pressure, all_t_amp, all_amp, all_t_energy, all_energy, integrated_energy, \ drive_amp, drive_amp_noise, drive_phase_noise, discretized_phase]
def plot_spectra_3d(files, ax_to_plot=0, diag=False, colormap='plasma'): '''Makes a cool 3d plot since waterfalls/cascaded plots end up kind being f****d up. ''' res_freqs = [] powers = [] fig = plt.figure(figsize=(7, 5)) ax = fig.gca(projection='3d') ax.get_proj = lambda: np.dot(Axes3D.get_proj(ax), np.diag([1, 1, 0.6, 1])) # fig.suptitle('XYZ Data', fontsize=18) files = files colors = bu.get_color_map(len(files_to_plot), cmap=colormap) i = 0 #colors = ['C0', 'C1', 'C2'] print("Processing %i files..." % len(files)) for fil_ind, fil in enumerate(files): # Display percent completion bu.progress_bar(fil_ind, len(files)) # Load data df = bu.DataFile() if new_trap: df.load_new(fil) else: df.load(fil) df.calibrate_stage_position() if diag: df.diagonalize(maxfreq=lpf, date=tfdate, plot=tf_plot) try: fac = df.conv_facs[ax_to_plot] # * (1.0 / 0.12e-12) except: fac = 1.0 if fullNFFT: NFFT = len(df.pos_data[ax_to_plot]) else: NFFT = userNFFT if diag: psd, freqs = mlab.psd(df.diag_pos_data[ax_to_plot], Fs=df.fsamp, \ NFFT=NFFT, window=window) else: psd, freqs = mlab.psd(df.pos_data[ax_to_plot], Fs=df.fsamp, \ NFFT=NFFT, window=window) inds = (freqs > ylim[0]) * (freqs < ylim[1]) * ( np.sqrt(psd) > zlim[0] * fac_for_resfreq) freqs = freqs[inds] psd = psd[inds] norm = bu.fft_norm(df.nsamp, df.fsamp) new_freqs = np.fft.rfftfreq(df.nsamp, d=1.0 / df.fsamp) xs = np.zeros_like(freqs) + fil_ind if fil_ind in files_to_plot: popt, pcov = bu.fit_damped_osc_amp(df.pos_data[ax_to_plot], fit_band=[10, 2000], \ fsamp=df.fsamp, plot=False) res_freqs.append(popt[1]) color = colors[i] i += 1 ax.plot(xs, np.log10(freqs), np.log10(np.sqrt(psd)), color=color) zlim_actual = (zlim[0] * fac_for_resfreq, zlim[1]) x = np.arange(len(res_freqs)) interpfunc = interpolate.UnivariateSpline(x, res_freqs, k=2) ax.scatter(x, np.log10(res_freqs), zs=np.log10(zlim_actual[0]), \ zdir='z', s=25, c=colors, alpha=1) ax.plot(x, np.log10(interpfunc(x)), zs=np.log10(zlim_actual[0]), \ zdir='z', lw=2, color='k', zorder=1) # ax.grid() if ylim: ax.set_ylim(np.log10(ylim[0]), np.log10(ylim[1])) if zlim: ax.set_zlim(np.log10(zlim_actual[0]), np.log10(zlim_actual[1])) ax.set_xticks([]) ax.set_yticks(np.log10(yticks)) ax.set_yticklabels(yticks) ax.set_zticks(np.log10(zticks)) ax.set_zticklabels(zticklabels) # ax.ticklabel_format(axis='z', style='sci') ax.set_xlabel('Closer to Focus $\\rightarrow$', labelpad=0) ax.set_ylabel('Frequency [Hz]', labelpad=20) ax.set_zlabel('ASD [Arb/$\\sqrt{\\rm Hz}$]', labelpad=15) # if xlim: # ax.set_xlim(*xlim) # if ylim: # ax.set_ylim(*ylim) # if zlim: # ax.set_zlim(*zlim) # fig.tight_layout() ax.view_init(elev=15, azim=-15) fig.tight_layout() fig.subplots_adjust(top=1.35, left=-0.07, right=0.95, bottom=-0.05) plt.show()
def proc_mc(i): ### Build the path name, assuming the monte-carlo's are ### zero-indexed cdir = os.path.join(dirname, 'mc_{:d}'.format(i)) ### Load the simulation parameters saved alongside the data param_path = os.path.join(cdir, 'params.p') params = pickle.load(open(param_path, 'rb')) ### Define some values that are necessary for analysis pressure = params['pressure'] drive_amp = params['drive_amp'] fsig = params['drive_freq'] drive_freq = params['drive_freq'] p0 = params['p0'] Ibead = params['Ibead'] kappa = params['kappa'] fsamp = params['fsamp'] fsamp_ds = fsamp try: t_therm = params['t_therm'] except: t_therm = 0.0 try: init_angle = params['init_angle'] except Exception: init_angle = np.pi / 2.0 beta_rot = pressure * np.sqrt(m0) / kappa phieq = -1.0 * np.arcsin(2.0 * np.pi * drive_freq * beta_rot / (drive_amp * p0)) time_constant = Ibead / beta_rot gamma_calc = 1.0 / time_constant # print(pressure, time_constant, t_therm) ### Load the data datfiles, lengths = bu.find_all_fnames(cdir, ext=ext, verbose=False, \ sort_time=True, use_origin_timestamp=True) ### Invert the data file array so that the last files are processed first ### since the last files should be the most thermalized datfiles = datfiles[::-1] nfiles = lengths[0] ### Depeding on the requested behavior, instantiate some arrays if concatenate: long_t = [] long_sig = [] long_sig_2 = [] if average: psd_array = [] ### Loop over the datafiles for fileind, file in enumerate(datfiles): # print(file) ### Break the loop if we've acquired enough data if fileind > nspectra_to_combine - 1: break ### Load the data, taking into account the file type if hdf5: fobj = h5py.File(file, 'r') dat = np.copy(fobj['sim_data']) fobj.close() else: dat = np.load(file) ### Determine the length of the data nsamp = dat.shape[1] nsamp_ds = int(nsamp / downsample_fac) ### Load the angles and construct the x-component of the dipole ### based on the integrated angular positions tvec = dat[0] theta = dat[1] phi = dat[2] px = p0 * np.cos(phi) * np.sin(theta) E_phi = 2.0 * np.pi * drive_freq * (tvec + t_therm) + init_angle ones = np.ones(len(tvec)) dipole = np.array([ones, theta, phi]) efield = np.array([ones, ones * (np.pi / 2), E_phi]) lib_angle = bu.angle_between_vectors(dipole, efield, coord='s') ### construct an estimate of the cross-polarized light crossp = np.sin(phi)**2 ### Normalize to avoid numerical errors. Try to get the max to sit at 10 crossp *= (10.0 / np.max(np.abs(crossp))) ### Build up the long signal if concatenation is desired if concatenate: if not len(long_sig): long_t = tvec long_sig = crossp long_phi = phi long_lib = lib_angle else: long_t = np.concatenate((tvec, long_t)) long_sig = np.concatenate((crossp, long_sig)) long_phi = np.concatenate((phi, long_phi)) long_lib = np.concatenate((lib_angle, long_lib)) ### Using a hilbert transform, demodulate the amplitude and phase of ### the carrier signal. Filter things if desired. carrier_amp, carrier_phase \ = bu.demod(crossp, fsig, fsamp, harmind=2.0, filt=True, \ bandwidth=4000.0, plot=plot_demod, ncycle_pad=100, \ tukey=True, tukey_alpha=5e-4) # carrier_phase = phi - E_phi if plot_raw_data: phi_lab = '$\\phi$' theta_lab = '$\\theta - \\pi / 2$' lib_lab = '$\\left| \\measuredangle (\\vec{E}) (\\vec{d}) \\right|$' # plt.plot(carrier_phase) plt.plot(tvec, carrier_phase, alpha=1.0, label=phi_lab) plt.plot(tvec, theta - np.pi / 2, alpha=0.7, label=theta_lab) plt.plot(tvec, lib_angle, alpha=0.7, label=lib_lab) plt.title('In Rotating Frame', fontsize=14) plt.xlabel('Time [s]') plt.ylabel('Angular Coordinate [rad]') plt.legend(loc='lower right', fontsize=12) plt.tight_layout() # plt.show() freqs = np.fft.rfftfreq(nsamp, d=1.0 / fsamp) norm = bu.fft_norm(nsamp, fsamp) plt.figure() plt.loglog(freqs, np.abs(np.fft.rfft(carrier_phase)) * norm, label=phi_lab) plt.loglog(freqs, np.abs(np.fft.rfft(theta - np.pi / 2)) * norm, label=theta_lab) plt.loglog(freqs, np.abs(np.fft.rfft(lib_angle)) * norm, label=lib_lab) plt.xlabel('Frequency [Hz]') plt.ylabel('ASD [rad / $\\sqrt{ \\rm Hz}$]') plt.legend(loc='lower right', fontsize=12) plt.xlim(330, 1730) plt.ylim(5e-7, 3e-2) plt.tight_layout() plt.show() input() ### Downsample the data if desired if downsample: ### Use scipy's fourier-based downsampling carrier_phase_ds, tvec_ds = signal.resample(carrier_phase, nsamp_ds, t=tvec, window=None) carrier_phase = np.copy(carrier_phase_ds) tvec = np.copy(tvec_ds) dt = tvec_ds[1] - tvec_ds[0] fsamp_ds = 1.0 / dt ### Compute the frequencies and ASD values of the downsampled signal freqs = np.fft.rfftfreq(nsamp_ds, d=dt) carrier_phase_asd = bu.fft_norm(nsamp_ds, fsamp_ds) * np.abs( np.fft.rfft(carrier_phase_ds)) else: ### Compute the frequencies and ASD values freqs = np.fft.rfftfreq(nsamp, d=1.0 / fsamp) carrier_phase_asd = bu.fft_norm(nsamp, fsamp) * np.abs( np.fft.rfft(carrier_phase)) ### Add the data from the current file to the array of PSDs if average: if not len(psd_array): psd_array = np.zeros( (nspectra_to_combine, len(carrier_phase_asd)), dtype=np.float64) psd_array[fileind, :] += carrier_phase_asd**2 ### Compute the mean and uncertainty of the PSDs, then compute the ASD if average: avg_psd = np.mean(psd_array, axis=0) fit_asd = np.sqrt(avg_psd) ### Use propogation of uncertainty and the standard error on the mean asd_errs = 0.5 * fit_asd * (np.std(psd_array, axis=0) \ * np.sqrt(1.0 / nspectra_to_combine)) / avg_psd ### If concatenation was desired, first demodulate the amplitude and phase of the ### carrier signal, and then downsample the carrier phase. if concatenate: ### Compute the new values of nsamp nsamp = len(long_sig) if downsample: nsamp_ds = int(nsamp / downsample_fac) else: nsamp_ds = nsamp ### Hilbert transform demodulation carrier_amp_long, carrier_phase_long \ = bu.demod(long_sig, fsig, fsamp, harmind=2.0, filt=False, \ bandwidth=5000.0, plot=False, ncycle_pad=ncycle_pad, \ tukey=True, tukey_alpha=1e-4) carrier_phase_long = long_phi - 2.0 * np.pi * drive_freq * ( long_t + t_therm) - init_angle ### Downsampling carrier_phase_ds, tvec_ds = signal.resample(carrier_phase_long, nsamp_ds, \ t=long_t, window=None) long_lib_ds, tvec_ds_2 = signal.resample(long_lib, nsamp_ds, \ t=long_t, window=None) ### Compute the ASD of the downsampled signals fit_asd = bu.fft_norm(nsamp_ds, fsamp_ds) * np.abs( np.fft.rfft(carrier_phase_ds)) fit_asd_2 = bu.fft_norm(nsamp_ds, fsamp_ds) * np.abs( np.fft.rfft(long_lib_ds)) asd_errs = [] ### Compute the new frequency arrays freqs = np.fft.rfftfreq(nsamp_ds, d=1.0 / fsamp_ds) ### Fit either the averaged ASD or the ASD of the concatenated signal params, cov = bu.fit_damped_osc_amp(fit_asd, fsamp_ds, plot=False, \ sig_asd=True, linearize=True, \ asd_errs=asd_errs, fit_band=[500.0,600.0], \ gamma_guess=gamma_calc, \ weight_lowf=True, weight_lowf_val=0.5, \ weight_lowf_thresh=200) # plt.loglog(freqs, fit_asd_2) # plt.show() ### Fit either the averaged ASD or the ASD of the concatenated signal params_2, cov_2 = bu.fit_damped_osc_amp(fit_asd_2, fsamp_ds, plot=False, \ sig_asd=True, linearize=True, \ asd_errs=[], fit_band=[1050.0,1150.0], \ gamma_guess=gamma_calc, freq_guess=2.0*params[1], \ weight_lowf=True, weight_lowf_val=0.5, \ weight_lowf_thresh=200) outdict = {'pressure': pressure, 'freqs': freqs, \ 'fit_asd': fit_asd, 'params': params, 'cov': cov, \ 'fit_asd_2': fit_asd_2, 'params_2': params_2, 'cov_2': cov_2, \ 'gamma_calc': gamma_calc, 'drive_freq': drive_freq} return outdict
def weigh_bead_efield(files, elec_ind, pow_ind, colormap='plasma', sort='time',\ file_inds=(0,10000), plot=True, print_res=False, pos=False, \ save_mass=False, new_trap=False, correct_phase_shift=False): '''Loops over a list of file names, loads each file, diagonalizes, then plots the amplitude spectral density of any number of data or cantilever/electrode drive signals INPUTS: files, list of files names to extract data data_axes, list of pos_data axes to plot cant_axes, list of cant_data axes to plot elec_axes, list of electrode_data axes to plot diag, boolean specifying whether to diagonalize OUTPUTS: none, plots stuff ''' date = re.search(r"\d{8,}", files[0])[0] suffix = files[0].split('/')[-2] if new_trap: trap_str = 'new_trap' else: trap_str = 'old_trap' charge_file = '/data/{:s}_processed/calibrations/charges/'.format( trap_str) + date save_filename = '/data/{:s}_processed/calibrations/masses/'.format(trap_str) \ + date + '_' + suffix + '.mass' bu.make_all_pardirs(save_filename) if pos: charge_file += '_recharge.charge' else: charge_file += '.charge' try: nq = np.load(charge_file)[0] found_charge = True except: found_charge = False if not found_charge or manual_charge: user_nq = input('No charge file or manual requested. Guess q: ') nq = int(user_nq) if correct_phase_shift: print('Correcting anomalous phase-shift during analysis.') # nq = -16 print('qbead: {:d} e'.format(int(nq))) q_bead = nq * constants.elementary_charge run_index = 0 masses = [] nfiles = len(files) if not print_res: print("Processing %i files..." % nfiles) all_eforce = [] all_power = [] all_param = [] mass_vec = [] p_ac = [] p_dc = [] e_ac = [] e_dc = [] pressure_vec = [] zamp_avg = 0 zphase_avg = 0 zamp_N = 0 zfb_avg = 0 zfb_N = 0 power_avg = 0 power_N = 0 Nbad = 0 powpsd = [] for fil_ind, fil in enumerate(files): # 15-65 # 4 # if fil_ind == 16 or fil_ind == 4: # continue bu.progress_bar(fil_ind, nfiles) # Load data df = bu.DataFile() try: if new_trap: df.load_new(fil) else: df.load(fil, load_other=True) except Exception: traceback.print_exc() continue try: # df.calibrate_stage_position() df.calibrate_phase() except Exception: traceback.print_exc() continue if ('20181129' in fil) and ('high' in fil): pressure_vec.append(1.5) else: try: pressure_vec.append(df.pressures['pirani']) except Exception: pressure_vec.append(0.0) ### Extract electrode data if new_trap: top_elec = df.electrode_data[1] bot_elec = df.electrode_data[2] else: top_elec = mon_fac * df.other_data[elec_ind] bot_elec = mon_fac * df.other_data[elec_ind + 1] fac = 1.0 if np.std(top_elec) < 0.5 * np.std(bot_elec) \ or np.std(bot_elec) < 0.5 * np.std(top_elec): print( 'Adjusting electric field since only one electrode was digitized.' ) fac = 2.0 nsamp = len(top_elec) zeros = np.zeros(nsamp) voltages = [zeros, top_elec, bot_elec, zeros, \ zeros, zeros, zeros, zeros] efield = bu.trap_efield(voltages, new_trap=new_trap) eforce2 = fac * sign * efield[2] * q_bead tarr = np.arange(0, df.nsamp / df.fsamp, 1.0 / df.fsamp) # fig, axarr = plt.subplots(2,1,sharex=True,figsize=(10,8)) # axarr[0].plot(tarr, top_elec, label='Top elec.') # axarr[0].plot(tarr, bot_elec, label='Bottom elec.') # axarr[0].set_ylabel('Apparent Voltages [V]') # axarr[0].legend(fontsize=12, loc='upper right') # axarr[1].plot(tarr, efield[2]) # axarr[1].set_xlabel('Time [s]') # axarr[1].set_ylabel('Apparent Electric Field [V/m]') # fig.tight_layout() # plt.show() # input() freqs = np.fft.rfftfreq(df.nsamp, d=1.0 / df.fsamp) drive_ind = np.argmax(np.abs(np.fft.rfft(eforce2))) drive_freq = freqs[drive_ind] zamp = np.abs( np.fft.rfft(df.zcal) * bu.fft_norm(df.nsamp, df.fsamp) * \ np.sqrt(freqs[1] - freqs[0]) ) zamp *= (1064.0e-9 / 2.0) * (1.0 / (2.9 * np.pi)) zphase = np.angle(np.fft.rfft(df.zcal)) zamp_avg += zamp[drive_ind] zamp_N += 1 #plt.loglog(freqs, zamp) #plt.scatter(freqs[drive_ind], zamp[drive_ind], s=10, color='r') #plt.show() zfb = np.abs(np.fft.rfft(df.pos_fb[2]) * bu.fft_norm(df.nsamp, df.fsamp) * \ np.sqrt(freqs[1] - freqs[0]) ) zfb_avg += zfb[drive_ind] zfb_N += 1 #eforce2 = (top_elec * e_top_func(0.0) + bot_elec * e_bot_func(0.0)) * q_bead if noise: e_dc.append(np.mean(eforce2)) e_ac_val = np.abs(np.fft.rfft(eforce2))[drive_ind] e_ac.append(e_ac_val * bu.fft_norm(df.nsamp, df.fsamp) \ * np.sqrt(freqs[1] - freqs[0]) ) zphase_avg += (zphase[drive_ind] - np.angle(eforce2)[drive_ind]) if np.sum(df.power) == 0.0: current = np.abs(df.other_data[pow_ind]) / trans_gain else: fac = 1e-6 current = fac * df.power / trans_gain power = current / pd_gain power = power / line_filter_trans power = power / bs_fac power_avg += np.mean(power) power_N += 1 if noise: p_dc.append(np.mean(power)) p_ac_val = np.abs(np.fft.rfft(power))[drive_ind] p_ac.append(p_ac_val * bu.fft_norm(df.nsamp, df.fsamp) \ * np.sqrt(freqs[1] - freqs[0]) ) fft1 = np.fft.rfft(power) fft2 = np.fft.rfft(df.pos_fb[2]) if not len(powpsd): powpsd = np.abs(fft1) Npsd = 1 else: powpsd += np.abs(fft1) Npsd += 1 # freqs = np.fft.rfftfreq(df.nsamp, d=1.0/df.fsamp) # plt.loglog(freqs, np.abs(np.fft.rfft(eforce2))) # plt.loglog(freqs, np.abs(np.fft.rfft(power))) # plt.show() # input() # fig, axarr = plt.subplots(2,1,sharex=True,figsize=(10,8)) # axarr[0].plot(tarr, power) # axarr[0].set_ylabel('Measured Power [Arb.]') # axarr[1].plot(tarr, power) # axarr[1].set_xlabel('Time [s]') # axarr[1].set_ylabel('Measured Power [Arb.]') # bot, top = axarr[1].get_ylim() # axarr[1].set_ylim(1.05*bot, 0) # fig.tight_layout() # plt.show() # input() bins, dat, errs = bu.spatial_bin(eforce2, power, nbins=200, width=0.0, #width=0.05, \ dt=1.0/df.fsamp, harms=[1], \ add_mean=True, verbose=False, \ correct_phase_shift=correct_phase_shift, \ grad_sign=0) dat = dat / np.mean(dat) #plt.plot(bins, dat, 'o') #plt.show() popt, pcov = opti.curve_fit(line, bins*1.0e13, dat, \ absolute_sigma=False, maxfev=10000) test_vals = np.linspace(np.min(eforce2 * 1.0e13), np.max(eforce2 * 1.0e13), 100) fit = line(test_vals, *popt) lev_force = -popt[1] / (popt[0] * 1.0e13) mass = lev_force / (9.806) #umass = ulev_force / 9.806 #lmass = llev_force / 9.806 if mass > upper_outlier or mass < lower_outlier: print('Crazy mass: {:0.2f} pg.... ignoring'.format(mass * 1e15)) # fig, axarr = plt.subplots(3,1,sharex=True) # axarr[0].plot(eforce2) # axarr[1].plot(power) # axarr[2].plot(df.pos_data[2]) # ylims = axarr[1].get_ylim() # axarr[1].set_ylim(ylims[0], 0) # plt.show() continue all_param.append(popt) all_eforce.append(bins) all_power.append(dat) mass_vec.append(mass) if noise: print('DC power: ', np.mean(p_dc), np.std(p_dc)) print('AC power: ', np.mean(p_ac), np.std(p_ac)) print('DC field: ', np.mean(e_dc), np.std(e_dc)) print('AC field: ', np.mean(e_ac), np.std(e_ac)) return #plt.plot(mass_vec) mean_popt = np.mean(all_param, axis=0) mean_lev = np.mean(mass_vec) * 9.806 plot_vec = np.linspace(np.min(all_eforce), mean_lev, 100) if plot: fig = plt.figure(dpi=200, figsize=(6, 4)) ax = fig.add_subplot(111) ### Plot force (in pN / g = pg) vs power plt.plot(np.array(all_eforce).flatten()[::5]*1e15*(1.0/9.806), \ np.array(all_power).flatten()[::5], \ 'o', alpha = 0.5) #for params in all_param: # plt.plot(plot_vec, line(plot_vec, params[0]*1e13, params[1]), \ # '--', color='r', lw=1, alpha=0.05) plt.plot(plot_vec*1e12*(1.0/9.806)*1e3, \ line(plot_vec, mean_popt[0]*1e13, mean_popt[1]), \ '--', color='k', lw=2, \ label='Implied mass: %0.1f pg' % (np.mean(mass_vec)*1e15)) left, right = ax.get_xlim() # ax.set_xlim((left, 500)) ax.set_xlim(*xlim) bot, top = ax.get_ylim() ax.set_ylim((0, top)) plt.legend() plt.xlabel('Applied electrostatic force/$g$ (pg)') plt.ylabel('Optical power (arb. units)') plt.grid() plt.tight_layout() if save_example: fig.savefig(example_filename) fig.savefig(example_filename[:-4] + '.pdf') fig.savefig(example_filename[:-4] + '.svg') x_plotvec = np.array(all_eforce).flatten() y_plotvec = np.array(all_power).flatten() yresid = (y_plotvec - line(x_plotvec, mean_popt[0] * 1e13, mean_popt[1])) / y_plotvec plt.figure(dpi=200, figsize=(3, 2)) plt.hist(yresid * 100, bins=30) plt.legend() plt.xlabel('Resid. Power [%]') plt.ylabel('Counts') plt.grid() plt.tight_layout() plt.figure(dpi=200, figsize=(3, 2)) plt.plot(x_plotvec * 1e15, yresid * 100, 'o') plt.legend() plt.xlabel('E-Force [pN]') plt.ylabel('Resid. Pow. [%]') plt.grid() plt.tight_layout() derpfig = plt.figure(dpi=200, figsize=(3, 2)) #derpfig.patch.set_alpha(0.0) plt.hist(np.array(mass_vec) * 1e15, bins=10) plt.xlabel('Mass (pg)') plt.ylabel('Count') plt.grid() #plt.title('Implied Masses, Each from 50s Integration') #plt.xlim(0.125, 0.131) plt.tight_layout() if save_example: derpfig.savefig(example_filename[:-4] + '_hist.png') derpfig.savefig(example_filename[:-4] + '_hist.pdf') derpfig.savefig(example_filename[:-4] + '_hist.svg') plt.show() final_mass = np.mean(mass_vec) final_err_stat = 0.5 * np.std(mass_vec) #/ np.sqrt(len(mass_vec)) final_err_sys = np.sqrt((0.015**2 + 0.01**2) * final_mass**2) final_pressure = np.mean(pressure_vec) if save_mass: save_arr = [final_mass, final_err_stat, final_err_sys] np.save(open(save_filename, 'wb'), save_arr) print('Bad Files: %i / %i' % (Nbad, nfiles)) if print_res: gresid_fac = (2.0 * np.pi * freqs[drive_ind])**2 / 9.8 print(' mass [pg]: {:0.1f}'.format(final_mass * 1e15)) print(' st.err [pg]: {:0.2f}'.format(final_err_stat * 1e15)) print(' sys.err [pg]: {:0.2f}'.format(final_err_sys * 1e15)) print(' qbead [e]: {:d}'.format( int(round(q_bead / constants.elementary_charge)))) print(' P [mbar]: {:0.2e}'.format(final_pressure)) print(' <P> [arb]: {:0.2e}'.format(power_avg / power_N)) print(' zresid [g]: {:0.3e}'.format( (zamp_avg / zamp_N) * gresid_fac)) print(' zphase [rad]: {:0.3e}'.format(zphase_avg / zamp_N)) print(' zfb [arb]: {:0.3e}'.format(zfb_avg / zfb_N)) outarr = [ final_mass*1e15, final_err_stat*1e15, final_err_sys*1e15, \ q_bead/constants.elementary_charge, \ final_pressure, power_avg / power_N, \ (zamp_avg / zamp_N) * gresid_fac, \ zphase_avg / zamp_N, zfb_avg / zfb_N ] return outarr else: scaled_params = np.array(all_param) scaled_params[:, 0] *= 1e13 outdic = {'eforce': all_eforce, 'power': all_power, \ 'linear_fit_params': scaled_params, \ 'ext_masses': mass_vec} return outdic