Exemplo n.º 1
0
class DarkCount(Spyrelet):
    requires = {'srs': SRS900}
    qutag = None
    currents = []
    darkcountspercurrent = []

    @Task()
    def qutagInit(self):
        print('qutag successfully initialized')

    @qutagInit.initializer
    def initialize(self):
        from lantz.drivers.qutools import QuTAG
        self.qutag = QuTAG()
        devType = self.qutag.getDeviceType()
        if (devType == self.qutag.DEVTYPE_QUTAG):
            print("found quTAG!")
        else:
            print("no suitable device found - demo mode activated")
        print("Device timebase:" + str(self.qutag.getTimebase()))
        return

    @qutagInit.finalizer
    def finalize(self):
        return

    @Task()
    def getDarkCounts(self):
        self.srs.SIM928_voltage[5] = 0
        #self.srs.SIM928_voltage[6]=0
        #self.srs.module_reset[6]
        self.srs.module_reset[5]
        self.srs.wait_time(100000)
        qutagparams = self.qutag_params.widget.get()
        start = qutagparams['Start Channel']
        stop_1 = qutagparams['Stop Channel 1']
        #stop_2 = qutagparams['Stop Channel 2']
        ##True = rising edge, False = falling edge. Final value is threshold voltage
        self.qutag.setSignalConditioning(start, self.qutag.SIGNALCOND_MISC,
                                         True, 0.1)
        #self.qutag.setSignalConditioning(stop_1,self.qutag.SIGNALCOND_MISC,True,0.1)
        self.qutag.enableChannels((start, stop_1))
        biasCurrentParams = self.bias_current.widget.get()
        qutagParams = self.qutag_params.widget.get()
        resistance = 10000
        startCurrent = biasCurrentParams['Start Current'].to('A').magnitude
        stepSize = biasCurrentParams['Step Size'].to('A').magnitude
        stopCurrent = biasCurrentParams['Stop Current'].to('A').magnitude
        print('start current is' + str(startCurrent))
        print('step size is' + str(stepSize))
        print('stop current is' + str(stopCurrent))
        expParams = self.exp_params.widget.get()
        currentCurrent = startCurrent
        self.srs.SIM928_voltage[5] = currentCurrent * resistance
        self.srs.SIM928_on[5]
        self.srs.wait_time(100000)
        points = ((stopCurrent - startCurrent) / stepSize) + (1 + stepSize)
        print(points)
        BC = []
        DCR_1 = []
        for i in range(int(points)):
            lost = self.qutag.getLastTimestamps(True)
            time.sleep(expParams['Exposure Time'].magnitude)
            timestamps = self.qutag.getLastTimestamps(True)
            tstamp = timestamps[0]  # array of timestamps
            tchannel = timestamps[1]  # array of channels
            values = timestamps[2]  # number of recorded timestamps
            print(tchannel)
            darkcounts = values
            BC.append(currentCurrent)
            self.currents.append(currentCurrent * resistance)
            DCR_1.append(darkcounts / expParams['Exposure Time'].magnitude)
            self.darkcountspercurrent.append(
                darkcounts / expParams['Exposure Time'].magnitude)
            currentCurrent += stepSize
            self.srs.SIM928_voltage[5] = currentCurrent * resistance
            values = {
                'bc': self.currents,
                'dc': self.darkcountspercurrent,
            }
            self.getDarkCounts.acquire(values)
        self.srs.SIM928_voltage[5] = 0
        self.srs.module_reset[5]
        datadir = 'D:\Data\\09.09.2019\\'
        print(BC)
        print(DCR_1)
        np.savetxt(datadir + expParams['File Name'] + '.csv', (BC, DCR_1),
                   delimiter=',')
        print('Data stored under File Name: ' + expParams['File Name'])
        return

    @Element(name='Bias Current')
    def bias_current(self):
        params = [
            #    ('arbname', {'type': str, 'default': 'arbitrary_name'}),,
            ('Start Current', {
                'type': float,
                'default': 2,
                'units': 'uA'
            }),
            ('Step Size', {
                'type': float,
                'default': 0.2,
                'units': 'uA'
            }),
            ('Stop Current', {
                'type': float,
                'default': 10,
                'units': 'uA'
            })
        ]
        w = ParamWidget(params)
        return w

    @Element(name='Experimental Parameters')
    def exp_params(self):
        params = [
            #    ('arbname', {'type': str, 'default': 'arbitrary_name'}),,
            ('Exposure Time', {
                'type': int,
                'default': 10,
                'units': 's'
            }),
            ('Points per Bias Current', {
                'type': int,
                'default': 1.0
            }),
            ('File Name', {
                'type': str
            })
        ]
        w = ParamWidget(params)
        return w

    @Element(name='QuTAG Parameters')
    def qutag_params(self):
        params = [
            #    ('arbname', {'type': str, 'default': 'arbitrary_name'}),,
            ('Start Channel', {
                'type': int,
                'default': 0
            }),
            ('Stop Channel 1', {
                'type': int,
                'default': 1
            }),
            ('Stop Channel 2', {
                'type': int,
                'default': 2
            }),
            ('Total Hist Width Multiplier', {
                'type': int,
                'default': 5
            }),
            ('Bin Count', {
                'type': int,
                'default': 1000
            })
        ]
        w = ParamWidget(params)
        return w

    @getDarkCounts.initializer
    def initialize(self):
        print('The identification of this instrument is : ' + self.srs.idn)
        print(self.srs.self_test)
        return

    @getDarkCounts.finalizer
    def finalize(self):
        return

    @Element(name='Histogram')
    def darkcountsplot(self):
        p = LinePlotWidget()
        p.plot('Dark Counts vs. Bias Current')
        return p

    @darkcountsplot.on(getDarkCounts.acquired)
    def darkcountsplot_update(self, ev):
        w = ev.widget
        bc = np.array(self.currents)
        cs = np.array(self.darkcountspercurrent)
        w.set('Dark Counts vs. Bias Current', xs=bc, ys=cs)
        return
Exemplo n.º 2
0
class PLThinFilm(Spyrelet):
    requires = {'wm': Bristol_771}
    qutag = None
    laser = NetworkConnection('1.1.1.1')

    def configureQutag(self):
        qutagparams = self.qutag_params.widget.get()
        start = qutagparams['Start Channel']
        stop = qutagparams['Stop Channel']
        ##True = rising edge, False = falling edge. Final value is threshold voltage
        self.qutag.setSignalConditioning(start, self.qutag.SIGNALCOND_MISC,
                                         True, 1)
        self.qutag.setSignalConditioning(stop, self.qutag.SIGNALCOND_MISC,
                                         True, 0.1)
        self.qutag.enableChannels((start, stop))

    def homelaser(self, start):
        current = self.wm.measure_wavelength()
        with Client(self.laser) as client:
            while current < start - 0.001 or current > start + 0.001:
                setting = client.get('laser1:ctl:wavelength-set', float)
                offset = current - start
                client.set('laser1:ctl:wavelength-set', setting - offset)
                time.sleep(3)
                current = self.wm.measure_wavelength()
                print(current, start)

    def createHistogram(self, stoparray, timebase, bincount, period, index,
                        wls):
        hist = [0] * bincount
        for stoptime in stoparray:
            binNumber = int(stoptime * timebase * bincount / (period))
            if binNumber >= bincount:
                continue
            else:
                hist[binNumber] += 1
        out_name = "D:\\Data\\9.04.2019\\1T"
        np.savez(os.path.join(out_name, str(index + 59)), hist, wls)
        #np.savez(os.path.join(out_name,str(index+40)),hist,wls)
        print('Data stored under File Name: ' +
              self.exp_parameters.widget.get()['File Name'] + str(index))

    @Task()
    def startpulse(self, timestep=100e-9):

        ##Qutag Part
        self.configureQutag()
        expparams = self.exp_parameters.widget.get()
        wlparams = self.wl_parameters.widget.get()
        self.homelaser(wlparams['start'])
        print('Laser Homed!')
        qutagparams = self.qutag_params.widget.get()
        lost = self.qutag.getLastTimestamps(True)  # clear Timestamp buffer
        stoptimestamp = 0
        synctimestamp = 0
        bincount = qutagparams['Bin Count']
        timebase = self.qutag.getTimebase()
        start = qutagparams['Start Channel']
        stop = qutagparams['Stop Channel']
        for i in range(expparams['# of points']):
            ##Wavemeter measurements
            stoparray = []
            startTime = time.time()
            wls = []
            lost = self.qutag.getLastTimestamps(True)
            while time.time(
            ) - startTime < expparams['Measurement Time'].magnitude:
                lost = self.qutag.getLastTimestamps(True)
                time.sleep(5 * 0.1)
                timestamps = self.qutag.getLastTimestamps(True)

                tstamp = timestamps[0]  # array of timestamps
                tchannel = timestamps[1]  # array of channels
                values = timestamps[2]  # number of recorded timestamps
                for k in range(values):
                    # output all stop events together with the latest start event
                    if tchannel[k] == start:
                        synctimestamp = tstamp[k]
                    else:
                        stoptimestamp = tstamp[k]
                        stoparray.append(stoptimestamp)
                wls.append(str(self.wm.measure_wavelength()))
            self.createHistogram(stoparray, timebase, bincount, 0.1, i, wls)
            print(i)
            with Client(self.laser) as client:
                setting = client.get('laser1:ctl:wavelength-set', float)
                client.set('laser1:ctl:wavelength-set', setting - 0.008)
                time.sleep(1)

    @Task()
    def qutagInit(self):
        print('qutag successfully initialized')

    @Element(name='Wavelength parameters')
    def wl_parameters(self):
        params = [
            #    ('arbname', {'type': str, 'default': 'arbitrary_name'}),,
            ('start', {
                'type': float,
                'default': 1535.71
            }),
            ('stop', {
                'type': float,
                'default': 1535.50
            })
        ]
        w = ParamWidget(params)
        return w

    @Element(name='Experiment Parameters')
    def exp_parameters(self):
        params = [
            #    ('arbname', {'type': str, 'default': 'arbitrary_name'}),,
            ('# of points', {
                'type': int,
                'default': 50
            }),
            ('Measurement Time', {
                'type': int,
                'default': 100,
                'units': 's'
            }),
            ('File Name', {
                'type': str
            })
        ]
        w = ParamWidget(params)
        return w

    @Element(name='QuTAG Parameters')
    def qutag_params(self):
        params = [
            #    ('arbname', {'type': str, 'default': 'arbitrary_name'}),,
            ('Start Channel', {
                'type': int,
                'default': 0
            }),
            ('Stop Channel', {
                'type': int,
                'default': 1
            }),
            ('Bin Count', {
                'type': int,
                'default': 1000
            })
        ]
        w = ParamWidget(params)
        return w

    @startpulse.initializer
    def initialize(self):
        self.wm.start_data()

    @startpulse.finalizer
    def finalize(self):
        self.wm.stop_data()
        print('Lifetime measurements complete.')
        return

    @qutagInit.initializer
    def initialize(self):
        from lantz.drivers.qutools import QuTAG
        self.qutag = QuTAG()
        devType = self.qutag.getDeviceType()
        if (devType == self.qutag.DEVTYPE_QUTAG):
            print("found quTAG!")
        else:
            print("no suitable device found - demo mode activated")
        print("Device timebase:" + str(self.qutag.getTimebase()))
        return

    @qutagInit.finalizer
    def finalize(self):
        return
Exemplo n.º 3
0
class Lifetime(Spyrelet):
	requires = {
		'wm': Bristol_771
	}
	qutag = None
	conn1 = NetworkConnection('1.1.1.2')
	#conn1 = conn1 = SerialConnection('COM1') 
	dlc = Client(conn1)

	def configureQutag(self):
		qutagparams = self.qutag_params.widget.get()
		start = qutagparams['Start Channel']
		stop = qutagparams['Stop Channel']
		##True = rising edge, False = falling edge. Final value is threshold voltage
		self.qutag.setSignalConditioning(start,self.qutag.SIGNALCOND_MISC,True,1)
		self.qutag.setSignalConditioning(stop,self.qutag.SIGNALCOND_MISC,True,0.1)
		self.qutag.enableChannels((start,stop))

	def createHistogram(self,stoparray, timebase, bincount, period, index, wls):
		hist = [0]*bincount
		for stoptime in stoparray:
			binNumber = int(stoptime*timebase*bincount/(period))
			if binNumber >= bincount:
				continue
			else:
				hist[binNumber]+=1
		out_name = "D:\\Data\\10.9.2019\\film"
		np.savez(os.path.join(out_name,str(index)),hist,wls)
		#np.savez(os.path.join(out_name,str(index+40)),hist,wls)
		print('Data stored under File Name: ' + self.exp_parameters.widget.get()['File Name'] + str(index))


	@Task()
	def startpulse(self, timestep=1e-9):
		with Client(self.conn1) as dlc:
			print(dlc.get("laser1:ctl:wavelength"))

		time.sleep(1000)

		self.configureQutag()

		qutagparams = self.qutag_params.widget.get()
		lost = self.qutag.getLastTimestamps(True) # clear Timestamp buffer
		stoptimestamp = 0
		synctimestamp = 0
		bincount = qutagparams['Bin Count']
		timebase = self.qutag.getTimebase()
		start = qutagparams['Start Channel']
		stop = qutagparams['Stop Channel']

		expparams = self.exp_parameters.widget.get()
		for i in range(expparams['# of points']):
			##Wavemeter measurements
			stoparray = []
			startTime = time.time()
			wls=[]
			lost = self.qutag.getLastTimestamps(True)
			while time.time()-startTime < expparams['Measurement Time'].magnitude:
				lost = self.qutag.getLastTimestamps(True)
				time.sleep(30*100e-3)
				timestamps = self.qutag.getLastTimestamps(True)

				tstamp = timestamps[0] # array of timestamps
				tchannel = timestamps[1] # array of channels
				values = timestamps[2] # number of recorded timestamps
				for k in range(values):
					# output all stop events together with the latest start event
					if tchannel[k] == start:
						synctimestamp = tstamp[k]
					else:
						stoptimestamp = tstamp[k]
						stoparray.append(stoptimestamp)
				wls.append(str(self.wm.measure_wavelength()))
			self.createHistogram(stoparray, timebase, bincount, 100e-3,i, wls)
			print(i)
			#self.fungen.voltage[2] = self.fungen.voltage[2].magnitude + 2*dcparams['DC step size'].magnitude
			#time.sleep(100000)


	@Task()
	def qutagInit(self):
		print('qutag successfully initialized')
		

	@Element(name='Pulse parameters')
	def pulse_parameters(self):
		params = [
	#    ('arbname', {'type': str, 'default': 'arbitrary_name'}),,
		('pulse height', {'type': float, 'default': 3, 'units':'V'}),
		('pulse width', {'type': float, 'default': 500e-9, 'units':'s'}),
		('period', {'type': float, 'default': 0.1, 'units':'s'}),
		]
		w = ParamWidget(params)
		return w

	@Element(name='DC parameters')
	def DC_parameters(self):
		params = [
	#    ('arbname', {'type': str, 'default': 'arbitrary_name'}),,
		('DC height', {'type': float, 'default': 0, 'units':'V'}),
		('DC step size', {'type': float, 'default': 0.1, 'units':'V'}),
		]
		w = ParamWidget(params)
		return w

	@Element(name='Experiment Parameters')
	def exp_parameters(self):
		params = [
	#    ('arbname', {'type': str, 'default': 'arbitrary_name'}),,
		('# of points', {'type': int, 'default': 10}),
		('Measurement Time', {'type': int, 'default': 10, 'units':'s'}),
		('File Name', {'type': str})
		]
		w = ParamWidget(params)
		return w

	@Element(name='QuTAG Parameters')
	def qutag_params(self):
		params = [
	#    ('arbname', {'type': str, 'default': 'arbitrary_name'}),,
		('Start Channel', {'type': int, 'default': 0}),
		('Stop Channel', {'type': int, 'default': 1}),
		('Bin Count', {'type': int, 'default': 1000})
		]
		w = ParamWidget(params)
		return w

	@startpulse.initializer
	def initialize(self):
		self.wm.start_data()

	@startpulse.finalizer
	def finalize(self):
		self.wm.stop_data()
		print('Lifetime measurements complete.')
		return

	@qutagInit.initializer
	def initialize(self):
		from lantz.drivers.qutools import QuTAG
		self.qutag = QuTAG()
		devType = self.qutag.getDeviceType()
		if (devType == self.qutag.DEVTYPE_QUTAG):
			print("found quTAG!")
		else:
			print("no suitable device found - demo mode activated")
		print("Device timebase:" + str(self.qutag.getTimebase()))
		return

	@qutagInit.finalizer
	def finalize(self):
		return
Exemplo n.º 4
0
class Lifetime(Spyrelet):
    requires = {'fungen': Keysight_33622A, 'wm': Bristol_771}
    qutag = None

    def configureQutag(self):
        qutagparams = self.qutag_params.widget.get()
        start = qutagparams['Start Channel']
        stop = qutagparams['Stop Channel']
        ##True = rising edge, False = falling edge. Final value is threshold voltage
        self.qutag.setSignalConditioning(start, self.qutag.SIGNALCOND_MISC,
                                         True, 1)
        self.qutag.setSignalConditioning(stop, self.qutag.SIGNALCOND_MISC,
                                         True, 0.1)
        self.qutag.enableChannels((start, stop))

    def createHistogram(self, stoparray, timebase, bincount, period, index,
                        wls):
        hist = [0] * bincount
        for stoptime in stoparray:
            binNumber = int(stoptime * timebase * bincount / (period))
            if binNumber >= bincount:
                continue
            else:
                hist[binNumber] += 1
        out_name = "D:\\Data\\9.1.2019\\T1"
        np.savez(os.path.join(out_name, str(index)), hist, wls)
        #np.savez(os.path.join(out_name,str(index+40)),hist,wls)
        print('Data stored under File Name: ' +
              self.exp_parameters.widget.get()['File Name'] + str(index))

    @Task()
    def startpulse(self, timestep=1e-9):
        self.fungen.output[1] = 'OFF'
        self.fungen.output[2] = 'OFF'
        self.fungen.clear_mem(1)
        self.fungen.clear_mem(2)
        params = self.pulse_parameters.widget.get()
        pulse = Arbseq_Class('pulse', timestep)
        pulse.delays = [0]
        pulse.heights = [1]
        pulse.widths = [params['pulse width'].magnitude]
        pulse.totaltime = params['pulse width'].magnitude
        pulse.nrepeats = 0
        pulse.repeatstring = 'once'
        pulse.markerstring = 'highAtStartGoLow'
        pulse.markerloc = 0
        pulse.create_sequence()

        dc = Arbseq_Class('dc', timestep)
        dc.delays = [0]
        dc.heights = [0]
        dc.widths = [params['pulse width'].magnitude]
        dc.totaltime = params['pulse width'].magnitude
        dc.repeatstring = 'repeat'
        dc.markerstring = 'lowAtStart'
        dc.markerloc = 0
        period = params['period'].magnitude
        width = params['pulse width'].magnitude
        repeats = period / width - 1
        dc.nrepeats = repeats
        dc.create_sequence()

        dc2 = Arbseq_Class('dc', timestep)
        dc2.delays = [0]
        dc2.heights = [1]
        dc2.widths = [params['pulse width'].magnitude]
        dc2.totaltime = params['pulse width'].magnitude
        dc2.repeatstring = 'repeat'
        dc2.markerstring = 'lowAtStart'
        dc2.markerloc = 0
        period = params['period'].magnitude
        print(period)
        width = params['pulse width'].magnitude
        repeats = period / width
        dc2.nrepeats = repeats
        dc2.create_sequence()

        self.fungen.send_arb(pulse, 1)
        self.fungen.send_arb(dc, 1)
        self.fungen.send_arb(dc2, 2)

        seq1 = [pulse, dc]

        self.fungen.create_arbseq('pulsetest', seq1, 1)
        self.fungen.wait()
        self.fungen.voltage[1] = params['pulse height']
        self.fungen.output[1] = 'ON'

        dcparams = self.DC_parameters.widget.get()

        self.fungen.create_arbseq('dc2', [dc2], 2)
        self.fungen.wait()
        self.fungen.voltage[2] = dcparams['DC height']
        self.fungen.output[2] = 'ON'

        self.configureQutag()

        qutagparams = self.qutag_params.widget.get()
        lost = self.qutag.getLastTimestamps(True)  # clear Timestamp buffer
        stoptimestamp = 0
        synctimestamp = 0
        bincount = qutagparams['Bin Count']
        timebase = self.qutag.getTimebase()
        start = qutagparams['Start Channel']
        stop = qutagparams['Stop Channel']

        expparams = self.exp_parameters.widget.get()
        for i in range(expparams['# of points']):
            ##Wavemeter measurements
            stoparray = []
            startTime = time.time()
            wls = []
            lost = self.qutag.getLastTimestamps(True)
            while time.time(
            ) - startTime < expparams['Measurement Time'].magnitude:
                lost = self.qutag.getLastTimestamps(True)
                time.sleep(30 * period)
                timestamps = self.qutag.getLastTimestamps(True)

                tstamp = timestamps[0]  # array of timestamps
                tchannel = timestamps[1]  # array of channels
                values = timestamps[2]  # number of recorded timestamps
                for k in range(values):
                    # output all stop events together with the latest start event
                    if tchannel[k] == start:
                        synctimestamp = tstamp[k]
                    else:
                        stoptimestamp = tstamp[k]
                        stoparray.append(stoptimestamp)
                wls.append(str(self.wm.measure_wavelength()))
            self.createHistogram(stoparray, timebase, bincount, period, i, wls)
            print(i)
            self.fungen.voltage[2] = self.fungen.voltage[
                2].magnitude + 2 * dcparams['DC step size'].magnitude
            time.sleep(100000)

        self.fungen.output[1] = 'OFF'

    @Task()
    def qutagInit(self):
        print('qutag successfully initialized')

    @Element(name='Pulse parameters')
    def pulse_parameters(self):
        params = [
            #    ('arbname', {'type': str, 'default': 'arbitrary_name'}),,
            ('pulse height', {
                'type': float,
                'default': 3,
                'units': 'V'
            }),
            ('pulse width', {
                'type': float,
                'default': 500e-9,
                'units': 's'
            }),
            ('period', {
                'type': float,
                'default': 0.1,
                'units': 's'
            }),
        ]
        w = ParamWidget(params)
        return w

    @Element(name='DC parameters')
    def DC_parameters(self):
        params = [
            #    ('arbname', {'type': str, 'default': 'arbitrary_name'}),,
            ('DC height', {
                'type': float,
                'default': 0,
                'units': 'V'
            }),
            ('DC step size', {
                'type': float,
                'default': 0.1,
                'units': 'V'
            }),
        ]
        w = ParamWidget(params)
        return w

    @Element(name='Experiment Parameters')
    def exp_parameters(self):
        params = [
            #    ('arbname', {'type': str, 'default': 'arbitrary_name'}),,
            ('# of points', {
                'type': int,
                'default': 10
            }),
            ('Measurement Time', {
                'type': int,
                'default': 10,
                'units': 's'
            }),
            ('File Name', {
                'type': str
            })
        ]
        w = ParamWidget(params)
        return w

    @Element(name='QuTAG Parameters')
    def qutag_params(self):
        params = [
            #    ('arbname', {'type': str, 'default': 'arbitrary_name'}),,
            ('Start Channel', {
                'type': int,
                'default': 0
            }),
            ('Stop Channel', {
                'type': int,
                'default': 1
            }),
            ('Bin Count', {
                'type': int,
                'default': 1000
            })
        ]
        w = ParamWidget(params)
        return w

    @startpulse.initializer
    def initialize(self):
        self.wm.start_data()
        self.fungen.output[1] = 'OFF'
        self.fungen.output[2] = 'OFF'
        self.fungen.clear_mem(1)
        self.fungen.clear_mem(2)
        self.fungen.wait()

    @startpulse.finalizer
    def finalize(self):
        self.wm.stop_data()
        self.fungen.output[1] = 'OFF'
        self.fungen.output[2] = 'OFF'
        print('Lifetime measurements complete.')
        return

    @qutagInit.initializer
    def initialize(self):
        from lantz.drivers.qutools import QuTAG
        self.qutag = QuTAG()
        devType = self.qutag.getDeviceType()
        if (devType == self.qutag.DEVTYPE_QUTAG):
            print("found quTAG!")
        else:
            print("no suitable device found - demo mode activated")
        print("Device timebase:" + str(self.qutag.getTimebase()))
        return

    @qutagInit.finalizer
    def finalize(self):
        return
Exemplo n.º 5
0
class TwoPulsePhotonEcho(Spyrelet):
    requires = {
        'fungen': Keysight_33622A
        # 'srs': SRS900
    }
    qutag = None
    xs = np.array([])
    ys = np.array([])
    hist = []

    def configureQutag(self):
        qutagparams = self.qutag_params.widget.get()
        start = qutagparams['Start Channel']
        stop = qutagparams['Stop Channel']
        ##True = rising edge, False = falling edge. Final value is threshold voltage
        self.qutag.setSignalConditioning(start, self.qutag.SIGNALCOND_MISC,
                                         True, 1)
        self.qutag.setSignalConditioning(stop, self.qutag.SIGNALCOND_MISC,
                                         True, 0.1)
        self.qutag.enableChannels((start, stop))

    def createHistogram(self, stoparray, timebase, bincount, totalWidth, tau):
        lowBound = 1.9 * tau
        highBound = 2.1 * tau
        hist = [0] * bincount
        for stoptime in stoparray:
            binNumber = int(stoptime * timebase * bincount / (totalWidth))
            if binNumber >= bincount:
                continue
                print('error')
            else:
                hist[binNumber] += 1
        out_name = "D:\\Data\\7.31.2019\\250mTSNSPD"
        x = []
        for i in range(bincount):
            x.append(i * totalWidth / bincount)
        np.savez(os.path.join(out_name, str(int(round(tau * 1e6, 0)))), hist,
                 x)
        print('Data stored under File Name: ' + str(tau))

    def createPlottingHist(self, stoparray, timebase, bincount, totalWidth):
        for stoptime in stoparray:
            binNumber = int(stoptime * timebase * bincount / (totalWidth))
            if binNumber >= bincount:
                continue
            else:
                self.hist[binNumber] += 1

    def initHist(self, bincount):
        self.hist = [0] * bincount

    @Task()
    def startpulse(self, timestep=1e-9):
        params = self.pulse_parameters.widget.get()
        tau = params['start tau']
        period = params['period'].magnitude
        repeat_unit = params['repeat unit'].magnitude
        pulse_width = params['pulse width'].magnitude
        buffer_time = params['buffer time'].magnitude
        shutter_offset = params['shutter offset'].magnitude
        wholeRange = params['measuring range'].magnitude

        self.configureQutag()
        for i in range(
                int((params['stop tau'] - params['start tau']) /
                    params['step tau']) + 1):
            xs = np.array([])
            ys = np.array([])
            hist = []
            self.dataset.clear()
            self.fungen.output[1] = 'OFF'
            self.fungen.output[2] = 'OFF'
            self.fungen.clear_mem(1)
            self.fungen.clear_mem(2)
            self.fungen.wait()
            # self.srs.module_reset[5]
            # self.srs.SIM928_voltage[5]=params['srs bias'].magnitude+0.000000001*i
            # self.srs.SIM928_on[5]

            ## build pulse sequence for AWG channel 1
            chn1buffer = Arbseq_Class('chn1buffer', timestep)
            chn1buffer.delays = [0]
            chn1buffer.heights = [0]
            chn1buffer.widths = [repeat_unit]
            chn1buffer.totaltime = repeat_unit
            chn1buffer.nrepeats = buffer_time / repeat_unit
            chn1buffer.repeatstring = 'repeat'
            chn1buffer.markerstring = 'lowAtStart'
            chn1buffer.markerloc = 0
            chn1bufferwidth = repeat_unit * chn1buffer.nrepeats
            chn1buffer.create_sequence()

            chn1pulse = Arbseq_Class('chn1pulse', timestep)
            chn1pulse.delays = [0]
            chn1pulse.heights = [1]
            chn1pulse.widths = [pulse_width]
            chn1pulse.totaltime = pulse_width
            chn1pulse.nrepeats = 0
            chn1pulse.repeatstring = 'once'
            chn1pulse.markerstring = 'highAtStartGoLow'
            chn1pulse.markerloc = 0
            chn1pulsewidth = pulse_width
            chn1pulse.create_sequence()

            chn1dc = Arbseq_Class('chn1dc', timestep)
            chn1dc.delays = [0]
            chn1dc.heights = [0]
            chn1dc.widths = [repeat_unit]
            chn1dc.totaltime = repeat_unit
            chn1dc.repeatstring = 'repeat'
            chn1dc.markerstring = 'lowAtStart'
            chn1dc.markerloc = 0
            chn1dcrepeats = int(
                (tau.magnitude - 1.5 * pulse_width) / repeat_unit)
            chn1dc.nrepeats = chn1dcrepeats
            chn1dcwidth = repeat_unit * chn1dcrepeats
            print(tau.magnitude, pulse_width, chn1dcrepeats)
            chn1dc.create_sequence()

            chn1pulse2 = Arbseq_Class('chn1pulse2', timestep)
            chn1pulse2.delays = [0]
            chn1pulse2.heights = [1]
            chn1pulse2.widths = [pulse_width * 2]
            chn1pulse2.totaltime = pulse_width * 2
            chn1pulse2width = pulse_width * 2
            chn1pulse2.nrepeats = 0
            chn1pulse2.repeatstring = 'once'
            chn1pulse2.markerstring = 'lowAtStart'
            chn1pulse2.markerloc = 0
            chn1pulse2.create_sequence()

            chn1pulse3 = Arbseq_Class('chn1pulse3', timestep)
            chn1pulse3.delays = [0]
            chn1pulse3.heights = [0]
            chn1pulse3.widths = [repeat_unit]
            chn1pulse3.totaltime = repeat_unit
            chn1pulse3width = shutter_offset
            chn1pulse3.nrepeats = shutter_offset / repeat_unit
            chn1pulse3.repeatstring = 'repeat'
            chn1pulse3.markerstring = 'lowAtStart'
            chn1pulse3.markerloc = 0
            chn1pulse3.create_sequence()

            chn1dc2 = Arbseq_Class('chn1dc2', timestep)
            chn1dc2.delays = [0]
            chn1dc2.heights = [0]
            chn1dc2.widths = [repeat_unit]
            chn1dc2.totaltime = repeat_unit
            chn1dc2.repeatstring = 'repeat'
            chn1dc2.markerstring = 'lowAtStart'
            chn1dc2repeats = int(
                (period - chn1bufferwidth - chn1pulsewidth - chn1dcwidth -
                 chn1pulse2width - chn1pulse3width) / repeat_unit)
            chn1dc2.nrepeats = chn1dc2repeats
            chn1dc2.markerloc = 0
            #print((chn1dc2repeats*params['repeat unit'].magnitude) + tau.magnitude + params['pulse width'].magnitude)
            print(params['repeat unit'].magnitude * chn1dc2.nrepeats)
            chn1dc2.create_sequence()

            ## build pulse sequence for AWG channel 2
            chn2buffer = Arbseq_Class('chn2buffer', timestep)
            chn2buffer.delays = [0]
            chn2buffer.heights = [1]
            chn2buffer.widths = [repeat_unit]
            chn2buffer.totaltime = repeat_unit
            chn2buffer.nrepeats = buffer_time / repeat_unit
            chn2buffer.repeatstring = 'repeat'
            chn2buffer.markerstring = 'lowAtStart'
            chn2buffer.markerloc = 0
            chn2bufferwidth = repeat_unit * chn2buffer.nrepeats
            chn2buffer.create_sequence()

            chn2pulse1 = Arbseq_Class('chn2pulse1', timestep)
            chn2pulse1.delays = [0]
            chn2pulse1.heights = [1]
            chn2pulse1.widths = [pulse_width]
            chn2pulse1.totaltime = pulse_width
            chn2pulse1width = pulse_width
            chn2pulse1.nrepeats = 0
            chn2pulse1.repeatstring = 'once'
            chn2pulse1.markerstring = 'highAtStartGoLow'
            chn2pulse1.markerloc = 0
            chn2pulse1.create_sequence()

            chn2dc1 = Arbseq_Class('chn2dc1', timestep)
            chn2dc1.delays = [0]
            chn2dc1.heights = [1]
            chn2dc1.widths = [repeat_unit]
            chn2dc1.totaltime = repeat_unit
            chn2dc1.repeatstring = 'repeat'
            chn2dc1.markerstring = 'lowAtStart'
            chn2dc1.markerloc = 0
            chn2dc1repeats = int(
                (tau.magnitude - 1.5 * pulse_width) / repeat_unit)
            chn2dc1.nrepeats = chn2dc1repeats
            chn2dc1width = repeat_unit * chn2dc1repeats
            chn2dc1.create_sequence()

            chn2pulse2 = Arbseq_Class('chn2pulse2', timestep)
            chn2pulse2.delays = [0]
            chn2pulse2.heights = [1]
            chn2pulse2.widths = [pulse_width * 2]
            chn2pulse2.totaltime = pulse_width * 2
            chn2pulse2width = pulse_width * 2
            chn2pulse2.nrepeats = 0
            chn2pulse2.repeatstring = 'once'
            chn2pulse2.markerstring = 'lowAtStart'
            chn2pulse2.markerloc = 0
            chn2pulse2.create_sequence()

            chn2pulse3 = Arbseq_Class('chn2pulse3', timestep)
            chn2pulse3.delays = [0]
            chn2pulse3.heights = [1]
            chn2pulse3.widths = [repeat_unit]
            chn2pulse3.totaltime = repeat_unit
            chn2pulse3width = shutter_offset
            chn2pulse3.nrepeats = shutter_offset / repeat_unit
            chn2pulse3.repeatstring = 'repeat'
            chn2pulse3.markerstring = 'lowAtStart'
            chn2pulse3.markerloc = 0
            chn2pulse3.create_sequence()

            chn2dc2 = Arbseq_Class('chn2dc2', timestep)
            chn2dc2.delays = [0]
            chn2dc2.heights = [-1]
            chn2dc2.widths = [repeat_unit]
            chn2dc2.totaltime = repeat_unit
            chn2dc2.repeatstring = 'repeat'
            chn2dc2.markerstring = 'lowAtStart'
            chn2dc2repeats = int(
                (period - chn2bufferwidth - chn2pulse1width - chn2dc1width -
                 chn2pulse2width - chn2pulse3width) / repeat_unit)
            chn2dc2.nrepeats = chn2dc2repeats
            chn2dc2.markerloc = 0
            print(repeat_unit * chn2dc2.nrepeats)
            chn2dc2.create_sequence()

            self.fungen.send_arb(chn1buffer, 1)
            self.fungen.send_arb(chn1pulse, 1)
            self.fungen.send_arb(chn1dc, 1)
            self.fungen.send_arb(chn1pulse2, 1)
            self.fungen.send_arb(chn1pulse3, 1)
            self.fungen.send_arb(chn1dc2, 1)
            self.fungen.send_arb(chn2buffer, 2)
            self.fungen.send_arb(chn2pulse1, 2)
            self.fungen.send_arb(chn2dc1, 2)
            self.fungen.send_arb(chn2pulse2, 2)
            self.fungen.send_arb(chn2pulse3, 2)
            self.fungen.send_arb(chn2dc2, 2)

            seq = [
                chn1buffer, chn1pulse, chn1dc, chn1pulse2, chn1pulse3, chn1dc2
            ]
            seq2 = [
                chn2buffer, chn2pulse1, chn2dc1, chn2pulse2, chn2pulse3,
                chn2dc2
            ]

            self.fungen.create_arbseq('twoPulse', seq, 1)
            self.fungen.create_arbseq('shutter', seq2, 2)
            self.fungen.wait()
            self.fungen.voltage[
                1] = params['pulse height'].magnitude + 0.000000000001 * i
            self.fungen.voltage[2] = 7.1 + 0.0000000000001 * i

            print(self.fungen.voltage[1], self.fungen.voltage[2])
            self.fungen.output[2] = 'ON'
            self.fungen.trigger_delay(1, shutter_offset)
            self.fungen.sync()
            time.sleep(1)
            self.fungen.output[1] = 'ON'
            #self.fungen.output[2] = 'OFF'

            ##Qutag Part
            self.configureQutag()
            qutagparams = self.qutag_params.widget.get()
            lost = self.qutag.getLastTimestamps(True)  # clear Timestamp buffer
            stoptimestamp = 0
            synctimestamp = 0
            bincount = qutagparams['Bin Count']
            timebase = self.qutag.getTimebase()
            start = qutagparams['Start Channel']
            stop = qutagparams['Stop Channel']
            stoparray = []
            tempStopArray = []
            histCounter = 0
            quenchCounter = 0
            self.initHist(bincount)
            for j in range(int(
                    self.exp_parameters.widget.get()['# of Passes'])):
                lost = self.qutag.getLastTimestamps(True)
                time.sleep(period)
                timestamps = self.qutag.getLastTimestamps(True)

                tstamp = timestamps[0]  # array of timestamps
                tchannel = timestamps[1]  # array of channels
                values = timestamps[2]  # number of recorded timestamps
                # print(values)
                for k in range(values):
                    # output all stop events together with the latest start event
                    # if tchannel[k] == start:
                    # 	synctimestamp = tstamp[k]
                    if tchannel[k] == stop:
                        #stoptimestamp = tstamp[k]
                        # if tstamp[k]*1e-6>2*tau.magnitude-1 and tstamp[k]*1e-6<2*tau.magnitude+2:
                        stoparray.append(tstamp[k])
                        #tempStopArray.append(stoptimestamp)
                # histCounter+=1
                # if histCounter%20==0:
                # 	self.createPlottingHist(tempStopArray, timebase, bincount,qutagparams['Total Hist Width Multiplier']*tau.magnitude)
                # 	self.xs = np.asarray(range(len(self.hist)))
                # 	self.ys=np.asarray(self.hist)
                # 	values = {
                # 	't': np.asarray(range(len(self.hist))),
                # 	'y': np.asarray(self.hist),
                # 	}
                # 	self.startpulse.acquire(values)
                # 	tempStopArray = []
                # TODO: quench protection
                # if self.srs.SIM928_voltage[???] >= qunech threshold and quenchCounter<=10:
                # 	self.srs.SIM928_off[6]
                # 	time.sleep(period*10)
                # 	self.srs.SIM928_on[6]
                # 	quenchCounter+=1
                # elif quenchCounter>10:
                # 	print('quenched more than 10 times')
                # 	break
                # else:
                # 	continue

            self.createHistogram(stoparray, timebase, bincount, wholeRange,
                                 tau.magnitude)

            tau += params['step tau']
            #self.fungen.output[1] = 'OFF'

    @Task()
    def qutagInit(self):
        print('qutag successfully initialized')

    @Element(name='QuTAG Parameters')
    def qutag_params(self):
        params = [
            #    ('arbname', {'type': str, 'default': 'arbitrary_name'}),,
            ('Start Channel', {
                'type': int,
                'default': 0
            }),
            ('Stop Channel', {
                'type': int,
                'default': 1
            }),
            ('Total Hist Width Multiplier', {
                'type': int,
                'default': 5
            }),
            ('Bin Count', {
                'type': int,
                'default': 1000
            })
        ]
        w = ParamWidget(params)
        return w

    @Element(name='Experiment Parameters')
    def exp_parameters(self):
        params = [
            #    ('arbname', {'type': str, 'default': 'arbitrary_name'}),,
            ('# of Passes', {
                'type': int,
                'default': 100
            }),
            # ('File Name', {'type': str})
        ]
        w = ParamWidget(params)
        return w

    @Element(name='Histogram')
    def averaged(self):
        p = LinePlotWidget()
        p.plot('Channel 1')
        return p

    @averaged.on(startpulse.acquired)
    def averaged_update(self, ev):
        w = ev.widget
        xs = self.xs
        ys = self.ys
        w.set('Channel 1', xs=xs, ys=ys)
        return

    @Element(name='Pulse parameters')
    def pulse_parameters(self):
        params = [
            #    ('arbname', {'type': str, 'default': 'arbitrary_name'}),,
            ('pulse height', {
                'type': float,
                'default': 3,
                'units': 'V'
            }),
            ('pulse width', {
                'type': float,
                'default': 300e-9,
                'units': 's'
            }),
            ('period', {
                'type': float,
                'default': 0.1,
                'units': 's'
            }),
            ('repeat unit', {
                'type': float,
                'default': 50e-9,
                'units': 's'
            }),
            ('start tau', {
                'type': float,
                'default': 3e-6,
                'units': 's'
            }),
            ('stop tau', {
                'type': float,
                'default': 10e-6,
                'units': 's'
            }),
            ('step tau', {
                'type': float,
                'default': 1e-6,
                'units': 's'
            }),
            # ('srs bias', {'type': float, 'default': 1.2, 'units':'V'}),
            ('shutter offset', {
                'type': float,
                'default': 500e-9,
                'units': 's'
            }),
            ('measuring range', {
                'type': float,
                'default': 70e-6,
                'units': 's'
            }),
            ('buffer time', {
                'type': float,
                'default': 100e-6,
                'units': 's'
            }),
        ]
        w = ParamWidget(params)
        return w

    @qutagInit.initializer
    def initialize(self):
        from lantz.drivers.qutools import QuTAG
        self.qutag = QuTAG()
        devType = self.qutag.getDeviceType()
        if (devType == self.qutag.DEVTYPE_QUTAG):
            print("found quTAG!")
        else:
            print("no suitable device found - demo mode activated")
        print("Device timebase:" + str(self.qutag.getTimebase()))
        return

    @qutagInit.finalizer
    def finalize(self):
        return

    @startpulse.initializer
    def initialize(self):
        self.fungen.output[1] = 'OFF'
        self.fungen.output[2] = 'OFF'
        self.fungen.clear_mem(1)
        self.fungen.clear_mem(2)
        self.fungen.wait()

    @startpulse.finalizer
    def finalize(self):
        self.fungen.output[1] = 'OFF'
        self.fungen.output[2] = 'OFF'
        print('Two Pulse measurements complete.')
        return
