Skip to content

Pulse Sequence Generation

caryan edited this page Feb 1, 2013 · 2 revisions

Pulse Sequence Generation

Pulses specified using the PatternGen class. The pulse and channel parameters are stored in two json encoded parameter files: the pulseParams.json file which gives calibration and timing information and the Qubit2ChannelMap.json which maps the logical qubit channels to physical AWG channels. Currently the BBN-APS and Tektronix 5000 AWGs are supported out of the box. These files contain pulse parameters keyed to qubit names and channel names. The JSON format is human-readable, but you can also use PulseParamGUI to create/edit the pulseParam.json file.

Initial setup

Startup Matlab and move into the base directory of the QLab package. There there is an install script: installQlab.m. Run the script and it will ask for a few directory locations:

  1. The location of the the configuration files. This is usually `QLABROOT/experiments/muWaveDetection/cfg'.
  2. The location where you want the created AWG files to be put.
  3. The location of the PyQLab package. This is only necessary for the pulse sequence plotter and can be left empty.

After the the script is run, it will print out some paths that you should add to the Matlab path.

Sequence Parameters

To avoid hard-coded values most variables are loaded from json encoded configuration files. The pulseParams.json contains parameters for both physical and logical channels.

Parameters keyed to a logical channel name

  • piAmp - in DAC levels
  • pi2Amp - in DAC levels
  • sigma - width of Gaussians, tanh, etc in samples
  • delta - derivative scaling factor for DRAG pulses, dimensionless
  • pulseLength - total pulse length (eg, 4*sigma) in samples
  • pulseType - (eg. 'square', 'gauss', 'drag')
  • buffer - space to put between points, in samples
  • SSBFreq - the detuning of the qubit from the pulsing frame in MHz (e.g. if the carrier frequency is 4.1 GHz and the qubit frequency is 4.0 GHz, then this is -100)

Parameters keyed to physical channel name

  • delay - shifts entire waveform forward or back by this # of samples. Negative delays shift earlier in time (shift 'left').
  • offset - channel offset in DAC levels. For the TekAWGs, set this to 8192. For the BBNAPS, set it to 0.
  • bufferPadding - pad pulse gating pulses by this number of points on each side
  • bufferReset - minimum time between gating pulses
  • bufferDelay - shifts gating channel by this # of samples. Same sign convention as delay.
  • correctionT - amplitude imbalance and phase error correction matrix
  • samplingRate - the output sample rate of the channel in GS/s.
  • linkList - set to true to enable link list generation (i.e. if using this channel with a BBN APS)

Linking logical and physical channels

The logical channels are connected to physical channels through the `Qubit2ChanelMap.json'. This specifies the AWG, analog channels, digital channel for gating pulses and the microwave source used to implement the logical channel. The AWG names are for convenience and will correspond to the sequence filenames produced.

The Qubit2ChannelMap.json also specified the digitizerTrig and slaveTrig channels. These currently produce pulses 500pts before the sequence fixed point and at the beginning of the sequence respectively. Unfortunately, timing of these pulses had not yet been moved to a configuration file and so must be changed in lines 170-190 of compileSequences.

Pulse Labels

PatternGen understands the following pulse labels. Use of one of these labels essentially chooses certain parameters from the defaults passed in to the PatternGen constructor.

  • Pulses with fixed amplitudes - Xp, Xm, X90p, X90m, X45p, X45m, Yp, ..., Up, ..., U90m
  • Pulses with variable amplitude - Xtheta, Ytheta, Utheta
  • Frame change pulses - (variable amp) Zf, (fixed amp) Zp, Zm, Z90p, Z90m
  • Measurement pulses - M

The first letter of the pulse label indicates the rotation axis (the 'angle' parameter) of the pulse. So, X90p is a rotation about X, Y90p is a rotation about Y, and U90p means that you will specify the angle.

Sequence Generation

The sequence files are found in QLabRoot/experiments/muWaveDetection/sequences/. They are in a constant state of improvement and so they may not Here is an example function for producing a Ramsey experiment with optional TPPI. The main generic steps in any sequence are:

  1. Create PatternGen instances for each logical channel.
  2. Create cell arrays of cell arrays of Pulse objects to represent sequences. Each inner cell array corresponds to a sequence. Pulse objects can take arrays for most parameters which will be iterated over up the numSteps parameters.
  3. If desired create similar nested cell arrays.
  4. Setup the sequence parameters: fixed point, cycle length, number of steps for each sequence, number of repeats, the sequence name and the measurement length.
  5. Setup a dictionary linking IQkeys to the pulse sequence cell arrays and some other parameters.
  6. Setup which AWG's you want to compile for. Empty AWG's will automatically be dropped so just list all of them.
  7. Call the universal compileSequences which handles the rest. It will print messages giving the total number of sequences and if streaming is necessary the minimum spacing between sequences. If this is too long the number of repeats can be increased.

Example Sequence

function RamseyCalSequence(qubit, pulseSpacings, pulsePhases, makePlot)
%RamseyCalSequence Ramsey fringes with variable pulse spacing: pi/2-tau-pi/2
% RamseyCalSequence(qubit, pulseSpacings, pulsePhases, makePlot)
%   qubit - target qubit e.g. 'q1'
%   pulseSpacings - array of pulse spacings to scan over e.g. 60*(1:200)
%   pulsePhases - array or float of final pulse phases
%   makePlot - whether to plot a sequence or not (boolean)

basename = 'Ramsey';
fixedPt = pulseSpacings(end)+1000;
cycleLength = fixedPt+2100; 
nbrRepeats = 1;

pg = PatternGen(qubit);

patseq = {{...
    pg.pulse('X90p'), ...
    pg.pulse('QId', 'width', pulseSpacings), ...
    pg.pulse('U90p', 'angle', pulsePhases)
   }};
calseq = {{pg.pulse('QId')}, {pg.pulse('QId')}, {pg.pulse('Xp')}, {pg.pulse('Xp')}};

seqParams = struct(...
    'basename', basename, ...
    'suffix', '', ...
    'numSteps', length(pulseSpacings), ...
    'nbrRepeats', nbrRepeats, ...
    'fixedPt', fixedPt, ...
    'cycleLength', cycleLength, ...
    'measLength', 2000);
patternDict = containers.Map();
if ~isempty(calseq), calseq = {calseq}; end
qubitMap = jsonlab.loadjson(getpref('qlab','Qubit2ChannelMap'));
IQkey = qubitMap.(qubit).IQkey;
patternDict(IQkey) = struct('pg', pg, 'patseq', {patseq}, 'calseq', calseq, 'channelMap', qubitMap.(qubit));

measChannels = {'M1'};
awgs = {'TekAWG', 'BBNAPS1', 'BBNAPS2'};

compileSequences(seqParams, patternDict, measChannels, awgs, makePlot);
end