In [1]:
import auspex.config as config
config.auspex_dummy_mode = True
In [2]:
from QGL import *
from auspex.qubit import *
Channel library setup
In [3]:
cl = ChannelLibrary(db_resource_name=":memory:")
pl = PipelineManager()
q1 = cl.new_qubit("q1")
aps2_1 = cl.new_APS2("BBNAPSa", address="192.168.2.4", trigger_interval=200e-6)
aps2_2 = cl.new_APS2("BBNAPSb", address="192.168.2.2")
dig_1 = cl.new_Alazar("Alazar_1", address="1", sampling_rate=500e6, record_length=1024)
h1 = cl.new_source("Holz_1", "HolzworthHS9000", "HS9004A-009-1", reference='10MHz', power=-30)
h2 = cl.new_source("Holz_2", "HolzworthHS9000", "HS9004A-009-2", reference='10MHz', power=-30)
cl.set_measure(q1, aps2_1, dig_1.ch("1"), trig_channel=aps2_1.ch("m2"), gate=False, generator=h1)
cl.set_control(q1, aps2_2, generator=h2)
cl.set_master(aps2_1, aps2_1.ch("m1"))
cl["q1"].measure_chan.frequency = 0e6
cl["q1"].measure_chan.autodyne_freq = 10e6
Pipeline setup: Take Note: we use the buffers
keyword argument to automatically generate buffers instead of writers. This is sometimes convenient if you don't require data to be written to file. It becomes immediately available in the notebook after running!
In [ ]:
pl.create_default_pipeline(buffers=True)
pl["q1"].add(Display(label="blub"))
pl["q1"]["Demodulate"]["Integrate"].add(Display(label="int", plot_dims=1))
pl.show_pipeline()
Initialize software demodulation parameters. If these are not properly configured than the Channelizer
filter will report 'insufficient decimation' or other errors. The integration boxcar parameters are then defined.
In [14]:
demod = pl["q1"]["Demodulate"]
demod.frequency = cl["q1"].measure_chan.frequency
demod.decimation_factor = 16
In [15]:
integ = pl["q1"]["Demodulate"]["Integrate"]
integ.box_car_start = 0.2e-6
integ.box_car_stop= 1.9e-6
Once a QubitExperiment
has been created, we can programmatically add sweeps as shown here.
In [ ]:
lengths = np.linspace(20e-9, 2020e-9, 31)
exp = QubitExperiment(RabiWidth(q1,lengths),averages=50)
exp.set_fake_data(dig_1, np.exp(-lengths/1e-6)*np.cos(1e7*lengths))
# exp.add_qubit_sweep(q1,"measure", "frequency", np.linspace(6.512e9, 6.522e9, 11))
exp.run_sweeps()
We fetch the data and data descriptor directly from the buffer. The data is automatically reshaped to match the experiment axes, and the descriptor enumerates all of the values of these axes for convenience plotting, etc..
In [21]:
data, descriptor = exp.outputs_by_qubit["q1"][0].get_data()
In [22]:
descriptor.axes
Out[22]:
In [23]:
data.shape
Out[23]:
We even include a convenience extent
function conforming to the infinitely forgettable matplotlib format.
In [24]:
import matplotlib.pyplot as plt
%matplotlib inline
plt.imshow(np.real(data), aspect='auto', extent=descriptor.extent())
plt.xlabel("Delay (µs)")
plt.ylabel("Frequency (GHz)");
In [25]:
exp = QubitExperiment(RabiWidth(q1,lengths),averages=50)
exp.add_qubit_sweep(q1,"measure", "frequency", np.linspace(6.512e9, 6.522e9, 5))
exp.add_qubit_sweep(q1,"measure", "amplitude", np.linspace(0.0, 1.0, 21))
If we inspect the internal representation of the "output connector" into which the instrument driver will dump its data, we can see all of the axes it contains.
In [26]:
exp.output_connectors["q1"].descriptor.axes
Out[26]:
The DataAxis
entries are "baked in" using hardware looping, while the SweepAxis
entries are external software loops facilitated by Auspex.