2.1. Modelling a Simple TablePulseTemplate

This example demonstrates how to set up a simple TablePulseTemplate.

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. First, let us instantiate a TablePulseTemplate object:

In [1]:
from qctoolkit.pulses import TablePulseTemplate

template = TablePulseTemplate(identifier='foo')

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). We add these to our TablePulseTemplate object template with the correct interpolation strategies as follows:

In [2]:
template.add_entry(0, 0)
template.add_entry(2, 2, interpolation='hold')
template.add_entry(4, 3, interpolation='linear')
template.add_entry(6, 0, interpolation='jump')

Note that we could omit the first instruction: If the time value of the first call to add_entry is greater than zero, a starting entry (0,0) is automatically set. Note further that 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.

We plot template to see if everything is correct (ignore the matplotlib warning here):

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

try:
    plot(template, sample_rate=100)
except:
    pass
<IPython.core.display.Javascript object>

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_template = TablePulseTemplate()
param_template.add_entry('ta', 'va', interpolation='hold')
param_template.add_entry('tb', 'vb', interpolation='linear')
param_template.add_entry('tend', 0, interpolation='jump')

Instead of using numerical values, we simply insert parameter names in our calls to add_entry. 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)
{'va', 'ta', 'tb', 'tend', 'vb'}

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]:
%matplotlib notebook
parameters = {'ta': 2,
              'va': 2,
              'tb': 4,
              'vb': 3,
              'tend': 6}
plot(param_template, parameters, sample_rate=100)
<IPython.core.display.Javascript object>

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

In [7]:
%matplotlib notebook
parameters = {'ta': 2,
              'va': 2,
              'tb': 6,
              'vb': 3,
              'tend': 8}
plot(param_template, parameters, sample_rate=100)
<IPython.core.display.Javascript object>