In-Place Waveform Library Updates¶
This example notebook shows how one can update pulses data in-place without recompiling.
© Raytheon BBN Technologies 2020
Set the SAVE_WF_OFFSETS
flag in order that QGL will output a map of the waveform data within the compiled binary waveform library.
In [8]:
from QGL import *
import QGL
import os.path
import pickle
QGL.drivers.APS2Pattern.SAVE_WF_OFFSETS = True
Create the usual channel library with a couple of AWGs.
In [3]:
cl = ChannelLibrary(":memory:")
q1 = cl.new_qubit("q1")
aps2_1 = cl.new_APS2("BBNAPS1", address="192.168.5.101")
aps2_2 = cl.new_APS2("BBNAPS2", address="192.168.5.102")
dig_1 = cl.new_X6("X6_1", address=0)
h1 = cl.new_source("Holz1", "HolzworthHS9000", "HS9004A-009-1", power=-30)
h2 = cl.new_source("Holz2", "HolzworthHS9000", "HS9004A-009-2", power=-30)
cl.set_control(q1, aps2_1, generator=h1)
cl.set_measure(q1, aps2_2, dig_1.ch(1), generator=h2)
cl.set_master(aps2_1, aps2_1.ch("m2"))
cl["q1"].measure_chan.frequency = 0e6
cl.commit()
Creating engine...
Compile a simple sequence.
In [6]:
mf = RabiAmp(cl["q1"], np.linspace(-1, 1, 11))
plot_pulse_files(mf, time=True)
Compiled 11 sequences. <module 'QGL.drivers.APS2Pattern' from '/Users/growland/workspace/QGL/QGL/drivers/APS2Pattern.py'> <module 'QGL.drivers.APS2Pattern' from '/Users/growland/workspace/QGL/QGL/drivers/APS2Pattern.py'>
Open the offsets file (in the same directory as the .aps2
files, one per AWG slice.)
In [13]:
offset_f = os.path.join(os.path.dirname(mf), "Rabi-BBNAPS1.offsets")
with open(offset_f, "rb") as FID:
offsets = pickle.load(FID)
offsets
Out[13]:
{'Waveform(Utheta, 122815, 24)_0x2e0defb474f06986': ([0], 24), 'Waveform-TA(LOW, 96)_-0xf824eec18a1ee52': ([24], 4), 'Waveform(Utheta, 122815, 24)_-0x37af64bdef1017bf': ([28], 24), 'Waveform(Utheta, 122815, 24)_0x17bffe1abeb2c360': ([52], 24), 'Waveform(Utheta, 122815, 24)_0x30d81103120ed2bd': ([76], 24), 'Waveform(Utheta, 122815, 24)_0x455274f4ee41ba32': ([100], 24), 'Waveform(Utheta, 122815, 24)_-0x6218db19881971aa': ([124], 24), 'Waveform(Utheta, 122815, 24)_-0x274e23c9beffce37': ([148], 24), 'Waveform(Utheta, 122815, 24)_-0x1b783f0cedf12d43': ([172], 24), 'Waveform(Utheta, 122815, 24)_-0x51d0ae3b11be45ce': ([196], 24), 'Waveform(Utheta, 122815, 24)_-0x20b43f5ea9db1e21': ([220], 24)}
Let's replace every single pulse with a fixed amplitude Utheta
In [17]:
pulses = {l: Utheta(q1, amp=0.1, phase=0) for l in offsets}
wfm_f = os.path.join(os.path.dirname(mf), "Rabi-BBNAPS1.aps2")
QGL.drivers.APS2Pattern.update_wf_library(wfm_f, pulses, offsets)
We see that the data in the file has been updated.
In [19]:
plot_pulse_files(mf, time=True)
<module 'QGL.drivers.APS2Pattern' from '/Users/growland/workspace/QGL/QGL/drivers/APS2Pattern.py'> <module 'QGL.drivers.APS2Pattern' from '/Users/growland/workspace/QGL/QGL/drivers/APS2Pattern.py'>
Profiling¶
How long does this take?
In [20]:
%timeit mf = RabiAmp(cl["q1"], np.linspace(-1, 1, 100))
Compiled 100 sequences. Compiled 100 sequences. Compiled 100 sequences. Compiled 100 sequences. Compiled 100 sequences. Compiled 100 sequences. Compiled 100 sequences. Compiled 100 sequences. 317 ms ± 6.15 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
Getting the offsets is fast, and only needs to be done once
In [25]:
def get_offsets():
offset_f = os.path.join(os.path.dirname(mf), "Rabi-BBNAPS1.offsets")
with open(offset_f, "rb") as FID:
offsets = pickle.load(FID)
return offsets
%timeit offsets = get_offsets()
61.1 µs ± 638 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)
In [24]:
%timeit pulses = {l: Utheta(q1, amp=0.1, phase=0) for l in offsets}
39.3 µs ± 1.17 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)
In [26]:
wfm_f = os.path.join(os.path.dirname(mf), "Rabi-BBNAPS1.aps2")
%timeit QGL.drivers.APS2Pattern.update_wf_library(wfm_f, pulses, offsets)
# %timeit QGL.drivers.APS2Pattern.update_wf_library("/Users/growland/workspace/AWG/Rabi/Rabi-BBNAPS1.aps2", pulses, offsets)
1.25 ms ± 19.1 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
Moral of the story: 300 ms for initial compilation, and roughly 1.3 ms for update_in_place.
In [ ]: