Exemple #1
0
def write_APS2_file(awgData, fileName):
    '''
	Main function to pack channel sequences into an APS2 h5 file.
	'''
    # Convert QGL IR into a representation that is closer to the hardware.
    awgData['ch12']['linkList'], wfLib = preprocess(
        awgData['ch12']['linkList'], awgData['ch12']['wfLib'],
        awgData['ch12']['correctionT'])

    # compress marker data
    for field in ['ch12m1', 'ch12m2', 'ch12m3', 'ch12m4']:
        if 'linkList' in awgData[field].keys():
            PatternUtils.convert_lengths_to_samples(awgData[field]['linkList'],
                                                    SAMPLING_RATE)
            compress_marker(awgData[field]['linkList'])
        else:
            awgData[field]['linkList'] = []

    #Create the waveform vectors
    wfInfo = []
    wfInfo.append(create_wf_vector({key: wf.real
                                    for key, wf in wfLib.items()}))
    wfInfo.append(create_wf_vector({key: wf.imag
                                    for key, wf in wfLib.items()}))

    # build instruction vector
    instructions = create_instr_data([
        awgData[s]['linkList']
        for s in ['ch12', 'ch12m1', 'ch12m2', 'ch12m3', 'ch12m4']
    ], wfInfo[0][1])

    #Open the HDF5 file
    if os.path.isfile(fileName):
        os.remove(fileName)
    with h5py.File(fileName, 'w') as FID:
        FID['/'].attrs['Version'] = 3.0
        FID['/'].attrs['channelDataFor'] = np.uint16([1, 2])

        #Create the groups and datasets
        for chanct in range(2):
            chanStr = '/chan_{0}'.format(chanct + 1)
            chanGroup = FID.create_group(chanStr)
            #Write the waveformLib to file
            FID.create_dataset(chanStr + '/waveforms', data=wfInfo[chanct][0])

            #Write the instructions to channel 1
            if np.mod(chanct, 2) == 0:
                FID.create_dataset(chanStr + '/instructions',
                                   data=instructions)
Exemple #2
0
def preprocess(seqs, shapeLib, T):
	for seq in seqs:
		PatternUtils.propagate_frame_changes(seq)
	seqs = PatternUtils.convert_lengths_to_samples(seqs, SAMPLING_RATE, ADDRESS_UNIT)
	PatternUtils.quantize_phase(seqs, 1.0/2**13)
	wfLib = build_waveforms(seqs, shapeLib)
	PatternUtils.correct_mixers(wfLib, T)
	return seqs, wfLib
Exemple #3
0
def write_sequence_file(awgData, fileName):
	'''
	Main function to pack channel sequences into an APS2 h5 file.
	'''
	# Convert QGL IR into a representation that is closer to the hardware.
	awgData['ch12']['linkList'], wfLib = preprocess(awgData['ch12']['linkList'],
	                                                awgData['ch12']['wfLib'],
	                                                awgData['ch12']['correctionT'])

	# compress marker data
	for field in ['ch12m1', 'ch12m2', 'ch12m3', 'ch12m4']:
		if 'linkList' in awgData[field].keys():
			PatternUtils.convert_lengths_to_samples(awgData[field]['linkList'], SAMPLING_RATE)
			compress_marker(awgData[field]['linkList'])
		else:
			awgData[field]['linkList'] = []

	#Create the waveform vectors
	wfInfo = []
	wfInfo.append(create_wf_vector({key:wf.real for key,wf in wfLib.items()}))
	wfInfo.append(create_wf_vector({key:wf.imag for key,wf in wfLib.items()}))

	# build instruction vector
	instructions = create_instr_data([awgData[s]['linkList'] for s in ['ch12', 'ch12m1', 'ch12m2', 'ch12m3', 'ch12m4']],
		wfInfo[0][1])

	#Open the HDF5 file
	if os.path.isfile(fileName):
		os.remove(fileName)
	with h5py.File(fileName, 'w') as FID:
		FID['/'].attrs['Version'] = 3.0
		FID['/'].attrs['channelDataFor'] = np.uint16([1,2])

		#Create the groups and datasets
		for chanct in range(2):
			chanStr = '/chan_{0}'.format(chanct+1)
			chanGroup = FID.create_group(chanStr)
			#Write the waveformLib to file
			FID.create_dataset(chanStr+'/waveforms', data=wfInfo[chanct][0])

			#Write the instructions to channel 1
			if np.mod(chanct,2) == 0:
				FID.create_dataset(chanStr+'/instructions', data=instructions)
