Introduction

The Tektronix AWG70000A series internally use .seqx files. The QCoDeS driver for the AWGs knows how to compile these files and broadbean knows what QCoDeS need to do so.

Step 1: Make a sequence

[1]:
# We make a sequence consisting of a bsic element with:
# a wait time, a ramp up, a sine, a ramp down, and more wait time
# And then we vary the sine frequency
%matplotlib notebook
import numpy as np

import broadbean as bb
from broadbean.plotting import plotter

sine = bb.PulseAtoms.sine
ramp = bb.PulseAtoms.ramp

##########################
# settings

SR = 25e9
t1 = 10e-9  # first wait time (s)
ramp_time = 5e-9  # the ramp time (s)
t_sine = 25e-9  # the sine time (s)
high_level = 0.1  # the high level (V)
sine_amp = 0.05  # the sine amplitude (V)
t2 = 150e-9  # the second wait time (s)
f0 = 1e9  # the base frequency of the sine (Hz)

baseshape = bb.BluePrint()
baseshape.insertSegment(0, ramp, (0, 0), dur=t1)
baseshape.insertSegment(1, ramp, (0, high_level), dur=ramp_time)
baseshape.insertSegment(
    2, sine, (f0, sine_amp, high_level, 0), dur=t_sine, name="drive"
)
baseshape.insertSegment(3, ramp, (high_level, 0), dur=ramp_time)
baseshape.insertSegment(4, ramp, (0, 0), dur=t2, name="wait")
baseshape.setSegmentMarker("wait", (0, t_sine), 1)
baseshape.setSegmentMarker("drive", (0, t_sine), 2)
baseshape.setSR(SR)
[2]:
# Check that it looks the way we expect
plotter(baseshape)
[3]:
# Make it into a sequence
baseelem = bb.Element()
baseelem.addBluePrint(1, baseshape)

# Add elements and vary the sine freq.

sine_freqs = np.linspace(1e9, 2e9, 5)

seq = bb.Sequence()
seq.setSR(SR)

# We set each element of the sequence to wait for
# a trigger from trigger input 'A'

for index, freq in enumerate(sine_freqs):
    elem = baseelem.copy()
    elem.changeArg(1, "drive", "freq", freq)
    seq.addElement(index + 1, elem)
    seq.setSequencingTriggerWait(index + 1, 1)  # 1: trigA, 2: trigB, 3: EXT

# and set the last element to point back to the first one
seq.setSequencingGoto(index + 1, 1)

seq.name = "tutorial_sequence"  # the sequence name will be needed later

Step 2: Initialise the driver

[4]:
# import and initialise the driver and ensure that the sample
# rate and channel voltage is correct

from qcodes.instrument_drivers.tektronix.AWG70002A import AWG70002A

awg = AWG70002A("awg", "TCPIP0::172.20.2.243::inst0::INSTR")
---------------------------------------------------------------------------
ModuleNotFoundError                       Traceback (most recent call last)
Cell In[4], line 4
      1 # import and initialise the driver and ensure that the sample
      2 # rate and channel voltage is correct
----> 4 from qcodes.instrument_drivers.tektronix.AWG70002A import AWG70002A
      6 awg = AWG70002A("awg", "TCPIP0::172.20.2.243::inst0::INSTR")

ModuleNotFoundError: No module named 'qcodes'
[5]:
awg.sample_rate(SR)
awg.ch1.awg_amplitude(0.5)  # this is the peak-to-peak amplitude of the channel

# Now we must update the Sequence object with this information
seq.setChannelAmplitude(1, awg.ch1.awg_amplitude())
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
Cell In[5], line 1
----> 1 awg.sample_rate(SR)
      2 awg.ch1.awg_amplitude(0.5)  # this is the peak-to-peak amplitude of the channel
      4 # Now we must update the Sequence object with this information

NameError: name 'awg' is not defined

Step 3: Make output for the driver

[6]:
# If the sequence has been built correctly, it's a one-liner
seqx_input = seq.outputForSEQXFile()
---------------------------------------------------------------------------
KeyError                                  Traceback (most recent call last)
Cell In[6], line 2
      1 # If the sequence has been built correctly, it's a one-liner
