Pulse Programmers¶
Devices¶
| Device | Tested | Library |
|---|---|---|
| Pulse Blaster ESR 500 Pro | 06/2021 | SpinCore SpinAPI |
| Insys FM214x3GDA (as multichannel TTL pulse generator) | 03/2025 | Atomize_ITC libs |
| Pulse Blaster Micran | 12/2023 | — |
The device is available via ctypes. The original C library was written by SpinCore Technologies.
The Insys device is available via ctypes. The original library can be found here.
Functions¶
pulser_name()¶
This function returns device name.
pulser_pulse(**kargs)¶
# Default DETECTION pulse, no phase cycling
pulser_pulse()
# A named microwave pulse at 100 ns, length 100 ns
pulser_pulse(
name='P0', channel='MW',
start='100 ns', length='100 ns',
delta_start='0 ns', length_increment='0 ns')
The keyword arguments:
| Keyword | Default | Description |
|---|---|---|
name |
'P0' |
name of the pulse |
channel |
'DETECTION' |
channel string (CH0, CH1, …, CH20) |
start |
'0 ns' |
start time of the pulse (ns, us, ms, s) |
length |
'100 ns' |
length of the pulse (ns, us, ms, s) |
delta_start |
'0 ns' |
start time increment of the pulse (ns, us, ms, s) |
length_increment |
'0 ns' |
pulse length increment (ns, us, ms, s) |
phase_list |
[] |
phase cycling sequence (+x, -x, +y, -y) |
This function sets a pulse with specified parameters. The default argument is name = 'P0', channel = 'DETECTION', start = '0 ns', length = '100 ns', delta_start = '0 ns', length_increment = '0 ns', phase_list = []. The pulse sequence will be checked for overlap. In the auto defence mode (default option; can be changed in the config file) channels AMP_ON and LNA_PROTECT will be added automatically according to the delays indicated in the config file. In this mode AMP_ON and LNA_PROTECT pulses will be joined in one pulse if the distance between them is less than 12 ns (can be changed in the config file).
Allowed channels: 'DETECTION', 'TRIGGER', 'AMP_ON', 'LNA_PROTECT', 'MW', '-X', '+Y', 'TRIGGER_AWG', 'AWG', 'LASER_1', 'LASER_2' ('LASER' is accepted as 'LASER_1'), 'SYNT2' (Insys FM214x3GDA only), and the free channels 'CH10', …, 'CH20' (Pulse Blaster ESR 500 Pro) or 'CH11', …, 'CH14' (Insys FM214x3GDA). Pulse Blaster Micran has no free channels.
Allowed phase_list values: '+x', '-x', '+y', '-y'
Output format (time args): 'number' + 'ns' | 'us' | 'ms' | 's'
Range (Pulse Blaster ESR 500 Pro): pulse length 10 ns – 1900 ns; sequence ≈ 10 s max
Range (Insys FM214x3GDA): pulse length 3.2 ns – 1900 ns; sequence ≈ 10 s max
LASER_1 and LASER_2 are trigger pulses for two lasers, or for the flash lamp and the Q-switch of one laser. They can be up to 15 µs long (15001.6 ns for Insys FM214x3GDA) and may overlap other pulses.
In the case of Insys FM214x3GDA start, length, delta_start, and length_increment will be rounded to a multiple of 3.2 (TRIGGER_AWG timing, and the DETECTION start/delta_start, follow the grid set by awg_time_resolution(): 3.2 ns by default, optionally 0.8 ns).
In the case of Pulse Blaster ESR 500 Pro and Pulse Blaster Micran the DETECTION pulse may carry a phase_list. This list declares the acquisition phase cycle and is used by pulser_acquisition_cycle() whenever that function is called without an explicit acq_cycle argument; passing acq_cycle directly still overrides it. Alternatively, the acquisition phases can be indicated directly in pulser_acquisition_cycle() and the DETECTION pulse left without a phase_list. The plain TRIGGER channel must always have an empty phase_list. In the case of Insys FM214x3GDA a phase_list of DETECTION pulse is used to phase cycle the data.
pulser_update()¶
This function updates a pulse sequence and sends instructions to the pulse programmer. It has to be called after changes have been applied to pulses either via any of the pulser functions or by changing a pulse property directly. Only by calling the function the changes are committed and the real pulses will change.
pulser_next_phase()¶
This function switches all pulses to the next phase. The phase sequence is declared in the pulser_pulse() in the form of phase_list = ['-y', '+x', '-x', '+x', ...]. By repeatedly calling the function one can run through the complete list of phases for the pulses. The length of all phase lists specified for different MW pulses has to be the same. This function also immediately updates the pulse sequence, as it is done by calling pulser_update(). The first call of the function corresponds to the first phase in the phase_list argument of the pulser_pulse().
pulser_acquisition_cycle(data1, data2, acq_cycle=None)¶
# Two-step phase cycle (+x, -x)
i, q = pulser_acquisition_cycle(
np.array([1, 0]), np.array([0, 1]),
acq_cycle=['+x', '-x'])
# acq_cycle omitted: the phase_list of the DETECTION pulse is used
i, q = pulser_acquisition_cycle(np.array([1, 0]), np.array([0, 1]))
This function can be used to shorten the syntax for acquisition in the case of phase cycling. The arguments are (i) two numpy arrays from a quadrature detector, (ii) array of mathematical operations to perform. Data arrays can be both 2D and 1D, representing, respectively, the case of raw oscillograms or integrated data. The length of acq_cycle array and the 1D arrays or the amount of the individual oscillograms in the 2D array should be equal. The data arrays will be treated inside the function as a complex number:
The symbol at the index J of the acq_cycle array means that the corresponding values from the data arrays will be added with the following factor to the resulting array:
Allowed operations: '+x', '-x', '+y', '-y'
| Symbol | Factor | Operation |
|---|---|---|
+x |
+1 |
answer = answer + data1[J] + 1j*data2[J] |
-x |
-1 |
answer = answer - data1[J] - 1j*data2[J] |
+y |
+1j |
answer = answer + 1j*data1[J] - data2[J] |
-y |
-1j |
answer = answer - 1j*data1[J] + data2[J] |
The output of the function is the real and imaginary parts of the answer array after complete cycle of mathematical transformations. These can be both 1D and 2D arrays, depending on the shape of the input data arrays.
For Pulse Blaster ESR 500 Pro and Pulse Blaster Micran the acq_cycle argument is optional. When it is omitted (or an empty list is given) the function falls back to the phase_list declared on the DETECTION pulse; an explicitly supplied acq_cycle always takes precedence.
Although this function is available for Insys FM214x3GDA, it is better to use a modified version of digitizer_get_curve(). In this case acquisition phases should be given directly in the phase list key argument of the DETECTION pulse. For Insys FM214x3GDA the function has a modified signature pulser_acquisition_cycle(data1, data2, points, phases, adc_window, acq_cycle=['+x'], lo=None, hi=None) and is normally called internally by digitizer_get_curve(): the data is taken from the running on-board accumulators (the legacy data1 and data2 arguments are accepted but ignored), and the keywords lo and hi indicate the range of points to recompute. The factor table above applies to the acq_cycle argument in the same way.
pulser_repetition_rate(*r_rate)¶
This function queries (if called without argument) or sets (if called with one argument) the repetition rate of the pulse sequence. If there is an argument it will be set as a repetition rate. If there is no argument the current repetition rate is returned as a string. The maximum available repetition rate depends on the total length of the pulse sequence.
Max: 5 MHz
pulser_shift(*pulses)¶
pulser_shift() # shift all active pulses by their delta_start
pulser_shift('P0', 'P1') # shift only the named pulses
This function can be called with either no argument or with a list of comma separated pulse names (i.e. 'P0', 'P1'). If no argument is given the start time of all pulses that have a nonzero delta_start and are currently active (do not have a length of 0) are shifted by their corresponding delta_start value. If there is one argument or a list of comma separated pulse names only the start time of the listed pulses are changed. Calling this function also resets the phase (if specified in the argument phase_list of the pulser_pulse()) to the first phase in the phase_list.
pulser_increment(*pulses)¶
pulser_increment() # increment all active pulses by their length_increment
pulser_increment('P0') # increment only the named pulses
This function can be called with either no argument or with a list of comma separated pulse names (i.e. 'P0', 'P1'). If no argument is given the lengths of all pulses that have a nonzero length_increment and are currently active (do not have a length of 0) are incremented by their corresponding length_increment value. If there is one argument or a list of comma separated pulse names only the lengths of the listed pulses are changed. Calling this function also resets the phase (if specified in the argument phase_list of the pulser_pulse()) to the first phase in the phase_list.
pulser_redefine_start(*, name, start)¶
pulser_redefine_start(name='P0', start='100 ns')
# Multiple pulses at once
pulser_redefine_start(name=['P0', 'P1'], start=['0 ns', '320 ns'])
This function should be called with two keyword arguments, namely name and start. The first argument specifies the name of the pulse as a string. The second argument defines a new value of pulse start as a string in the format number + [' ms', ' us', ' ns']. Arguments can be either single strings or lists, for example: name = ['P0', 'P1'], start = ['0 ns', '320 ns']. The main purpose of the function is non-uniform sampling. Please note, that the function does not update the pulse programmer. The pulser_update() function should be called to apply changes.
In the case of Insys FM214x3GDA start will be rounded to a multiple of 3.2 (for TRIGGER_AWG/DETECTION pulses: to the grid set by awg_time_resolution()).
pulser_redefine_delta_start(*, name, delta_start)¶
pulser_redefine_delta_start(name='P0', delta_start='10 ns')
# Multiple pulses
pulser_redefine_delta_start(
name=['P0', 'P1'], delta_start=['0 ns', '32 ns'])
This function should be called with two keyword arguments, namely name and delta_start. The first argument specifies the name of the pulse as a string. The second argument defines a new value of delta_start as a string in the format number + [' ms', ' us', ' ns']. Arguments can be either single strings or lists, for example: name = ['P0', 'P1'], delta_start = ['0 ns', '32 ns']. The main purpose of the function is non-uniform sampling. Please note, that the function does not update the pulse programmer. The pulser_update() function should be called to apply changes.
In the case of Insys FM214x3GDA delta_start will be rounded to a multiple of 3.2 (for TRIGGER_AWG/DETECTION pulses: to the grid set by awg_time_resolution()).
pulser_redefine_length_increment(*, name, length_increment)¶
pulser_redefine_length_increment(name='P2', length_increment='2 ns')
# Multiple pulses
pulser_redefine_length_increment(
name=['P0', 'P1'], length_increment=['0 ns', '3.2 ns'])
This function should be called with two keyword arguments, namely name and length_increment. The first argument specifies the name of the pulse as a string. The second argument defines a new value of length increment as a string in the format number + [' ms', ' us', ' ns']. Arguments can be either single strings or lists, for example: name = ['P0', 'P1'], length_increment = ['0 ns', '3.2 ns']. The main purpose of the function is non-uniform sampling. Please note, that the function does not update the pulse programmer. The pulser_update() function should be called to apply changes.
In the case of Insys FM214x3GDA length_increment will be rounded to a multiple of 3.2 (for TRIGGER_AWG pulses: to the grid set by awg_time_resolution()).
awg_time_resolution(resolution)¶
awg_time_resolution('3.2 ns') # default 3.2 ns grid
awg_time_resolution('0.8 ns') # enable the 0.8 ns AWG timing grid
This function sets the effective time grid for AWG pulse timing and is only available for Insys FM214x3GDA. The grid applies to the start, length, delta_start, and length_increment of TRIGGER_AWG pulses and awg_pulse() pulses, and to the start and delta_start of the DETECTION pulse. All other TTL channels always stay on the 3.2 ns grid. The function should be used before defining pulses.
The default resolution is '3.2 ns', which is one pulser tick. With '0.8 ns', which is one DAC sample, the TTL trigger and gate stay on the 3.2 ns hardware grid and the sub-tick remainder is produced by leading zero samples inside the pulse's DAC gate segment. The DETECTION window is likewise placed on the 3.2 ns grid and its sub-tick residual is corrected digitally at readout by shifting the integration window and aligning the trace. This correction is exact for a decimation of 1 or 2 and is rounded to 1.6 ns for a decimation of 4.
Allowed: '3.2 ns', '0.8 ns'
pulser_reset()¶
The function switches the pulse programmer back to the initial state (including phase) in which it was in at the start of the experiment. This function can be called only without arguments. It includes the complete functionality of pulser_pulse_reset(), but also immediately updates the pulse programmer as it is done by calling pulser_update().
Note
This function is not available for Insys FM214x3GDA. The function
pulser_pulse_reset() can be used instead.
pulser_pulse_reset(*pulses)¶
pulser_pulse_reset() # reset all pulses (incl. phases)
pulser_pulse_reset('P1') # reset only the named pulses
This function switches the pulse programmer back to the initial state in which it was in at the start of the experiment. This function can be called with either no argument or with a list of comma separated pulse names. If no argument is given all pulses are reset to their initial states (including phases). The function does not update the pulser, if you want to reset all pulses and also update the pulser use the function pulser_reset() instead.
Note
For Insys FM214x3GDA, pulser_pulse_reset() also resets the acquisition index for the next full scan. Use pulser_pulse_reset(reset_index=False) to restore pulse parameters between rows of a 2D scan while preserving the acquisition index and accumulated data. This does not reopen the board. Reset AWG pulse parameters separately with awg_pulse_reset(); call the default pulser_pulse_reset() after the complete 2D scan.
pulser_stop()¶
This function stops the pulse programmer. The function should always be called at the end of an experimental script in the case of Pulse Blaster ESR 500 Pro.
Note
This function is not available for Insys FM214x3GDA. The function
pulser_close() must be used instead.
pulser_state()¶
This function queries the pulse programmer state and should be called only without arguments.
Note
This function is only available for Pulse Blaster ESR 500 Pro.
pulser_visualize()¶
This function visualizes the pulse sequence as 2D plot and should be called only without arguments.
pulser_pulse_list()¶
This function should be called only without arguments and it returns the declared pulse sequence as an array.
pulser_open()¶
This function should be called only without arguments and is only available for Insys FM214x3GDA and Pulse Blaster Micran. In the case of Insys FM214x3GDA, the function should be used after defining pulses and repetition rate with pulser_pulse() and pulser_repetition_rate().
For Insys FM214x3GDA this function checks whether the FPGA is available in both test mode and real execution. In test mode it only reads the board status and does not mark the board as busy. During real execution it reserves the board before initialization and raises RuntimeError if another acquisition is using the FPGA or recovery requires a reboot. This protection applies to scripts launched from the GUI or a terminal using the same Atomize installation.
pulser_close()¶
This function should be called only without arguments and is only available for Insys FM214x3GDA and Pulse Blaster Micran. The function must be used at the end of an experimental script to gracefully close the board.
For Insys FM214x3GDA, call this function in a finally block so that handled errors also release the board. Only the process and driver instance that opened the FPGA may clear its busy status. Calling it in test mode, after a rejected open, or again after successful closing leaves the status unchanged. Reported cleanup failures raise RuntimeError and keep further acquisition blocked.
Warning
For Insys FM214x3GDA, if the acquisition process terminates without releasing the FPGA, or initialization or cleanup reports an uncertain hardware state, the computer must be rebooted before another acquisition. Restarting Atomize does not clear this condition. Status records from an earlier boot are ignored after reboot. Do not manually clear the busy status to bypass recovery.
pulser_default_synt(num, *pulses)¶
pulser_default_synt(1) # all AWG pulses from synthesizer 1
pulser_default_synt(2, 'P3', 'P5') # AWG pulses of the TRIGGER_AWG pulses 'P3' and 'P5' from synthesizer 2
This function selects the source of the AWG path of the microwave bridge. With 1 (default) all AWG pulses use synthesizer 1: the SYNT2 channel is kept on during the whole pulse sequence. With 2 the listed pulses, given by the names of their TRIGGER_AWG pulses, use synthesizer 2 and all other AWG pulses stay on synthesizer 1: the SYNT2 channel is switched off around the listed pulses, starting synt2_lead before and ending synt2_trail after their gate (both 16 ns by default, set in the config file). The switching follows start and length changes of these pulses. It should be called after the pulses are defined. In test mode the function checks that at least one pulse is given with 2, that the names are TRIGGER_AWG pulses, and that a switching window does not overlap an AWG pulse that stays on synthesizer 1. The SYNT2 channel cannot be set with pulser_pulse().
Allowed: 1, 2
Note
This function is only available for Insys FM214x3GDA.
pulser_phase_reset()¶
This function resets the phase index to zero in order to start phase cycling once again.
Note
This function is only available for Pulse Blaster ESR 500 Pro and Pulse Blaster Micran.
pulser_clear()¶
This is a special function for clearing pulse array {self.pulse_array} and other status flags of the device module. The function is usually used in GUI applications that use the device module.
pulser_full_stop()¶
This is a special function for a complete stop of the pulse programmer, which means all the pulse instructions will be set to zero.
Note
This function is only available for Pulse Blaster Micran.
pulser_test_flag(flag)¶
This is a special function for changing test mode. The function is usually used in GUI applications that use the device module.
Allowed: 'None', 'test'