<SYSTEM_TASK:>
Given the following text description, write Python code to implement the functionality described below step by step
<END_TASK>
<USER_TASK:>
Description:
 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.
Step1:  Create the usual channel library with a couple of AWGs.
Step2:  Compile a simple sequence.
Step3:  Open the offsets file (in the same directory as the .aps2 files, one per AWG slice.)
Step4:  Let's replace every single pulse with a fixed amplitude Utheta
Step5:  We see that the data in the file has been updated.
Step6:  Profiling
How long does this take?
Step7:  Getting the offsets is fast, and only needs to be done once
<ASSISTANT_TASK:>
Python Code:
from QGL import *
import QGL
import os.path
import pickle
QGL.drivers.APS2Pattern.SAVE_WF_OFFSETS = True
Explanation: 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.
End of explanation
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()
Explanation: Create the usual channel library with a couple of AWGs.
End of explanation
mf = RabiAmp(cl["q1"], np.linspace(-1, 1, 11))
plot_pulse_files(mf, time=True)
Explanation: Compile a simple sequence.
End of explanation
offset_f = os.path.join(os.path.dirname(mf), "Rabi-BBNAPS1.offsets")
with open(offset_f, "rb") as FID:
    offsets = pickle.load(FID)
offsets
Explanation: Open the offsets file (in the same directory as the .aps2 files, one per AWG slice.)
End of explanation
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)
Explanation: Let's replace every single pulse with a fixed amplitude Utheta
End of explanation
plot_pulse_files(mf, time=True)
Explanation: We see that the data in the file has been updated.
End of explanation
%timeit mf = RabiAmp(cl["q1"], np.linspace(-1, 1, 100))
Explanation: Profiling
How long does this take?
End of explanation
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()
%timeit 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")
%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)
Explanation: Getting the offsets is fast, and only needs to be done once
End of explanation
<END_TASK>