----> 2 seqx_input = seq.outputForSEQXFile()

File /opt/hostedtoolcache/Python/3.9.19/x64/lib/python3.9/site-packages/broadbean/sequence.py:990, in Sequence.outputForSEQXFile(self)
    973 """
    974 Generate a tuple matching the call signature of the QCoDeS
    975 AWG70000A driver's `makeSEQXFile` function. If channel delays
   (...)
    986         go_to, wfms, amplitudes, seqname)
    987 """
    989 # most of the footwork is done by the following function
--> 990 elements = self._prepareForOutputting()
    991 # _prepareForOutputting asserts that channel amplitudes and
    992 # full sequencing is specified
    993 seqlen = len(elements)

File /opt/hostedtoolcache/Python/3.9.19/x64/lib/python3.9/site-packages/broadbean/sequence.py:884, in Sequence._prepareForOutputting(self)
    882     ampkey = f"channel{chan}_amplitude"
    883     if ampkey not in self._awgspecs.keys():
--> 884         raise KeyError(
    885             "No amplitude specified for channel {chan}. Can not continue."
    886         )
    888 # Apply channel delays.
    889 delays = []

KeyError: 'No amplitude specified for channel {chan}. Can not continue.'

Step 4: Build, send, load, and assign a .seqx file

[7]:
# compile a binary .seqx file
seqx_output = awg.makeSEQXFile(*seqx_input)
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
Cell In[7], line 2
      1 # compile a binary .seqx file
----> 2 seqx_output = awg.makeSEQXFile(*seqx_input)

NameError: name 'awg' is not defined
[8]:
# transfer it to the awg harddrive
awg.sendSEQXFile(seqx_output, "tutorial.seqx")
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
Cell In[8], line 2
      1 # transfer it to the awg harddrive
----> 2 awg.sendSEQXFile(seqx_output, "tutorial.seqx")

NameError: name 'awg' is not defined
[9]:
# load it into awg active memory
awg.loadSEQXFile("tutorial.seqx")
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
Cell In[9], line 2
      1 # load it into awg active memory
----> 2 awg.loadSEQXFile("tutorial.seqx")

NameError: name 'awg' is not defined
[10]:
# assign tracks from the sequence to the awg sequencer
awg.ch1.setSequenceTrack("tutorial_sequence", 1)

# NB: Each channel has an assigned resolution, either 8, 9, or 10.
# 8 means 8 bits for the waveform, 2 bits for the markers (i.e. 2 markers)
# 9 means 9 bits for the waveform, 1 bit for the markers (i.e. 1 marker)
# 10 means 10 bit for the waveform, no markers
#
# Since we want to have two markers, we make sure that the resolution is 8
awg.ch1.resolution(8)
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
Cell In[10], line 2
      1 # assign tracks from the sequence to the awg sequencer
----> 2 awg.ch1.setSequenceTrack("tutorial_sequence", 1)
      4 # NB: Each channel has an assigned resolution, either 8, 9, or 10.
      5 # 8 means 8 bits for the waveform, 2 bits for the markers (i.e. 2 markers)
      6 # 9 means 9 bits for the waveform, 1 bit for the markers (i.e. 1 marker)
      7 # 10 means 10 bit for the waveform, no markers
      8 #
      9 # Since we want to have two markers, we make sure that the resolution is 8
     10 awg.ch1.resolution(8)

NameError: name 'awg' is not defined

Step 5: Play it

[11]:
awg.ch1.state(1)
awg.play()
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
Cell In[11], line 1
----> 1 awg.ch1.state(1)
      2 awg.play()

NameError: name 'awg' is not defined
[12]:
# force trigger the instrument to play the next part of the sequence
awg.force_triggerA()
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
Cell In[12], line 2
      1 # force trigger the instrument to play the next part of the sequence
----> 2 awg.force_triggerA()

NameError: name 'awg' is not defined
[13]:
# eventually shut down and turn off
awg.stop()
awg.ch1.state(0)
awg.close()
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
Cell In[13], line 2
      1 # eventually shut down and turn off
----> 2 awg.stop()
      3 awg.ch1.state(0)
      4 awg.close()

NameError: name 'awg' is not defined