class HoleBurningSNSPD(Spyrelet):
	requires = {
		'fungen': Keysight_33622A
	}
	qutag = None

	def configureQutag(self):
		qutagparams = self.qutag_params.widget.get()
		start = qutagparams['Start Channel']
		stop = qutagparams['Stop Channel']
		##True = rising edge, False = falling edge. Final value is threshold voltage
		self.qutag.setSignalConditioning(start,self.qutag.SIGNALCOND_MISC,True,1)
		self.qutag.setSignalConditioning(stop,self.qutag.SIGNALCOND_MISC,True,0.1)
		self.qutag.enableChannels((start,stop))

	def createHistogram(self,stoparray, timebase, bincount, period, index, wls):
		hist = [0]*bincount
		for stoptime in stoparray:
			binNumber = int(stoptime*timebase*bincount/(period))
			if binNumber >= bincount:
				continue
			else:
				hist[binNumber]+=1
		out_name = "D:\\Data\\8.2.2019\\thinfilm\\holeburning\\test"
		np.savez(os.path.join(out_name,str(index)),hist,wls)
		#np.savez(os.path.join(out_name,str(index+40)),hist,wls)
		print('Data stored under File Name: ' + self.exp_parameters.widget.get()['File Name'] + str(index))


	@Task()
	def startpulse(self, timestep=1e-9):
		self.fungen.output[1] = 'OFF'
		self.fungen.output[2] = 'OFF'
		repeat_unit = 50e-9
		buffer_time = 100e-6
		pulse_width = 500e-9
		period = 200e-3
		self.fungen.clear_mem(1)
		self.fungen.clear_mem(2)
		params = self.pulse_parameters.widget.get()

		chn1buffer = Arbseq_Class('chn1buffer', timestep)
		chn1buffer.delays = [0]
		chn1buffer.heights = [0]
		chn1buffer.widths = [repeat_unit]
		chn1buffer.totaltime = repeat_unit
		chn1buffer.nrepeats = buffer_time/repeat_unit
		chn1buffer.repeatstring = 'repeat'
		chn1buffer.markerstring = 'lowAtStart'
		chn1buffer.markerloc = 0
		chn1bufferwidth = repeat_unit*chn1buffer.nrepeats
		chn1buffer.create_sequence()

		pulse = Arbseq_Class('pulse', timestep)
		pulse.delays = [0]
		pulse.heights = [0]
		pulse.widths = [repeat_unit]
		pulse.totaltime = repeat_unit
		pulserepeat = 400000
		pulse.nrepeats = pulserepeat
		chn1pulsewidth=pulserepeat*repeat_unit
		pulse.repeatstring = 'repeat'
		pulse.markerstring = 'lowAtStart'
		pulse.markerloc = 0
		pulse.create_sequence()

		chn1dc = Arbseq_Class('chn1dc', timestep)
		chn1dc.delays = [0]
		chn1dc.heights = [0]
		chn1dc.widths = [repeat_unit]
		chn1dc.totaltime = repeat_unit
		chn1dc.repeatstring = 'repeat'
		chn1dc.markerstring = 'lowAtStart'
		chn1dc.markerloc = 0
		chn1dcrepeats = 200000
		chn1dc.nrepeats = chn1dcrepeats
		chn1dcwidth = repeat_unit*chn1dcrepeats
		chn1dc.create_sequence()
		
		chn1pulse2 = Arbseq_Class('chn1pulse2', timestep)
		chn1pulse2.delays = [0]
		chn1pulse2.heights = [1]
		chn1pulse2.widths = [pulse_width]
		chn1pulse2.totaltime = pulse_width
		chn1pulse2width = pulse_width
		chn1pulse2.nrepeats = 0
		chn1pulse2.repeatstring = 'once'
		chn1pulse2.markerstring = 'highAtStartGoLow'
		chn1pulse2.markerloc = 0
		chn1pulse2.create_sequence()

		# chn1pulse3 = Arbseq_Class('chn1pulse3', timestep)
		# chn1pulse3.delays = [0]
		# chn1pulse3.heights = [0]
		# chn1pulse3.widths = [repeat_unit]
		# chn1pulse3.totaltime = repeat_unit 
		# chn1pulse3width = shutter_offset
		# chn1pulse3.nrepeats = shutter_offset/repeat_unit
		# chn1pulse3.repeatstring = 'repeat'
		# chn1pulse3.markerstring = 'lowAtStart'
		# chn1pulse3.markerloc = 0
		# chn1pulse3.create_sequence()

		chn1dc2 = Arbseq_Class('chn1dc2', timestep)
		chn1dc2.delays = [0]
		chn1dc2.heights = [0]
		chn1dc2.widths = [pulse_width]
		chn1dc2.totaltime = pulse_width
		chn1dc2.repeatstring = 'repeat'
		chn1dc2.markerstring = 'lowAtStart'
		chn1dc2repeats = 2e5
		ch1dc2width=chn1dc2repeats*pulse_width
		chn1dc2.nrepeats = chn1dc2repeats
		chn1dc2.markerloc = 0
		#print((chn1dc2repeats*params['repeat unit'].magnitude) + tau.magnitude + params['pulse width'].magnitude)
		chn1dc2.create_sequence()

		totalTime=chn1bufferwidth+chn1pulsewidth+chn1dcwidth+chn1pulse2width+ch1dc2width

		chn2buffer = Arbseq_Class('chn2buffer', timestep)
		chn2buffer.delays = [0]
		chn2buffer.heights = [1]
		chn2buffer.widths = [repeat_unit]
		chn2buffer.totaltime = repeat_unit
		chn2buffer.nrepeats = buffer_time/repeat_unit
		chn2buffer.repeatstring = 'repeat'
		chn2buffer.markerstring = 'lowAtStart'
		chn2buffer.markerloc = 0
		chn2bufferwidth = repeat_unit*chn2buffer.nrepeats
		chn2buffer.create_sequence()

		chn2pulse1 = Arbseq_Class('chn2pulse1', timestep)
		chn2pulse1.delays = [0]
		chn2pulse1.heights = [1]
		chn2pulse1.widths = [repeat_unit]
		chn2pulse1.totaltime = repeat_unit
		chn2pulse1.nrepeats = pulserepeat
		chn2pulse1width = pulse_width
		chn2pulse1.repeatstring = 'repeat'
		chn2pulse1.markerstring = 'lowAtStart'
		chn2pulse1.markerloc = 0
		chn2pulse1.create_sequence()

		chn2dc1 = Arbseq_Class('chn2dc1', timestep)
		chn2dc1.delays = [0]
		chn2dc1.heights = [1]
		chn2dc1.widths = [repeat_unit]
		chn2dc1.totaltime = repeat_unit
		chn2dc1.repeatstring = 'repeat'
		chn2dc1.markerstring = 'lowAtStart'
		chn2dc1.markerloc = 0
		chn2dc1repeats = chn1dcrepeats
		chn2dc1.nrepeats = chn1dcrepeats
		chn2dc1width = repeat_unit*chn2dc1repeats
		chn2dc1.create_sequence()
	
		chn2pulse2 = Arbseq_Class('chn2pulse2', timestep)
		chn2pulse2.delays = [0]
		chn2pulse2.heights = [-1]
		chn2pulse2.widths = [pulse_width]
		chn2pulse2.totaltime = pulse_width
		chn2pulse2width = pulse_width
		chn2pulse2.nrepeats = 0
		chn2pulse2.repeatstring = 'once'
		chn2pulse2.markerstring = 'highAtStartGoLow'
		chn2pulse2.markerloc = 0
		chn2pulse2.create_sequence()

		chn2dc2 = Arbseq_Class('chn2dc2', timestep)
		chn2dc2.delays = [0]
		chn2dc2.heights = [-1]
		chn2dc2.widths = [pulse_width]
		chn2dc2.totaltime = pulse_width
		chn2dc2.repeatstring = 'repeat'
		chn2dc2.markerstring = 'lowAtStart'
		chn2dc2repeats = chn1dc2repeats
		chn2dc2.nrepeats = chn2dc2repeats
		chn2dc2.markerloc = 0
		chn2dc2.create_sequence()


		self.fungen.send_arb(chn1buffer, 1)
		self.fungen.send_arb(pulse, 1)
		self.fungen.send_arb(chn1dc, 1)
		self.fungen.send_arb(chn1pulse2, 1)
		self.fungen.send_arb(chn1dc2, 1)
		self.fungen.send_arb(chn2buffer, 2)
		self.fungen.send_arb(chn2pulse1, 2)
		self.fungen.send_arb(chn2dc1, 2)
		self.fungen.send_arb(chn2pulse2, 2)
		self.fungen.send_arb(chn2dc2, 2)

		seq = [chn1buffer, pulse, chn1dc, chn1pulse2, chn1dc2]
		seq2=[chn2buffer,chn2pulse1,chn2dc1,chn2pulse2,chn2dc2]

		self.fungen.create_arbseq('pulsetest', seq2, 2)
		self.fungen.wait()
		self.fungen.voltage[2] = 7.1
		self.fungen.output[2] = 'ON'
		#self.fungen.sync()

		self.fungen.create_arbseq('pulsetest', seq, 1)
		self.fungen.wait()
		self.fungen.voltage[1] = params['pulse height']
		self.fungen.sync()
		self.fungen.output[1] = 'ON'

		#time.sleep(100000)

		self.configureQutag()

		qutagparams = self.qutag_params.widget.get()
		lost = self.qutag.getLastTimestamps(True) # clear Timestamp buffer
		stoptimestamp = 0
		synctimestamp = 0
		bincount = qutagparams['Bin Count']
		timebase = self.qutag.getTimebase()
		start = qutagparams['Start Channel']
		stop = qutagparams['Stop Channel']

		expparams = self.exp_parameters.widget.get()
		for i in range(expparams['# of points']):
			##Wavemeter measurements
			stoparray = []
			startTime = time.time()
			wls=[]
			lost = self.qutag.getLastTimestamps(True)
			while time.time()-startTime < expparams['Measurement Time'].magnitude:
				lost = self.qutag.getLastTimestamps(True)
				time.sleep(30*totalTime)
				timestamps = self.qutag.getLastTimestamps(True)

				tstamp = timestamps[0] # array of timestamps
				tchannel = timestamps[1] # array of channels
				values = timestamps[2] # number of recorded timestamps
				for k in range(values):
					# output all stop events together with the latest start event
					if tchannel[k] == start:
						synctimestamp = tstamp[k]
					else:
						stoptimestamp = tstamp[k]
						stoparray.append(stoptimestamp)
			self.createHistogram(stoparray, timebase, bincount, totalTime,i, wls)
			print(i)
			#self.fungen.voltage[2] = self.fungen.voltage[2].magnitude + 2*dcparams['DC step size'].magnitude

		self.fungen.output[1] = 'OFF'

	@Task()
	def qutagInit(self):
		print('qutag successfully initialized')
		

	@Element(name='Pulse parameters')
	def pulse_parameters(self):
		params = [
	#    ('arbname', {'type': str, 'default': 'arbitrary_name'}),,
		('pulse height', {'type': float, 'default': 3, 'units':'V'}),
		('pulse width', {'type': float, 'default': 500e-9, 'units':'s'}),
		('period', {'type': float, 'default': 0.1, 'units':'s'}),
		]
		w = ParamWidget(params)
		return w

	@Element(name='DC parameters')
	def DC_parameters(self):
		params = [
	#    ('arbname', {'type': str, 'default': 'arbitrary_name'}),,
		('DC height', {'type': float, 'default': 0, 'units':'V'}),
		('DC step size', {'type': float, 'default': 0.1, 'units':'V'}),
		]
		w = ParamWidget(params)
		return w

	@Element(name='Experiment Parameters')
	def exp_parameters(self):
		params = [
	#    ('arbname', {'type': str, 'default': 'arbitrary_name'}),,
		('# of points', {'type': int, 'default': 10}),
		('Measurement Time', {'type': int, 'default': 10, 'units':'s'}),
		('File Name', {'type': str})
		]
		w = ParamWidget(params)
		return w

	@Element(name='QuTAG Parameters')
	def qutag_params(self):
		params = [
	#    ('arbname', {'type': str, 'default': 'arbitrary_name'}),,
		('Start Channel', {'type': int, 'default': 0}),
		('Stop Channel', {'type': int, 'default': 1}),
		('Bin Count', {'type': int, 'default': 1000})
		]
		w = ParamWidget(params)
		return w

	@startpulse.initializer
	def initialize(self):
		self.fungen.output[1] = 'OFF'
		self.fungen.output[2] = 'OFF'
		self.fungen.clear_mem(1)
		self.fungen.clear_mem(2)
		self.fungen.wait()

	@startpulse.finalizer
	def finalize(self):
		self.fungen.output[1] = 'OFF'
		self.fungen.output[2] = 'OFF'
		print('Lifetime measurements complete.')
		return

	@qutagInit.initializer
	def initialize(self):
		from lantz.drivers.qutools import QuTAG
		self.qutag = QuTAG()
		devType = self.qutag.getDeviceType()
		if (devType == self.qutag.DEVTYPE_QUTAG):
			print("found quTAG!")
		else:
			print("no suitable device found - demo mode activated")
		print("Device timebase:" + str(self.qutag.getTimebase()))
		return

	@qutagInit.finalizer
	def finalize(self):
		return
