-
Notifications
You must be signed in to change notification settings - Fork 15
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.
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:
- The location of the the configuration files. This is usually `QLABROOT/experiments/muWaveDetection/cfg'.
- The location where you want the created AWG files to be put.
- 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.
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.
- 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)
- 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)
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
.
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.
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:
- Create
PatternGen
instances for each logical channel. - 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. - If desired create similar nested cell arrays.
- Setup the sequence parameters: fixed point, cycle length, number of steps for each sequence, number of repeats, the sequence name and the measurement length.
- Setup a dictionary linking IQkeys to the pulse sequence cell arrays and some other parameters.
- Setup which AWG's you want to compile for. Empty AWG's will automatically be dropped so just list all of them.
- 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.
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