Exemple #4
0
def preprocess(seqs, shapeLib, T):
    for seq in seqs:
        PatternUtils.propagate_frame_changes(seq)
    seqs = PatternUtils.convert_lengths_to_samples(seqs, SAMPLING_RATE,
                                                   ADDRESS_UNIT)
    PatternUtils.quantize_phase(seqs, 1.0 / 2**13)
    wfLib = build_waveforms(seqs, shapeLib)
    PatternUtils.correct_mixers(wfLib, T)
    return seqs, wfLib
Exemple #5
0
 def __init__(self, waveform):
     self.label = waveform.label
     self.key = waveform.key
     self.amp = waveform.amp
     self.length = PatternUtils.convert_length_to_samples(
         waveform.length, SAMPLING_RATE, ADDRESS_UNIT)
     self.phase = waveform.phase
     self.frameChange = waveform.frameChange
     self.isTimeAmp = waveform.isTimeAmp
     self.frequency = waveform.frequency
     self.repeat = 1
     self.markerDelay1 = None
     self.markerDelay2 = None
Exemple #6
0
def preprocess(seqs, shapeLib, T):
	seqs, miniLLrepeat = unroll_loops(seqs)
	for seq in seqs:
		PatternUtils.propagate_frame_changes(seq)
	seqs = PatternUtils.convert_lengths_to_samples(seqs, SAMPLING_RATE, ADDRESS_UNIT)
	PatternUtils.quantize_phase(seqs, 1.0/2**13)
	compress_sequences(seqs)
	wfLib = build_waveforms(seqs, shapeLib)
	PatternUtils.correct_mixers(wfLib, T)
	for ct in range(len(seqs)):
		seqs[ct] = apply_min_pulse_constraints(seqs[ct], wfLib)
	return seqs, miniLLrepeat, wfLib
Exemple #7
0
def preprocess(seqs, shapeLib, T):
    seqs, miniLLrepeat = unroll_loops(seqs)
    for seq in seqs:
        PatternUtils.propagate_frame_changes(seq)
    seqs = PatternUtils.convert_lengths_to_samples(seqs, SAMPLING_RATE,
                                                   ADDRESS_UNIT)
    PatternUtils.quantize_phase(seqs, 1.0 / 2**13)
    compress_sequences(seqs)
    wfLib = build_waveforms(seqs, shapeLib)
    PatternUtils.correct_mixers(wfLib, T)
    for ct in range(len(seqs)):
        seqs[ct] = apply_min_pulse_constraints(seqs[ct], wfLib)
    return seqs, miniLLrepeat, wfLib
Exemple #8
0
def preprocess(seqs, shapeLib, T):
    for seq in seqs:
        for ct, e in enumerate(seq):
            if isinstance(e, Compiler.Waveform):
                seq[ct] = APSWaveform(e)
    seqs, miniLLrepeat = unroll_loops(seqs)
    for seq in seqs:
        PatternUtils.propagate_frame_changes(seq, wf_type=APSWaveform)
    PatternUtils.quantize_phase(seqs, 1.0 / 2**13, wf_type=APSWaveform)
    compress_sequences(seqs)
    wfLib = build_waveforms(seqs, shapeLib)
    PatternUtils.correct_mixers(wfLib, T)
    for ct in range(len(seqs)):
        seqs[ct] = apply_min_pulse_constraints(seqs[ct], wfLib)
    return seqs, miniLLrepeat, wfLib
