예제 #1
0
    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))
예제 #2
0
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')
예제 #3
0
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))
예제 #4
0
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