Exemplo n.º 7
0
class PLThinFilm(Spyrelet):
	requires = {
		'wm': Bristol_771,
		'fungen': Keysight_33622A,
		'SRS': SRS900
	}
	qutag = None
	laser = NetworkConnection('1.1.1.2')
	xs=np.array([])
	ys=np.array([])
	hist=[]

	def configureQutag(self):
		qutagparams = self.qutag_params.widget.get()
		start = qutagparams['Start Channel']
		stop = qutagparams['Stop Channel']
		##True = rising edge, False = falling edge. Final value is threshold voltage
		self.qutag.setSignalConditioning(start,self.qutag.SIGNALCOND_MISC,True,1)
		self.qutag.setSignalConditioning(stop,self.qutag.SIGNALCOND_MISC,True,0.1)
		self.qutag.enableChannels((start,stop))

	def homelaser(self,start):
		current=self.wm.measure_wavelength()
		with Client(self.laser) as client:

			while current<start-0.001 or current>start+0.001:
				setting=client.get('laser1:ctl:wavelength-set', float)
				offset=current-start
				client.set('laser1:ctl:wavelength-set', setting-offset)
				time.sleep(3)
				current=self.wm.measure_wavelength()
				print(current, start)

	def createHistogram(self,stoparray, timebase, bincount, period, index, wls,out_name,extra_data=False):
		print('creating histogram')

		hist = [0]*bincount
		for stoptime in stoparray:
			# stoptime=ps
			# timebase = converts to seconds
			# bincount: # of bins specified by user
			# period: measurement time specified by user
			binNumber = int(stoptime*timebase*bincount/(period))
			if binNumber >= bincount:
				continue
				print('error')
			else:
				hist[binNumber]+=1
		if extra_data==False:
			np.savez(os.path.join(out_name,str(index)),hist,wls)
		if extra_data!=False:
			np.savez(os.path.join(out_name,str(index)),hist,wls,extra_data)
		#np.savez(os.path.join(out_name,str(index+40)),hist,wls)
		print('Data stored under File Name: ' + out_name +'\\'+str(index)+'.npz')

	def resetTargets(self,targets,totalShift,i,channel):
		print('AWG limit exceeded, resetting voltage targets')

		# get the current wavelength
		current=self.wm.measure_wavelength()

		# adjust all targets to be lower again
		# reset totalShift
		print('totalShift: '+str(totalShift))
		newTargets=[j-totalShift for j in targets]
		print('newTargets')
		voltageTargets=newTargets
		totalShift=0

		# bring voltage back to ideal
		
		self.fungen.offset[channel]=Q_(voltageTargets[i-1],'V')
		# drive to last wavelength again
		self.homelaser(current)
		wl=self.wm.measure_wavelength()
		return voltageTargets,totalShift,wl

	def reset_quench(self):
		"""
		A typical quench shows the voltage exceeding 2mV.
		"""
		qutagparams = self.qutag_params.widget.get()
		# vm1=qutagparams['Voltmeter Channel 1']
		vm2=qutagparams['Voltmeter Channel 2']
		# vs1=qutagparams['Battery Port 1']
		vs2=qutagparams['Battery Port 2']

		# self.SRS.clear_status()
		# V1=self.SRS.SIM970_voltage[vm1].magnitude
		self.SRS.clear_status()
		V2=self.SRS.SIM970_voltage[vm2].magnitude

		quenchfix='YES'

		# i=0
		# while (float(V1)>=0.010):
		# 	i+=1
		# 	print('Voltage 1 higher than 10mV, resetting')
		# 	self.SRS.SIM928_on_off[vs1]='OFF'
		# 	self.SRS.SIM928_on_off[vs2]='OFF'
		# 	self.SRS.SIM928_on_off[vs1]='ON'
		# 	self.SRS.SIM928_on_off[vs2]='ON'
		# 	print('checking Voltage 1 again')
		# 	self.SRS.clear_status()
		# 	time.sleep(1)
		# 	V1=self.SRS.SIM970_voltage[vm1].magnitude
		# 	print('Voltage 1: '+str(V1)+'V')
		# 	if i>10:
		# 		self.fungen.output[1]='OFF'
		# 		self.fungen.output[2]='OFF'
		# 		quenchfix='NO'
		# 		break

		i=0
		while (float(V2)>=0.010):
			i+=1
			print('Voltage 2 higher than 10mV, resetting')
			self.SRS.SIM928_on_off[vs1]='OFF'
			self.SRS.SIM928_on_off[vs2]='OFF'
			self.SRS.SIM928_on_off[vs1]='ON'
			self.SRS.SIM928_on_off[vs2]='ON'
			print('checking Voltage 2 again')
			self.SRS.clear_status()
			time.sleep(1)
			V2=self.SRS.SIM970_voltage[vm2].magnitude
			print('Voltage 2: '+str(V2)+'V')
			if i>10:
				self.fungen.output[1]='OFF'
				self.fungen.output[2]='OFF'
				quenchfix='NO'
				break
		return quenchfix
	
	@Task()
	def piezo_scan(self,timestep=100e-9):
		
		#self.fungen.output[1]='ON'
		piezo_params=self.piezo_parameters.widget.get()
		Vstart=piezo_params['voltage start']
		Vstop=piezo_params['voltage end']
		pts=piezo_params['scan points']

		voltageTargets=np.linspace(Vstart,Vstop,pts)
		reversedTargets=voltageTargets[::-1]
		voltageTargets=reversedTargets

		print('voltageTargets: '+str(voltageTargets))


		channel=piezo_params['AWG channel']

		# turn off AWG
		self.fungen.output[channel]='OFF'

		##Qutag Part
		self.configureQutag()
		expparams = self.exp_parameters.widget.get()
		wlparams = self.wl_parameters.widget.get()

		# drive to the offset estimated by the piezo voltage
		# 1MOhm impedance of laser mismatch with 50Ohm impedance of AWG
		# multiplies voltage 2x
		# 140V ~ 40GHz ~ 315pm

		piezo_range=(Vstop.magnitude-Vstart.magnitude)*0.315/(140)*piezo_params['Scale factor'] #pm
		print('piezo_range: '+str(piezo_range)+str(' nm'))

		wl_start=wlparams['start']-piezo_range
		wl_stop=wlparams['stop']+piezo_range
		wlpts=np.linspace(wl_start,wl_stop,pts)

		self.homelaser(wlparams['start']-piezo_range)
		print('Laser Homed!')
		qutagparams = self.qutag_params.widget.get()
		lost = self.qutag.getLastTimestamps(True) # clear Timestamp buffer
		stoptimestamp = 0
		synctimestamp = 0
		bincount = qutagparams['Bin Count']
		timebase = self.qutag.getTimebase()
		start = qutagparams['Start Channel']
		stop = qutagparams['Stop Channel']

		PATH="C:\\Data\\"+self.exp_parameters.widget.get()['File Name']

		if PATH!="C:\\Data\\":
			if (os.path.exists(PATH)):
				print('deleting old directory with same name')
				os.system('rm -rf '+str(PATH))
			print('making new directory')
			Path(PATH).mkdir(parents=True, exist_ok=True)
		else:
			print("Specify a foldername & rerun task.")
			print("Task will error trying to saving data.")

		# turn on AWG
		self.fungen.output[channel]='ON'

		last_wl=self.wm.measure_wavelength()
		wls=[]
		totalShift=0

		for i in range(pts):
			print(i)
			if (voltageTargets[i]>5) or (voltageTargets[i]<-5):

				newTargets,newShift,wl=self.resetTargets(voltageTargets,totalShift,i,channel)
				voltageTargets=newTargets
				totalShift=newShift

			self.fungen.offset[channel]=Q_(voltageTargets[i],'V')
			wl=self.wm.measure_wavelength()
			counter=0
			if len(wls)!=0:
				last_wl=np.mean(np.array(wls).astype(np.float))
			
			print('i: '+str(i)+', initializing')

			while ((wl<wlpts[i]-0.0002) or (wl>wlpts[i]+0.0002)):
					offset=wl-wlpts[i]
					Voff=offset/0.315*140/(piezo_params['Scale factor']*2)
					if offset<0:
						if voltageTargets[i]+Voff<-5:
							newTargets,newShift,wl=self.resetTargets(voltageTargets,totalShift,i,channel)
							voltageTargets=newTargets
							totalShift=newShift
							print('AWG limit exceeded, resetting voltage targets')
						else:
							newTargets=[j+Voff for j in voltageTargets]
							voltageTargets=newTargets
							self.fungen.offset[channel]=Q_(newTargets[i],'V')
							time.sleep(3)
							wl=self.wm.measure_wavelength()
							counter+=Voff
							totalShift+=Voff
					else:
						if voltageTargets[i]+Voff>5:
							newTargets,newShift,wl=self.resetTargets(voltageTargets,totalShift,i,channel)
							voltageTargets=newTargets
							totalShift=newShift
							print('AWG limit exceeded, resetting voltage targets')
						else:
							newTargets=[j+Voff for j in voltageTargets]
							voltageTargets=newTargets
							self.fungen.offset[channel]=Q_(newTargets[i],'V')
							time.sleep(3)
							wl=self.wm.measure_wavelength()
							counter+=Voff
							totalShift+=Voff

			print('taking data')
			print('current target wavelength: '+str(wlpts[i]))
			print('current set voltage: '+str(voltageTargets[i]))
			print('actual wavelength: '+str(self.wm.measure_wavelength()))
			
			time.sleep(1)
			##Wavemeter measurements
			stoparray = []
			startTime = time.time()
			wls=[]
			lost = self.qutag.getLastTimestamps(True)
			counter2=0

			looptime=startTime
			while looptime-startTime < expparams['Measurement Time'].magnitude:
				loopstart=time.time()
				# get the lost timestamps
				lost = self.qutag.getLastTimestamps(True)
				# wait half a milisecond
				time.sleep(5*0.1)
				# get thte timestamps in the last half milisecond
				timestamps = self.qutag.getLastTimestamps(True)

				tstamp = timestamps[0] # array of timestamps
				tchannel = timestamps[1] # array of channels
				values = timestamps[2] # number of recorded timestamps

				for k in range(values):
					# output all stop events together with the latest start event
					if tchannel[k] == start:
						synctimestamp = tstamp[k]
					else:
						stoptimestamp = tstamp[k]
						stoparray.append(stoptimestamp)
				wl=self.wm.measure_wavelength()
				wls.append(str(wl))
				looptime+=time.time()-loopstart
				#print('i: '+str(i)+', looptime-startTime: '+str(looptime-startTime))
				quenchfix=self.reset_quench()
				if quenchfix!='YES':
					print('SNSPD quenched and could not be reset')
					self.fungen.output[1]='OFF'
					self.fungen.output[2]='OFF'
					endloop

				
				while ((wl<wlpts[i]-0.0002) or (wl>wlpts[i]+0.0002)) and (time.time()-startTime < expparams['Measurement Time'].magnitude):
					offset=wl-wlpts[i]
					Voff=offset/0.315*140/(piezo_params['Scale factor']*2)
					if offset<0:
						if voltageTargets[i]+Voff<-5:
							break
						else:
							newTargets=[j+Voff for j in voltageTargets]
							voltageTargets=newTargets
							self.fungen.offset[channel]=Q_(newTargets[i],'V')
							time.sleep(3)
							wl=self.wm.measure_wavelength()
							counter2+=Voff
							totalShift+=Voff
					else:
						if voltageTargets[i]+Voff>5:
							break
						else:
							newTargets=[j+Voff for j in voltageTargets]
							voltageTargets=newTargets
							self.fungen.offset[channel]=Q_(newTargets[i],'V')
							time.sleep(3)
							wl=self.wm.measure_wavelength()
							counter2+=Voff
							totalShift+=Voff
				
			print('actual  wavelength: '+str(wl))
			print('targets shift during measurement:  '+str(counter2)+'V')
				

			self.createHistogram(stoparray, timebase, bincount,
				expparams['AWG Pulse Repetition Period'].magnitude,i, wls,
				"C:\\Data\\"+self.exp_parameters.widget.get()['File Name'])
		# turn off AWG
		self.fungen.output[channel]='OFF'
	

	@Task()
	def startpulse(self, timestep=100e-9):

		self.fungen.output[1]='OFF'
		#self.fungen.output[2]='OFF'
		self.SRS.SIMmodule_on[6] ##Turn on the power supply of the SNSPD
		time.sleep(3)  ##wait 1s to turn on the SNSPD

		##Qutag Part
		self.configureQutag()
		expparams = self.exp_parameters.widget.get()
		wlparams = self.wl_parameters.widget.get()
		self.homelaser(wlparams['start'])
		print('Laser Homed!')
		qutagparams = self.qutag_params.widget.get()
		lost = self.qutag.getLastTimestamps(True) # clear Timestamp buffer
		stoptimestamp = 0
		synctimestamp = 0
		bincount = qutagparams['Bin Count']
		timebase = self.qutag.getTimebase()
		start = qutagparams['Start Channel']
		stop = qutagparams['Stop Channel']

		self.fungen.frequency[1]=expparams['AWG Pulse Frequency']
		self.fungen.voltage[1]=3.5
		self.fungen.offset[1]=1.75
		self.fungen.phase[1]=0   
		self.fungen.pulse_width[1]=expparams['AWG Pulse Width']
		self.fungen.waveform[1]='PULS'
		self.fungen.output[1]='ON'
		

		#PATH="C:\\Data\\12.18.2020_ffpc\\"+self.exp_parameters.widget.get()['File Name']+"\\motor_scan"
		PATH="Q:\\Data\\5.28.2021_ffpc\\"+self.exp_parameters.widget.get()['File Name']
		print('here')
		print('PATH: '+str(PATH))
		if PATH!="Q:\\Data\\5.28.2021_ffpc\\":
			if (os.path.exists(PATH)):
				print('deleting old directory with same name')
				os.system('rm -rf '+str(PATH))
			print('making new directory')
			Path(PATH).mkdir(parents=True, exist_ok=True)
			#os.mkdir(PATH)
		else:
			print("Specify a foldername & rerun task.")
			print("Task will error trying to saving data.")

		wlTargets=np.linspace(wlparams['start'],wlparams['stop'],expparams['# of points'])
		

		print('wlTargets: '+str(wlTargets))
		for i in range(expparams['# of points']):
			print(i)
			with Client(self.laser) as client:

				setting=client.get('laser1:ctl:wavelength-set', float)
				client.set('laser1:ctl:wavelength-set', wlTargets[i])
				wl=self.wm.measure_wavelength()
				

			while ((wl<wlTargets[i]-0.001) or (wl>wlTargets[i]+0.001)):
					print('correcting for laser drift')
					self.homelaser(wlTargets[i])
					wl=self.wm.measure_wavelength()
					print('current target wavelength: '+str(wlTargets[i]))
					print('actual wavelength: '+str(self.wm.measure_wavelength()))
					time.sleep(1)


			print('taking data')
			print('current target wavelength: '+str(wlTargets[i]))
			print('actual wavelength: '+str(self.wm.measure_wavelength()))
			
			time.sleep(1)
			##Wavemeter measurements
			stoparray = []
			startTime = time.time()
			wls=[]
			lost = self.qutag.getLastTimestamps(True)
			#counter2=0

			looptime=startTime
			while looptime-startTime < expparams['Measurement Time'].magnitude:
				loopstart=time.time()
				# get the lost timestamps
				lost = self.qutag.getLastTimestamps(True)
				# wait half a milisecond
				time.sleep(5*0.1)   #
				# get thte timestamps in the last half milisecond
				timestamps = self.qutag.getLastTimestamps(True)

				tstamp = timestamps[0] # array of timestamps
				tchannel = timestamps[1] # array of channels
				values = timestamps[2] # number of recorded timestamps

				for k in range(values):
					# output all stop events together with the latest start event
					if tchannel[k] == start:
						synctimestamp = tstamp[k]
					else:
						stoptimestamp = tstamp[k]
						stoparray.append(stoptimestamp)
				wl=self.wm.measure_wavelength()
				wls.append(str(wl))
				looptime+=time.time()-loopstart
				print('i: '+str(i)+', looptime-startTime: '+str(looptime-startTime))
				# quenchfix=self.reset_quench()
				# if quenchfix!='YES':
				# 	print('SNSPD quenched and could not be reset')
				# 	# self.fungen.output[1]='OFF'
				# 	self.fungen.output[2]='OFF'
				# 	endloop

				
				while ((wl<wlTargets[i]-0.001) or (wl>wlTargets[i]+0.001)) and (time.time()-startTime < expparams['Measurement Time'].magnitude):
					print('correcting for laser drift')
					self.homelaser(wlTargets[i])
					wl=self.wm.measure_wavelength()
			print('actual  wavelength: '+str(wl))
			#print('I am here')
			self.createHistogram(stoparray, timebase, bincount, expparams['AWG Pulse Repetition Period'].magnitude,str(i), wls,PATH)
			# self.createHistogram(stoparray, timebase, bincount,period,str(i),
			# 	wls,PATH,savefreqs)
		self.fungen.output[1]='OFF'
		self.SRS.SIMmodule_off[6] ##turn off the SNSPD power suppy after the measurement

	#@Task()
	#def spectralDiffusion_wRFsource(self):
		""" Task to measure spectral diffusion on timescales < T1. Assumes that
		1 channel of the keysight AWG is sending a sine wave to an EOM. The
		amplitude of the RF drive for the EOM is set such that the sidebands
		have an equal amplitude to the pump beam. This tasks sweeps the
		frequency of the sine wave (separation of the EOM sidebands) while
		collecting PL, which can be used to determine the spectral diffusion
		linewidth since the saturation of the ions will be determined by how
		much the sidebands overlap with the spectral  diffusion lineshape.
		
		This task is good for modulating between 1MHz and 200MHz. 
		JDSU EOM amplifier has nonlinear performance below 1MHz (amplification
		increases), but the N5181A works down to 100kHz if desired.
		"""

		# get the parameters for the experiment from the widget
		"""
		SD_wRFparams=self.SD_wRFparams.widget.get()
		startFreq=SD_wRFparams['Start frequency']
		stopFreq=SD_wRFparams['Stop frequency']

		power=SD_wRFparams['RF Power']

		runtime=SD_wRFparams['Runtime']
		wl=SD_wRFparams['Wavelength']
		points=SD_wRFparams['# of points']
		period=SD_wRFparams['Period']
		foldername=self.SD_wRFparams.widget.get()['File Name']

		# convert the period & runtime to floats
		period=period.magnitude
		runtime=runtime.magnitude

		# set the amplitude of the RF signal
		self.source.set_RF_Power(power)

		# home the laser
		self.configureQutag()
		self.homelaser(wl)
		print('Laser Homed!')

		##Qutag Part
		qutagparams = self.qutag_params.widget.get()
		lost = self.qutag.getLastTimestamps(True) # clear Timestamp buffer
		stoptimestamp = 0
		synctimestamp = 0
		bincount = qutagparams['Bin Count']
		timebase = self.qutag.getTimebase()
		start = qutagparams['Start Channel']
		stop = qutagparams['Stop Channel']

		PATH="D:\\Data\\"+foldername
		if PATH!="D:\\Data\\":
			if (os.path.exists(PATH)):
				print('deleting old directory with same name')
				os.system('rm -rf '+str(PATH))
			print('making new directory')
			Path(PATH).mkdir(parents=True, exist_ok=True)

		# make a vector containing all the frequency setpoints for the EOM
		freqs=np.linspace(startFreq,stopFreq,points)

		# now loop through all the set frequencies of the EOM modulation
		# and record the PL on the qutag

		# turn on the RF source & set it in CW mode
		self.source.FM_ON()
		self.source.set_CW_mode()

		for i in range(points):

			#set the frequency on the RF source
			self.source.set_CW_Freq(freqs[i])
			

			# want to actively stabilize the laser frequency since it can
			# drift on the MHz scale
			with Client(self.laser) as client:

				setting=client.get('laser1:ctl:wavelength-set', float)
				client.set('laser1:ctl:wavelength-set', wl)
				currentwl=self.wm.measure_wavelength()
				

			while ((currentwl<wl-0.001) or (currentwl>wl+0.001)):
					print('correcting for laser drift')
					self.homelaser(wl)
					currentwl=self.wm.measure_wavelength()
					print('current target wavelength: '+str(wl))
					print('actual wavelength: '+str(currentwl))
					time.sleep(1)


			print('taking data')
			print('current frequency: '+str(freqs[i]))
			print('current target wavelength: '+str(wl))
			print('actual wavelength: '+str(self.wm.measure_wavelength()))
			
			time.sleep(1)


			stoparray = []
			startTime = time.time()
			wls=[]
			savefreqs=[]
			lost = self.qutag.getLastTimestamps(True)

			looptime=startTime
			while looptime-startTime < runtime:
				loopstart=time.time()
				# get the lost timestamps
				lost = self.qutag.getLastTimestamps(True)
				# wait half a milisecond
				time.sleep(5*0.1)
				# get thte timestamps in the last half milisecond
				timestamps = self.qutag.getLastTimestamps(True)

				tstamp = timestamps[0] # array of timestamps
				tchannel = timestamps[1] # array of channels
				values = timestamps[2] # number of recorded timestamps

				for k in range(values):
					# output all stop events together with the latest start event
					if tchannel[k] == start:
						synctimestamp = tstamp[k]
					else:
						stoptimestamp = tstamp[k]
						stoparray.append(stoptimestamp)
				currentwl=self.wm.measure_wavelength()
				wls.append(str(currentwl))
				savefreqs.append(float(freqs[i]))
				looptime+=time.time()-loopstart

				while ((currentwl<wl-0.001) or (currentwl>wl+0.001)) and (time.time()-startTime < runtime):
					print('correcting for laser drift')
					self.homelaser(wl)
					currentwl=self.wm.measure_wavelength()
			print('actual  wavelength: '+str(currentwl))

			self.createHistogram(stoparray, timebase, bincount,period,str(i),
				wls,PATH,savefreqs)

		# turnn off the RF output of the N5181A whenn done
		self.source.RF_OFF()
		"""
	@Task()
	def spectralDiffusion_wAWG(self):
		""" Task to measure spectral diffusion on timescales < T1. Uses the 
		Agilent N5181A RF source to send a sine wave to the phase EOM. The
		amplitude of the RF drive for the EOM is set such that the sidebands
		have an equal amplitude to the pump beam (Calibrated on 11/19/20 to 
		be 6Vpp for the JDSU phase EOM). This tasks sweeps the
		frequency of the sine wave (separation of the EOM sidebands) while
		collecting PL, which can be used to determine the spectral diffusion
		linewidth since the saturation of the ions will be determined by how
		much the sidebands overlap with the spectral  diffusion lineshape.
		
		The Keysight AWG only works up to 80MHz. 

		Could potentially modify code to use Siglent AWG which can go up to 120MHz
		"""
		self.fungen.output[1]='OFF'
		self.fungen.output[2]='OFF'
		# some initialization of the function generator
		self.fungen.clear_mem(1)
		self.fungen.clear_mem(2)
		self.fungen.wait()
		#self.fungen.output[1]='ON'
		self.SRS.SIMmodule_on[6] ##Turn on the power supply of the SNSPD
		time.sleep(1)  ##wait 1s to turn on the SNSPD


		# get the parameters for the experiment from the widget
		SD_wAWGparams=self.SD_wAWGparams.widget.get()
		startFreq=SD_wAWGparams['Start frequency']
		stopFreq=SD_wAWGparams['Stop frequency']
		EOMvoltage=SD_wAWGparams['EOM voltage']
		runtime=SD_wAWGparams['Runtime']
		EOMchannel=SD_wAWGparams['EOM channel']
		Pulsechannel=SD_wAWGparams['Pulse channel']
		Pulsefreq=SD_wAWGparams['Pulse Frequency']
		Pulsewidth=SD_wAWGparams['Pulse Width']
		period=SD_wAWGparams['Pulse Repetition Period']
		wl=SD_wAWGparams['Wavelength']
		points=SD_wAWGparams['# of points']
		foldername=SD_wAWGparams['File Name']

		# convert the period & runtime to floats
		period=period.magnitude
		runtime=runtime.magnitude
		self.fungen.clear_mem(EOMchannel)
		self.fungen.clear_mem(Pulsechannel)
		self.fungen.waveform[Pulsechannel]='PULS'
		self.fungen.waveform[EOMchannel]='SIN'


		# set the sine wave driving the EOM on the other channel
		self.fungen.waveform[EOMchannel]='SIN'
		self.fungen.voltage[EOMchannel]=EOMvoltage
		self.fungen.offset[EOMchannel]=0
		self.fungen.phase[EOMchannel]=0


		self.fungen.waveform[Pulsechannel]='PULS'
		self.fungen.frequency[Pulsechannel]=Pulsefreq
		self.fungen.voltage[Pulsechannel]=3.5
		self.fungen.offset[Pulsechannel]=1.75
		self.fungen.phase[Pulsechannel]=0
		self.fungen.pulse_width[Pulsechannel]=Pulsewidth


		self.fungen.output[EOMchannel]='ON'
		self.fungen.output[Pulsechannel]='ON'
		

		# home the laser
		self.configureQutag()
		self.homelaser(wl)
		print('Laser Homed!')

		##Qutag Part
		qutagparams = self.qutag_params.widget.get()
		lost = self.qutag.getLastTimestamps(True) # clear Timestamp buffer
		stoptimestamp = 0
		synctimestamp = 0
		bincount = qutagparams['Bin Count']
		timebase = self.qutag.getTimebase()
		start = qutagparams['Start Channel']
		stop = qutagparams['Stop Channel']

		PATH="C:\\Data\\12.29.2020_ffpc\\SD0.1mW20dBatt195227GHz\\"+str(foldername)
		print('PATH: '+str(PATH))
		if PATH!="C:\\Data\\12.29.2020_ffpc\\SD0.1mW20dBatt195227GHz\\":
			if (os.path.exists(PATH)):
				print('deleting old directory with same name')
				os.system('rm -rf '+str(PATH))
				print('PATH: '+str(PATH))
			print('making new directory')
			Path(PATH).mkdir(parents=True, exist_ok=True)
		else:
			print("Specify a foldername & rerun task.")
			print("Task will error trying to saving data.")

		# make a vector containing all the frequency setpoints for the EOM
		freqs=np.linspace(startFreq,stopFreq,points)

		# now loop through all the set frequencies of the EOM modulation
		# and record the PL on the qutag


		for i in range(points):
			self.fungen.frequency[EOMchannel]=freqs[i]

			# want to actively stabilize the laser frequency since it can
			# drift on the MHz scale
			with Client(self.laser) as client:

				setting=client.get('laser1:ctl:wavelength-set', float)
				client.set('laser1:ctl:wavelength-set', wl)
				currentwl=self.wm.measure_wavelength()
				

			while ((currentwl<wl-0.001) or (currentwl>wl+0.001)):
					print('correcting for laser drift')
					self.homelaser(wl)
					currentwl=self.wm.measure_wavelength()
					print('current target wavelength: '+str(wl))
					print('actual wavelength: '+str(currentwl))
					time.sleep(1)


			print('taking data')
			print('current frequency: '+str(freqs[i]))
			print('current target wavelength: '+str(wl))
			print('actual wavelength: '+str(self.wm.measure_wavelength()))
			
			time.sleep(1)


			stoparray = []
			startTime = time.time()
			wls=[]
			savefreqs=[]
			lost = self.qutag.getLastTimestamps(True)

			looptime=startTime
			while looptime-startTime < runtime:
				loopstart=time.time()
				# get the lost timestamps
				lost = self.qutag.getLastTimestamps(True)
				# wait half a milisecond
				time.sleep(5*0.1)
				# get thte timestamps in the last half milisecond
				timestamps = self.qutag.getLastTimestamps(True)

				tstamp = timestamps[0] # array of timestamps
				tchannel = timestamps[1] # array of channels
				values = timestamps[2] # number of recorded timestamps

				for k in range(values):
					# output all stop events together with the latest start event
					if tchannel[k] == start:
						synctimestamp = tstamp[k]
					else:
						stoptimestamp = tstamp[k]
						stoparray.append(stoptimestamp)
				currentwl=self.wm.measure_wavelength()
				wls.append(str(currentwl))
				savefreqs.append(float(freqs[i]))
				looptime+=time.time()-loopstart

				# quenchfix=self.reset_quench()
				# if quenchfix!='YES':
				# 	print('SNSPD quenched and could not be reset')
				# 	self.fungen.output[1]='OFF'
				# 	self.fungen.output[2]='OFF'
				# 	endloop

				while ((currentwl<wl-0.001) or (currentwl>wl+0.001)) and (time.time()-startTime < runtime):
					print('correcting for laser drift')
					self.homelaser(wl)
					currentwl=self.wm.measure_wavelength()
			print('actual  wavelength: '+str(currentwl))

			self.createHistogram(stoparray, timebase, bincount,period,str(i),wls,PATH,savefreqs)

		self.fungen.output[EOMchannel]='OFF'  ##turn off the AWG for both channels
		self.fungen.output[Pulsechannel]='OFF'
		self.SRS.SIMmodule_off[6] ##turn off the SNSPD power suppy after the measurement


	@Task()
	def qutagInit(self):
		print('qutag successfully initialized')

	@Element(name='Wavelength parameters')
	def wl_parameters(self):
		params = [
	#    ('arbname', {'type': str, 'default': 'arbitrary_name'}),,
		# ('start', {'type': float, 'default': 1535.665}),
		('start', {'type': float, 'default': 1535.527}),
		('stop', {'type': float, 'default':  1535.685})
		# ('stop', {'type': float, 'default': 1535.61})
		]
		w = ParamWidget(params)
		return w

	@Element(name='Piezo scan parameters')
	def piezo_parameters(self):
		params=[
			('voltage start',{'type': float,'default':-3,'units':'V'}),
			('voltage end',{'type': float,'default':3,'units':'V'}),
			('scan points',{'type':int,'default':100}),
			('AWG channel',{'type':int,'default':0}),
			('Scale factor',{'type':float,'default':2})
		]
		w=ParamWidget(params)
		return w

	@Element(name='Experiment Parameters')
	def exp_parameters(self):
		params = [
	#    ('arbname', {'type': str, 'default': 'arbitrary_name'}),,
		('# of points', {'type': int, 'default': 40}),
		('Measurement Time', {'type': int, 'default': 180, 'units':'s'}),
		('File Name', {'type': str}),
		('AWG Pulse Repetition Period',{'type': float,'default': 2e-3,'units':'s'}),
		('AWG Pulse Frequency',{'type': int,'default': 500,'units':'Hz'}),
		('AWG Pulse Width',{'type': float,'default': 300e-9,'units':'s'}),
		]
		w = ParamWidget(params)
		return w

	@Element(name='QuTAG Parameters')
	def qutag_params(self):
		params = [
	#    ('arbname', {'type': str, 'default': 'arbitrary_name'}),,
		('Start Channel', {'type': int, 'default': 0}),
		('Stop Channel', {'type': int, 'default': 2}),
		('Bin Count', {'type': int, 'default': 1000}),
		# ('Voltmeter Channel 1',{'type':int,'default':1}),
		('Voltmeter Channel 2',{'type':int,'default':2}),
		# ('Battery Port 1',{'type':int,'default':5}),
		('Battery Port 2',{'type':int,'default':6})
		]
		w = ParamWidget(params)
		return w

	@Element(name='Spectral diffusion experiment parameters')
	def SD_wAWGparams(self):
		""" Widget containing the parameters used in the spectral diffusion
		experiment.

		Default EOM voltage calibrated by Christina and Yizhong on 11/19/20.
		(rough estimate for equal amplitude sidebands)
		"""
		params=[
		('Start frequency',{'type':float,'default':3.1e6,'units':'Hz'}),
		('Stop frequency',{'type':float,'default':3.3e6,'units':'Hz'}),
		('EOM voltage',{'type':float,'default':6,'units':'V'}),
		('Runtime',{'type':float,'default':300,'units':'s'}),
		('EOM channel',{'type':int,'default':1}),
		('Pulse channel',{'type':int,'default':2}),
		('Pulse Repetition Period',{'type': float,'default': 0.001,'units':'s'}),
		('Pulse Frequency',{'type': int,'default': 1000,'units':'Hz'}),
		('Pulse Width',{'type': float,'default': 500e-9,'units':'s'}),
		('Wavelength',{'type':float,'default':1535.61}),
		('# of points',{'type':int,'default':2}),
		('File Name',{'type':str}),
		]
		w=ParamWidget(params)
		return w

	#@Element(name='Spectral diffusion experiment parameters')
	#def SD_wRFparams(self):
		""" Widget containing the parameters used in the spectral diffusion
		experiment.

		Default EOM voltage calibrated by Christina and Yizhong on 11/19/20.
		(rough estimate for equal amplitude sidebands)
		"""
		"""
		params=[
		('Start frequency',{'type':float,'default':5e6,'units':'Hz'}),
		('Stop frequency',{'type':float,'default':200e6,'units':'Hz'}),
		('RF Power',{'type':float,'default':-1.30,'units':'dBm'}),
		('Runtime',{'type':float,'default':10,'units':'s'}),
		('Wavelength',{'type':float,'default':1536.480}),
		('Period',{'type':float,'default':100e-3,'units':'s'}),
		('# of points',{'type':int,'default':40}),
		('File Name',{'type':str}),
		]
		w=ParamWidget(params)
		return w
		"""

	@startpulse.initializer
	def initialize(self):
		self.wm.start_data()

	@startpulse.finalizer
	def finalize(self):
		self.wm.stop_data()
		print('Lifetime measurements complete.')
		return

	@qutagInit.initializer
	def initialize(self):
		from lantz.drivers.qutools import QuTAG
		self.qutag = QuTAG()
		devType = self.qutag.getDeviceType()
		print('devType: '+str(devType))
		if (devType == self.qutag.DEVTYPE_QUTAG):
			print("found quTAG!")
		else:
			print("no suitable device found - demo mode activated")
		print("Device timebase:" + str(self.qutag.getTimebase()))
		return

	@qutagInit.finalizer
	def finalize(self):
		return
