def run(self): # ----------------- lines below commented out on 2021-02-07 to avoid writing to disk # create files samples = self.parameters[0] delay = self.parameters[-2:] # enable_scan_pts = self.mw['PTS'][2] scan_carrier_freq = (self.scan['type'] == 'Carrier frequency') # do_enable_iq = self.awgparams['enable IQ'] # npulses = self.pulseparams['num pulses'] # if scan_carrier_freq: # # we can scan frequency either using PTS or using the SB freq # #self.scan['type'] = 'frequency' # self.scan['type'] = 'no scan' # this tells the SeqList class to simply put one sequence as the PTS will # # scan the frequency # now create teh sequences self.sequences = SequenceList(sequence=self.seq, delay=delay, pulseparams=self.pulseparams, scanparams=self.scan, timeres=self.timeRes) # write the files to the AWG520/sequencefiles directory self.awgfile = AWGFile(ftype='SEQ', timeres=self.timeRes) self.awgfile.write_sequence(sequences=self.sequences, seqfilename="scan.seq", repeat=samples) # ----------------------------------------------------------------------------------------------- # now upload the files # self.done.emit() # uncomment these lines when you are ready to connect to the AWG -------------------------------------------- try: if self.awgparams['awg device'] == 'awg520': # print("Upload OK!") self.awgcomm = AWG520() # transfer all files to AWG t = time.process_time() for filename in os.listdir(self.dirPath): self.awgcomm.sendfile(self.awgPath / filename, self.dirPath / filename) transfer_time = time.process_time() - t time.sleep(1) self.logger.info( 'time elapsed for all files to be transferred is:{0:.3f} seconds' .format(transfer_time)) self.awgcomm.cleanup() self.done.emit() else: raise ValueError('AWG520 is the only AWG supported') except ValueError as err: self.logger.error('Value Error {0}'.format(err)) except RuntimeError as err: self.logger.error('Run time error {0}'.format(err))
def write_trigger_sequence(dwell_time, numsteps, tres): # the strings needed to make the sequence tstartstr = str(int(100 / tres)) tstopstr = str(int(0.5 * dwell_time / (tres * _ns))) greenstopstr = str(int(dwell_time / (tres * _ns))) seqfilename = dirPath / 'odmr_trigger.seq' # filename for sequences # create a sequence where measure is on for 1/2 dwell time, and then turns off, but green remains on throughout # the adwin will measure till it receives the next positive edge and then latch seq = [['Measure', tstartstr, tstopstr], ['Green', tstartstr, greenstopstr]] # params = {'type':'number','start': 1, 'stepsize': 1, 'steps': steps-1} s = Sequence(seq, timeres=tres) s.create_sequence() # this part here is not necessary in the actual program, I am just using it to check that the above sequence will do # what I want it to do # tt = np.linspace(0, s.maxend, len(s.c1markerdata)) # plt.plot(tt, s.wavedata[0, :], 'r-', tt, s.wavedata[1, :], 'b-', tt, s.c1markerdata, 'g--', tt, s.c2markerdata, # 'y-') # plt.show() # this is the section where I actually write the waveform to a file, to repeat it for numsteps, # and then wait to receive a software trigger from the Pc before doing it again awgfile = AWGFile(s, timeres=tres, dirpath=dirPath) awgfile.write_waveform('trig', 1, s.wavedata[0, :], s.c1markerdata) awgfile.write_waveform('trig', 2, s.wavedata[1, :], s.c2markerdata) wfmlen = len(s.c2markerdata) # first create an empty waveform in channel 1 and 2 but turn on the green laser # so that measurements can start after a trigger is received. arm_sequence = Sequence([['Green', '0', str(wfmlen)]], timeres=tres) arm_sequence.create_sequence() awgfile.write_waveform('arm', 1, arm_sequence.wavedata[0, :], arm_sequence.c1markerdata) awgfile.write_waveform('arm', 2, arm_sequence.wavedata[1, :], arm_sequence.c2markerdata) # now we create a sequence file that will be loaded to the AWG try: with open(seqfilename, 'wb') as sfile: sfile.write(awgfile.seqheader) temp_str = 'LINES ' + str( 2) + '\r\n' # there are only 2 lines in this file sfile.write(temp_str.encode()) # have to convert to binary format temp_str = '"arm_1.wfm","arm_2.wfm",0,1,0,0\r\n' # the arm sequence will be loaded and will keep # repeating and wait for the software trigger from the PC sfile.write(temp_str.encode()) # the trig wfm is repeated numsteps # 2020-01-04: after lot of experimenting with Arduino code it appears that interrupt of the arduino is # unable to accept fast triggers, i.e. it does not work if the triggers have 1 ms spacing, but works if # they have 10 ms spacing. So we have decided not to mess with it, and instead simply to use the old # arduino code where all timing comes from the arduino itself but require that it takes one trigger from # the AWG to start a scan linestr = '"trig_1.wfm","trig_2.wfm",' + str(1) + ',1,0,0\r\n' sfile.write(linestr.encode()) sfile.write(b'JUMP_MODE SOFTWARE\r\n' ) # tells awg to wait for a software trigger except (IOError, ValueError) as error: # replace these with logger writes, but for now just send any errors to stderr sys.stderr.write(sys.exc_info()) sys.stderr.write(error.message + '\n')
class UploadThread(QtCore.QThread): """this is the upload thread to send all the files to teh AWG. it has following variables: 1. seq = the sequence list of strings 2. scan = scan parameters dictionary 3. params = misc. params list such as count time etc 4. awgparams = awg params dict 5. pulseparams = pulseparams dict 6. mwparams = mw params dict 7. timeRes = awg clock rate in ns This class emits two Pyqtsignals 1. done - to let the app know when the upload is finished 2. rbinfo - to communicate the random scan info such as final sequence list, final states list, and the scan lengths to the app """ done = QtCore.pyqtSignal() rbinfo = QtCore.pyqtSignal( list, list, list ) # rbinfo emits a signal of (final states, final sequences, scan lengths) def __init__(self, parent=None, dirPath=dirPath, awgPath=awgPath): #super().__init__(self) QtCore.QThread.__init__(self, parent) # self.timeRes = timeRes self.logger = logging.getLogger('threadlogger.uploadThread') self.dirPath = dirPath self.awgPath = awgPath # 2020-07-21: due to random crashes with QT when upload button is pressed , we are now writing the files in # the main app, and only using this thread to upload the files to the AWG. # -------------------------- uncomment this block if you want to go back ---------------------------- # if scan == None: # self.scan = dict([('type', 'amplitude'), ('start', '0'), ('stepsize', '50'), ('steps', '20')]) # else: # self.scan = scan # if seq == None: # self.seq = [['Green','0','1000'],['Measure','10','400']] # minimal measurement sequence # else: # self.seq = seq # if mwparams == None: # self.mw = {'PTS': [True, '2.870', False, '2.840', '0.001', '100', '2.940'], \ # 'SRS': [False, '2.870', False, '2.840','0.001', '100', '2.940']} # else: # self.mw = mwparams # if awgparams == None: # self.awgparams = {'awg device': 'awg520', 'time resolution': 1, \ # 'pulseshape': 'Square', 'enable IQ': False, 'iterate pulses': False, 'num pulses': 1} # if pulseparams == None: # self.pulseparams = {'amplitude': 0, 'pulsewidth': 20, 'SB freq': 0.00, 'IQ scale factor': 1.0, # 'phase': 0.0, 'skew phase': 0.0} # if params == None: # self.parameters = [50000, 300, 1000, 10, 50, 820, 10] # should make into dictionary with keys 'sample', 'count time', # 'reset time', 'avg', 'threshold', 'AOM delay', 'microwave delay' def run(self): # ----------------- lines below commented out on 2021-02-07 to avoid writing to disk # create files samples = self.parameters[0] delay = self.parameters[-2:] # enable_scan_pts = self.mw['PTS'][2] scan_carrier_freq = (self.scan['type'] == 'Carrier frequency') scan_random = ( self.scan['type'] == 'random scan' ) # if the scan is a random scan, it should update the RB fields in the app. This is a boolean generated for this purpose. # do_enable_iq = self.awgparams['enable IQ'] # npulses = self.pulseparams['num pulses'] # if scan_carrier_freq: # # we can scan frequency either using PTS or using the SB freq # #self.scan['type'] = 'frequency' # self.scan['type'] = 'no scan' # this tells the SeqList class to simply put one sequence as the PTS will # # scan the frequency # now create the sequences self.sequences = SequenceList(sequence=self.seq, delay=delay, pulseparams=self.pulseparams, scanparams=self.scan, timeres=self.timeRes, compseqnum=self.CompSeqNum, paulirandnum=self.PauliRandNum) # write the files to the AWG520/sequencefiles directory self.awgfile = AWGFile(ftype='SEQ', timeres=self.timeRes) self.awgfile.write_sequence(sequences=self.sequences, seqfilename="scan.seq", repeat=samples) if scan_random: final_states = list(list(zip(*self.sequences.rbinfo_list))[0]) final_seqs = list(list(zip(*self.sequences.rbinfo_list))[1]) x_arr = self.sequences.rbscanlengths self.rbinfo.emit(final_states, final_seqs, x_arr) # ----------------------------------------------------------------------------------------------- # now upload the files # self.done.emit() # uncomment these lines when you are ready to connect to the AWG -------------------------------------------- try: if self.awgparams['awg device'] == 'awg520': # print("Upload OK!") self.awgcomm = AWG520() # transfer all files to AWG t = time.process_time() for filename in os.listdir(self.dirPath): self.awgcomm.sendfile(self.awgPath / filename, self.dirPath / filename) transfer_time = time.process_time() - t time.sleep(1) self.logger.info( 'time elapsed for all files to be transferred is:{0:.3f} seconds' .format(transfer_time)) self.awgcomm.cleanup() self.done.emit() else: raise ValueError('AWG520 is the only AWG supported') except ValueError as err: self.logger.error('Value Error {0}'.format(err)) except RuntimeError as err: self.logger.error('Run time error {0}'.format(err))
def write_list_sequence(tres=1): repeat=15 # the strings needed to make the sequence seq = [['S2','1000','1010+t'],['Green','1050+t','4050+t'],['Measure','1080+t','1180+t']] delay = [820,10] pulseparams = {'amplitude': 0, 'pulsewidth': 20, 'SB freq': 0.00, 'IQ scale factor': 1.0,'phase': 0.0, 'skew phase': 0.0, 'num pulses': 1} scan = dict([('type', 'time'), ('start', 10), ('stepsize', 10), ('steps', 9)]) seqlist = SequenceList(sequence=seq, delay=delay, pulseparams=pulseparams, scanparams=scan,timeres=tres) # this part here is not necessary in the actual program, I am just using it to check that the above sequence will do # what I want it to do # tt = np.linspace(0, s.maxend, len(s.c1markerdata)) # plt.plot(tt, s.wavedata[0, :], 'r-', tt, s.wavedata[1, :], 'b-', tt, s.c1markerdata, 'g--', tt, s.c2markerdata, # 'y-') # plt.show() # this is the section where I actually write the waveform to a file, awgfile = AWGFile(ftype='SEQ',timeres=tres,dirpath=dirPath) # awgfile.write_sequence(sequences=seqlist,seqfilename="scan.seq", repeat=10000) # instead of using the awgfile write_sequence function above, will do it explicitly here to test try: if not seqlist: self.logger.error("Invalid sequence or no sequence object given") raise ValueError("Invalid sequencelist or no sequencelist object given") else: seqlist.create_sequence_list() slist = seqlist.sequencelist # list of sequences wfmlen = len(slist[0].c1markerdata) # get the length of the waveform in the first sequence scanlen = len(slist) # first create an empty waveform in channel 1 and 2 but turn on the green laser # so that measurements can start after a trigger is received. arm_sequence = Sequence([['Green', '0', str(wfmlen)]], timeres=tres) arm_sequence.create_sequence() awgfile.write_waveform(arm_sequence, 'arm', 1) awgfile.write_waveform(arm_sequence, 'arm', 2) # create scan.seq file try: fname = Path(dirPath/ 'scan.seq') with open(fname, 'wb') as sfile: sfile.write(awgfile.seqheader) temp_str = 'LINES ' + str(scanlen + 1) + '\r\n' sfile.write(temp_str.encode()) # have to convert to binary format temp_str = '"arm_1.wfm","arm_2.wfm",0,1,0,0\r\n' # the arm sequence will be loaded and will wait # for trigger sfile.write(temp_str.encode()) for i in list(range(scanlen)): # now we take each sequence in the slist arry and write it to a wfm file with the name given by # "i+1_1.wfm and i+1_2.wfm awgfile.write_waveform(slist[i], '' + str(i + 1), 1) awgfile.write_waveform(slist[i], '' + str(i + 1), 2) # the scan.seq file is now updated to execute those 2 wfms for repeat number of times and wait # for a trigger to move to the next point. linestr = '"' + str(i + 1) + '_1.wfm"' + ',' + '"' + str(i + 1) + '_2.wfm"' + ',' + str(repeat) + ',1,0,0\r\n' sfile.write(linestr.encode()) sfile.write( b'JUMP_MODE SOFTWARE\r\n') # tells the AWG that jump trigger is controlled by the computer. except (IOError, ValueError) as error: # sys.stderr.write(sys.exc_info()) # sys.stderr.write(error.message+'\n') sys.stderr.write(sys.exc_info()) sys.stderr.write("Error occurred in either file I/O or data conversion:{0}".format(error)) raise except: sys.stderr.write(sys.exc_info()) raise