def conclude(): global my_SRS, task save = input("Save plot and data? y/n") if save == 'y': name = input("Enter a filename:") plt.savefig(name) np.savetxt(name + '.csv', (xs, ys, bys), delimiter=",") task.close() #turn off the microwave excitation SRSctl.disableSRS_RFOutput(my_SRS) elif save == 'n': task.close() SRSctl.disableSRS_RFOutput(my_SRS) else: print('Error, try again') return plt.show() #stop the pulse blaster pb_stop() #Close the DAQ once we are done DAQ.closeDAQtask(task) sys.exit()
def closeExp(): #turn off the microwave excitation SRSctl.disableSRS_RFOutput(my_SRS) #stop the pulse blaster pb_stop() #Close the DAQ once we are done DAQ.closeDAQTask(task) return
def runExperiment(): global my_SRS #Plotting setup, xs is the frequencies, ys is the average intensities for the signal, bys is avg intensities for background style.use("fivethirtyeight") fig = plt.figure() ax1 = fig.add_subplot(1, 1, 1) xs = [] ys = [] bys = [] initPB() #initiate RF generator with channel and model type; set amplitude my_SRS = SRSctl.initSRS(27, 'SG386') SRSctl.setSRS_RFAmplitude(my_SRS, .14, units="Vpp") #set test frequency and modulation SRSctl.setSRS_Freq(my_SRS, config['START_FREQUENCY'], 'GHz') SRSctl.setupSRSmodulation(my_SRS, config['sequence_name']) #Get the instruction Array instructionArray = PBctl.programPB(config['sequence_name'], [config['t_AOM']]) print(instructionArray) #Program the PulseBlaster status = pb_start_programming(PULSE_PROGRAM) for i in range(0, len(instructionArray)): PBctl.pb_inst_pbonly(instructionArray[i][0], instructionArray[i][1], instructionArray[i][2], instructionArray[i][3]) pb_stop_programming() #Configure the DAQ global task task = DAQ.configureDAQ(ESR.Nsamples) #turn on the microwave excitation - changed the sequence here, zhao, 02/24/2020 SRSctl.enableSRS_RFOutput(my_SRS) global f #Set f to be the start frequency f = config['START_FREQUENCY'] #start the pulse blaster # you can start pulseblaster at the beginning the experiment and turn it off until everything is done -- Zhao, 6/11/2020 pb_start() #Throw away the first NThrow samples to get the photodiode warmed up for i in range(NThrow): DAQ.readDAQ(task, ESR.Nsamples * 2, 10) #Begin the animation - All of the experiment work is done in the animate function. FuncAnimation runs animate in a loop automatically ani = animation.FuncAnimation( fig, animate, fargs=(xs, ys, bys), interval=200 ) ## not sure if this is the best approach. maybe try to use the "frames" variable for this function -- Zhao, 6/11/2020
def animate(i, xs, ys, bys): #Defines f as a global variable so we can update between function calls global t #If f goes past end frequency, we are done if t > END_LENGTH: closeExp() save = input("Save plot? y/n") if save == 'y': name = input("Enter a filename:") plt.savefig(name) task.close() sys.exit() elif save == 'n': task.close() sys.exit() else: print('Error, try again') return else: #Get the next instruction Array sequenceArgs = [t * ns, t_AOM, t_readoutDelay] instructionArray = PBctl.programPB(sequence_name, sequenceArgs) #Program the PulseBlaster status = pb_start_programming(PULSE_PROGRAM) for i in range(0, len(instructionArray)): PBctl.pb_inst_pbonly(instructionArray[i][0], instructionArray[i][1], instructionArray[i][2], instructionArray[i][3]) pb_stop_programming() #start the pulse blaster pb_start() #Read from the DAQ output = DAQ.readDAQ(task, RABI.Nsamples * 2, 10) #Average all the samples that we got signal = output[0::2] background = output[1::2] sig_average = np.mean(signal) back_average = np.mean(background) #back_average = 1 print('signal', sig_average) print('background', back_average) #stop the pulse blaster pb_stop() #Increment the frequency for the next round t += STEP_LENGTH #Bunch of plotting code xs.append(t) ys.append(sig_average) bys.append(back_average) ax1.clear() ax1.plot(xs, ys, 'r-', xs, bys, 'b-') plt.xticks(rotation=45, ha='right') plt.subplots_adjust(bottom=0.30) plt.title('Photodiode Readout vs MW Pulse Duration') plt.ylabel('Photodiode Voltage (V)') plt.xlabel('MW Pulse Duration (ns)')
def animate(i, xs, ys, bys): global f, my_SRS, task #If f goes past end frequency, we are done if f > config['END_FREQUENCY']: conclude() else: #init RF generator with new frequency SRSctl.setSRS_Freq(my_SRS, f, 'GHz') #Read from the DAQ output = DAQ.readDAQ( task, ESR.Nsamples * 2, 10 ) ### please check this - Does this read out with external trigger? -- Zhao, 6/11/2020 #Average all the samples that we got signal = output[0::2] background = output[1::2] sig_average = np.mean(signal) back_average = np.mean(background) print('signal', sig_average) print('background', back_average) #Increment the frequency for the next round f += STEP_FREQUENCY #Bunch of plotting code xs.append(f) ys.append(sig_average) bys.append(back_average) ax1.clear() ax1.plot(xs, ys, 'r-', xs, bys, 'b-') # Plots xs, ys, bys plt.xticks(rotation=45, ha='right') plt.subplots_adjust(bottom=0.30) plt.title('Photodiode Readout vs Frequency') plt.ylabel('Photodiode Voltage (V)') plt.xlabel('Frequency (GHz)')
def runExperiment(expConfigFile): # This function runs the experiment with input parameters configured by the user in the experiment config file (e.g. ESRconfig, Rabiconfig, etc) and plots and saves the data. try: '''Runs the experiment.''' expCfg = import_module(expConfigFile) expCfg.N_scanPts = len(expCfg.scannedParam) #protection against non-integer user inputs for N_scanPts. validateUserInput(expCfg) #Check if save directory exists, and, if not, creates a "Saved Data" folder in the current directory, where all data will be saved. if not (isdir(expCfg.savePath)): makedirs(expCfg.savePath) print('Warning: Save directory did not exist, creating folder named Saved_Data in the working directory. Data will be saved to this directory.') #Initialise SRS and program PulseBlaster SRS = SRSctl.initSRS(conCfg.GPIBaddr,conCfg.modelName) SRSctl.setSRS_RFAmplitude(SRS,expCfg.microwavePower) SRSctl.setupSRSmodulation(SRS,expCfg.sequence) sequenceArgs = expCfg.updateSequenceArgs() expParamList = expCfg.updateExpParamList() if expCfg.sequence != 'ESRseq': SRSctl.setSRS_Freq(SRS, expCfg.microwaveFrequency) #Program PB seqArgList = [expCfg.scannedParam[-1]] seqArgList.extend(sequenceArgs) instructionArray=PBctl.programPB(expCfg.sequence,seqArgList) else: SRSctl.setSRS_Freq(SRS, expCfg.scannedParam[0]) #Program PB instructionArray=PBctl.programPB(expCfg.sequence,sequenceArgs) SRSctl.enableSRS_RFOutput(SRS) #Configure DAQ DAQclosed = False DAQtask = DAQctl.configureDAQ(expCfg.Nsamples) if expCfg.plotPulseSequence: # Plot sequence plt.figure(0) [t_us,channelPulses,yTicks]=seqCtl.plotSequence(instructionArray,expCfg.PBchannels) for channel in channelPulses: plt.plot(t_us, list(channel)) plt.yticks(yTicks) plt.xlabel('time (us)') plt.ylabel('channel') # If we are plotting a Rabi with pulse length <5*t_min, warn the user in the sequence plot title that the instructions sent to the PulseBlaster microwave channel are for a 5*t_min pulse, but that the short pulse flags are simultaneously pulsed to produce the desired pulse length if expCfg.sequence == 'RabiSeq' and (seqArgList[0]<(5*t_min)): plt.title('Pulse Sequence plot (at last scan point). Close to proceed with experiment...\n(note: we plot the instructions sent to the PulseBlaster (PB) for each channel. For microwave pulses<',5*t_min,'ns, the microwave\nchannel (PB_MW) is instructed to pulse for',5*t_min,'ns, but the short-pulse flags of the PB are pulsed simultaneously (not shown) to\nproduce the desired output pulse length at PB_MW. This can be verified on an oscilloscope.)', fontsize=7) else: plt.title('Pulse Sequence plot (at last scan point)\n close to proceed with experiment...') plt.show() #Initialize data arrays meanSignalCurrentRun = np.zeros(expCfg.N_scanPts) meanBackgroundCurrentRun = np.zeros(expCfg.N_scanPts) contrastCurrentRun = np.zeros(expCfg.N_scanPts) signal = np.zeros([expCfg.N_scanPts,expCfg.Navg]) background = np.zeros([expCfg.N_scanPts,expCfg.Navg]) contrast = np.zeros([expCfg.N_scanPts,expCfg.Navg]) #Run experiment for i_run in range (0,expCfg.Navg): print('Run ',i_run+1,' of ',expCfg.Navg) if expCfg.randomize: if i_run>0: shuffle(expCfg.scannedParam) for i_scanPoint in range (0, expCfg.N_scanPts): #setup next scan iteration (e.g. for ESR experiment, change microwave frequency; for T2 experiment, reprogram pulseblaster with new delay) if expCfg.sequence == 'ESRseq': SRSctl.setSRS_Freq(SRS, expCfg.scannedParam[i_scanPoint]) else: seqArgList[0] = expCfg.scannedParam[i_scanPoint] instructionArray= PBctl.programPB(expCfg.sequence,seqArgList) print('Scan point ',i_scanPoint+1,' of ',expCfg.N_scanPts) #read DAQ cts=DAQctl.readDAQ(DAQtask,2*expCfg.Nsamples,expCfg.DAQtimeout) #Extract signal and background counts sig = cts[0::2] bkgnd = cts[1::2] #Take average of counts meanSignalCurrentRun[i_scanPoint] = np.mean(sig) meanBackgroundCurrentRun[i_scanPoint] = np.mean(bkgnd) if expCfg.shotByShotNormalization: contrastCurrentRun[i_scanPoint] = np.mean(calculateContrast(expCfg.contrastMode,sig,bkgnd)) else: contrastCurrentRun[i_scanPoint] = calculateContrast(expCfg.contrastMode,meanSignalCurrentRun[i_scanPoint],meanBackgroundCurrentRun[i_scanPoint]) if i_run==0: if expCfg.livePlotUpdate: xValues=expCfg.scannedParam[0:i_scanPoint+1] plt.plot([x/expCfg.plotXaxisUnits for x in xValues],contrastCurrentRun[0:i_scanPoint+1], 'b-') plt.ylabel('Contrast') plt.xlabel(expCfg.xAxisLabel) plt.draw() plt.pause(0.0001) # Save data at intervals dictated by saveSpacing_inPulseLengthPts and at final delay point if (i_scanPoint%expCfg.saveSpacing_inScanPts == 0) or (i_scanPoint==expCfg.N_scanPts-1): data = np.zeros([i_scanPoint+1,3]) data[:,0] = expCfg.scannedParam[0:i_scanPoint+1] data[:,1] = meanSignalCurrentRun[0:i_scanPoint+1] data[:,2] = meanBackgroundCurrentRun[0:i_scanPoint+1] dataFile = open(expCfg.dataFileName, 'w') for line in data: dataFile.write("%.0f\t%.8f\t%.8f\n" % tuple(line)) paramFile = open(expCfg.paramFileName, 'w') expParamList[1] = i_scanPoint+1 paramFile.write(expCfg.formattingSaveString % tuple(expParamList)) dataFile.close() paramFile.close() #Sort current run counts in order of increasing delay dataCurrentRun = np.transpose(np.array([expCfg.scannedParam,meanSignalCurrentRun,meanBackgroundCurrentRun,contrastCurrentRun])) sortingIndices = np.argsort(dataCurrentRun[:,0]) dataCurrentRun = dataCurrentRun[sortingIndices] #Fill in current run data: sortedScanParam = dataCurrentRun[:,0] signal[:,i_run] = dataCurrentRun[:,1] background[:,i_run] = dataCurrentRun[:,2] contrast[:,i_run] = dataCurrentRun[:,3] #Update quantities for plotting updatedSignal = np.mean(signal[:,0:i_run+1],1) updatedBackground = np.mean(background[:,0:i_run+1],1) updatedContrast = np.mean(contrast[:,0:i_run+1],1) #Update plot: if expCfg.livePlotUpdate: plt.clf() plt.plot([x/expCfg.plotXaxisUnits for x in sortedScanParam] ,updatedContrast,'b-') plt.ylabel('Contrast') plt.xlabel(expCfg.xAxisLabel) plt.draw() plt.pause(0.001) # Save data at intervals dictated by saveSpacing_inAverages and after final scan if (i_run%expCfg.saveSpacing_inAverages == 0) or (i_run==expCfg.Navg-1): data = np.zeros([expCfg.N_scanPts,3]) data[:,0] = sortedScanParam data[:,1] = updatedSignal data[:,2] = updatedBackground dataFile = open(expCfg.dataFileName, 'w') for item in data: dataFile.write("%.0f\t%.8f\t%.8f\n" % tuple(item)) paramFile = open(expCfg.paramFileName, 'w') expParamList[3] = i_run+1 paramFile.write(expCfg.formattingSaveString % tuple(expParamList)) dataFile.close() paramFile.close() #Turn off SRS output SRSctl.disableSRS_RFOutput(SRS) #Close DAQ task: DAQctl.closeDAQTask(DAQtask) DAQclosed=True plt.show() except KeyboardInterrupt: print('User keyboard interrupt. Quitting...') sys.exit() finally: if 'SRS' in vars(): #Turn off SRS output SRSctl.disableSRS_RFOutput(SRS) if ('DAQtask' in vars()) and (not DAQclosed): #Close DAQ task: DAQctl.closeDAQTask(DAQtask) DAQclosed=True
# Configure the core clock pb_core_clock(500.0) #Get the first instruction Array instructionArray = PBctl.programPB(sequence_name, sequenceArgs) print(instructionArray) #Program the PulseBlaster status = pb_start_programming(PULSE_PROGRAM) for i in range(0, len(instructionArray)): PBctl.pb_inst_pbonly(instructionArray[i][0], instructionArray[i][1], instructionArray[i][2], instructionArray[i][3]) pb_stop_programming() #Configure the DAQ task = DAQ.configureDAQ(RABI.Nsamples) #turn on the microwave excitation - changed the sequence here, zhao, 02/24/2020 #SRSctl.enableSRS_RFOutput(my_SRS) UNCOMMENT THIS! #Set t to be the start time and initalize the average variable to 0 t = START_LENGTH average = 0 #Throw away the first NThrow samples to get the photodiode warmed up for i in range(NThrow): pb_start() DAQ.readDAQ(task, RABI.Nsamples * 2, 10) pb_stop()
print('Error: startDelay is too short. Please set startDelay>',5*t_min,'ns.') sys.exit() if startDelay%(t_min): startDelay = t_min*round(startDelay/t_min) print('Warning: startDelay is not a multiple of',t_min,'ns. Rounding...\nstartDelay now set to:',startDelay,'ns.') t_readoutDelay = np.linspace(startDelay,endDelay, N_scanPts, endpoint=True) stepSize = t_readoutDelay[1]-t_readoutDelay[0] if (stepSize%t_min): roundedStepSize = t_min*round(stepSize/t_min) endDelay = (N_scanPts-1)*roundedStepSize + startDelay print('Warning: requested time step is ',stepSize,'ns, which is not an integer multiple of ',t_min,'ns. Rounding step size to the nearest multiple of ',t_min,':\nStep size is now',roundedStepSize,'.\nstartDelay=',startDelay,' and \nendDelay=',endDelay) t_readoutDelay = np.linspace(startDelay,endDelay, N_scanPts, endpoint=True) #Configure DAQ DAQclosed = False DAQtask = DAQctl.configureDAQ(Nsamples) fluorescence = np.zeros(N_scanPts) if plotPulseSequence: instructionArray= PBctl.programPB('optimReadoutSeq', [t_readoutDelay[-1],t_AOM]) [t_us,channelPulses,yTicks]=seqCtl.plotSequence(instructionArray,PBchannels) plt.figure(0) for channel in channelPulses: plt.plot(t_us, list(channel)) plt.yticks(yTicks) plt.xlabel('time (us)') plt.ylabel('channel') plt.title('Pulse Sequence plot (at last scan point)') #Run readout delay scan: for i in range (0, N_scanPts):