Exemplo n.º 8
0
class Rabi2(Spyrelet):
    requires = {'fungen': Keysight_33622A}
    qutag = None

    def configureQutag(self):
        qutagparams = self.qutag_params.widget.get()
        start = qutagparams['Start Channel']
        stop = qutagparams['Stop Channel']
        ##True = rising edge, False = falling edge. Final value is threshold voltage
        self.qutag.setSignalConditioning(start, self.qutag.SIGNALCOND_MISC,
                                         True, 1)
        self.qutag.setSignalConditioning(stop, self.qutag.SIGNALCOND_MISC,
                                         True, 0.1)
        self.qutag.enableChannels((start, stop))

    def createHistogram(self, stoparray, timebase, bincount, period, index):
        hist = [0] * bincount
        for stoptime in stoparray:
            binNumber = int(stoptime * timebase * bincount / (period))
            if binNumber >= bincount:
                continue
            else:
                hist[binNumber] += 1
        out_name = "D:\\Data\\5.27.2019\\Rabi2\\Round5"
        np.savez(os.path.join(out_name, str(index * 50 + 200)), hist)
        print('Data stored under File Name: ' +
              self.exp_parameters.widget.get()['File Name'] + str(index))

    def makePulse(self, pulse_width, i):
        timestep = 1e-9
        self.fungen.output[1] = 'OFF'
        self.fungen.output[2] = 'OFF'
        self.fungen.clear_mem(1)
        self.fungen.clear_mem(2)
        params = self.pulse_parameters.widget.get()
        period = params['period'].magnitude
        repeat_unit = 50e-9

        buffer1 = Arbseq_Class('buffer1', timestep)
        buffer1.delays = [0]
        buffer1.heights = [0]
        buffer1.widths = [pulse_width]
        buffer1.totaltime = pulse_width
        buffer1.nrepeats = 0
        buffer1.repeatstring = 'once'
        buffer1.markerstring = 'highAtStartGoLow'
        buffer1.markerloc = 0
        buffer1.create_sequence()

        pulse = Arbseq_Class('pulse', timestep)
        pulse.delays = [0]
        pulse.heights = [1]
        pulse.widths = [pulse_width]
        pulse.totaltime = pulse_width
        pulse.nrepeats = 0
        pulse.repeatstring = 'once'
        pulse.markerstring = 'lowAtStart'
        pulse.markerloc = 0
        pulse.create_sequence()

        offset1 = Arbseq_Class('offset1', timestep)
        offset1.delays = [0]
        offset1.heights = [0]
        offset1.widths = [pulse_width]
        offset1.totaltime = pulse_width
        offset1.nrepeats = 0
        offset1.repeatstring = 'once'
        offset1.markerstring = 'lowAtStart'
        offset1.markerloc = 0
        offset1.create_sequence()

        dc = Arbseq_Class('dc', timestep)
        dc.delays = [0]
        dc.heights = [0]
        dc.widths = [params['pulse width'].magnitude]
        dc.totaltime = params['pulse width'].magnitude
        dc.repeatstring = 'repeat'
        dc.markerstring = 'lowAtStart'
        dc.markerloc = 0
        width = params['pulse width'].magnitude
        repeats = period / width - 3
        dc.nrepeats = repeats
        dc.create_sequence()

        buffer2 = Arbseq_Class('buffer2', timestep)
        buffer2.delays = [0]
        buffer2.heights = [1]
        buffer2.widths = [pulse_width]
        buffer2.totaltime = pulse_width
        buffer2.nrepeats = 0
        buffer2.repeatstring = 'once'
        buffer2.markerstring = 'lowAtStart'
        buffer2.markerloc = 0
        buffer2.create_sequence()

        pulse2 = Arbseq_Class('pulse2', timestep)
        pulse2.delays = [0]
        pulse2.heights = [1]
        pulse2.widths = [pulse_width]
        pulse2.totaltime = pulse_width
        pulse2.nrepeats = 0
        pulse2.repeatstring = 'once'
        pulse2.markerstring = 'lowAtStart'
        pulse2.markerloc = 0
        pulse2.create_sequence()

        offset2 = Arbseq_Class('offset2', timestep)
        offset2.delays = [0]
        offset2.heights = [1]
        offset2.widths = [pulse_width]
        offset2.totaltime = pulse_width
        offset2.nrepeats = 0
        offset2.repeatstring = 'once'
        offset2.markerstring = 'lowAtStart'
        offset2.markerloc = 0
        offset2.create_sequence()

        dc2 = Arbseq_Class('dc2', timestep)
        dc2.delays = [0]
        dc2.heights = [-1]
        dc2.widths = [params['pulse width'].magnitude]
        dc2.totaltime = params['pulse width'].magnitude
        dc2.repeatstring = 'repeat'
        dc2.markerstring = 'lowAtStart'
        dc2.markerloc = 0
        period2 = params['period'].magnitude
        width2 = params['pulse width'].magnitude
        repeats = period2 / width2 - 3
        dc2.nrepeats = repeats
        dc2.create_sequence()

        self.fungen.send_arb(buffer1, 1)
        self.fungen.send_arb(pulse, 1)
        self.fungen.send_arb(offset1, 1)
        self.fungen.send_arb(dc, 1)
        self.fungen.send_arb(buffer2, 2)
        self.fungen.send_arb(pulse2, 2)
        self.fungen.send_arb(offset2, 2)
        self.fungen.send_arb(dc2, 2)

        seq = [buffer1, pulse, offset1, dc]
        seq2 = [buffer2, pulse2, offset2, dc2]

        self.fungen.create_arbseq('twoPulse', seq, 1)
        self.fungen.create_arbseq('shutter', seq2, 2)
        self.fungen.wait()
        self.fungen.voltage[
            1] = params['pulse height'].magnitude + 0.000000000001 * i
        self.fungen.voltage[2] = 7.1 + 0.000000000001 * i
        self.fungen.sync()

        print(self.fungen.voltage[1])
        self.fungen.output[2] = 'ON'
        self.fungen.output[1] = 'ON'

    @Task()
    def startpulse(self, timestep=1e-9):
        self.configureQutag()

        qutagparams = self.qutag_params.widget.get()
        lost = self.qutag.getLastTimestamps(True)  # clear Timestamp buffer
        stoptimestamp = 0
        synctimestamp = 0
        bincount = qutagparams['Bin Count']
        timebase = self.qutag.getTimebase()
        start = qutagparams['Start Channel']
        stop = qutagparams['Stop Channel']
        pulse_width = 200e-9
        expparams = self.exp_parameters.widget.get()
        period = self.pulse_parameters.widget.get()['period'].magnitude
        for i in range(expparams['# of points']):
            self.makePulse(pulse_width, i)
            stoparray = []
            startTime = time.time()
            lost = self.qutag.getLastTimestamps(True)
            while time.time(
            ) - startTime < expparams['Measurement Time'].magnitude:
                time.sleep(10 * period)
                timestamps = self.qutag.getLastTimestamps(True)

                tstamp = timestamps[0]  # array of timestamps
                tchannel = timestamps[1]  # array of channels
                values = timestamps[2]  # number of recorded timestamps
                print(values)
                for k in range(values):
                    # output all stop events together with the latest start event
                    # if tchannel[k] == start:
                    # 	synctimestamp = tstamp[k]
                    # else:
                    # 	stoptimestamp = tstamp[k]
                    stoparray.append(tstamp[k])
            self.createHistogram(stoparray, timebase, bincount, period, i)
            pulse_width += 50e-9

        self.fungen.output[1] = 'OFF'

    @Task()
    def qutagInit(self):
        print('qutag successfully initialized')

    @Element(name='Pulse parameters')
    def pulse_parameters(self):
        params = [
            #    ('arbname', {'type': str, 'default': 'arbitrary_name'}),,
            ('pulse height', {
                'type': float,
                'default': 3,
                'units': 'V'
            }),
            ('pulse width', {
                'type': float,
                'default': 300e-9,
                'units': 's'
            }),
            ('period', {
                'type': float,
                'default': 0.1,
                'units': 's'
            }),
        ]
        w = ParamWidget(params)
        return w

    @Element(name='Experiment Parameters')
    def exp_parameters(self):
        params = [
            #    ('arbname', {'type': str, 'default': 'arbitrary_name'}),,
            ('# of points', {
                'type': int,
                'default': 20
            }),
            ('Measurement Time', {
                'type': int,
                'default': 10,
                'units': 's'
            }),
            ('File Name', {
                'type': str
            })
        ]
        w = ParamWidget(params)
        return w

    @Element(name='QuTAG Parameters')
    def qutag_params(self):
        params = [
            #    ('arbname', {'type': str, 'default': 'arbitrary_name'}),,
            ('Start Channel', {
                'type': int,
                'default': 0
            }),
            ('Stop Channel', {
                'type': int,
                'default': 1
            }),
            ('Bin Count', {
                'type': int,
                'default': 1000
            })
        ]
        w = ParamWidget(params)
        return w

    @startpulse.initializer
    def initialize(self):
        self.fungen.output[1] = 'OFF'
        self.fungen.output[2] = 'OFF'
        self.fungen.clear_mem(1)
        self.fungen.clear_mem(2)
        self.fungen.wait()

    @startpulse.finalizer
    def finalize(self):
        self.fungen.output[1] = 'OFF'
        self.fungen.output[2] = 'OFF'
        print('Lifetime measurements complete.')
        return

    @qutagInit.initializer
    def initialize(self):
        from lantz.drivers.qutools import QuTAG
        self.qutag = QuTAG()
        devType = self.qutag.getDeviceType()
        if (devType == self.qutag.DEVTYPE_QUTAG):
            print("found quTAG!")
        else:
            print("no suitable device found - demo mode activated")
        print("Device timebase:" + str(self.qutag.getTimebase()))
        return

    @qutagInit.finalizer
    def finalize(self):
        return