Exemple #9
0
def merge_APS_markerData(IQLL, markerLL, markerNum):
	'''
	Helper function to merge two marker channels into an IQ channel.
	'''
	if len(markerLL) == 0:
		return
	assert len(IQLL) <= len(markerLL), "Sequence length mismatch"
	if len(IQLL) < len(markerLL):
		for ct in range(len(markerLL) - len(IQLL)):
			IQLL.append([])

	for seq in markerLL:
		PatternUtils.convert_lengths_to_samples(seq, SAMPLING_RATE, ADDRESS_UNIT)

	markerAttr = 'markerDelay' + str(markerNum)

	#Step through the all the miniLL's together
	for miniLL_IQ, miniLL_m in zip_longest(IQLL, markerLL):
		#Find the switching points of the marker channels
		switchPts = []
		prevAmplitude = 0
		t = 0
		for entry in miniLL_m:
			if hasattr(entry, 'amp') and prevAmplitude != entry.amp:
				switchPts.append(t)
				prevAmplitude = entry.amp
			t += entry.length

		if len(switchPts) == 0:
			# need at least a WAIT on an empty IQ LL in order to match segment sequencing
			if len(miniLL_IQ) == 0:
				miniLL_IQ.append(ControlFlow.qwait())
			continue

		# Push on an extra switch point if we have an odd number of switches (to maintain state)
		if len(switchPts) % 2 == 1:
			switchPts.append(t)

		#Assume switch pts seperated by 0 or 1 point are single trigger blips
		blipPts = (np.diff(switchPts) <= 1).nonzero()[0]
		for pt in blipPts[::-1]:
			del switchPts[pt+1]

		# if the IQ sequence is empty, make an ideally length-matched sequence
		if len(miniLL_IQ) == 0:
			miniLL_IQ.append(ControlFlow.qwait())
			miniLL_IQ.append(padding_entry(max(switchPts[0], MIN_ENTRY_LENGTH)))
			for length in np.diff(switchPts):
				miniLL_IQ.append(padding_entry(max(length, MIN_ENTRY_LENGTH)))

		#Find the cummulative length for each entry of IQ channel
		timePts = np.cumsum([0] + [entry.length for entry in miniLL_IQ])

		#Ensure the IQ LL is long enough to support the blips
		if max(switchPts) >= timePts[-1]:
			dt = max(switchPts) - timePts[-1]
			if hasattr(miniLL_IQ[-1], 'isTimeAmp') and miniLL_IQ[-1].isTimeAmp:
				miniLL_IQ[-1].length += dt + 4
			else:
				# inject before any control flow statements at the end of the sequence
				idx = len(miniLL_IQ)
				while idx > 0 and isinstance(miniLL_IQ[idx-1], ControlFlow.ControlInstruction):
					idx -=1
				miniLL_IQ.insert(idx, padding_entry(max(dt+4, MIN_ENTRY_LENGTH)))

		#Now map onto linklist elements
		curIQIdx = 0
		trigQueue = []
		for switchPt in switchPts:
			# skip if:
			#   1) control-flow instruction or label (i.e. not a waveform)
			#   2) the trigger count is too long
			#   3) the previous trigger pulse entends into the current entry
			while (not isinstance(miniLL_IQ[curIQIdx], Compiler.Waveform) or
				(switchPt - timePts[curIQIdx]) > (ADDRESS_UNIT * MAX_TRIGGER_COUNT) or
				len(trigQueue) > 1):
				# update the trigger queue, dropping triggers that have played
				trigQueue = [t - miniLL_IQ[curIQIdx].length for t in trigQueue]
				trigQueue = [t for t in trigQueue if t >= 0]
				curIQIdx += 1
				# add padding pulses if needed
				if curIQIdx >= len(miniLL_IQ):
					pad = max(MIN_ENTRY_LENGTH, min(trigQueue, 0))
					miniLL_IQ.append(padding_entry(pad))
			#Push on the trigger count

			#If our switch point is before the start of the LL entry then we are in trouble...
			if switchPt - timePts[curIQIdx] < 0:
				#See if the previous entry was a TA pair and whether we can split it
				needToShift = switchPt - timePts[curIQIdx-1]
				assert needToShift > MIN_ENTRY_LENGTH + ADDRESS_UNIT, "Sequential marker blips too close together."
				if isinstance(miniLL_IQ[curIQIdx-1], Compiler.Waveform) and \
					miniLL_IQ[curIQIdx-1].isTimeAmp and \
					miniLL_IQ[curIQIdx-1].length > (needToShift + MIN_ENTRY_LENGTH):

					miniLL_IQ.insert(curIQIdx, deepcopy(miniLL_IQ[curIQIdx-1]))
					miniLL_IQ[curIQIdx-1].length = needToShift-ADDRESS_UNIT
					miniLL_IQ[curIQIdx].length -= needToShift-ADDRESS_UNIT
					miniLL_IQ[curIQIdx].markerDelay1 = None
					miniLL_IQ[curIQIdx].markerDelay2 = None
					setattr(miniLL_IQ[curIQIdx], markerAttr, ADDRESS_UNIT)
					#Recalculate the timePts
					timePts = np.cumsum([0] + [entry.length for entry in miniLL_IQ])
				else:
					setattr(miniLL_IQ[curIQIdx], markerAttr, 0)
					print("Had to push marker blip out to start of next entry.")

			else:
				setattr(miniLL_IQ[curIQIdx], markerAttr, switchPt - timePts[curIQIdx])
				trigQueue.insert(0, switchPt - timePts[curIQIdx])
			# update the trigger queue
			trigQueue = [t - miniLL_IQ[curIQIdx].length for t in trigQueue]
			trigQueue = [t for t in trigQueue if t >= 0]
			curIQIdx += 1

	#Replace any remaining empty entries with None
	for miniLL_IQ in IQLL:
		for entry in miniLL_IQ:
			if isinstance(entry, Compiler.Waveform) and not hasattr(entry, markerAttr):
				setattr(entry, markerAttr, None)
