Skip to content
Snippets Groups Projects
Commit 012996e7 authored by Stephan Philips's avatar Stephan Philips
Browse files

updated sequencing in keysight upload module

parent 1956a4b2
No related branches found
No related tags found
No related merge requests found
No preview for this file type
No preview for this file type
......@@ -2,7 +2,7 @@ import numpy as np
import matplotlib.pyplot as plt
from segments import *
from keysight_fx import *
import uuid
'''
ideas:
......@@ -19,23 +19,23 @@ class pulselib:
def __init__(self):
self.awg_channels = ['P1','P2','P3','P4','P5','B0','B1','B2','B3','B4','B5','I_MW', 'Q_MW', 'M1', 'M2']
self.awg_channels_to_physical_locations = [{'B0',('AWG1', 1)},
{'P1',('AWG1', 2)},
{'B1',('AWG1', 3)},
{'P2',('AWG1', 4)},
{'B2',('AWG2', 1)},
{'P3',('AWG2', 2)},
{'B3',('AWG2', 3)},
{'P4',('AWG2', 4)},
{'B4',('AWG3', 1)},
{'P5',('AWG3', 2)},
{'B5',('AWG3', 3)},
{'B1',('AWG3', 4)},
{'I_MW',('AWG4', 1)},
{'Q_MW',('AWG4', 2)},
{'M1',('AWG4', 3)},
{'M2',('AWG4', 4)}]
self.awg_channels = ['P1','P2','P3','P4','P5','B0','B1','B2','B3','B4','B5','G1','I_MW', 'Q_MW', 'M1', 'M2']
self.awg_channels_to_physical_locations = dict({'B0':('AWG1', 1),
'P1':('AWG1', 2),
'B1':('AWG1', 3),
'P2':('AWG1', 4),
'B2':('AWG2', 1),
'P3':('AWG2', 2),
'B3':('AWG2', 3),
'P4':('AWG2', 4),
'B4':('AWG3', 1),
'P5':('AWG3', 2),
'B5':('AWG3', 3),
'G1':('AWG3', 4),
'I_MW':('AWG4', 1),
'Q_MW':('AWG4', 2),
'M1':('AWG4', 3),
'M2':('AWG4', 4)})
self.awg_channels_kind = []
# Not implemented
self.awg_markers =['mkr1', 'mkr2', 'mkr3' ]
......@@ -52,17 +52,17 @@ class pulselib:
# Keysight properties.
self.backend = 'keysight'
self.awg = keysight_awg(self.segments_bin, self.awg_channels_to_physical_locations, self.awg_channels)
# self.awg.add_awg('AWG1',awg1)
# self.awg.add_awg('AWG2',awg1)
# self.awg.add_awg('AWG3',awg1)
# self.awg.add_awg('AWG4',awg1)
self.awg.add_awg('AWG1','awg1')
self.awg.add_awg('AWG2','awg1')
self.awg.add_awg('AWG3','awg1')
self.awg.add_awg('AWG4','awg1')
self.sequencer = sequencer(self.awg, self.segments_bin)
def add_awgs(self, awg):
for i in awg:
self.devices.append(i)
self.awg.add_awg(i)
def mk_segment(self, name):
return self.segments_bin.new(name)
......@@ -136,15 +136,50 @@ class sequencer():
def __init__(self, awg_system, segment_bin):
self.awg = awg_system
self.segment_bin = segment_bin
self.channels = segment_bin.channels
self.sequences = dict()
def add_sequence(self, name, sequence):
self.sequences[name] = sequence
def start_sequence(self, name):
self.awg.upload(self.sequences[name])
self.awg.upload(self.sequences[name], self.get_sequence_upload_data(name))
self.awg.start(self.sequences[name])
def get_sequence_upload_data(self, name):
'''
Function that generates sequence data per channel.
It will also assign unique id's to unique sequences (sequence that depends on the time of playback). -> mainly important for iq mod purposes.
structure:
dict with key of channel:
for each channels list of sequence:
name of the segments,
number of times to play
uniqueness -> segment is reusable?
identifiers for marking differnt locations in the ram of the awg.
'''
upload_data = dict()
# put in a getter to make sure there is no error -- it exists...
seq = self.sequences[name]
for i in self.channels:
sequence_data_single_channel = []
for k in seq:
input_data = {'segment':k[0], 'ntimes':k[1]}
unique = getattr(self.segment_bin.get_segment(k[0]), i).unique
input_data['unique'] = unique
# Make unique uuid's for each segment
if unique == True:
input_data['identifier'] = [uuid.uuid4() for i in range(k[1])]
sequence_data_single_channel.append(input_data)
upload_data[i] = sequence_data_single_channel
return upload_data
p = pulselib()
seg = p.mk_segment('INIT')
seg2 = p.mk_segment('Manip')
......@@ -179,7 +214,7 @@ seg3.B5.add_block(30,600,0.1)
seg3.B5.wait(200)
p.show_sequences()
SEQ = [['INIT', 1, 0], ['Manip', 1, 0], ['INIT', 1, 0] ]
SEQ = [['INIT', 2, 0], ['Manip', 1, 0], ['INIT', 1, 0] ]
p.add_sequence('mysequence', SEQ)
......@@ -187,10 +222,10 @@ p.start_sequence('mysequence')
SEQ2 = [['INIT', 1, 0], ['Manip', 1, 0], ['Readout', 1, 0] ]
p.add_sequence('mysequence2', SEQ2)
# p.add_sequence('mysequence2', SEQ2)
p.start_sequence('mysequence2')
# p.start_sequence('mysequence2')
# insert in the begining of a segment
# seg.insert_mode()
# seg.clear()
......
......@@ -7,6 +7,8 @@ class keysight_awg():
def __init__(self, segment_bin, channel_locations,channels):
self.awg = dict()
self.awg_memory = dict()
# dict containing the number of the last segment number.
self.segment_count = dict()
self.current_waveform_number = 0
self.channel_locations = channel_locations
......@@ -39,14 +41,23 @@ class keysight_awg():
@property
def allocatable_mem(self):
alloc = self.maxmem
for i in self.awg_memory:
if alloc > i:
allow = i
for i in self.awg_memory.items():
if alloc > i[1]:
allow = i[1]
return alloc
def upload(self, sequence_data):
def get_new_segment_number(self, channel):
'''
gets a segment number for the new segment. These numbers just need to be unique.
'''
awg_name = self.channel_locations[channel][0]
self.segment_count[awg_name] += 1
return self.segment_count[awg_name]
def upload(self, sequence_data_raw, sequence_data_processed):
# step 1 collect vmin and vmax data, check if segments are intialized (e.g. have at least one pulse):
for i in sequence_data:
for i in sequence_data_raw:
segment_name = i[0]
if self.segment_bin.used(segment_name) == False:
raise ValueError("Empty segment provided .. (segment name: '{}')".format(segment_name))
......@@ -56,31 +67,79 @@ class keysight_awg():
# step 2 calculate Vpp/Voff needed for each channel.
self.adjust_vpp_data()
# step 3 check memory allocation (e.g. what can we reuse of the old sequences)
mem_needed = 0
for i in sequence_data:
segment_name = i[0]
if segment_name in self.segmentdata:
if self.segment_bin.get_segment(segment_name).last_mod > self.segmentdata(segment_name):
print('discarded , ', segment_name)
continue
else:
mem_needed += self.segment_bin.get_segment(segment_name).total_time
print(mem_needed)
# If memory full, clear
if mem_needed > self.allocatable_mem:
print("memory cleared .. upload will take a bit longer.")
self.clear_mem()
# step 3 check memory allocation (e.g. what can we reuse of the sequences in the memory of the AWG.)
mem_needed = dict()
for i in self.awg:
mem_needed[i] = 0
for chan, sequence_data in sequence_data_processed.items():
# loop trough all elements in the sequence and check how much data is needed.
t = 0
for i in sequence_data:
segment_name = i['segment']
repetitions= i['ntimes']
unique = i['unique']
# Check if stuff in the memory, if present, needs to be updated.
if segment_name in self.segmentdata[chan] and unique == False:
if self.segment_bin.get_segment(segment_name).last_mod > self.segmentdata(segment_name):
print('Reusing {} for channel {} '.format(segment_name, chan) )
continue
if unique == True:
mem_needed[self.channel_locations[chan][0]] += self.segment_bin.get_segment(segment_name).total_time * repetitions
else:
mem_needed[self.channel_locations[chan][0]] += self.segment_bin.get_segment(segment_name).total_time
# If memory full, clear (if one is full it is very likely all others are also full, so we will just clear everything.)
for i in self.awg:
if mem_needed[i] > self.allocatable_mem:
print("memory cleared .. upload will take a bit longer.")
self.clear_mem()
# step 4 upload the sequences to the awg.
for i in sequence_data:
segment_name = i[0]
if segment_name in self.segmentdata:
if self.segment_bin.get_segment(segment_name).last_mod <= self.segmentdata(segment_name):
segmend_data, channels = self.segment_bin.get_pulse(segment_name)
# This is the location to do post processing?
for chan, sequence_data in sequence_data_processed.items():
# Upload here sequences.
# Keep counting time of the segments. This is important for IQ data.
time = 0
for my_segment in sequence_data:
segment_name = my_segment['segment']
repetitions= my_segment['ntimes']
unique = my_segment['unique']
# Check if we need to skip the upload.
if segment_name in self.segmentdata[chan] and unique == False:
if self.segment_bin.get_segment(segment_name).last_mod > self.segmentdata(segment_name):
continue
if unique == False:
points = get_and_upload_waveform(chan,segment_name, time)
time += points
else:
for uuid in range(repetitions):
points = get_and_upload_waveform(chan,segment_name, time, my_segment['identifier'][uuid])
time += points
# step 5 make the queue
def get_and_upload_waveform(self, channel, segment_name, time, uuid=None):
'''
get the wavform for channel with the name segment_name.
The waveform occurs at time time in the sequence.
This function also adds the waveform to segmentdata variable
'''
seg_number = get_new_segment_number(chan)
segment_data = self.segment_bin.get_pulse(segment_name, chan, time)
# upload data
if uuid is None:
self.segmentdata[channel][segment_name] = seg_number
else:
self.segmentdata[channel][uuid] = seg_number
return len(segment_data)
def adjust_vmin_vmax_data(self, Vmin_max_data):
'''
Function that updates the values of the minimun and maximun volages needed for each channels.
......@@ -185,9 +244,12 @@ class keysight_awg():
name is name you want to give to your awg object. This needs to be unique and should is to describe which
channel belongs to which awg.
'''
# Make sure you start with a empty memory
# awg.flush_waveform()
self.awg[name] = awg, self.maxmem
self.awg_memory[name] =self.maxmem
self.segdata_awg_mem[name] = dict()
self.segment_count[name] = 0
def clear_mem(self):
'''
......@@ -198,6 +260,10 @@ class keysight_awg():
self.segmentdata = dict()
for i in self.awg.items():
i[1].flush_waveform()
for i in self.segment_count.items():
i[1] = 0
for i in self.awg_memory:
i = self.maxmem
print("Done.")
\ No newline at end of file
......@@ -16,6 +16,7 @@ class segment_container():
self.name = name
self.waveform_cache = None
self._Vmin_max_data = dict()
for i in self.channels:
self._Vmin_max_data[i] = {"v_min" : None, "v_max" : None}
......@@ -25,7 +26,7 @@ class segment_container():
# for i in self.channels:
# self.vpp_data[i] = {"V_min" : None, "V_max" : None}
# put this in a dict, you might have overwite.. . me layzy
# Not superclean should be in a different namespace.
for i in self.channels:
setattr(self, i, segment_single())
......@@ -122,6 +123,7 @@ class segment_single():
self.my_pulse_data = np.zeros([1,2])
self.last = None
self.IQ_data = [] #todo later.
self.unique = True
@last_edited
def add_pulse(self,array):
......@@ -222,4 +224,4 @@ class marker_single():
self.my_pulse_data = np.zeros([1,2])
def add(self, start, stop):
self.my_pulse_data = np,append(self.my_pulse_data, [[start,0],[start,1],[stop,1],[stop,0]])
self.my_pulse_data = np.append(self.my_pulse_data, [[start,0],[start,1],[stop,1],[stop,0]])
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment