8.3 Using Pulses
When pulses have been defined and the experiment is started (indicated by
the begin of the EXPERIMENT
section) all pulses get set (as long as
their lengths are defined and non-zero) and all channels or PODs that
have been assigned pulses (that are really used during the experiment) are
switched on.
There are two methods to change the properties of pulses. The first one
works by calling a dedicated function. To change the start position of,
for example, pulse 1 by the start position change time
(DELTA_START
) as defined in the properties of the pulse the
function pulser_shift() can be used:
pulser_shift( P1 ); // or pulser_shift( 1 ); |
Also the start position of several pulses at once can be changed because
this function also accepts a (comma separated) list of pulses. If the
function is called with no arguments at all the start positions of all
pulses that have the DELTA_START
property defined are changed.
There is a similar function for changing the length of pulses by their
DELTA_LENGTH
, called pulser_increment():
pulser_increment( P3 ); // or pulser_increment( 3 ); |
As for the pulser_shift() function also this functions accepts a
comma separated list of pulses, and calling it with no arguments
automatically lengthens all pulses that have the DELTA_LENGTH
property defined.
The second method allows to you to change the start position or length
of a pulse directly and in increments differing from DELTA_START
or DELTA_LENGTH
. If, for example, the position of pulse 4 has to
be changed to 500 ns and its length to 120 ns, one may simply
write
P4.START = 500 ns; P4.LENGTH = 120 ns; |
This method can also be used to switch off a pulse completely by assigning 0 to the pulse length.
Of course, as in the definition of the pulses in the PREPARATION
section the properties of the pulse itself and other pulses can be used
in setting the new values, e.g.:
P4.START = P3.START + 200 ns; P4.LENGTH = 2 * P4.LENGTH + 20 ns; |
As you see, these properties (i.e. start positions and lengths and the corresponding delta start positions and lengths) of pulses can be treated nearly as if they are just normal variables.
Also the values for DELTA_START
and DELTA_LENGTH
can be
changed in this way at any time during the experiment:
P4.DELTA_START = 20 ns; P4.DELTA_LENGTH = 10 ns; |
This holds even if these properties haven't been defined in the
PREPARATION
section at all.
The only pulse properties that may not be changed during the experiment are the function and the phase sequence associated with the pulse.
There is only one point that needs to be taken care of: Just calling one of these methods to change pulse properties does not change the real pulses immediately. Instead, all these changes are stored internally in the program. The changes only get send to the pulser when the function pulser_update() is called. Therefor, the normal way to change the pulse pattern is to change all necessary pulse properties and when everything is done to call pulser_update() in order to commit the changes. In this moment the program will also do all its usual checks, e.g. it will test that no pulses overlap.
There is a further function that resets all pulses to their initial
state, pulser_pulse_reset(). This function can, for example, be
used for repeating the same experiment several times without having to
reset each pulse individually. As in the other functions the argument
can be either one pulse, a list of pulses or no argument, in which case
all pulses are reset to their initial positions and lengths (i.e. as
set in the initial definition of the pulse in the PREPARATIONS
section.
Here is now a somewhat shortened example of a 2 pulse Hahn-echo experiment. Two microwave pulses are needed, a pi-half and a pi pulse, plus a detection pulse to trigger the digitizer. This trigger pulse must move twice as fast as the second microwave pulse because the distance of the echo from the second pulse is always as large as the distance between both the microwave pulses.
DEVICES: dg2020_b; // Berlin X-band spectrometer pulser tds520c; // digitizer VARIABLES: tau_0 = 200 ns; delta_tau = 50 ns; pi_pulse = 100 ns; I, J; data[ 20, 1024]; Window; ASSIGNMENTS: TIMEBASE: 5 ns; TRIGGER_MODE: INTERNAL, REPEAT_TIME = 20 ms; MICROWAVE: POD = P8, V_HIGH = 5 V, V_LOW = 0 V; DETECTION: POD = P5, V_HIGH = 3 V, V_LOW = 0 V; PREPARATIONS: P0: FUNCTION = MICROWAVE, // 1st microwave pulse START = 0 ns, LENGTH = pi_pulse / 2; P1: FUNCTION = MICROWAVE, // 2nd microwave pulse LENGTH = pi_pulse, START = P0.START + P0.LENGTH / 2 + tau_0 - P1.LENGTH / 2, DELTA_START = delta_tau; P2: FUNCTION = DETECTION, // trigger pulse LENGTH = 5 ns, START = P1.START + P1.LENGTH / 2 + tau_0, DELTA_START = 2 * delta_tau; Window = digitizer_define_window( P2.START + 250 ns, 100 ns ); EXPERIMENT: FOR J = 1 : 20 { // repeat experiment 20 times FOR I = 1 : 1024 { digitizer_start_acquisition( ); data[ J, I ] = digitizer_get_area( CH1, Window ); pulser_shift( ); // move all pulses pulser_update( ); // commit the changes } pulser_pulse_reset( ); // reset all pulses } |
Beside the functions for changing the positions and lengths of pulses
there are also functions to adjust the phases of pulses, needed for
for phase cycled experiments. When the experiment starts the phase of
a pulse is set to the first phase of its associated phase sequence
(defined in the PHASES
section). To switch to the next phase the
function pulser_next_phase() has to be used. In contrast to the
functions pulser_shift() and pulser_increment() this function
can not be used for phase changes of individual pulses but alway applies
to all pulses that have been assigned a phase sequence. Thus this function
does not accepts any arguments.
Again, the necessary changes are only send to the pulser when the function pulser_update() is called afterwards. By repeatedly invoking pulser_next_phase() one can run through the complete phase sequence. To reset all pulses to their start phase (i.e. the first phase of the associated phase sequence) the function pulser_phase_reset() can be used.
The next (rather simplified) example is a script for a phase cycled (1-dimensional) stimulated echo experiment. We need three microwave pulses and a further detection pulse that triggers the digitizer at the right moment. During the experiment the first two microwave pulses have to be phase cycled.
DEVICES: dg2020_b; // Berlin X-band spectrometer pulser tds520c; // digitizer VARIABLES: tau_0 = 250 ns; // start distance between 1st & 2nd pulse delta_tau = 25 ns; // and the change of this distance t_0 = 400 ns; // start distance between 2nd & 3rd pulse delta_t = 50 ns; // and the change of this distance Curve_length = 128; // number of points of curve area, data; I, J; ASSIGNMENTS: TIMEBASE: 5 ns; TRIGGER_MODE: INTERNAL, REP_FREQ = 200 Hz; MW: POD = P1, P2, P3, P4, INVERTED, V_HIGH = 5 V, V_LOW = 0 V; DETECTION: POD = P0, V_HIGH = 5 V, V_LOW = 0 V; PHASE_SETUP: MW, // cycle microwave channel +X: POD = P1, // POD 1 on for +X -X: POD = P2, // POD 2 on for -X +Y: POD = P3, // POD 3 on for +Y -Y: POD = P4; // POD 4 on for -Y PHASES: PHASE_SEQUENCE_0 = +x, -x, +x, -x; // for 1st pulse PHASE_SEQUENCE_1 = +x, +x, -x, -x; // for 2nd pulse PREPARATIONS: P0: FUNCTION = MW, // 1st microwave pulse START = 0 ns, LENGTH = pi_half_pulse_length, PHASE_CYCLE = PHASE_SEQUENCE_0; P1: FUNCTION = MW, // 2nd microwave pulse START = P0.START + P0.LENGTH + tau0, LENGTH = pi_half_pulse_length, PHASE_CYCLE = PHASE_SEQUENCE_1; P2: FUNCTION = MW, // 3rd microwave pulse START = P1.START + P1.LENGTH + t0, LENGTH = pi_half_pulse_length, DELTA_START = delta_t; P3: FUNCTION = DETECTION, // digitizer trigger pulse START = P2.START + P2.LENGTH, LENGTH = 10 ns, DELTA_START = delta_t; Window = digitizer_define_window( P3.START + 250 ns, 100 ns ); init_1d( ); EXPERIMENT: FOR I = 1: Curve_length { data = 0.0; FOR J = 1 : 4 { digitizer_start_acquisition( ); area = digitizer_get_area( CH1, Window ); IF J == 1 OR J == 4 { data += area; // add 1st & 4th area } ELSE { data -= area; // subtract 2nd & 3rd area } pulser_next_phase( ); pulser_update( ); } display( I, data ); pulser_shift( ); pulser_update( ); } |
• Simplified pulse cycling |
8.3.1 Simplified pulse cycling
The inner loop in the previous example runs through the 4 different
phase settings, adding up the areas with the correct sign. Instead of
writing out this loop one could also define an acquisition sequence
and use the EDL
function get_phase_cycled_area()
.
This function does everything automatically that had to be spelled out
explicitely in the loop in the previous example and thus makes the
script much simpler. The only changes needed are in the PHASES
and EXPERIMENT
section: first, an acquisition sequence must be
defined and, second, the whole inner loop can be replaced by a single
function call.
PHASES: PHASE_SEQUENCE_0 = +x, -x, +x, -x; // for 1st pulse PHASE_SEQUENCE_1 = +x, +x, -x, -x; // for 2nd pulse ACQUISITION_SEQUENCE = +, -, -, +; ... Window = digitizer_define_window( P3.START + 250 ns, 100 ns ); EXPERIMENT: FOR I = 1: 128 { data = get_phase_cycled_area( CH1, Window ); display( I, data ); pulser_shift( ); pulser_update( ); } |
As can be seen from this example get_phase_cycled_area()
not only sets the pulse phases but also starts the digitizer
acquisition, fetches the measured areas from the digitizer and adds up
the areas according to the acquisition sequence.
get_phase_cycled_area()
can handle one as well as two
acquisition sequences, see below. But also a single acquisition
sequence may need data from two different digitizer channels, for
example an acquisition sequence like this:
ACQUISITION_SEQUENCE = +A, -B, -A, +B; |
which means that the value for the first phase setting has to be
fetched from the first digitizer channel (associated with A
)
and that for the second phase setting the value from the second
digitizer channel (associated with B
) has to be subtracted,
etc. In this case get_phase_cycled_area()
expects its
second argument to be the second digitizer channel, i.e. it must be
called like this:
data = get_phase_cycled_area( CH1, CH2, Window ); |
In some cases one might be interested not only in the value from just
one digitizer window but from two or more. Thus you may specify,
following the digitizer channel(s) to be used for fetching data as many
windows as you need. For each of the windows the phase cycled area is
measured. Of course, in these cases not just one data value will be
returned but an array of data values with as many elements as there are
digitizer windows passed to the function. It is the responsibility of
the writer of the EDL
script to supply an array long enough
to hold exactly as many data as returned by the function. Here's an
example:
VARIABLES: Window_1, Window_2; I; data[ 2 ]; PHASES: PHASE_SEQUENCE_0 = +x, -x, +x, -x; // for 1st pulse PHASE_SEQUENCE_1 = +x, +x, -x, -x; // for 2nd pulse ACQUISITION_SEQUENCE = +A, -B, -A, +B; ... Window_1 = digitizer_define_window( P3.START + 250 ns, 100 ns ); Window_2 = digitizer_define_window( P3.START + 650 ns ); EXPERIMENT: FOR I = 1: 128 { data = get_phase_cycled_area( CH1, CH2, Window_1, Window_2 ); display( I, data[ 1 ], 1, I, data[ 2 ], 2 ); pulser_shift( ); pulser_update( ); } |
Finally, if there are two acquisition sequences
get_phase_cycled_area()
will return 2 values for each
digitizer window. Thus it will returns an array of values, where the
first two values are the data from both the acquisition sequences of
the first window, the next two from the second window etc.
This document was generated by Jens Thoms Toerring on September 6, 2017 using texi2html 1.82.