2.20. Dynamic Nuclear Polarisation/Changing repetition count during runtime

This example demonstrates how to change the repetition count of pulses during runtime. One possible application of changing parameters during runtime is dynamic nuclear polarisation. We will call parameters which are able to change after program creation volatile. Since this example is meant to illustrate how the concept of changing the values of volatile parameter works, we will use simple example pulses.

First we have to connect to the AWG (If you want to run this cell, set awg_name and possibly awg_address according to the AWG you are using).

[ ]:
from qupulse.hardware.setup import HardwareSetup
from doc.source.examples.hardware.zhinst import add_to_hardware_setup
from doc.source.examples.hardware.tabor import add_tabor_to_hardware_setup

awg_name = 'TABOR'
awg_address = None
hardware_setup = HardwareSetup()

if awg_name == 'ZI':
    hdawg, channel_pairs = add_to_hardware_setup(hardware_setup, awg_address, name=awg_name)
    used_awg = hdawg.channel_pair_AB
elif awg_name == 'TABOR':
    teawg, channel_pairs = add_tabor_to_hardware_setup(hardware_setup, tabor_address=awg_address, name=awg_name)
    used_awg = channel_pairs[0]
else:
    ValueError('Unknown AWG')

As a next step we create our dnp pulse template, with three different pumping schemes: ‘minus’, ‘zero’ and ‘plus’. In reality these could for example be t-, s- and cs-pumping pulses.

[3]:
from qupulse.pulses import PointPT, RepetitionPT

zero = PointPT([(0, 0), ('t_quant', 0)], ('X', 'Y'))
minus = PointPT([(0, '-x'), ('t_quant', '-x')], ('X', 'Y'))
plus = PointPT([(0, 'x'), ('t_quant', 'x')], ('X', 'Y'))

dnp = RepetitionPT(minus, 'n_minus') @ RepetitionPT(zero, 'n_zero') @ RepetitionPT(plus, 'n_plus')

On program creation, we set the parameters and channel mappings of the program as usual. However we want to be able to change how often we repeat each of the pulses dynamically. For that we have to say on program creating which of the parameters are supposed to change during runtime, using the keyword volatile.

[4]:
sample_rate = used_awg.sample_rate / 10**9
n_quant = 192
t_quant = n_quant / sample_rate

dnp_prog = dnp.create_program(parameters=dict(t_quant=float(t_quant), n_minus=3, n_zero=3, n_plus=3, x=0.25),
                              channel_mapping={'X': '{}_A'.format(awg_name), 'Y': '{}_B'.format(awg_name)},
                              volatile={'n_minus', 'n_zero', 'n_plus'})
dnp_prog.cleanup()

Now we can upload our program to the AWG and use it as usual.

[5]:
hardware_setup.register_program('dnp', dnp_prog)
hardware_setup.arm_program('dnp')

used_awg.run_current_program()

print(used_awg._known_programs['dnp'].program.program)
LOOP 1 times:
  ->EXEC <qupulse._program.waveforms.MultiChannelWaveform object at 0x00000000093D6948> 3 times
  ->EXEC <qupulse._program.waveforms.MultiChannelWaveform object at 0x0000000005174888> 3 times
  ->EXEC <qupulse._program.waveforms.MultiChannelWaveform object at 0x00000000093E3708> 3 times

As expected our pumping pulses are executed 3 times each.

We can now adjust the repetitions of the pulses by simply using the function update_parameters. We need to give update_parameters the name of the program we want to change and the values to which we want to set certain parameters. Say, next time we run the program we only want to do one zero pulse but 5 plus pulses instead of 3. Then we can simply do:

[6]:
hardware_setup.update_parameters('dnp', dict(n_zero=1, n_plus=5))

This changes the program in the AWG and the program memory accordingly such that next time we run the program the AWG will output 3 minus, 1 zero and 5 plus pulses.

[7]:
used_awg.run_current_program()

print(used_awg._known_programs['dnp'].program.program)
LOOP 1 times:
  ->EXEC <qupulse._program.waveforms.MultiChannelWaveform object at 0x00000000093D6948> 3 times
  ->EXEC <qupulse._program.waveforms.MultiChannelWaveform object at 0x0000000005174888> 1 times
  ->EXEC <qupulse._program.waveforms.MultiChannelWaveform object at 0x00000000093E3708> 5 times

As we can see the AWG now outputs 3 minus pulses, 1 zero pulse and 5 plus pulses as desired.