Experiment
Useful experiments for qubit measurements.
Everything exported to
quick.experiment.
🟢var
Global experiment variable. Serve as a template to generate variable dictionary.
Example:
Details:
rr: 0 # readout channel
r: 0 # generator channel for readout pulse
q: 2 # generator channel for qubit pulse
r_freq: 5000 # [MHz] readout pulse frequency
r_power: -30 # [dB] readout pulse power
r_length: 2 # [us] readout pulse length
r_phase: 0 # [deg] readout pulse phase
r_offset: 0 # [us] readout window offset
r_threshold: 0 # threshold, above which is 1-state
r_reset: 0 # [us] wait time for qubit reset (active reset).
r_relax: 1 # [us] readout relax time
q_freq: 5000 # [MHz] qubit pulse frequency
q_length: 2 # [us] qubit pulse length
q_length_2: null # [us] half pi pulse length
q_delta: -180 # [MHz] qubit anharmonicity
q_gain: 1 # [-1, 1] qubit pulse (pi pulse) gain
q_gain_2: 0.5 # [-1, 1] half pi pulse gain
Note: in most experiments here, if
q_length_2is false value (eg.None),q_lengthwill be used in place.
🟡configs
Global config templates used by BaseExperiment. These are default Mercator protocols for the experiments. It is loaded from here. Mostly internal use.
All of the programs are saved as strings for variable insersion. The experiment variables will be inserted into the Mercator protocol templates with quick.evalStr.
🔵BaseExperiment
e = quick.experiment.BaseExperiment(data_path=None, title="", soccfg=None, soc=None, var=None, **kwargs)
General base class for other experiments using Mercator protocol. If not overwriten, all the other experiment class have the properties and methods described here. If not specified, all **kwargs in the other experiment class are passed into this constructor.
Parameters:
data_path=None(str) directory to save data. If not provided, data will not be saved to file.title=""(str) filename of data. A prefix of experiment name will be added to it, eg.(BaseExperiment)your title.soccfg=NoneQICK board socket config object. If not provided, the last connected one will be used by callingquick.getSoc().soc=NoneQICK board socket object.var=Noneexperimental variables to be inserted into the corresponding Mercator protocol template of the experiment (inquick.experiment.configs) and pre-defined experiment-specific variables. It will NOT be modified. The default value inquick.experiment.varwill be used if any keys are missing.**kwargsother keyword arguments. Any keys inself.varcan be used as variable overwriting(by a value) or sweeping(by a list). The sweeping order is determined by the order of keyword arguments. Keys not inself.varare used to overwrite Mercator protocol and therefore overwrite the pulse sequence. The overwriting happens after variable insertions.
Details: (Advanced: How BaseExperment works?)
It will gather some necessary information first:
- a. the template program (
quick.experiment.configs) - b. the template variable (
quick.experiment.var) - c. new variable defined before calling
__init__, liketimeinT1 - d. input variable (
varargument) - e. other keyword arguments that has the same key as in (b), (c), (d) combined.
- f. other keyword arguments that does not belong to (e), and not predefined (predefined:
data_pathetc). - g. internal variable (
self._var)
The logic of execution is:
- In
__init__, iterables in (e) will be stored asself.sweep, initial values and non-iterables in (e) will overwrite (d). Then (d) will overwrite (c) and then overwrite (b), formingself.var. self.eval_configwill evaluate the Mercator protocol by inserting some variables (eg.self.var) with (g) into (a), formingself.config. Then (f) will overwriteself.config.- During most runs,
self.sweepwill be performed byquick.Sweep. In each loop, a set of variable will be generated fromself.var, andself.eval_configis called to generate the Mercator protocol config for that specific loop run.
The whole process is illustrated in the diagram below:

- BaseExperiment.key
Same as experiment class name. Used to obtain config template by quick.experiment.configs[self.key]. Will be saved in data metainformation as params["quick.experiment"].
- BaseExperiment.var
The experiment variable dictionary used in the experiment. Variables are inserted into the Mercator protocol of the experiment by quick.evalStr in each sweep/run.
- BaseExperiment._var
The internal variable dictionary used in the experiment. This dictionary will be used as global variables in self.eval_config, but it will not be saved or modified by user input. Thus, you can use it as internal variables of the experiment for further flexibility.
- BaseExperiment.var_label
The experiment variable label dictionary used in the experiment. This determines the data label and unit.
- BaseExperiment.data
Data acquired by the experiment. Same structure as saved by the data saver quick.Saver. It is just a copy of data saved in the memory.
- BaseExperiment.config
Program config (pulse sequence) dictionary in Mercator protocol.
- BaseExperiment.config_update
Config update dictionary. Used to overwrite self.config after variable insertion in each sweep/run.
- BaseExperiment.sweep
Sweep dictionary. Store sweeping variables.
- BaseExperiment.m
The Mercator instance created by the experiment.
- BaseExperiment.eval_config
Perform variable insertion and then config overwriting, generating self.config from the template quick.experiment.configs[self.key]. This function use self._var as global variables when evaluating strings.
Parameters:
v(dict) variable dictionary, used in variable insertion.
- BaseExperiment.prepare
prepare the standard S21 measurements (amplitude, phase, I, Q), create data saver. Mostly for internal use.
Parameters:
indep_params=[](list) a list of 2-tuples, specifying meta information for independent variables, in the format of("Name", "Unit"). Note that variables inself.sweepare automatically added without passing in.dep_params=[](list) a list of 2-tuples, specifying meta information for dependent variables, in the format of("Name", "Unit"). If empty, default values will be generated according to the following arguments.dB=False(bool) whether to measure amplitude in log scale (dB with normalization).population=False(bool) whether to measure the qubit population.
- BaseExperiment.add_data
add and save data. Mostly for internal use.
Parameters:
data(2D ArrayLike) a list of data rows. Each row should be a list of numerical data, in the exact order defined inindep_paramsanddep_params.
- BaseExperiment.acquire_S21
acquire data for standard S21 measurement. Run the program specified by self.config in Mercator protocol. Mostly for internal use.
Parameters:
indep_list(list) a list of values for independent variables, in the exact order as specified byprepare.dB=False(bool) whether to measure amplitude in log scale (dB with normalization).decimated=False(bool) whether to acquire for time-series output.population=False(bool) whether to measure the qubit population.
= BaseExperiment.run
Run the experiment. See details below.
Parameters:
silent=False(bool) Whether to avoid any printing.dB=False(bool) whether to measure amplitude in log scale (dB with normalization).population=False(bool) whether to measure the qubit population.
Return:
ethe experiment object itself.
Detail:
This method performs the following steps:
- Call
self.prepareto prepare the data saver. - Use
quick.Sweepto sweep the variables inself.sweep. In each sweep:- Call
self.eval_configto generate the correspondingself.config - Call
self.acquire_S21to execute and save data withquick.Mercator
- Call
- Call and return
self.conclude
- BaseExperiment.conclude
finalize the experiment, print message for completion. Mostly for internal use.
Parameters:
silent=False(bool) Whether to avoid any printing.
Return:
ethe experiment object itself.
- BaseExperiment.light
Light the internal Mercator object.
Return:
ethe experiment object itself.
🟢LoopBack
Base class:
BaseExperiment
Measure the loop-back signal. No variable sweeping.
indep_params = [("Time", "us")]dep_params = [("Amplitude", ""), ("Phase", "rad"), ("I", ""), ("Q", "")]
- LoopBack.run
run the experiment.
Parameters:
silent=False(bool) Whether to avoid any printing.dB=False(bool) whether to measure amplitude in log scale (dB with normalization).
Return:
ethe experiment object itself.
🟢ResonatorSpectroscopy
Base class:
BaseExperiment
Measure the resonator spectroscopy, including the power spectroscopy.
- Arbitrary variable sweeping
dep_params = [("Amplitude", "dB"), ("Phase", "rad"), ("I", ""), ("Q", "")]
- ResonatorSpectroscopy.run
run the experiment.
Parameters:
silent=False(bool) Whether to avoid any printing.dB=True(bool) whether to measure amplitude in log scale (dB with normalization).
Return:
ethe experiment object itself.
🟢QubitSpectroscopy
Base class:
BaseExperiment
Measure the qubit spectroscopy, or two-tone spectroscopy.
- Arbitrary variable sweeping
dep_params = [("Amplitude", ""), ("Phase", "rad"), ("I", ""), ("Q", "")]- include
(Population, "")bye.run(population=True) - use log magnitude by
e.run(dB=True)
- include
🟢Rabi
Base class:
BaseExperiment
Measure the Rabi oscillation.
- Arbitrary variable sweeping, plus:
cycle=0(int) number of extra pi pulse.cycle=0gives 1 pi pulse.
dep_params = [("Population", ""), ("Amplitude", ""), ("Phase", "rad"), ("I", ""), ("Q", "")]- remove
(Population, "")bye.run(population=False)
- remove
- Rabi.run
run the experiment.
Parameters:
silent=False(bool) Whether to avoid any printing.population=True(bool) whether to measure the qubit population.
Return:
ethe experiment object itself.
🟢IQScatter
Base class:
BaseExperiment
Measure the IQ scatter data.
- Arbitrary variable sweeping, plus:
rr_length=None(us) readout window length. IfNone,r_lengthwill be used.
dep_params = [("I 0", ""), ("Q 0", ""), ("I 1", ""), ("Q 1", "")]
Can be used to measure IQ trace by setting
rep=0, hard_avg=1000and settingrr_lengthto the desired ADC window length.
- IQScatter.run
run the experiment.
Parameters:
silent=False(bool) Whether to avoid any printing.
Return:
ethe experiment object itself.
🟢DispersiveSpectroscopy
Base class:
BaseExperiment
Measure the dispersive spectroscopy.
- Arbitrary variable sweeping
dep_params = [("Amplitude 0", "dB"), ("Phase 0", "rad"), ("I 0", ""), ("Q 0", ""), ("Amplitude 1", "dB"), ("Phase 1", "rad"), ("I 1", ""), ("Q 1", "")]
- DispersiveSpectroscopy.run
run the experiment.
Parameters:
silent=False(bool) Whether to avoid any printing.dB=True(bool) whether to measure amplitude in log scale (dB with normalization).
Return:
ethe experiment object itself.
🟢T1
Base class:
BaseExperiment
Measure the T1 decay.
- Arbitrary variable sweeping, plus:
time=0(us) readout delay time.
dep_params = [("Population", ""), ("Amplitude", ""), ("Phase", "rad"), ("I", ""), ("Q", "")]- remove
(Population, "")bye.run(population=False)
- remove
- T1.run
run the experiment.
Parameters:
silent=False(bool) Whether to avoid any printing.population=True(bool) whether to measure the qubit population.
Return:
ethe experiment object itself.
🟢T2Ramsey
Base class:
BaseExperiment
Measure the T2 decay with fringe by Ramsey oscillation.
- Arbitrary variable sweeping, plus:
time=0(us) readout delay time.fringe_freq=0(MHz) fringe frequency.
dep_params = [("Population", ""), ("Amplitude", ""), ("Phase", "rad"), ("I", ""), ("Q", "")]- remove
(Population, "")bye.run(population=False)
- remove
- T2Ramsey.run
run the experiment.
Parameters:
silent=False(bool) Whether to avoid any printing.population=True(bool) whether to measure the qubit population.
Return:
ethe experiment object itself.
🟢T2Echo
Base class:
BaseExperiment
Measure the T2 decay with fringe by Hahn echo or CPMG method. Pi pulses for echo will always be on +y axis (90 degrees phase).
- Arbitrary variable sweeping, plus:
time=0(us) readout delay time.cycle=0(int) extra cycle in the CPMG method. Each extra cycle introduces 1 extra pi pulse, implementing the CPMG pulse sequence.cycle=0gives 1 pi pulse.fringe_freq=0(MHz) fringe frequency.
dep_params = [("Population", ""), ("Amplitude", ""), ("Phase", "rad"), ("I", ""), ("Q", "")]- remove
(Population, "")bye.run(population=False)
- remove
- T2Echo.run
run the experiment.
Parameters:
silent=False(bool) Whether to avoid any printing.population=True(bool) whether to measure the qubit population.
Return:
ethe experiment object itself.
🟢QND
Base class:
BaseExperiment
QNDness measurement by randomized Pi pulse and repeated readout.
- Arbitrary variable sweeping, plus:
cycle=10(int) cycles of randomized Pi pulse and readout.random=100(int) number of randomization.
dep_params = [("Correlation", "")]
- QND.run
run the experiment.
Parameters:
silent=False(bool) Whether to avoid any printing.
Return:
ethe experiment object itself.