class Lifetimewithshutter(Spyrelet):
    requires = {'fungen': Keysight_33622A, 'wm': Bristol_771, 'srs': SRS900}
    qutag = None

    def configureQutag(self):
        qutagparams = self.qutag_params.widget.get()
        start = qutagparams['Start Channel']
        stop = qutagparams['Stop Channel']
        ##True = rising edge, False = falling edge. Final value is threshold voltage
        self.qutag.setSignalConditioning(start, self.qutag.SIGNALCOND_MISC,
                                         True, 1)
        self.qutag.setSignalConditioning(stop, self.qutag.SIGNALCOND_MISC,
                                         True, 0.1)
        self.qutag.enableChannels((start, stop))

    def createHistogram(self, stoparray, timebase, bincount, period, index,
                        wls):
        hist = [0] * bincount
        for stoptime in stoparray:
            binNumber = int(stoptime * timebase * bincount / (period))
            if binNumber >= bincount:
                print('lost: ' + str(stoptime))
            else:
                hist[binNumber] += 1
        out_name = "D:\\Data\\5.15.2019\\T1"
        np.savez(
            os.path.join(
                out_name,
                self.exp_parameters.widget.get()['File Name'] + str(index)),
            hist, wls)
        print('Data stored under File Name: ' +
              self.exp_parameters.widget.get()['File Name'] + str(index))

    @Task()
    def startpulse(self, timestep=1e-9):
        self.fungen.output[1] = 'OFF'
        self.fungen.output[2] = 'OFF'
        self.fungen.clear_mem(1)
        self.fungen.clear_mem(2)
        self.fungen.wait()
        params = self.pulse_parameters.widget.get()
        tau = params['start tau']
        period = params['period'].magnitude

        chn1pulse = Arbseq_Class('chn1pulse', timestep)
        chn1pulse.delays = [0]
        chn1pulse.heights = [1]
        chn1pulse.widths = [params['pulse width'].magnitude]
        chn1pulse.totaltime = params['pulse width'].magnitude
        chn1pulse.nrepeats = 0
        chn1pulse.repeatstring = 'once'
        chn1pulse.markerstring = 'highAtStartGoLow'
        chn1pulse.markerloc = 0
        chn1pulsewidth = params['pulse width'].magnitude
        chn1pulse.create_sequence()

        chn1dc = Arbseq_Class('chn1dc', timestep)
        chn1dc.delays = [0]
        chn1dc.heights = [0]
        chn1dc.widths = [params['repeat unit'].magnitude]
        chn1dc.totaltime = params['repeat unit'].magnitude
        chn1dc.repeatstring = 'repeat'
        chn1dc.markerstring = 'lowAtStart'
        chn1dc.markerloc = 0
        chn1dcrepeats = int((tau.magnitude - params['pulse width'].magnitude) /
                            (params['repeat unit'].magnitude))
        chn1dc.nrepeats = chn1dcrepeats
        chn1dcwidth = (params['repeat unit'].magnitude) * chn1dcrepeats
        print(tau.magnitude, params['pulse width'].magnitude, chn1dcrepeats)
        chn1dc.create_sequence()

        chn1pulse2 = Arbseq_Class('chn1pulse2', timestep)
        chn1pulse2.delays = [0]
        chn1pulse2.heights = [1]
        chn1pulse2.widths = [params['pulse width'].magnitude]
        chn1pulse2.totaltime = params['pulse width'].magnitude
        chn1pulse2width = params['pulse width'].magnitude
        chn1pulse2.nrepeats = 0
        chn1pulse2.repeatstring = 'once'
        chn1pulse2.markerstring = 'lowAtStart'
        chn1pulse2.markerloc = 0
        chn1pulse2.create_sequence()

        chn1pulse3 = Arbseq_Class('chn1pulse3', timestep)
        chn1pulse3.delays = [0]
        chn1pulse3.heights = [0]
        chn1pulse3.widths = [params['repeat unit'].magnitude]
        chn1pulse3.totaltime = params['repeat unit'].magnitude
        chn1pulse3width = 400e-9
        chn1pulse3.nrepeats = 400e-9 / params['repeat unit'].magnitude
        chn1pulse3.repeatstring = 'repeat'
        chn1pulse3.markerstring = 'lowAtStart'
        chn1pulse3.markerloc = 0
        chn1pulse3.create_sequence()

        chn1dc2 = Arbseq_Class('chn1dc2', timestep)
        chn1dc2.delays = [0]
        chn1dc2.heights = [0]
        chn1dc2.widths = [params['repeat unit'].magnitude]
        chn1dc2.totaltime = params['repeat unit'].magnitude
        chn1dc2.repeatstring = 'repeat'
        chn1dc2.markerstring = 'lowAtStart'
        chn1dc2repeats = int(
            (params['period'].magnitude - tau.magnitude -
             params['pulse width'].magnitude - chn1pulse3width) /
            (params['repeat unit'].magnitude))
        chn1dc2.nrepeats = chn1dc2repeats
        chn1dc2.markerloc = 0
        print((chn1dc2repeats * params['repeat unit'].magnitude) +
              tau.magnitude + params['pulse width'].magnitude)
        chn1dc2.create_sequence()

        chn2pulse1 = Arbseq_Class('chn2pulse1', timestep)
        chn2pulse1.delays = [0]
        chn2pulse1.heights = [1]
        # chn2pulse1width = pulsewidth+pulse2width+dcwidth
        chn2pulse1.widths = [params['pulse width'].magnitude]
        chn2pulse1.totaltime = params['pulse width'].magnitude
        chn2pulse1.nrepeats = 0
        chn2pulse1.repeatstring = 'once'
        chn2pulse1.markerstring = 'highAtStartGoLow'
        chn2pulse1.markerloc = 0
        chn2pulse1.create_sequence()
        chn2dc1 = Arbseq_Class('chn2dc1', timestep)
        chn2dc1.delays = [0]
        chn2dc1.heights = [1]
        chn2dc1.widths = [params['repeat unit'].magnitude]
        chn2dc1.totaltime = params['repeat unit'].magnitude
        chn2dc1.repeatstring = 'repeat'
        chn2dc1.markerstring = 'lowAtStart'
        chn2dc1.markerloc = 0
        chn2dc1repeats = int(
            (tau.magnitude - params['pulse width'].magnitude) /
            (params['repeat unit'].magnitude))
        chn2dc1.nrepeats = chn2dc1repeats
        chn2dc1width = (params['repeat unit'].magnitude) * chn2dc1repeats
        chn2dc1.create_sequence()

        chn2pulse2 = Arbseq_Class('chn2pulse2', timestep)
        chn2pulse2.delays = [0]
        chn2pulse2.heights = [1]
        chn2pulse2.widths = [params['pulse width'].magnitude]
        chn2pulse2.totaltime = params['pulse width'].magnitude
        chn2pulse2width = params['pulse width'].magnitude
        chn2pulse2.nrepeats = 0
        chn2pulse2.repeatstring = 'once'
        chn2pulse2.markerstring = 'lowAtStart'
        chn2pulse2.markerloc = 0
        chn2pulse2.create_sequence()

        chn2pulse3 = Arbseq_Class('chn2pulse3', timestep)
        chn2pulse3.delays = [0]
        chn2pulse3.heights = [1]
        chn2pulse3.widths = [params['repeat unit'].magnitude]
        chn2pulse3.totaltime = params['repeat unit'].magnitude
        chn2pulse3width = 400e-9
        chn2pulse3.nrepeats = 400e-9 / params['repeat unit'].magnitude
        chn2pulse3.repeatstring = 'repeat'
        chn2pulse3.markerstring = 'lowAtStart'
        chn2pulse3.markerloc = 0
        chn2pulse3.create_sequence()

        chn2dc2 = Arbseq_Class('chn2dc2', timestep)
        chn2dc2.delays = [0]
        chn2dc2.heights = [-1]
        chn2dc2.widths = [params['repeat unit'].magnitude]
        chn2dc2.totaltime = params['repeat unit'].magnitude
        chn2dc2.repeatstring = 'repeat'
        chn2dc2.markerstring = 'lowAtStart'
        chn2dc2repeats = int(
            (params['period'].magnitude - tau.magnitude -
             params['pulse width'].magnitude - chn2pulse3width) /
            (params['repeat unit'].magnitude))
        chn2dc2.nrepeats = chn2dc2repeats
        chn2dc2.markerloc = 0
        print((chn2dc2repeats * params['repeat unit'].magnitude) +
              tau.magnitude + params['pulse width'].magnitude)
        chn2dc2.create_sequence()

        self.fungen.send_arb(chn1pulse, 1)
        self.fungen.send_arb(chn1dc, 1)
        self.fungen.send_arb(chn1pulse2, 1)
        self.fungen.send_arb(chn1pulse3, 1)
        self.fungen.send_arb(chn1dc2, 1)
        self.fungen.send_arb(chn2pulse1, 2)
        self.fungen.send_arb(chn2dc1, 2)
        self.fungen.send_arb(chn2pulse2, 2)
        self.fungen.send_arb(chn2pulse3, 2)
        self.fungen.send_arb(chn2dc2, 2)

        seq = [chn1pulse, chn1dc, chn1pulse2, chn1pulse3, chn1dc2]
        seq2 = [chn2pulse1, chn2dc1, chn2pulse2, chn2pulse3, chn2dc2]

        self.fungen.create_arbseq('twoPulse', seq, 1)
        self.fungen.create_arbseq('shutter', seq2, 2)
        self.fungen.wait()
        self.fungen.voltage[
            1] = params['pulse height'].magnitude + 0.000000000001
        self.fungen.voltage[2] = 7.0 + 0.0000000000001

        print(self.fungen.voltage[1], self.fungen.voltage[2])
        self.fungen.output[1] = 'ON'
        self.fungen.output[2] = 'ON'
        #self.fungen.output[2] = 'OFF'
        self.fungen.trigger_delay(1, 400e-9)
        self.fungen.sync()

        self.srs.module_reset[5]
        self.srs.SIM928_voltage[5] = params['srs bias'].magnitude
        self.srs.SIM928_on[5]

        self.configureQutag()

        qutagparams = self.qutag_params.widget.get()
        lost = self.qutag.getLastTimestamps(True)  # clear Timestamp buffer
        stoptimestamp = 0
        synctimestamp = 0
        bincount = qutagparams['Bin Count']
        timebase = self.qutag.getTimebase()
        start = qutagparams['Start Channel']
        stop = qutagparams['Stop Channel']

        expparams = self.exp_parameters.widget.get()
        for i in range(expparams['# of points']):
            ##Wavemeter measurements
            stoparray = []
            startTime = time.time()
            wls = []
            lost = self.qutag.getLastTimestamps(True)
            while time.time(
            ) - startTime < expparams['Measurement Time'].magnitude:
                lost = self.qutag.getLastTimestamps(True)
                time.sleep(30 * period)
                timestamps = self.qutag.getLastTimestamps(True)

                tstamp = timestamps[0]  # array of timestamps
                tchannel = timestamps[1]  # array of channels
                values = timestamps[2]  # number of recorded timestamps
                for k in range(values):
                    # output all stop events together with the latest start event
                    if tchannel[k] == start:
                        synctimestamp = tstamp[k]
                    else:
                        stoptimestamp = tstamp[k]
                        stoparray.append(stoptimestamp)
                wls.append(str(self.wm.measure_wavelength()))
            self.createHistogram(stoparray, timebase, bincount, period, i, wls)
            print('Approx. ' + str(
                int((expparams['# of points'] - i) /
                    expparams['Measurement Time'].magnitude)) + ' min left')
            #self.fungen.voltage[2] = self.fungen.voltage[2].magnitude + 2*dcparams['DC step size'].magnitude

        self.fungen.output[1] = 'OFF'
        self.fungen.output[2] = 'OFF'
        startTime = time.time()
        startWl = self.wm.measure_wavelength()
        stoparray = []
        lastwls = []
        while time.time(
        ) - startTime < expparams['Measurement Time'].magnitude:
            time.sleep(period)
            timestamps = self.qutag.getLastTimestamps(True)

            tstamp = timestamps[0]  # array of timestamps
            tchannel = timestamps[1]  # array of channels
            values = timestamps[2]  # number of recorded timestamps
            for k in range(values):
                # output all stop events together with the latest start event
                if tchannel[k] == start:
                    synctimestamp = tstamp[k]
                else:
                    stoptimestamp = tstamp[k]
                    stoparray.append(stoptimestamp)
            lastwls.append(str(self.wm.measure_wavelength()))
        self.createHistogram(stoparray, timebase, bincount, period, 'bg',
                             lastwls)

    @Task()
    def qutagInit(self):
        print('qutag successfully initialized')

    @Element(name='Pulse parameters')
    def pulse_parameters(self):
        params = [
            #    ('arbname', {'type': str, 'default': 'arbitrary_name'}),,
            ('pulse height', {
                'type': float,
                'default': 3,
                'units': 'V'
            }),
            ('pulse width', {
                'type': float,
                'default': 1000e-9,
                'units': 's'
            }),
            ('period', {
                'type': float,
                'default': 0.1,
                'units': 's'
            }),
            ('repeat unit', {
                'type': float,
                'default': 50e-9,
                'units': 's'
            }),
            ('start tau', {
                'type': float,
                'default': 2e-6,
                'units': 's'
            }),
            ('stop tau', {
                'type': float,
                'default': 10e-6,
                'units': 's'
            }),
            ('step tau', {
                'type': float,
                'default': 1e-6,
                'units': 's'
            }),
            ('srs bias', {
                'type': float,
                'default': 1.2,
                'units': 'V'
            })
        ]
        w = ParamWidget(params)
        return w

    @Element(name='Experiment Parameters')
    def exp_parameters(self):
        params = [
            #    ('arbname', {'type': str, 'default': 'arbitrary_name'}),,
            ('# of points', {
                'type': int,
                'default': 10
            }),
            ('Measurement Time', {
                'type': int,
                'default': 300,
                'units': 's'
            }),
            ('File Name', {
                'type': str
            })
        ]
        w = ParamWidget(params)
        return w

    @Element(name='QuTAG Parameters')
    def qutag_params(self):
        params = [
            #    ('arbname', {'type': str, 'default': 'arbitrary_name'}),,
            ('Start Channel', {
                'type': int,
                'default': 0
            }),
            ('Stop Channel', {
                'type': int,
                'default': 1
            }),
            ('Bin Count', {
                'type': int,
                'default': 1000
            })
        ]
        w = ParamWidget(params)
        return w

    @startpulse.initializer
    def initialize(self):
        self.wm.start_data()
        self.fungen.output[1] = 'OFF'
        self.fungen.output[2] = 'OFF'
        self.fungen.clear_mem(1)
        self.fungen.clear_mem(2)
        self.fungen.wait()

    @startpulse.finalizer
    def finalize(self):
        self.wm.stop_data()
        self.fungen.output[1] = 'OFF'
        self.fungen.output[2] = 'OFF'
        print('Lifetime measurements complete.')
        return

    @qutagInit.initializer
    def initialize(self):
        from lantz.drivers.qutools import QuTAG
        self.qutag = QuTAG()
        devType = self.qutag.getDeviceType()
        if (devType == self.qutag.DEVTYPE_QUTAG):
            print("found quTAG!")
        else:
            print("no suitable device found - demo mode activated")
        print("Device timebase:" + str(self.qutag.getTimebase()))
        return

    @qutagInit.finalizer
    def finalize(self):
        return