2.1. Modelling a Simple TablePulseTemplate

This example demonstrates how to set up a simple TablePulseTemplate(or short TablePT).

The pulse we want to model using the qctoolkit

The pulse we want to model using the qctoolkit

Assume we want to model a pulse as depicted by the figure above. Since the structure is relatively simple and relies only on a few critical points between which the values are interpolated (indicated by the crosses in the figure), we will do so by using a TablePulseTemplate and setting values at appropriate times.

For our first try, let’s just fix some values for the parameters. Let us set \(t_a\) = 2, \(v_a\) = 2, \(t_b\) = 4, \(v_b\) = 3, \(t_{end}\) = 6. Our pulse then holds a value of 0 for 2 units of time, then jumps to 2 and subsequently ramps to 3 over the next 2 units of time. Finally, it returns to holding 0 for another 2 units of time. The supporting points for the table are thus (0,0), (2,2), (4,3), (6,0).

Let us first put these entries into a list with the correct interpolation strategies:

In [1]:
entry_list = [(0, 0),
              (2, 2, 'hold'),
              (4, 3, 'linear'),
              (6, 0, 'jump')]

The interpolation set for an entry always applies to the range from the previous entry to the new entry. Thus, the value for the first entry is always ignored. The default value for interpolation is ‘hold’. ‘hold’ and ‘jump’ differ in that ‘hold’ will hold the previous value until the new entry is reached while ‘jump’ will immediately assume the value of the new entry.

Now, we must decide on which channel the TablePulseTemplate is defined on. As a TablePulseTemplate can contain multiple channels it takes a python dict whose keys are the channel identifiers and whose values are lists of entries like the one above. Channel identifiers can be either strings like ‘channel_A’ or integers. For this example we choose the channel ID ‘0’ for our pulse and create the TablePulseTemplate object template:

In [2]:
from qctoolkit.pulses import TablePT

entries = {0: entry_list}

template = TablePT(entries)

Notice that we used the alias TablePT. We plot template to see if everything is correct:

In [3]:
%matplotlib notebook
from qctoolkit.pulses.plotting import plot

_ = plot(template, sample_rate=100, show=True)

Alright, we got what we wanted.

Note that the time domain in pulse defintions does not correspond to any fixed real world time unit. The mapping from a single time unit in a pulse definition to real time in execution is made by setting a sample rate when converting the pulse templates to waveforms. For more on this, see The Sequencing Process: Obtaining Pulse Instances From Pulse Templates.

2.1.1. Introducing Parameters

Now we want to make the template parameterizable. This allows us to reuse the template for pulses with similar structure. Say we would like to have the same pulse, but the intermediate linear interpolation part should last 4 units of time instead of only 2. Instead of creating another template with hardcoded values, we instruct the TablePulseTemplate instance to rely on parameters.

In [4]:
param_entries = {0: [(0, 0),
                     ('ta', 'va', 'hold'),
                     ('tb', 'vb', 'linear'),
                     ('tend', 0, 'jump')]}

param_template = TablePT(param_entries)

Instead of using numerical values, we simply insert parameter names in our entry list. You can use any combination of numerical values or parameters names here. Note that we also gave our object the optional identifier ‘foo’. Our param_template thus now defines a set of parameters.

In [5]:
print(param_template.parameter_names)
{'ta', 'vb', 'tend', 'va', 'tb'}

We now have a pulse template that we can instantiate with different parameter values, which we simply provide as a dictionary. To achieve the same pulse as above:

In [6]:
parameters = {'ta': 2,
              'va': 2,
              'tb': 4,
              'vb': 3,
              'tend': 6}
_ = plot(param_template, parameters, sample_rate=100)

To instantiate the pulse with longer intermediate linear interpolation we now simply adjust the parameter values without touching the param_template itself:

In [7]:
parameters = {'ta': 2,
              'va': 2,
              'tb': 6,
              'vb': 3,
              'tend': 8}
_ = plot(param_template, parameters, sample_rate=100)