In [ ]:
import numpy as np
import matplotlib.pyplot as plt
import qkit
qkit.start()
from qkit.measure import samples_class as sample # Sample class
from qkit.measure.timedomain import sequence_library as sl # Sequence library for standard experiments
from qkit.measure.timedomain import pulse_sequence as ps # Pulse sequence class to build sequences of your own
from qkit.measure.timedomain import VirtualAWG as VirtAWG # virtual awg for managing your sequence objects
In [ ]:
testsample = sample.Sample()
testsample.readout_tone_length = 200e-9 # length of the readout tone
testsample.clock = 1e9 # sample rate of your physical awg/pulse generator
testsample.tpi = 100e-9 # duration of a pi-pulse
testsample.tpi2 = 50e-9 # duration of a pi/2-pulse
testsample.iq_frequency = 20e6 # iq_frequency for iq mixing (set to 0 for homodyne measurements)
#testsample.awg = my_awg #<- qkit instrument (your actual awg)
Pulse objects are initialized with:
mypulse = ps.Pulse(length, pulse-shape, name, amplitude, phase, iq_frequency, iq_dc_offset, iq_angle)
length is the pulse length in seconds
pulse-shape is the shape of the pulse. Currently rect (square pulse, this is the default) and gaussian shapes are implemented. To use gaussian shape, write shape = ps.ShapeLib.gauss
name is the name you want to give your pulse. This is not mandatory and only used for plotting.
amplitude: relative amplitude of your pulse.
phase: relative phase of your pulse in degree.
iq_frequency: If iq_frequency is 0, homodyne mixing is used.
iq_dc_offset, iq_angle are currently not in use, but will be used in the near future to enable a calibration of the mixers.
In [ ]:
#example:
pi = ps.Pulse(50e-9, name = "pi-pulse", shape = ps.ShapeLib.gauss, iq_frequency=50e6)
#this creates a 50ns gaussian pulse with name "pi-pulse" at an iq_frequency of 50MHz.
In [ ]:
my_sequence = ps.PulseSequence(testsample) # create sequence object
my_sequence.add(pi) # add pi pulse, as defined in the example above
my_sequence.add_wait(lambda t: t) # add a variable wait time with length t
my_sequence.add_readout() # add the readout
my_sequence.plot() # show SCHEMATIC plot of the pulse sequence
As you can see, wait times can be added with the add_wait command. In this case the wait time is given by a lambda function. This enable the implementation of variable time steps. This can also be used to add pulses with variable lengths.
In [ ]:
spinecho = sl.spinecho(testsample, n_pi = 2) # spinecho with 2 pi-pulses
spinecho.plot()
In [ ]:
vawg = VirtAWG.VirtualAWG(testsample) # by default, the virtual awg is initialized with a single channel
time = np.arange(0, 500e-9, 50e-9) # time t for the sequence
vawg.set_sequence(my_sequence, time) # set_sequence deletes all previously stored sequences in a channel
vawg.add_sequence(spinecho, time * 2) # add_sequence appends the next sequence to the sequences stored in the channel
# Note, this enables you to run multiple experiments, such as T1-measurement and spin-echo in parallel!#
vawg.plot()
# In the plot, the time starts at 0 together with the readout.
# The position of the readout is also used as a phase reference for all pulses.
In [ ]:
# If you do not want the experiments to run consecutively, but to interleave them instead:
vawg.set_interleave(True)
# This also works for more than 2 sequences.
vawg.plot()
If you are satisfied with the results, load the sequences onto your physical device with:
vawg.load()
Currently, this is only enabled for the tabor awg.
In [ ]:
vawg = VirtAWG.VirtualAWG(testsample, channels = 2) #Initialize with two channels channel (number is arbitrary)
vawg.set_sequence(my_sequence, time, channel = 1) # set my_sequence (T1 measurement) on channel 1
vawg.set_sequence(spinecho, time, channel = 2) # set spinecho on channel 2
vawg.plot()