Exemple #10
0
def merge_APS_markerData(IQLL, markerLL, markerNum):
    '''
	Helper function to merge two marker channels into an IQ channel.
	'''
    if len(markerLL) == 0:
        return
    assert len(IQLL) <= len(markerLL), "Sequence length mismatch"
    if len(IQLL) < len(markerLL):
        for ct in range(len(markerLL) - len(IQLL)):
            IQLL.append([])

    for seq in markerLL:
        PatternUtils.convert_lengths_to_samples(seq, SAMPLING_RATE,
                                                ADDRESS_UNIT,
                                                Compiler.Waveform)

    markerAttr = 'markerDelay' + str(markerNum)

    #Step through the all the miniLL's together
    for miniLL_IQ, miniLL_m in zip_longest(IQLL, markerLL):
        #Find the switching points of the marker channels
        switchPts = []
        prevAmplitude = 0
        t = 0
        for entry in miniLL_m:
            if hasattr(entry, 'amp') and prevAmplitude != entry.amp:
                switchPts.append(t)
                prevAmplitude = entry.amp
            t += entry.length

        if len(switchPts) == 0:
            # need at least a WAIT on an empty IQ LL in order to match segment sequencing
            if len(miniLL_IQ) == 0:
                miniLL_IQ.append(ControlFlow.qwait())
            continue

        # Push on an extra switch point if we have an odd number of switches (to maintain state)
        if len(switchPts) % 2 == 1:
            switchPts.append(t)

        #Assume switch pts seperated by 0 or 1 point are single trigger blips
        blipPts = (np.diff(switchPts) <= 1).nonzero()[0]
        for pt in blipPts[::-1]:
            del switchPts[pt + 1]

        # if the IQ sequence is empty, make an ideally length-matched sequence
        if len(miniLL_IQ) == 0:
            miniLL_IQ.append(ControlFlow.qwait())
            miniLL_IQ.append(padding_entry(max(switchPts[0],
                                               MIN_ENTRY_LENGTH)))
            for length in np.diff(switchPts):
                miniLL_IQ.append(padding_entry(max(length, MIN_ENTRY_LENGTH)))

        #Find the cummulative length for each entry of IQ channel
        timePts = np.cumsum([0] + [entry.length for entry in miniLL_IQ])

        #Ensure the IQ LL is long enough to support the blips
        if max(switchPts) >= timePts[-1]:
            dt = max(switchPts) - timePts[-1]
            if hasattr(miniLL_IQ[-1], 'isTimeAmp') and miniLL_IQ[-1].isTimeAmp:
                miniLL_IQ[-1].length += dt + 4
            else:
                # inject before any control flow statements at the end of the sequence
                idx = len(miniLL_IQ)
                while idx > 0 and isinstance(miniLL_IQ[idx - 1],
                                             ControlFlow.ControlInstruction):
                    idx -= 1
                miniLL_IQ.insert(idx,
                                 padding_entry(max(dt + 4, MIN_ENTRY_LENGTH)))

        #Now map onto linklist elements
        curIQIdx = 0
        trigQueue = []
        for ct, switchPt in enumerate(switchPts):
            # skip if:
            #   1) control-flow instruction or label (i.e. not a waveform)
            #   2) the trigger count is too long
            #   3) the previous trigger pulse entends into the current entry
            while (not isinstance(miniLL_IQ[curIQIdx], APSWaveform)
                   or (switchPt - timePts[curIQIdx]) >
                   (ADDRESS_UNIT * MAX_TRIGGER_COUNT) or len(trigQueue) > 1):
                # update the trigger queue, dropping triggers that have played
                trigQueue = [t - miniLL_IQ[curIQIdx].length for t in trigQueue]
                trigQueue = [t for t in trigQueue if t >= 0]
                curIQIdx += 1
                # add padding pulses if needed
                if curIQIdx >= len(miniLL_IQ):
                    if len(trigQueue) > 0:
                        pad = max(MIN_ENTRY_LENGTH, min(trigQueue, 0))
                    else:
                        pad = MIN_ENTRY_LENGTH
                    miniLL_IQ.append(padding_entry(pad))
            #Push on the trigger count

            #If our switch point is before the start of the LL entry then we are in trouble...
            if switchPt - timePts[curIQIdx] < 0:
                #See if the previous entry was a TA pair and whether we can split it
                needToShift = switchPt - timePts[curIQIdx - 1]
                assert needToShift > MIN_ENTRY_LENGTH + ADDRESS_UNIT, "Sequential marker blips too close together."
                if isinstance(miniLL_IQ[curIQIdx-1], APSWaveform) and \
                 miniLL_IQ[curIQIdx-1].isTimeAmp and \
                 miniLL_IQ[curIQIdx-1].length > (needToShift + MIN_ENTRY_LENGTH):

                    miniLL_IQ.insert(curIQIdx,
                                     deepcopy(miniLL_IQ[curIQIdx - 1]))
                    miniLL_IQ[curIQIdx - 1].length = needToShift - ADDRESS_UNIT
                    miniLL_IQ[curIQIdx].length -= needToShift - ADDRESS_UNIT
                    miniLL_IQ[curIQIdx].markerDelay1 = None
                    miniLL_IQ[curIQIdx].markerDelay2 = None
                    setattr(miniLL_IQ[curIQIdx], markerAttr, ADDRESS_UNIT)
                    #Recalculate the timePts
                    timePts = np.cumsum([0] +
                                        [entry.length for entry in miniLL_IQ])
                else:
                    setattr(miniLL_IQ[curIQIdx], markerAttr, 0)
                    print(
                        "Had to push marker blip out to start of next entry.")

            else:
                setattr(miniLL_IQ[curIQIdx], markerAttr,
                        switchPt - timePts[curIQIdx])
                trigQueue.insert(0, switchPt - timePts[curIQIdx])
            # update the trigger queue
            trigQueue = [t - miniLL_IQ[curIQIdx].length for t in trigQueue]
            trigQueue = [t for t in trigQueue if t >= 0]
            curIQIdx += 1

            # add padding pulses if needed
            if ct + 1 < len(switchPts) and curIQIdx >= len(miniLL_IQ):
                if len(trigQueue) > 0:
                    pad = max(MIN_ENTRY_LENGTH, min(trigQueue, 0))
                else:
                    pad = MIN_ENTRY_LENGTH
                miniLL_IQ.append(padding_entry(pad))