Pulse Programming
Pulse Programming
Bruker software support is available via phone, fax, e-mail or Internet. Please con-
tact your local office, or directly:
Address: Bruker BioSpin GmbH
Service & Support Department
Silberstreifen
D-76287 Rheinstetten
Germany
Phone: +49 (721) 5161 455
Fax: +49 (721) 5161 943
E-mail: [email protected]
FTP: ftp.bruker.de / ftp.bruker.com
WWW: www.bruker-biospin.de / www.bruker-biospin.com
Contents
Chapter 1 Basic pulse program writing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3
1.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3
1.2 Pulse program library . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4
1.3 Pulse program display . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4
1.4 Basic syntax rules . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4
1.5 Pulse generation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9
1.6 Delay generation. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 34
Chapter 2 Decoupling . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 47
2.1 Decoupling . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 47
2.2 Composite Pulse Decoupling (CPD) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 49
Chapter 3 Loops and conditions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 57
3.1 Loop statements . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 57
3.2 Conditional pulse program execution. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 59
3.3 Suspend/resume pulse program execution . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 66
Chapter 4 Data acquisition and storage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 67
4.1 Start data acquisition . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 67
4.2 Acquisition memory buffers. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 74
4.3 Writing data to disk . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 76
Chapter 5 The mc macro statement . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 81
5.1 The mc macro statement in 2D. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 81
5.2 The mc macro statement in 3D. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 86
5.3 Additional mc clauses. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 88
5.4 General syntax of mc . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 90
Chapter 6 Subroutines . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 93
6.1 Definition . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 93
Chapter 7 Miscellaneous . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 95
7.1 Multiple receivers. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 95
7.2 Real time outputs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 96
7.3 Gradients. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 99
7.4 Miscellaneous statements . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 104
I
Chapter 1
Basic pulse program writing
1.1 Introduction
A pulse program is an ASCII text consisting of a number of lines. Each line may
contain one or more pulse program statements which specify actions to be per-
formed by the acquisition hardware and software. You can set up a pulse program
with the TOPSPIN commands edpul or edcpul (see the Acquisition Reference
manual). The TOPSPIN acquisition commands gs, go, and zg execute the pulse
program defined by the acquisition parameter PULPROG which can be set with
eda or pulprog. Pulse program execution is a two-step process: After entering
gs, go, or zg, the pulse program compiler is invoked which translates the pulse
program text into an internal binary form that can be executed. Possible syntax
errors are reported. If errors are found, the acquisition will not be started. If, how-
ever, the compilation is successful, the compiled pulse program is loaded into the
acquisition hardware and the measurement begins.
as Avance-AQX. You can easily find out which type of spectrometer you have by
opening the cabinet door; one of the racks is named either AQS or AQX. Since
2005 Avance spectrometers are equipped with a new INDEXreceiver channel (DADC-
DRU). These instruments are named AV-II. These specific names are used in this
manual whenever a description onlyDONE
holds for oneINDEX
or two of them. TOPSPIN 2.0 and
newer only supports Avance-AQS and AV-II spectrometers.
Routine users normally use Bruker pulse programs delivered with TOPSPIN. The
edpul command displays a list of these pulse programs and allows you to view
their contents. Viewing Bruker pulse programs requires that the expinstall
command was executed once after the installation of TOPSPIN. This command cop-
ies the pulse programs suitable for your spectrometer into the data bank.
If you want to write own pulse programs, it can be helpful to start with a Bruker
pulse program and modify it to your needs.
Table 1.1 shows zgcw30 as an example of a simple Bruker pulse program. Here the
following pulse programming rues are used:
1. Pulse programs are line oriented. Each line specifies an action to be performed
by the acquisition hardware or software.
2. A semicolon (;) indicates the beginning of a comment. You can put it anywhere
in a line. The rest of the line will then be treated as a comment.
3. #include <filename> or #include “filename“
5
;zgcw30
;avance-version
INDEX with CW decoupling
;1D sequence
;using 30 degree flip angle
INDEX DONE
#include <Avance.incl>
1 ze
d11 pl26:f2
d11 cw:f2
2 d1
p1*0.33 ph1
go=2 ph31
wr #0
d11 do:f2
exit
ph1=0 2 2 0 1 3 3 1
ph31=0 2 2 0 1 3 3 1
This statement allows you to use pulse program text that is stored in a different
file. It allows you to keep your pulse program reasonably sized, and to use the
same code in various pulse programs. If the filename is given in angle brackets
(< >), the file is searched for in the directory $XWINNMRHOME/exp/stan/nmr/
lists/pp/. Alternatively, double quotes (“ “) can be used to specify the entire
path name of the file to be included.
4. 1 ze
Any pulse program line can start with a label (“1“ in the example above).
Labels are only required for lines which must be reached by loop or branch
statements such as go=label, lo to label times n or goto label. You
Basic pulse program writing 6
can, however, also use labels for numbering the lines. A label can be a number
or, an alphanumeric string followed by a comma. An example of the latter is:
firstlabel, ze INDEX
DONE
The statement ze has the following function: INDEX
• Reset the scan counter (which is displayed during acquisition) to 0
• Enable the execution of dummy scans. This will cause the pulse program
statement go=label to perform DS dummy scans before accumulating
NS data acquisition scans. If you replace ze with zd, go=label will
omit the dummy scans
• The statement zd automatically resets all phase program pointers to the
first element, whereas the statement ze sets all phase program pointers
such that they are at the first element after DS dummy scans.
5. d11 pl14:f2
Execute a delay whose duration is given by the acquisition parameter D[11].
Behind any delay statement, you can specify further statements to be executed
during that delay (note that the delay must be long enough for that statement).
In this example, the power level of channel f2 is switched to the value given by
the acquisition parameter PL[14].
6. d11 cw:f2
Execute a delay whose duration is given by the acquisition parameter D[11]
and, at the same time, turn on continuous wave (cw) decoupling on frequency
channel f2. Decoupling will remain active until it is explicitly switched off with
the statement do:f2. This delay and cw decoupling will begin immediately
after the delay specified in item 5 has finished.
Items 5 and 6 illustrate a general feature of pulse programs: the actions speci-
fied in two consecutive lines are executed sequentially. Actions specified on the
same line are executed simultaneously.
7. 2 d1
Execute a delay whose duration is given by the acquisition parameter D[1].
This line starts with the label “2“, the position where the statement go=2 will
loop back to.
8. p1*0.33 ph1
Execute a pulse on frequency channel f1. The pulse length of this pulse is given
by the acquisition parameter P[1] multiplied by 0.33. P[1] is normally used for
the pulse width of a 90° flip angle. The statement p1*0.33 would then execute
7
a 30° pulse. In general, you can specify the operator * behind (not before!) a
pulse or delay statement, followed by a floating point number. Note that the
channel f1 isINDEX
not specified; it is the default channel for p1, i.e.:
p1*0.33INDEX DONE
is identical to:
p1*0.33:f1
The pulse is executed with a power (amplitude) defined by the acquisition pa-
rameter PL[1]. PL[1] is the default power level for channel f1, but you can also
use a different parameter. For example, the statement pl7:f1 sets the channel f1
power to the value of PL[7]. It must be put on a separate line, with a delay, before
the line with the pulse statement. This gives the transmitter some time to settle
before the pulse is executed.
The phase of this pulse in our example is selected according to ph1, the name of
a phase program or phase list. It must be specified behind the pulse and defined
after the pulse program body. In this example we use the phase program
ph1=0 2 2 0 1 3 3 1
The phase of the pulse varies according to the current data acquisition scan. For
the first scan, p1 will get the phase 0*90°, for the second scan 2*90, for the third
scan 2*90, for the fourth scan 0*90, etc. After 8 scans, the list is exhausted. The
phase program is cycled so with scan 9 the phase will be set to the first element
of the list: 0*90°. Phase cycling is a method of artefact suppression in the spec-
trum to be acquired. The receiver phase must be cycled accordingly to ensure
that coherent signals of subsequent scans are accumulated, not cancelled. This is
achieved by the receiver phase program ph31 in our example.
9. go=2 ph31
Execute 1 data acquisition scan, then loop to the pulse program line with label
“2“. Repeat this until NS scans have been accumulated. Note that NS is an
acquisition parameter. The data acquisition scans are preceded by DS dummy
scans (because the statement ze is used at the beginning of the pulse sequence
rather than zd). A dummy scan does not acquire any data, but requires the same
time (given by the acquisition parameter AQ) as a real scan. Dummy scans are
used to put the spin system of the sample into a steady state before acquisition
starts.
The receiver phase is changed after each scan as described above for the pulse
phase. Phase cycling is done according to the phase program ph31. Phase
Basic pulse program writing 8
cycling is also used during the execution of dummy scans. Both DS and NS
must therefore be a multiple of the number of phases in the list.
The go=label statement executes a delay, theINDEXso-called pre-scan delay to avoid
pulse feed through before it starts digitizing the
DONE NMR signal. During this time
INDEX
the receiver gate is opened. For AQ_mod = DQD and for any value of AQ_mod
if you have an RX22 receiver, the frequency is switched from transmit to re-
ceive. DE is an acquisition parameter that can be set from eda or by entering de
on the command line. It consists of the sub-delays DE1, DE2, DEPA, DERX and
DEADC that can be set with the command edscon (see the Acquisition Refer-
ence manual). Normally, you can accept the default values for DE value and its
sub-delays. The total time the go=label statement requires to execute a scan is
DE+AQ+3 millisec. The duration of 3 millisec is required for preparation of the
next scan. It is valid for all Avance type spectrometers. AMX/ARX spectrome-
ters require 6 millisec.
10. wr #0
Writes the accumulated data as file fid into the EXPNO directory of the current
data set. Note that with the zgcw30 pulse program, data are only stored on disk
after all NS scans have been accumulated. You can, however, store the data to
disk at any time during the acquisition by entering the command tr on the
command line. You can process and plot these data while the acquisition con-
tinues. If you want to protect your data against power failures during long term
experiments, we recommend that you write the data on disk in regular intervals,
for example every 1000 scans. To accomplish this, you can set NS=1000, and
add the line:
lo to 1 times 30
before the exit statement. The pulse program then accumulates a total of
30.000 scans, but stores the result every 1000 scans.
Please note that the loop must include the ze statement. The reason for this is
that wr #0 adds the last acquired data to the data already present in the file.
The real time FID display will only show the data currently present in the acqui-
sition processor’s memory.
11. exit
Specifies the end of the pulse program.
9
1.5.1.1 p0-p63
The statement:
10mp
executes a pulse of width 10 millisec (called a fixed pulse because its duration can-
not be manipulated, see below). The duration must be followed by up, mp or sp.
These units indicate microseconds, milliseconds, and seconds, respectively. If you
would omit the terminating “p“, a delay would executed instead of a pulse.
The statement:
p0:r
executes a pulse of length P[0] which is varied randomly. The parameter V9 speci-
fies, in percent, the maximum amount which is added to or subtracted from P[0].
As such, the effective pulse varies between 0 and 2*P0. It can be set from eda, or
by typing v9 on the command line.
Please note that the gs command ignores the :r option.
The statement:
p30d1H
executes a pulse whose name is defined by the user, and whose duration is deter-
mined by an arithmetic expression. For example, the line:
11
The statement:
vp
executes a pulse whose duration is given by the current value of a pulse list. A
pulse list is a text file that contains one pulse duration per line. It can be set up with
the command edlist (described in the Acquisition Reference manual). The
statement vp uses the list file given by the acquisition parameter VPLIST. When
the pulse program begins, the first duration in the list is used. The statement ivp
moves the list pointer to the next duration. If the end of the list is reached, the
pointer is set to the first item. The statement ivp must be specified behind a delay,
for example:
d1 ivp
0.1u ivp
The statement vp will execute the pulse defined at position 5 of the pulse list. To
the right of the equal sign, any dimensionless expression is allowed. It may contain
any of the parameters listed in Table 1.3.
Basic pulse program writing 12
Instead of setting up a pulse list with edlist, a list of pulses can also be specified
INDEX
within the pulse program using a define statement, e.g.:
DONE= { 10INDEX
define list<pulse> Plist 20 30 }
This statement defines the pulse list Plist with values 10 µsec, 20 µsec and 30
µsec. User defined pulse lists must be initialized within the definition. There are
two alternatives to assigning values directly in {}-brackets. You can specify the
filename of a pulse list or the variable that contains such a filename, both in angle
brackets. Examples,
define list<pulse> P2list = <mypulselist>
define list<pulse> P3list = <$VPLIST>
In both cases, the file that contains the pulse list can be created with the command
edlist vp.
According to the define statements above:
P1list
executes a pulse of 10 µsec the first time it is invoked. In order to access different
list entries, you can append the .inc, .dec or .res postfix to the pulse statement to
increment, decrement or reset the index, respectively. Any index operations are
performed cyclically i.e. when the pointer is at last entry of a list, the next incre-
ment will move it to the first entry. Furthermore, list entries can be specified
directly in squared brackets counting from 0, i.e. the statement:
P1list[1]
executes a pulse of 20 µsec according to the above definition. Lists can be exe-
cuted and incremented with one statement, using the caret postfix operator. As
such, the statement:
P1list^
is equivalent to:
P1list P1list.inc
Finally, you can set the index directly in an arithmetic expression within double
quote characters, appending .idx to the pulse statement. The following example
shows the use of a pulse list that is assigned within its definition:
13
Caution: index operations on pulse lists only take effect in the next line. Further-
more, you cannot access two different entries of the same list on one line. This is
illustrated in the following example:
define list<pulse> locallist = {10 20 30 40}
locallist^ locallist ;uses the same list entry (10 ms) twice
locallist ;the ^ operator takes effect: 20ms
locallist[2] locallist[3] ;executes locallist[3] (40 ms) twice
Note that names for user defined items may consist of up to 19 characters, but only
the first 7 are interpreted: i.e Pulselist1 and Pulselist2 are allowed names but they
would address the same symbol.
A pulse duration can be manipulated with the operator “*“. Examples of allowed
statements:
p1*1.5
p30d1H*3.33
p3*oneThird
vp*3
The operator must be placed behind the pulse statement. oneThird is the name of a
macro which must have been defined at the beginning of the pulse program, e.g.:
#define oneThird 0.33
Note that fixed pulses cannot be manipulated. So the statement 10mp*0.33 would
be incorrect.
Basic pulse program writing 14
Each pulse statement p0-p31 has been assigned an acquisition parameter INP[0]-
INDEX
INP[31] These parameters take a duration value, in µsec. The pulse program state-
ments ipu0-ipu31 add the valueDONE of INP[0]-INP[31]
INDEXto the current value of p0-
p31, respectively. Likewise, dpu0-dpu31 subtract the value of INP[0]-INP[31]
from the current value of p0-p31. The statements rpu0-rpu31 reset p0-p31 to
their original values, i.e. to the values of the parameters P[0]-P[31]. The statements
presented in this paragraph must be specified behind a delay of any length (≥ 0) .
Some examples:
d1 ipu3
0.1u dpu0
d1 rpu0
The duration of the pulses p0-p31 is normally given by the parameters P[0]-P[31].
You can, however, replace these values by specifying an expression in the pulse
program. The following examples show how you can do this:
“p13=3s + aq - dw*10“
“p13=p13 + (p1*3.5 + d2/5.7)*td“
The result of such an expression must have a time dimension. You can therefore
include acquisition parameters such as pulses, fixed pulses, delays, fixed delays,
the acquisition time AQ and the dwell time DW within the expression. Further-
more, you can include parameters without a dimension such as the time domain
size TD. The complete list is shown in Table 1.3.
An expression must be specified between double quote characters (“ “). It can be
placed anywhere in the pulse program, as long as it occurs before the line that con-
tains the corresponding pulse statement (which would be p13 in our example).
Note that the second expression in the example above assigns a new value to p13
each time the expression is encountered, e.g. if it is contained in a pulse program
loop.
Expressions cannot be used in labelled pulse program lines. You can, however, put
a small duration behind a label and put the expression in the next line.
Expressions do not cause an extra delay in the pulse program. Pre-evaluation is
applied before the pulse program is started, and the result is stored in the available
15
d0-d31 [sec]
p0-p31 [µsec]
INDEX
l0-l31 (loop counters)
INDEX DONE
in0-in31[sec]
inp0-inp31 [µsec]
aq [sec]
dw [µsec]
dwov [µsec]
de1, depa, derx, deadc [µsec]
vd [sec]
vp [µsec]
nbl, ds, ns, nsdone, td, td1, td2
decim
cpdtim1-cpdtim8 [sec]
cnst0-cnst31
Table 1.3
The RF frequency of a pulse is selected via the spectrometer channel numbers f1,
... ,f8 (the actual numbers of the channels depend on your spectrometer type and
accessory). A pulse on a particular channel is executed with the frequency defined
Basic pulse program writing 16
all execute a pulse on channel f2, with the duration P[1], P[2]*0.33, p30d1H*3.33
and a values from VPLIST, respectively. The pulse frequency is the value of the
acquisition parameter SFO2; the default frequency for channel f2. If the channel is
not specified in the pulse statement, p1, p2, ..., p31 all use the default channel f1.
The default frequencies of the channels f1-f8 are given by the parameters SFO1-
SFO8 (see the description of SFO1, NUCLEI, and edasp in the Acquisition Ref-
erence manual for more information about defining frequencies for a particular
channel). These parameters are loaded into the synthesizer(s) before the pulse pro-
gram starts. This gives the hardware time to stabilize before the experiment begins.
You can change the frequency of a channel within a pulse program with the state-
ments fq1-fq8. They take the current value from a frequency list. A frequency list
is a text file whose lines contain frequency values (see the command edlist in
the Acquisition Reference manual). For example, the statement:
d1 fq2:f3
uses the frequency list whose file name is defined by the acquisition parameter
FQ2LIST (fq1 would use FQ1LIST, etc.). You can set FQ1LIST etc. from the
eda dialog box, and you can modify a selected list with edlist. The example
above sets the frequency of channel f3 by taking the current value from the list
defined by FQ2LIST. When fq2 is executed the first time, the current value is the
first value in the list . The next time fq2 is encountered (e.g. because it occurs sev-
eral times in the pulse program, or because it is contained in a loop) the current
value will be the next value in the list, etc. At the end of the list, the pointer will be
set to the first entry of the list. The statements fq1-fq8 not only set a frequency,
but also increment the list pointer to the next entry of the list. The list can, option-
ally, contain a frequency offset in MHz. If it does, the frequency list values in Hz
17
are added to this offset. If it doesn’t, the list values are added to the channel fre-
quency (SFO1 for f1, SFO2 for f2, etc.).
INDEX
The frequency can also be set to the values of the parameters CNST0-31 or to any
number, for example:
INDEX DONE
d1 fq=cnst20:f1 ; SFO1 [MHz] + CNST[20] [Hz]
d1 fq=3000:f1 ; SFO1 [MHz] + 3000[Hz]
set the frequency on channel f1 to the value of CNST20 and to 3000 Hz, respec-
tively. The default settings refer to SFOn as base frequency and the offsets are in
Hz. But the offset can be given in PPM as well, and the base channel frequency can
be BFn instead of SFOn. This is achieved by specifying options after the frequency
setting command. Example:
d1 fq=cnst20 (bf ppm):f1
Option Meaning
sfo base frequency SFOn
bf base frequency BFn
hz offset in Hz
ppm offset in ppm
Table 1.4 frequency command options
For Avance spectrometers, frequency lists can also be defined in the pulse program
using the define statement. The name of a list can be freely chosen, for example:
define list<frequency> username = { 200 300 400 }
The list must be initialized, specifying a list of frequency offsets between braces,
separated by white spaces. By default, the entries are taken as frequency offsets (in
Hz) to the default frequency (SFOx) of the channel, for which the list is used.
However, this behaviour can be changed by specifying a modifier before the first
entry of the list, e.g.:
Basic pulse program writing 18
The usage of these modifiers is deprecated now. Instead the options from table 1.4
should be specified before the first element, separated by a comma:
define list<frequency> absfq = {ppm bf, 4000, 5000, 6000}
Instead of list entries, a list definition can also contain the name of a list file
between angle brackets, e.g.:
define list<frequency> filefq = <freqlist>
The specified file can be created with the command edlist f1. Alternatively,
you can specify $FQxLIST between angle brackets, where x is a digit between 1
and 8. For example:
define list<frequency> f1list = <$FQ1LIST>
In this case the value of the parameter FQxLIST will be used as filename. The for-
mat of frequency lists is the following: the first line contains the modifiers accord-
ing to either table 1.4 or 1.5, the following lines contains the frequencies, one item
per line.
A maximum of 32 different frequency lists can be defined within a pulse program.
The name can be of arbitrary length, but only the first 7 characters are interpreted.
A difference between a regular frequency lists (interpreted by the fqn statements)
and a frequency list defined within the pulse program is that the latter is not
autoincremented. The list index can, however, be manipulated with postfix opera-
tors. The operators .inc, .dec, .res increment, decrement and reset the index,
respectively. Furthermore, you can use a caret operator (^) to execute the list and
increment the pointer with one statement. You can also address a list entry by spec-
19
ifying its index in square brackets []. Note that index manipulation statements are
executed at the end of the duration. This, for example, means that the statement:
INDEX
d1 fqlist^:f1 fqlist:f2
INDEX
sets both channels DONE
f1 and f2 to the same frequency and afterwards increments the
list pointer.
Note that the index runs from 0 and will be treated modulo the length of the list. As
such, by incrementing the index, the frequency can be cycled through a list.
You can also set the index with a relation adding the .idx postfix to the list name.
Example:
define list<frequency> fqlist = { 100 200 300}
ze
1 p1
d1 fqlist:f1 fqlist.inc ; set freq. to SFO1+100, incr. pointer
p1:f1 ; use frequency SFO1+100Hz
d1 fqlist^:f1 ; set frequency and increment pointer
p1:f1 fqlist.res ; use freq. SFO1+200, set pointer to 0
d1 fqlist:f1 ; set frequency to SFO1+100
p1:f1 ; use frequency SFO1+100
d1 fqlist[2]:f1 ; set frequency to SFO1 +300
p1:f1 ; use frequency SFO1+300
"fqlist.idx = 1" ; set pointer to entry 1
d1 fqlist:f1 ; set the frequency SFO1+200
p1:f1 ; use frequency SFO1+200
d1 fqlist.dec ; decrement pointer
go=1
exit
Pulse phases are relative phases with respect to the reference phase for signal
detection. A phase must be specified behind a pulse statement with the name of a
phase program. For example, the statements:
10mp:f1 ph3
p2*0.33:f2 ph4
Basic pulse program writing 20
p30d1H*3.33:f3 ph5
vp:f4 ph6
INDEX As such, the channel
execute pulses on the channels f1, f2, f3 and f4, respectively.
frequencies would be SFO1, SFO2, SFO3, and SFO4.
DONE INDEX The channel phases are set
according to the current value of the phase programs ph3, ph4, ph5, and ph6,
respectively. If a pulse is specified without a phase program, it will have the last
phase that was assigned to the channel on which the pulse is executed. Note that at
pulse program start, before any pulse has been executed, the phase on all channels
is zero.
The four examples above can also be written in the following form:
(10mp ph3):f1
(p2*0.33 ph4):f2
(p30d1H*3.33 ph5):f3
(vp ph6):f4
This form expresses more clearly that a phase is a property of a spectrometer chan-
nel.
In (1), the phases are expressed in units of 90°. The actual phase values are 0, 0,
90, 90, 180, 180, 270, 270.
INDEX
In (2), the phases are expressed in units of 360/5 degrees, corresponding to the
actual phase values
INDEX0*72, 3*72,DONE
2*72, 4*72, 1*72 = 0, 216, 144, 288, 72 degrees.
The divisor, to be specified in parentheses ( ) and before the actual phase list, can
be as large as 65536 (corresponding to 16 bits). This corresponds to a digital phase
resolution of 360/65536, which is better than 0.006°.
In (3) - (9), the operators “ * “ and “ ^ “ are used, which allow you to write long
phase programs in a compact form. For phase programs with less than 16 phases,
the explicit forms (1) and (2) are usually easier to read. The operator “*n“ (with n
= 2, 3, ...) must be specified behind a list of phases that is enclosed in braces { }. It
repeats the contents of the braces (n-1) times. The operator “^m“ (with n = 1, 2, 3,
...) must be specified behind a list of phases that is enclosed in braces { }, or
behind a previous “^m“ or behind an “*“ operator. Each “^m“ operator repeats the
contents of the braces exactly once, but the repeated phase list will be incremented
by m*360/d degrees (modulo d) where d is the divisor of the phase program. If no
divisor is specified, the default value of 4 is used. The following lines display the
phase programs (3) - (9) in their explicit forms:
ph1 = 0 0 0 0 2 2 2 2 ;(3’)
ph1 = 0 2 1 3 ;(4’)
ph1 = 0 2 1 3 2 0 3 1 ;(5’)
ph1 = 1 3 2 0 3 1 1 3 ;(6’)
ph1 = 0 2 0 2 1 3 1 3 2 0 2 0 ;(7’)
ph1 = 0 0 2 2 3 3 1 1 2 2 0 0 1 1 3 3 ;(8’)
ph1 = (5) 1 2 1 2 2 3 ;(9’)
In (10), the phase program is the sum of two other phase programs, one of which is
multiplied with an integer constant. This principle is illustrated by the following
example. Assume the following phase programs:
ph2 = 0 2 1 3
ph3 = 1 1 1 1 3 3 3 3
Phase programs must be specified at the end of the pulse program after the "exit"
statement (see the pulse program example in Table 1.1 at the beginning of this
chapter). Any pulse program can contain up to 32 different phase programs (ph0-
ph31).
At the start of a pulse program, the first phase of each phase program is valid. The
next phase becomes valid with the next scan or dummy scan. When the end of a
phase program is reached, it starts from the beginning (phase cycling).
p1 is executed with the currently active phase of ph8, then p2 is executed with the
next phase in ph8. The caret (^) postfix in the first line, increments the phase
pointer to the next phase in the list. This phase will become valid with the next
pulse program statement that includes this phase program (note that this can be the
same statement if it is included in a loop).
The following example is equivalent to the one above:
23
You can change all phases in a phase program by a constant amount with the :r
option. Each phase program ph0-ph31 has a constant assigned to it, PHCOR[0]-
PHCOR[31]. These can be set from eda, or by entering phcor0 etc. on the com-
mand line. For example, with ph8 = 0 1 2 3 and PHCOR[8]=2°, the phases of
the pulse:
(p1 ph8:r):f2
are 2, 92, 182, 272 degrees. Without the :r option, the phase cycle of p1 would be
0, 90, 180, 270 degrees. The :r option can be used together with the caret postfix,
e.g.:
(p1 ph8^:r):f2
Basic pulse program writing 24
increments all phases of ph3 by 90°. The next time that ph3 is encountered, its
phase cycle will be “1 3 3 1“. Likewise, the pulse program statement:
20u ip4
increments all phases of ph4 by 360/5 degrees. The next time that ph4 is encoun-
tered in the pulse program, its phase cycle will be “(5) 1 2 3 4“.
The statements dp0-dp31 decrement all phases of the associated phase program.
The statements rp0-rp31 reset all phases of a phase program to their original val-
ues, i.e. to the values they had before the first ip0-ip31 or dp0-dp31.
The statements:
6u ip3*2
7.5u dp4*2
The commands in this and the following section cause the pulse program to be
executed from the TCU, whereas normal phase program commands are executed
from the FCU. (Execution from the TCU makes the TCU performance slower. It
can be forced for normal phase programs as well with the command ’phaseOnTcu’
25
There are 2 ways to calculate constants from phase programs and set phases at
runtime:
(1)
"cnst30=ph1+nsdone*90"
p1 ph=cnst30
(2)
"ph1=(nsdone%8)*45"
p1 ph1
In example (1), cnst30 is calculated, using a phase program and adding a variable
amount to it depending on the current scan counter. cnst30 the is used some time
later in the pulse program to set the phase of pulse p1.
In (2), the current value of phase program ph1 is overwritten with some value cal-
culated from the scan counter. The pulse p1 will have this phase as long as no
phase program manipulation command is executed between the two statements.
Any such command will replace the current phase value with the value from the
original phase program.
Basic pulse program writing 26
The ip statement can also be used to add incrementsINDEXother than the amounts
defined in the definition of the phase program. This is done using the parameters
CNST[0]-CNST[31] (which can have DONE a positive or negative value). For example,
INDEX
the statement:
d11 ip1+cnst23
adds the value of CNST[23] to each phase of the phase program ph1.
A constant can also be defined in the pulse program. As such it is calculated at
runtime. For example, the section:
"cnst23=d0*360/24;"
d11 ip1+cnst23
calculates a phase from the current value of d0 and then puts it into the parameter
cnst23. Then it adds this value (in degrees) to each phase of the phase program
ph1. Note that ip1+cnst23 works on the original phase program ph1 whereas
ip1(*n)works on the current phase program ph1.
As an example, the next pulse program section increments the phase at runtime
depending on the number of scans done:
"cnst5 = 20"
2 d1
p1 ph1
6u ip1+cnst5 ; set the phase program to the original values + cnst5 °
"cnst5= nsdone*30"
go =2 ph31
ph1 = 0 2 2 0 1 3 3 1
TOPSPIN allows you set the phase for a particular spectrometer channel without
executing a pulse. In that case, you must specify a phase program behind a delay.
Examples:
(d1 ph1):f3
(0.1u ph3):f2
Instead of setting up ph0-ph31 at the end of the pulse program, a phase program
INDEX
may also be defined by a list definition, which must then occur at the begin of the
pulse program: INDEX DONE
define list<phase> PhList1 = { 0.0 180.0 90.0 270.0 }
This statement defines the phase program PhList1 with phase values of 0°, 180°,
90° and 270°. Note that in contrast to the previously described definitions of phase
programs, all angles are written in degree in this syntax. Instead of initializing the
phase program directly with {}-brackets, you may also specify the file name of a
phase program or the variable that contains such a filename, both in angle brack-
ets. Examples,
define list<phase> PhList2 <myphaseprogram>
define list<phase> PhList3 <$PHLIST>
In both cases, the file that contains the phase program can be created with the com-
mand edlist phase.
Phase setting from user-defined phase programs is done in exactly the same way as
with the standard phase programs by specifying the phase program after a pulse
statement.
After initialization, the current value of a user-defined phase program is its first
entry. You can access other entries by using the list operations .inc, .dec, or
.res to increment, decrement, or to reset the index. By using the caret postfix
operator (^) you can combine phase setting with an increment operation, as with
other list types or with the standard phase programs. However, in contrast to other
list types, you can neither retrieve a particular entry using the []-bracket notation,
nor set the index directly by assigning to PhList1.idx. Furthermore, no equivalents
to the ipX, dpX, and rpX statements available with the standard phase pro-
grams ph0-ph31 exist for user-defined phase programs.
Note that user-defined phase program names may consist of up to 19 characters,
but only the first 15 are interpreted. Up to 32 user-defined phase programs may be
defined in a single pulse program. It is furthermore possible to define the standard
phase programs ph0 to ph31 with the above syntax. In this case the phase pro-
gram base (used for the ip0-ip31, and dp0-dp31 statements) is implicitly
65536 (equivalent to 16 bits). Using an ipX command on a standard phase pro-
gram defined with the above syntax will shift all of its phase entries by
Basic pulse program writing 28
360° ⁄ 65536 ≈ 0, 006° . After 65536 ipX statements, the phase program entries would
have returned to their initial values.
INDEX
1.5.4 Pulse power and shape
DONE INDEX
1.5.4.1 Rectangular pulses
A rectangular pulse has a constant power while it is executed. It is set to the cur-
rent power of the spectrometer channel on which the pulse is executed. The default
power for channel f1, f2, ... , f8 is PL[1], PL[2], .., PL[8]. Here, PL is an acquisi-
tion parameter that consists of 32 elements PL[0] - PL[31]. It can be set from eda
or by entering pl0, pl1, etc. on the command line. You can set the power for a
particular channel with the statements pl0-pl31. For example:
d1 pl5:f2
sets the transmitter power for channel f2 to the value given by PL[5]. Any pulse
executed on this channel will then get the frequency SFO2 and the power PL[5].
The pl0-pl31 statements must be written behind a delay. The power setting
occurs within this delay, which must be at least 2 µsec.
In addition to the PL[0]-PL[31] parameters, you can use user defined power lists
on Avance spectrometers. A user defined power list is defined and initialized in a
single define statement, e.g.:
define list<power> pwl = { -6.0 -3.0 0 }
The define list<power> key is followed by the symbolic name, under which
the list can be accessed in the pulse program. The name is followed by an equal
sign and an initialization clause, which is a list of high power values, in dB,
enclosed in braces. Entries must be separated by white spaces.
You can access a power list by specifying its name, e.g.:
d1 pwl:f1
sets the power of channel f1 to -6.0 dB, when it is used for the first time. You can
move the pointer within a power list with the increment, decrement and reset post-
fix operators .inc, .dec, .res. For example, you can switch to the next entry of the
above list with the statement:
29
pwl.inc
Alternatively, you can use the caret (^) operator to set the power and increment the
INDEX
list pointer within one statement. For example, the statement:
d1 pwl^INDEX
:f1 DONE
is equivalent to:
d1 pwl:f1 pwl.inc
You can also access the list index in a relation, appending .idx to the symbolic
name, e.g:
"pwl.idx = pwl.idx + 1"
Note that list indices start with 0. All index calculations are performed modulo the
length of the list. In the above example pwl[3] = pwl[0] = -6.0.
Note that index manipulations are executed at the end of the duration. This means,
for example, that the statement:
d1 pwl^:f1 pwl:f2
will set both the f1 and f2 channel to the same power level.
As an alternative to initializing a list, you can specify a list file in angle brackets,
e.g.:
define list<power> fromfile = <pwlist>
Such a file can be created or modified with the command edlist va. Instead of a
filename you can also specify $VALIST, for example:
define list<power> fromva = <$VALIST>
A shaped pulse changes its amplitude (and possibly phase) in regular time inter-
vals while it is executing. The pulse shape is a sequence of numbers (stored in a
file, see below) describing the amplitude and phase values which are active during
each time interval. The interval length is automatically calculated by dividing the
pulse duration by the number of amplitude values in the shape file. If this is less
than the minimum duration, an error message is displayed which tells you what is
the minimum pulse duration for this shaped pulse.
The next 3 examples generate shaped pulses:
(10mp:sp2 ph7):f1
(p1:sp1 ph8):f2
(p30d1H*3.33:sp3 ph9):f3
The pulse durations are 10 millisec, P[1], and p30d1H*3.33, respectively. The
pulses are executed on the frequency channels f1, f2, and f3 (i.e. the pulse frequen-
cies are SFO1, SFO2, and SFO3), respectively. The pulse shape characteristics are
described by the entries 2, 1, and 3 (corresponding to :sp2, :sp1, and :sp3) of
the shaped pulse parameter table. This table is displayed when you click the
SHAPE button within eda. The table has 32 entries with the indices 0-31. You
may use the statements :sp0 - :sp31 to refer to the entries 0-31, respectively. As
you can see from the examples, a phase program can be appended to a shaped
pulse in the same way it can be appended to a rectangular pulse. The current phase
of the phase program is added to the phase of each component of the shaped pulse.
31
value that is currently active on the channel that you use. You can do that with the
(currentpower) modifier of the sp statement as shown the following example:
d20 pl9:f1 INDEX
; set power on channel f1 to PL[9]
p1:sp0(currentpower):f1 ; shaped pulse with abs. power PL[9]
p2:f1 DONE ; rectangular
INDEX pulse with power PL[9]
If, in this example, the value of PL[9] is very different from the value of SP[1], the
pulse shape may be compressed. The reason for this is that the CORTAB correc-
tion table for SP[1] is applied rather than for PL[9]. The advantage of this method
is that you can use pulses immediately before and after the shape.
You can access the SHAPE table entries from eda. However, you can also set the
entries from the command line. For example, spnam5 allows you to set the file
name of entry 5, spoffs2 sets the frequency offset of entry 2 and sp15 sets the
absolute power value of entry 15.
Phase alignment
Shapes with frequency offsets do vary the phase in order to efficiate the frequency
shift. By this variation the total phase of the shape is affected as well. The parame-
ter SPOAL[0..31] determines whether the phase is aligned relative to the start or
the end of the pulse. SPOAL has a range of 0 to 1. If SPOAL = 0, the relative
phase shift is 0 at the beginning of the pulse whereas it is determined by the fre-
quency offset SPOFFS and the pulse length at the end of the pulse. If SPOAL = 1
the relative phase shift is 0 at the end of the pulse.
In both cases, the variation of a shape pulse length takes 4 µsec per channel.
Note that varying the length of a shape with non-zero-offset-frequency will change
the offset frequency, as the frequency shift is obtained via phase shifting. This
phase shift won’t be recalculated during execution, so the offset will be changed
inverse proportional to the duration. (Doubling the duration means cutting the off-
set in half). An warning will be printed, when you change the duration of a shape
with offset.
Regular pulse shapes as described above need a short delay before and after the
pulse of ~4 µsec. On Avance-AQS, you can also generate the so-called fast shapes.
They do not require this delay so fast shaped pulses can be executed consecutively
in a loop or they can be executed right before or right after a rectangular pulse. Fast
shape pulses and can be executed with the options :spf0 - :spf31. They differ
from normal shapes in the following respects:
• They do not change the power setting but use the current setting.
• The minimum time for each interval is 350 nsec whereas for normal shapes it is
between 50 and 100 nsec. If this limit is violated, the pulse programs will stop
with the error message: "AQNEXT while FIFO busy".
• The timing of the shape cannot be changed during pulse program execution.
• The total time of the entire shape must be exactly the time for one interval times
the number of intervals in the shape pulse, where the timing resolution of the
time for the intervals is 50 ns (whereas the time resolution for normal shapes is
12.5 ns).
Fast shapes are typically used for solid states experiments.
On Avance-AQS, you can define initialized amplitude lists in a pulse program, for
Basic pulse program writing 34
example:
define list<amplitude> am1={70}
INDEX
The amplitude values represent the percentage of the power of a rectangular pulse.
DONE like: INDEX
The above list is interpreted by a statement
d11 am1:f1
which reduces the power on the f1 channel to 70% of PL[1] (assuming it was at its
default value PL[1]). All rectangular pulses on f1 will then be executed with this
reduced power. A statement like:
d12 pl1:f1
which executes a shaped pulse, resets the power on f1 to PL[1] after is has fin-
ished.
An example of a pulse program segment using an amplitude list is:
define list<amplitude> am1={70}
Table 1.6 shows the available types of statements for the generation of delays. The
35
1.6.1 d0-d31
The statement:
d0
d0:r
executes a delay of width D[0] which is varied randomly. The parameter V9 speci-
INDEX
fies, in percent, the maximum amount which is added to or subtracted from D[0].
As such, the effective delay variesDONE
between 0 andINDEX
2*D0. It can be set from eda, or
by typing v9 on the command line.
Please note that the gs command ignores the :r option.
executes a delay of 10 msec (called a fixed delay because its duration cannot be
manipulated, see below). The duration must be followed by u, m, or s. These units
indicate microseconds, milliseconds, and seconds, respectively.
is the expression that defines its duration. Note that the double-quote characters (“)
are obligatory.
With the above statements, the statement:
compTime
executes a delay whose name is defined in the pulse program, and whose duration
is determined by an arithmetic expression. The define statement must be inserted
somewhere at the beginning of the pulse program, before the actual pulse
sequence.The defining expression must also occur before the actual pulse
sequence. It is evaluated at compile time of the pulse program, not at run time.
Names for user defined delays must consist of alphanumeric characters, and the
first character must be an alphabetic character. The maximum length of the name is
11 characters. Caution, do not use any of the reserved words like ‚adc‘, ‚go‘,
37
executes a delay whose duration is given by the current value of a variable delay
list. A delay list is a text file that contains one delay per line. Delay lists are set up
with the command edlist vd (described in the Acquisition Reference manual).
The statement vd uses the list file defined by the acquisition parameter VDLIST.
When the pulse program is started, the first duration in the list is used. The pulse
program statement ivd can be used to move the list pointer to the next duration. If
the end of the list is encountered, the pointer is reset to the beginning. The state-
ment ivd must be specified behind a delay, for example:
d1 ivd
0.1u ivd
Here, vd will execute a delay whose duration is selected from position 5 of the
delay list. To the right of the equal sign any dimensionless expression is allowed.
This may contain parameters from Table 1.3.
This statement defines the delay list Dlist with the values 0.1sec, 0.2sec and
0.3sec. Instead of delay values, you can specify a list filename in the defined state-
ment. There are two way of doing this: you can specify the actual filename or
$VDLIST, both in <>. In the latter case, the file defined by the acquisition parame-
ter VDLIST is used. For example:
define list<delay> D2list = <mydelaylist>
Basic pulse program writing 38
In both cases, the file an be created or modified with the command edlist vd.
INDEX
In a pulse program that contains the statements above, the statement:
DONE INDEX
D1list
executes a delay of 0.1seconds the first time it is invoked. In order to access differ-
ent list entries, the list index can be incremented by adding .inc, decremented by
adding .dec or reset by adding .res. Index operations are performed modulo the
length of the list, i.e. when the pointer reaches the last entry of a list, the next incre-
ment will move it to the first entry. Furthermore, a particular list entry can be spec-
ified as an argument, in squared brackets, to the list name. For example, the
statement:
D1list[1]
executes a delay of 0.2 seconds. Note that the index runs from 0 to n-1, where n is
the number of list entries.
Lists can also be executed and incremented with one statement, using the caret
postfix operator. For example, the statement:
D1list^
is equivalent to:
D1list D1list.inc
Finally, you can set the index with an arithmetic expression within double quotes
using .idx postfix. The following example shows the usage of an initialized delay
list:
define list<delay> locallist = {0.1 0.2 0.3 0.4}
same line:
• Index operations take effect from the next line on
INDEX
• Furthermore, you cannot access two different entries of the same list in one
pulse program
INDEXline as illustrated
DONEin the following example:
locallist^ locallist ; executes the first list entry (0.1s) twice
locallist ; increment takes effect now (0.2s delay)
locallist[2] locallist[3] ; executes the third entry (0.4s) twice
Note that names for user defined items may consist of up to 19 characters but only
the 7 first are interpreted: i.e Delaylist1 and Delaylist2 are allowed names but
would address the same symbol.
The * operator must be specified behind the delay statement, not before. oneThird
is the name of a macro that must be defined at the beginning of the pulse program
with a statement like #define oneThird 0.33. Note that a statement like
10m*0.33 would be incorrect, since 10m is a fixed delay.
seconds). The pulse program statements id0-id31 add IN[0]-IN[31] to the current
value of d0-d31, respectively. Likewise, dd0-dd31 subtract IN[0]-IN[31] from
the current value of d0-d31. The statements rd0-INDEXrd31 reset d0-d31 to their origi-
nal value, i.e. to the values of the parameters D[0]-D[31]. The statements presented
in this paragraph must be specified DONE INDEX
behind a delay of any length. Examples:
d1 id3
0.1u dd0
d1 rd0
In Bruker pulse programs, D[0] and D10 are used as incrementable delays for 2D
and 3D experiments, IN0 and IN10 are the respective increments which are used to
calculate the sweep widths SW(F1) and SW(F2), respectively (see the description
of IN0, IN10 in the Acquisition Reference manual).
The result of such an expression must have a time dimension. You can therefore
include acquisition parameters such as pulses, fixed pulses, delays, fixed delays,
acquisition time AQ, dwell time DW etc. within the expression. Furthermore, you
can include parameters without a dimension such as the time domain size TD. The
complete list is shown in Table 1.3. An expression must be double-quoted (“ “). It
can be inserted anywhere in the pulse program, as long as it occurs before the
delay statement that uses the expression (d13 in our example). Please note that the
second expression in the example above assigns a new value to d13 each time the
expression is encountered, for example in a loop.
at the beginning of the pulse program. This delay is executed by the statement:
41
compensationTime.
In this expression the length of p4 and d2 are compared, and the delay delta will
become equal to the longer one.
In order to randomize a delay or a pulse only at a certain point of the program, one
can use the following expression:
"p4=random(p1,20)"
1.7.1 Rules
The following rules apply in pulse programs:
1. Pulses and delays specified on subsequent lines are executed sequentially.
2. Pulses and delays which are specified on the same line, and which are enclosed
in the same set of parentheses or without parenthesis are executed sequentially.
Basic pulse program writing 42
1.7.2 Examples
1.7.2.1 Rule 1
f1 p1 100u
f2 p2
1.7.2.2 Rule 2
1.7.2.3 Rule 3
f1 p1
100u p2
f2
The pulses p4 and p1 begin at the same time, p4 on channel f2 and p1 on channel
f1. The pulses p0 and p2 start simultaneously, but not before the sequence with the
longest duration of the previous line has finished (Figure 1.3).
p1 d2 p2
f1
p4 p0
f2
The following 2 lines have been extracted from the colocqf Bruker pulse program.
(d6) (d0 p4 ph2):f2 (d0 p2 ph4):f1
(p3 ph3):f2 (p1 ph5):f1 INDEX
We have three sets of parenthesesDONE in this case. The first item in each set of paren-
INDEX
thesis, i.e. d6 and d0, start at the same time. After d0, p4 on channel f2 and p2 on
channel f1 start simultaneously. Assuming that d6 is larger than d0+p4 and
d0+p2, the second line is executed after d6 has finished.
A final example for rule 3 is a line from the hncocagp3d Bruker pulse program:
(p13:sp4 ph1):f2 (p21 ph1):f3
The shaped pulse p13 on channel f2 is started simultaneously with the rectangular
pulse p21 on channel f3.
1.7.2.4 Rule 4:
The example in the previous section can be rewritten according to this rule
(
(d6)
(d0 p4 ph2):f2
(d0 p2 ph4):f1
)
(p3 ph3):f2 (p1 ph5):f1
There are three global alignment possibilities for the pulse trains: left alignment
(lalign) is the default, right alignment (ralign) will arrange the pulse
sequences such that all of them end at the same time, and center alignment
(center) will start the pulse trains in such a way that they are centered according
to the mid-point of the longest of them. The global alignment must be specified
after the first opening bracket:
(center
45
(d6)
(d0 p4 ph2):f2
(d0 p2 ph4):f1
INDEX
)
INDEX DONE
Pulse train 3 is now right-aligned relative to pulse train 1, pulse train 2 is centered
relative to pulse train 1. From this piece of code several situations may result
which are not obvious but best can be shown graphically: only in 2 of the 6 possi-
ble cases the sequence begins with the reference pulse train.
Basic pulse program writing 46
f1
INDEX
f2
DONE INDEX
f3
p2>2*d0+p1 f1
f2
f3
f1
p3>d0 f2
f3
f1
f2
f3
If the length of individual pulse trains change during pulse program evolution, the
alignment conditions will still be true.
Chapter 2
Decoupling
2.1 Decoupling
Each pulse program line can contain one (and only one) decoupling statement. For
example, the line:
Decoupling 48
d1 cw:f1
turns on cw decoupling on channel f2, i.e. with the frequency SFO2. This syntax is
the same as used for selecting pulse frequencies (see the chapter 1.5.2). The state-
ment:
0.1u cpds1:f3
turns on the composite decoupling sequence 1 on channel f3, i.e. with the fre-
quency SFO3. The statement:
3m do:f3
A 1 millisecond pulse is executed on channel f2, followed by a delay d1. Its phase
is cycled according to phase program ph1.
2.2.1 General
Composite pulse decoupling, as opposed to cw and hd decoupling, offers a large
degree of freedom to set up your own decoupling pulse sequences. Up to 8 differ-
ent CPD sequences can be used in a pulse program. For example, the line:
d1 (cpds1 ph2):f3 (cpds2 ph4):f2
starts, at the beginning of duration d1, CPD sequence 1 on channel f3 and, simulta-
neously, CPD sequence 2 on channel f2. CPD sequence 1 is obtained from a text
file defined by the acquisition parameter CPDPRG1. Likewise, CPD sequence 2 is
obtained from a text file defined by the acquisition parameter CPDPRG2, etc. A
CPD sequence ( = CPD program) can be a Bruker delivered sequence like
WALTZ16, GARP or BB or it can be a user defined sequence. CPD sequences can
be set up with the command edcpd (as described in the Acquisition Reference
manual). Table 2.2 shows the statements available to start a CPD sequence; and
Table 2.3 shows the statements available to build a CPD sequence.
As in pulse programs, the pulse width in CPD programs can be specified as a fixed
pulse, (e.g. 850up) or with the statements p0-p31. The Garp sequence shows the
usage of the lo to statement.
The Garp sequence, as well as the sequences in Table 2.5, make use of the state-
ment pcpd to generate pulses. This enables the execution of the same sequence for
different nuclei on different channels. For example, when executed on channel f2
(f3), the pulse duration of pcpd is given by the parameter g[2] (PCPD[3]). This
allows you to specify the 90° pulse width for two different nuclei in PCPD[2] and
PCPD[3], and decouple both nuclei within the same pulse program using the same
CPD program.
Table 2.5 shows two CPD sequences based on shaped pulses. Shapes are specified
in the same way they are specified in pulse programs using the :sp0, ... , :sp31
pulse selector options. The examples demonstrate the order in which duration mul-
tiplier, shape selector and phase must be specified.
The sequences in Table 2.4 and Table 2.5 do not contain a power setting statement.
51
p0, ... , p31 Generate pulses with durations P[0], ... , P[31].
10up, 5mp, 2.5sp Generate pulses in micro-, milli-, and seconds
pcpd1, ... INDEX
, pcpd8 Generate a pulse with duration according to PCPD[1],
... , PCPD[8], depending on the channel where the
INDEX DONE
CPD sequence is executed (use eda to set PCPD).
d0, ... , d31 Generate delays with durations D0, ... , D31.
10u, 5m, 2.5s Generate delays in micro-, milli-, and seconds.
*3.5 Multiplier. Can be appended to p0-p31 or d0-d31.
:135.5 Phase in degrees. Can be appended to pulses.
:sp0, ... , :sp31 Shaped pulse selectors. Can be appended to pulses.
pl= Power specifier (see example in Table 2.5):
pl=5 in dB
pl=sp13 according to shaped pulse parameters SP[0]-[15]
pl=pl25 according to PL[0]-[15]
fq= Frequency change
fq=2357 in Hz (relative to SFO1 for channel 1, SFO2 for 2...)
fq=cnst25 from the parameters CNST[0]-[31]
fq=fq2 from the frequency list specified in FQ2LIST
; Begin of a comment (until end of line)
lo to label times n Loop to label n times
jump to label Branch to label. Usually the last statement.
#addphase
Special phase control statements
#setphase
Therefore, the current power setting of the main pulse program for the respective
channel is valid.
The following section of a pulse program starts a CPD program on channel f2, but
keeps the f2 transmitter output disabled (statement cpdngs2) except for the peri-
ods given by p2. The p2 pulse actually serves as a gating pulse for CPD decou-
pling. It should not be specified with a phase program in order to prevent
overwriting the CPD program phases.
Decoupling 52
1 90up:0 1 pcpd*0.339:0
160up:180 pcpd*0.613:180
240up:0 INDEX
pcpd*2.864:0
........ pcpd*2.981:180
570up:0 DONE pcpd*0.770:0
INDEX
680up:180 .......
810up:0 pcpd*0.593:0
960up:180 lo to 1 times 2
1140up:0 2 pcpd*0.339:180
1000up:180 pcpd*0.613:0
850up:0 .......
710up:180 pcpd*2.843:180
......... pcpd*0.729:0
200up:0 pcpd*0.593:180
110up:180 lo to 2 times 2
jump to 1 jump to 1
1 pcpd*2:sp15:0 1 pcpd*14.156:sp15:60
pcpd*2:sp15:0 pcpd*14.156:sp15:150
pcpd*2:sp15:180 pcpd*14.156:sp15:0
pcpd*2:sp15:180 pcpd*14.156:sp15:150
pcpd*2:sp15:180 pcpd*14.156:sp15:60
pcpd*2:sp15:0 2 pcpd*14.156:sp15:240
pcpd*2:sp15:0 pcpd*14.156:sp15:330
pcpd*2:sp15:180 pcpd*14.156:sp15:180
pcpd*2:sp15:180 pcpd*14.156:sp15:330
pcpd*2:sp15:180 pcpd*14.156:sp15:240
pcpd*2:sp15:0 lo to 2 times 2
pcpd*2:sp15:0 3 pcpd*14.156:sp15:60
pcpd*2:sp15:0 pcpd*14.156:sp15:150
pcpd*2:sp15:180 pcpd*14.156:sp15:0
pcpd*2:sp15:180 pcpd*14.156:sp15:150
pcpd*2:sp15:0 pcpd*14.156:sp15:60
jump to 1 jump to 1
1u cpdngs2:f2
(p1 ph1 d1):f1
53
1 (p2 d2):f2
lo to 1 times 10
lo toINDEX
2 times 10
Example 1:
Pulse program statement to start the CPD sequence:
d1 cpds2:f2 ph2
Resulting phase of the pcpd pulse: 180 plus the current phase in ph2.
Example 2:
Pulse program statement to start the CPD sequence:
d1 cpd2:f2 ph2
Resulting phase of the pcpd shaped pulse: shaped pulse phase (according to
the phases in the shape file) the current phase in plus ph2.
Example 3:
Pulse program statement to start the CPD sequence:
d1 cpd2:f2
#setphase
pcpd:sp15:180
The first method to set the frequency is using a frequency list. The statements fq1-
fq8 interpret the parameters FQ1LIST-FQ8LIST, set the frequency from the cur-
rent list entry and move the list pointer to the next entry. In contrast to the lists used
pulse programs, lists used in CPD programs are expanded at compile time, not at
run time. In the following example, the first fq1 statement uses the first entry of
the frequency list, the next statement the second entry. If the frequency list con-
tains more than 2 entries, only the first two will be used.
1 pcpd:0 fq=fq1
pcpd:180 fq=fq1
jump to 1
Like in pulse programs, the frequency offset can be specified in two ways: either
the offset is at the top of the list in MHz, or no offset is specified in the list. In the
latter case, the measure frequency of the appropriate channel (SFO1 for F1, SFO2
for F2, etc.) is used as list offset.
The statement fq=cnst25 will set the frequency SFO1 + CNST25 [Hz]. The
parameter CNST25 can also be modified from the gs window. If used on channel
F2, the basic frequency SFO2 instead of SFO1 will be used etc.
55
where label can be any number. The loopcounter n can be a number or a symbolic
loopcounter l0 - l31, where the latter interpret the parameters L[0] - L[31]. It
must be equal to or greater than 1.
Loop counters defined in the pulse program can also be used in the CPD program.
For infinite CPD programs (which are terminated from the pulse program by the
statement do:fn) there is a special jump to label statement which executes an
unconditional jump to the specified label. For calculated jumps forward (see next
section), there exists the command jumpf ln where ln is a loopcounter L0 ..
L31.
You can manipulate the loopcounter of a CPD program after each scan according
to an arithmetic expression in the following way (this statement must be on the
first line of the CPD program):
bilev: "l5=nsdone%4+1"
This means that the loopcounter l5 will be modified after each scan according to
the above equation. The modification will take effect immediately after the scan.
The expression should be written such that the loopcounter is always greater than
zero. The variable loop counter then can be used within the CPD program such that
the first section changes with each scan. This can be done in two ways:
• the CPD program contains a loop using this loop counter.
• the CPD program uses a jump instruction to jump to a calculated label:
bilev: "l31=nsdone%4+1"
jumpf l31
1 pcpd*3:180
pcpd*4:0
Decoupling 56
...
2 pcpd*2:0
... INDEX
3 pcpd*3:180
... DONE INDEX
The jumpf l31 instruction has the effect that the cpd program continues at the
label which corresponds to the current value of the loopcounter calculated above.
Of course, each possible loopcounter value must have a corresponding label.
A bilev statement in a CPD program automatically changes the cpd statement in
the pulse program into the corresponding cpds. This means that the CPD sequence
is not continued at the point where it was stopped before, but starts from the begin-
ning each time it is called.
Chapter 3
Loops and conditions
Example 1:
label1, d1
p1:f2
lo to label1 times 10
p2:f2
p2:f2
The first lo statement in this example does not cause an extra delay in the
INDEX will add a delay of 2.5
pulse program. However, any further lo statement
µsec. TOPSPIN will display DONE
a correspondingINDEX
message when the pulse pro-
gram compiler is invoked, i.e. when entering one of the commands gs, zg,
go, or pulsdisp.
The lo statement exists in a number of variations as shown in Table 3.1.
Example 3:
ze
label1,INDEX
(d1 p1):f1
lo to label1
INDEX times l2
DONE
1u iu2
p2:f2
go=label1
1 ze 1 ze INDEX
2 d11 2 d11
3 0.1u DONE INDEX
3 0.1u
#ifdef PRESAT #include <Presat.incl>
d12 pl9:f1 p1 ph1
d1 cw:f1 d0
d13 do:f1 p0 ph2
d12 pl1:f1 go=2 ph31
#endif d11 wr #0 if #0 id0 zd
p1 ph1 lo to 3 times td1
d0 exit
p0 ph2
go=2 ph31
d11 wr #0 if #0 id0 zd
lo to 3 times td1
exit
#ifdef aFlag
#ifndef aFlag
#endif
causes the pulse program to ignore all subsequent statements until the statement:
#endif
In Table 3.2, #define PRESAT enables the presaturation statement block. Com-
menting out this line in C-syntax style (/*#define PRESAT*/), (not in pulse
program style ;#define
INDEX PRESAT ), would make the PRESAT flag undefined,
and the presaturation block would not be executed.
INDEX DONE
The #ifdef and #ifndef statements are evaluated by a pre-processor. The pulse
program compiler will use the pre-processed pulse program. For this reason, these
statements do not cause any timing changes. You can view a pre-processed pulse
program from the pulse program display. Just enter the pulsdisp command and
and click the button Show program. Note that in the pre-processed pulse program,
all conditional statements beginning with a ’#’ have been removed.
The example could be extended to include double quantum filtering. For this pur-
pose, an additional flag (e.g. #define DQF) could be defined.
The right part of Table 3.2 shows the same pulse program in a more condensed
form. The presaturation block is now contained in a separate file, Presat.incl,
which is included with the #include statement.
Conditions can be set or unset not only within the pulse program but also on the
command line with the zg command using the option -D. For example, the com-
mand zg -DDQF has the same effect as the line:
#define DQF
at the beginning of the pulse program. The argument must follow the -D option
with or without white space in between. The -D option can be given more than
once. As an alternative to command line options to zg, you can also set the acqui-
sition parameter ZGOPTNS. Once this parameter is set, the corresponding option
is used by zg and go. Thus, setting ZGOPTNS to "-DDQF -DPRESAT" and typ-
ing zg has the same effect as the command ’zg -DDQF -DPRESAT’.
Please note:
All statements beginning with a ’#’ character must start at the beginning of a line.
Spaces or tabs before ’#’ are not allowed.
You can use the statement #define not only to define aFlag, but also, as in C lan-
Loops and conditions 62
Example 2:
#define macro2 (p1 d1) \n\
(p2):f2
macro2
This pulse program section is equivalent to:
(p1 d1)
(p2):f2
The definition of macro2 extends over 2 lines using the \n\ character sequence.
In example 1, p1 and p2 start at the same time, while in this example p2 starts
after (p1 d1) has finished.
Example 3:
#define macro3 (p1 d1) \n (p2):f2
macro3
This pulse program is equivalent to:
(p1 d1)
(p2):f2
The definition of macro3 requires only one line. However, the \n character se-
quence enforces a new line when the macro is evaluated. As such, the pulse pro-
grams of the examples 2 and 3 are identical.
if (l7==0) if l7 is zero
if (l8!=0) if l8 is not zero
INDEX
if (l9 op(arith. expression)) op can be ==, !=, >, <, >=, or
INDEX DONE <=
Table 3.3
if (l5 > 2)
{
p1 ph1
}
else
{
p1 ph2
}
Assume that we will start with d0=10m. The pulse p2 will no longer be exe-
cuted when the expression “d0*2 + 7m > 500m“ becomes true.
Example 2:
ze
65
The TCU has 4 trigger input channels (on the TCU3 they are numbered 0-3
and correspond to the trigger commands 1-4); signals arriving at the TCU
can be checked using the trig specifiers. This example performs DS
dummy scans to maintain steady state conditions as long as no positive level
is detected on input channel 2. If such a level is detected, NS data acquisi-
tion scans are executed, then the pulse program again checks the external
trigger signal.
Example 3:
ze
lab1, d1 trigpl2
p1
go=lab1
This example starts executing the pulse sequence as soon as a positive level
is detected on input channel 2. After each scan, the pulse program will wait
until the next trigger signal is detected.
Example 4:
ze
lab1, d1
p1
lo to lab1 times l2
0.1u iu1 ;count number of scans
0.1u iu2 ;increment l2
if “l1 <= 3“ goto lab2 ;if scancounter < 4
0.1u ru2 ;reset l2 to L2
lab2, go=lab1
This example repeats the sequence (d1 p1) L[2] times before scan 1, L2+1
times before scan 2, and L2+2 times before scan 3. Then, l2 is reset to its
Loops and conditions 66
initial value L[2]. Before all remaining scans the sequence (d1 p1) is gen-
erated L[2] times. L[1] must be set to 1 before starting the sequence.
INDEX
3.3 Suspend/resume pulse program
DONE execution
INDEX
TOPSPIN allows you to stop (suspend) the pulse program execution at specified
positions in the pulse program. Pulse program suspension can be done condition-
ally or unconditionally using the statements shown in Table 3.6.
After suspension, the program execution can be resumed with the TOPSPIN com-
mand resume.
If you use suspend or autosuspend, you should not change any acquisition
parameters between suspending and resuming the acquisition. The reason is that
the acquisition uses the principle of precalculation which means a part of the pulse
program is interpreted (precalculated) before it is actually executed. After resume,
the precalculated part is executed without considering the parameter change.
The statement calcsuspend or calcautosuspend, however, stop precalcula-
tion. Here you can change parameters between suspending and resuming the
acquisition. Note that you must specify a delay which is long enough to restart pre-
calculation after resume. For example:
calcsuspend
2s
If, after resuming the acquisition, you would get the error message "timing too
short", you must increase this delay.
Chapter 4
Data acquisition and storage
The rcyc statements can be used for acquisition loops based on adc rather than
Data acquisition and storage 70
go=label or gonp=label. You should not specify phase programs behind rcyc
and rcycnp. Decoupling statements are allowed although it would not make sense
to use them here. Table 4.3 shows an example of INDEX
an acquisition loop with rcyc.
Note that the adc statement is part of the DE1 macro statement.
DONE INDEX
The rcyc statements can also be specified behind a delay, e.g. 100u rcyc=2.
They are then executed during that delay instead of the default 3 millisec. Such a
delay must be at least 100 µsec.
In that case, they are then executed during the specified delay rather than during
the default 3 millisec.
The statements ze and zd can be written behind a delay statement. Such a delay
must be at least 10 µsec and its minimum length depends on the number of phase
programs. They are then executed during the delay. If they are not specified with a
delay their execution will require 3 millisec.
The statement zd is normally executed as a part of the mc macro statement. As
such it does not appear in most Bruker pulse programs. One example where it is
specified explicitly is the pulse program selno.
Table 4.3 The same pulse program based on go, adc/rcyc, and adc/eosc
73
same pulse program realized via go=label, adc in conjunction with rcyc,
and adc in conjunction with eosc.
• You mustINDEX
enable the intermediate frequency using the statement syrec.
This, however, is only necessary for AQ_mod = DQD or, if your spectrome-
INDEX DONE
ters has an RX22 receiver, for any value of AQ_mod.
• The dwell time is generated during aq. For Avance-AQS, the dwell time is
generated on the SGU with the macro DWELL_GEN.
For an example of how to use the adc statement rather than go, please look at the
Bruker pulse program zgadc (enter edpul zgadc). This program will produce
exactly the same result as the program zg.
In pulse programs using the adc statement, the receiver phase must be specified
behind adc, e.g.:
adc ph31
This statement tell the receiver which phase is to be used for the next scan to
account for the receiver phase setting. Note that there must be sufficient time
between the end-of-scan interrupt signal of one scan and the receiver phase inter-
rupt signal of the next scan. Normally, the recycle delay is long enough for this
purpose. However, for some applications (like imaging experiments) the recycle
delay can be too short for correct interrupt handling. In that case, the receiver
1 ... 1 ...
... ...
2 d1 2u recph ph31
10u adc ph31 2 d1
aq DWELL_GEN:f1 10u adc
rcyc=2 aq DWELL_GEN:f1
10u ip31 d2 rcyc=2
lo to 1 times l1 10u ip31
... lo to 1 times l1
...
phase should be specified before the scan loop using the statement recph ph31
(see Table 4.4). The statement ip31 after the recycle loop increments all entries of
the phase program ph31 but does not set the phase. As such, the receiver phase is
INDEX
not changed after each scan but after NS scans.
DONE INDEX
4.1.6 External dwell pulses
The go and adc statements instruct the digitizer to acquire the desired number of
data points with a rate given by the dwell time. On AV-II systems, the DRU uses an
internal dwell clock of 20 MHz which is enabled by the macro DWELL_GEN. On
AQS systems, the dwell pulses are generated by the SGU which is dedicated to the
observe channel. This is the meaning of the macro DWELL_GEN which evaluates
to the statement:
aq cpdngs29:f1
The acquisition statements go=label, gonp=label, and adc put the acquired
data points into a memory buffer where they reside until new data points are added,
or until they are replaced by new data (replace mode is turned on by the statements
ze and zd). A memory buffer provides space for TD data points, where TD must
be set by the user.
In most 1D experiments, one FID is measured and stored in one memory buffer.
After NS scan have been accumulated, the contents of that memory is written to
disk (with the wr statement). Multi-dimensional experiments, imaging experi-
ments, experiments varying parameters such as the decoupling frequency or recov-
75
ery time generate several FID’s. In that case you can use one or several memory
buffers. If a single buffer is used, the buffer contents must be transferred to disk
before the next FID
INDEXcan be measured. If several buffers are used, several FID’s can
be measured before a disk transfer is required. The latter method is appropriate if
the FID’s of theINDEX DONE
experiment succeed one another so quickly that no disk transfer is
possible in between them.
The acquisition parameter NBL determines the number of memory buffers used
(default: NBL=1). Each buffer has a size TD. If TD is not a multiple of 256, the
buffer size will be rounded to the next multiple of 256 data points . The acquisition
commands will put the FID into the current buffer. The default current buffer is
buffer 1. The pulse program statement st makes the next buffer the current buffer
whereas the statement st0 makes the first buffer the current buffer. When the
number of buffers is exhausted, i.e. when st is executed for the NBL’th time, the
first buffer becomes the current buffer.
The statements st and st0 must be specified behind a delay which must be at
least 10 µsec, e.g.:
10u st
Table 4.5 shows an example, the Bruker pulse program noedif. The FID’s acquired
1 ze
d11 pl14:f2
d11 fq2:f2 st0
2 d1
3 d20 cw:f2
d13 do:f2
p1 ph1
go=2 ph31
d1 fq2:f2 st
lo to 3 times l4
d11 wr #0 if #0
exit
The size of NBL is limited by the constraint that NBL times TD must not exceed
the available RCU memory. For example, an RCU equipped with 4 Mb DRAM
allows for about 3.8 Mb FID data to be stored (the remainder is needed by the
INDEX
acquisition parameters). If necessary, you can upgrade your spectrometer with
more RCU DRAM. DONE INDEX
It is allowed to specify the statements if, zd, id0-id31, ip0-ip31, and decou-
pling statements behind the same delay that is used for wr. It is important to use
either a zd or ze statement after each wr before the next scan. Otherwise the data
will be added to data previously acquired in the same memory region.
The name of the output file is fid or ser. An fid file contains a single FID, whereas
a ser file contains a series of FID’s. The appropriate name is automatically chosen
by the pulse program compiler: if a pulse program contains one of the increment,
decrement, or reset file pointer statements, or st/st0, a ser file will be created.
If the pulse program uses a ser file, the acquisition command checks if a ser file
already exists and if it has the correct size. If this is the case, the first occurrence of
a wr statement will overwrite the ser file section defined by the current file pointer,
TD, and NBL. If a ser file does not exist or has the wrong size, a new ser file will
be created filled it with zeroes before acquisition starts. As such, the ser file is not
required to grow during the experiment. This method avoids the risk of running out
of disk space while acquisition is in progress.
77
before the actual pulse sequence. Without this statement, the status parameter
AQSEQ would be set to an arbitrary value. In that case you can still set it after the
acquisition has finished (before processing) is with the command 3s aqseq .
The wr statements (and all other statements in Table 4.6) can be specified behind a
delay (see the example in Table 4.5). The delay must be at least 10 µsec. The only
timing requirement for wr is that the disk transfer is finished before wr is called
79
again. If it is not, a run-time error message is printed. The actual execution time of
a disk write depends on the computer hardware, the operating system, and the sys-
tem load accordingINDEX to currently active processes and users. Bruker recommends to
acquire data only to a disk that is physically connected to the computer that con-
INDEX
trols the spectrometer. DONE
However, there is another limit if wr is used in conjunction with other commands
for data handling. The commands wr, if and zd may be combined on a single line.
Other commands, like ze must be on a separate line. Any sequence containing one
of these commands more than once must have a delay of 10 ms between two of
them.
Chapter 5
The mc macro statement
You can turn this sequence into a 2D sequence by taking the following steps:
• increment the file pointer after each disk write
• initialize the buffer after each disk write
• increment a delay, by convention d0, in each loop
• add a loop outside of the wr #0 statement to a second label - the size of
which is usually td1
• for phase sensitive acquisition: add a phase increment
When the indirect dimension is acquired phase insensitive, the 2D pulse program
would have the following form:
The mc macro statement 82
1 ze
2 d1
3 p1 INDEX
d0
go=2 DONE INDEX
d1 wr #0 if #0 zd id0
lo to 3 times td1
The last two lines can be replaced by the mc statement. In the above sequence, this
would take the form:
d1 mc #0 to 2 F1QF(id0)
The statement mc is a macro that includes a disk write (wr), a file increment (if)
and memory initialization (zd). It can be used with one or more clauses, e.g. F1QF,
which expands to a loop structure. Each clause can take one or more pulse program
statements, e.g. id0, as arguments. These statements are executed within the loop
created by the clause. Different mc clauses are used for phase sensitive, phase
insensitive and echo-antiecho experiments. However, the same mc clause, i.e. the
same pulse program, can be used for different types of phases sensitive experi-
ments like QSEQ, States, TPPI and States-TPPI. The experiment type is deter-
mined by the F1 acquisition parameter FnMODE. The allowed combinations of
FnMODE and mc clauses are listed in Table 5.1.
1 ze
2 d1
3 p1 ph1
d0
p0 ph2
go=2 ph31
d1 mc #0 to 2 F1PH(ip1, id0)
exit
ph1 =0 2 2 0 1 3 3 1
ph2 =0 2 0 2 1 3 1 3
ph31=0 2 2 0 1 3 3 1
The expanded pulse programs will have the following header which is the same for
the different values of FnMODE[F1]:
define delay MCWRK
define delay MCREST
"MCREST = d1 - d1"
As such, it is not specified in the expanded pulse programs below. Note that
MCWRK, MCREST are general delays that are defined during the expansion of
the mc statement. MCREST is zero for all expansions of cosyph but can be non-
zero for other pulse programs. MCWRK, however, is different for different expan-
sions. Note that the phase programs are, for each value of FnMODE, the same as in
the unexpanded pulse program.
FnMODE[F1] = QSEQ:
define loopcounter ST1CNT
"ST1CNT = td1 / ( 2 ) "
"MCWRK = 0.500000 * d1"
1 ze
The mc macro statement 84
FnMODE[F1] = States
define loopcounter ST1CNT
"ST1CNT = td1 / ( 2 ) "
"MCWRK = 0.500000 * d1"
1 ze
2 MCWRK
LBLSTS1, MCWRK
LBLF1, MCREST
3 p1 ph1
d0
p0 ph2
go=2 ph31
MCWRK wr #0 if #0 zd ip1
lo to LBLSTS1 times 2
MCWRK rp1 id0
lo to LBLF1 times ST1CNT
exit
FnMODE[F1] = TPPI
"MCWRK = d1"
1 ze
"in0 = in0 / 2"
2 MCWRK
LBLF1, MCREST
3 p1 ph1
d0
p0 ph2
85
go=2 ph31
MCWRK wr #0 if #0 zd ip1 id0
INDEX to LBLF1 times td1
lo
exit
INDEX DONE
FnMODE[F1] = States-TPPI
define loopcounter ST1CNT
"ST1CNT = td1 / ( 2 ) "
"MCWRK = 0.500000 * d1"
1 ze
2 MCWRK
LBLSTS1, MCWRK
LBLF1, MCREST
3 p1 ph1
d0
p0 ph2
go=2 ph31
MCWRK wr #0 if #0 zd ip1
lo to LBLSTS1 times 2
MCWRK id0
lo to LBLF1 times ST1CNT
exit
The expanded version of the pulse program can be found in the expno directory of
the dataset in the file pulseprogram. Note that the mc statement performs the fol-
lowing actions:
• In QSEQ, States, States-TPPI and Echo-Antiecho mode, mc creates two
loops and sets the corresponding labels and delays. The delay at the line to
which mc loops back to is split into two equal parts: one for the inner loop
label and one for the outer loop label.
• For FnMODE[F1] = QSEQ or TPPI, the value for the delay increment is
divided by 2 during run time. The parameter ND0, which represents the
number of occurrences d0 within the loop, must have same value for all val-
ues of FnMODE.
• For FnMODE[F1] = QSEQ or States, an rp1 statement is included within
the outer loop. This causes the phases of ph1 to be reset to their original val-
ues.
• For FnMODE[F1]= States, States-TPPI and Echo-Antiecho, the statements
specified in the first argument of the mc clause are executed in the inner loop
The mc macro statement 86
and the statements specified in the second argument are executed in the
outer loop.
• For FnMODE = QSEQ, the statements specifiedINDEX in the first and second argu-
ment of the mc clause are executed in the inner loop.
DONE INDEX
• For FnMODE = TPPI, only one loop is created so the statements specified
in the first and second argument of the mc clause are executed in that loop.
• For FnMODE = QF, the mc clause contains only one argument whose state-
ments are executed in the only loop that is created.
For large 2D data sets, it is often useful to test the experiment with the first incre-
ment. This can be done by setting the parameter TD[F1] to 1. The dimension of the
generated dataset will be 1D and can be processed as such. Note that you do not
have to change the value of the parameter PARMODE; it is still set to 2D. In the
same way, you can acquire a plane of a 3D dataset by setting TD[F1] or TD[F2] to
1, and a single row by setting TD[F1] and TD[F2] to 1.
The mc statement can also be used in 3D pulse programs. In this case, there are two
indirect dimensions, F1 and F2. For the F1 dimension, mc uses the clauses F1PH,
F1EA and F1QF, for the F2 dimension, it uses the clauses F2PH, F2EA and F2QF.
The F2PH clause creates a second loop within which a second delay is varied.
The pulse program noesyhmqcpr3d:
aqseq 312
1 d11 ze
2 d11 do:f2
3 d12 pl9:f1 pl2:f2
...
go=2 ph31 cpd2:f2
d11 do:f2 mc #0 to 2
F1PH(ip1 & ip29, id0)
F2PH(rd0 & ip5, id10)
exit
with
87
FnMODE[F2] = States-TPPI
FnMODE[F1] = States-TPPI:
expands to:
INDEX
INDEX
aqseq 312 DONE
If you reverse the acquisition order of this pulse program, i.e. if you specify:
aqseq 321
will expand to
"ST1CNT = td1 / ( 2 * 2 * 2 ) "
"MCWRK = 0.166667 * d11"
"MCREST = d11 - d11"
1 ze
d11 pl12:f2
2 MCWRK do:f2
LBLF1I1, MCWRK
LBLF1I2, MCWRK*3
LBLSTS1, MCWRK
LBLF1, MCREST
3 d12 pl9:f1
...
89
The pulse program line below shows how the F0 clause can be used:
d1 mc #0 to 1 F0(id9) F1QF(id0)
will expand to
MCWRK ip1 MCWRK ip3
lo to 3 times td0
For 3D pulse programs, the clauses F1I and F2I are available for the two indirect
dimensions.
The mc macro statement 90
Note the following things when you view the expanded pulseprogram:
• MCWRK is a fraction of <delay2> and is calculated according to the number
of arguments of the mc clauses
• MCREST is the difference between <delay1> and <delay2>
• the generated labels have names like LBLF*. Please do not use labels with
these names in your own user-defined pulse programs.
• a line starting with # is a comment to the statement(s) that follow it. The com-
ment contains the respective line number in the original pulse program, and, if
applicable, the expansions that were made.
Chapter 6
Subroutines
6.1 Definition
A class name may optionally be appended to the subroutine name. This serves to
identify the subroutine and to prevent it from illegal usage:
subroutine SR1:CLASS1(...)
This call together with the definition in the previous section will generate the code
p3:f2
If subroutines are defined with a class specification, it is mandatory that the same
specification is added to the call of the subroutine. If labels are specified, the pulse
program compiler changes them into unique names to avoid multiple definitions.
The compiler will insert the subroutine whose name is in SUBNAM1 at this place.
The precompiled pulse program pulseprogram in the raw data directory always
shows the expanded subroutine together with lines which mark its begin and end.
Chapter 7
Miscellaneous
If your spectrometer is equipped with multiple receivers, you can specify in the
pulse program which receiver you want to use to acquire the data. The receiver
number (1-8) can be appended to the following statements:
go, gonp, gosc, goscnp, adc, rcyc, rcycnp, eosc, eoscnp, ze, zd, st, st0,
aq, dw, dwov, recph, wr, if
The spectrometer TCU provides a number of real time outputs which are used to
control various spectrometer components, such as gating and blanking the trans-
mitters. Please refer to your hardware documentation to find out which output is
connected to a particular device. The pulse program compiler will select the cor-
rect output automatically, e.g. for a statement like p1:f2.
The file $XWINNMRHOME/exp/stan/nmr/lists/pp/Avance.incl contains a number of
macro definitions based on the outputs, which can be used in pulse programs. This
file can be viewed with the command edpul Avance.incl.
The hardware documentation will also inform you which of the outputs are free for
special purposes, e.g. for controlling a laser from a pulse program.
An alternative format for the setnmr command allows the setting of whole words
in hexadecimal:
setnmr3 0xffff0000 ;set the high 16 bits of nmr word 3.
The assignment of the bits in NMR0 is shown in table 7.1. Bits 0, 8 and 16 are used
to control which NCO is used in SGU1, bits 1, 9 and 17 for SGU2, and so on. If
NCOs are switched, it is possible either to keep the phase setting of the destination
NCO, or to take over the phase setting of some other NCO to the destination NCO.
The second possibility is called phase continuous frequency switching, the first
97
phase coherent. One can control this behaviour with bits 24-31. The details are
described in table 7.2. The phase of NCO1 can only be set from the accumulator,
the phase of NCO2 can be set from NCO1, and that of NCO3 from either NCO1 or
NCO2. Different bits can be combined, but, of course, it is not possible to set the
phase of NCO3 to that of NCO2 and NCO1 at the same time. Examples:
d1 cw:f1
d1 setnmr0|8 ; set to NCO2, keep the phase of NCO2
d1 setnmr0^8|0 ; set back to NCO1 frequency
d1 setnmr0|8^0|26 ;switch to NCO2, use the phase of NCO1
; for NCO2
This example refers to F1. If the same should be achieved on F2, the correspond-
ing bits for this channel 1, 9 and 17 have to be used instead of 1, 8 and 16.
Miscellaneous 98
The syntax is analogous to the setnmr command. Bit 1 is used for the amplifier
blanking of the amplifier to which the SGU is routed. The blanking information is
routed in the same way as the frequency. (see edasp command and parameter
RSEL). Bit 2 is used to control the NCO selection of another SGU (used in bandse-
lective homodecoupling experiments).
99
7.3 Gradients
INDEX
The term gradient refers to a magnetic field gradient that is added to the homoge-
neous field of the spectrometer DONE
INDEX magnet. A gradient is supplied by a gradient coil
and can be applied in the x, y and/or z spacial dimension. If a gradient is applied in
the x-dimension, the magnetic field will be constant within a y-z plane. In the y-z
plane through the center of the receiver coil, the x-gradient field is zero. In a y-z
plane at one edge of the receiver coil the x-gradient field is +M, whereas in a y-z
plane at the opposite edge it is -M. Here, M is the maximum gradient strength
which depends on the gradient amplifier. For y and z-gradients, the same principle
holds concerning the x-z plane and x-y plane, respectively.
A rectangular gradient has a constant strength during the time it is applied,
whereas a shaped gradient has a variable strength.
They are applied for 10 millisec, P[1], and gradPulse*3.33 and are described by
the gradient parameter table entries 2, 1, and 3, respectively. This table can be
opened by clicking on the GP031 button in eda. It has 32 entries with indices 0-
31. The statements :gp0 interprets entry 0, :gp1 interprets entry 1, etc.
Each entry of the gradient parameter table has 4 assigned parameters: GPX, GPY,
GPZ (the gradient strength multipliers for the 3 spatial dimensions), and a file
name (of the file that contains the gradient strength values).
GPX, GPY, GPZ
These are multipliers with values between 0 to 100. They are applied to the gradi-
ent strength values (which range from -1.0 to 1.0) in the shape file to obtain the
total gradient field strength.
File name
File name is the name of a gradient file. A gradient file can be generated from
Shape Tool window (command stdisp) or from the command line with the com-
mand st (for more information click Help ¤ Online Manual from the Shape Tool
window).
Gradient shape files are stored in JCAMP-DX format in the directory:
$XWINNMRHOME/exp/stan/nmr/lists/gp/
101
Note that if you specify an internal gradient shape, you don’t need a shape file,
however you should define the length of the shape as described below.
INDEX
All gradient parameters can be set from from the eda window by clicking the
GP031 edit button. Alternatively,
INDEX they can can be set by entering gpx0, gpy0,
DONE
gpz0, gpnam0, gpx1 etc. on the command line. As the gradient strength is
expressed as a percentage of the maximum strength, it takes a values between 0
and 100.
As described in the next section, you can also define gradient shape functions in
the pulse program rather than using shaped gradient files.
The length of an internal gradient function (or shape) must be specified at the
beginning of the pulse program, e.g.:
lgrad sin = 100; sine function with 100 values
If, however, a shaped pulse is manipulated with a function, the latter can be speci-
fied with or without parameters. For example:
p1 gp1 * sin
p2 gp2 * sin(100)
103
you can use these features even without ParaVision, but in a restricted manner:
• You can specify Object Oriented Gradients, that are converted into Physical
Gradients. This allows for:
- Acquisition of images with different slice orientation while using the same
pulseprogram. The gradients may be specified in spatial coordinates other
than x, y and z. The pulse program compiler multiplies the gradients with a
rotation matrix (see below) to get x, y and z.
- Acquisition of images with different slice thickness and field of view, every
spatial dimension may be multiplied by a scaling factor.
• The gradients are defined as a percentage of maximum_gradient strength, as
scalar values or functions, which may be combined by addition and multiplica-
tion.
• The functions are either Internal functions, which are handled accordingly by
the compiler, or gradient files containing the function values (see above).
• Scaling and rotation can be suppressed with the following options:
no_scale: Gradient is not scaled
direct_scale or shim_scale: Gradient is not scaled and not rotated
• Hardware dependencies can be accounted for by specifying different values for
xyz.
Examples:
10u grad{(0)|r2d(100)|(0)}; Ramp in the 2nd (or phase) dimension.
1m grad{sin(50,200)*r3d(89|90|91)+cos(50,200) |
(20)|(2|1|3,direct_scale)}
The 1st (or read) dimension contains sin(50,200), that means: a sine function with
50 % amplitude. The 2nd parameter indicates a gradient shape, consisting of 200
values, every value applied 1/200 ms = 5 us.
Miscellaneous 104
Every sine value is multiplied with the current value of r3d(89|90|91). The ampli-
tude of r3d is different for xyz to account for hardware dependencies.
INDEX
The 1st dimension also contains a 2nd gradient shape cos(50,200). You can com-
bine several gradient shapes in one statement, butINDEX
DONE the same length should be used.
The 2nd (or phase) dimension contains (20), indicating a scalar gradient with 20
per cent amplitude.
The 3rd (or slice) dimension contains (2|1|3, direct_scale), indicating a scalar gra-
dient with 2 per cent amplitude in x direction, 1 per cent in y and 3 per cent in z,
independent of rotation and scaling.
Example:
"blktr1=3u"
Example:
3u gatepulse 1 ;generate blanking pulse for f1
Miscellaneous 106
p1:f1
d1
2u gatepulse 1|2 ;generate blanking pulses
INDEX for f1 and f2
(p1):f1 (p2):f2
DONE INDEX
Note that gatepulse statement will only generate the blanking pulse for the
transmitter, the preamplifier and the ASU.
prints the message Hello World during runtime of an experiment. The timing of the
printout follows the interpretation of the pulse program on the TCU and may be
therefore ahead in time of the execution of the pulse program. However, for debug-
ging complex pulse programs it could be helpful.
Index
ASX spectrometer 3
Symbols Avance.incl include file 96
Avance-AQS spectrometer 3, 33, 54, 73, 74
#addphase statement 51, 53 Avance-AQX spectrometer 4
#define statement 13, 39, 61
#endif statement 60 B
#ifdef statement 60 BILEV decoupling 55
#ifndef statement 60 bilev statement 55
#include statement 61 blanking pulses 104
#setphase statement 51, 53 BLKTR[1]-BLKTR[8] parameter array 105
* operator 7, 13, 39 blktr1-blktr8 statements 105
.dec postfix 12, 18, 28, 38 Broadband decoupling 50
.idx postfix 12, 19, 29 Bruker pulse programs 4
.inc postfix 12, 18, 28, 38
.res postfix 12, 18, 28, 38 C
:f1 - :f8 option 16, 17, 19, 28, 30, 43, 48, 106
cag_par file 104
:gp0 - :gp31 options 100
caret postfix 12, 18, 22, 23, 29, 38
:r option 9, 10, 23, 35, 36, 69
CNST[0]-CNST[31] parameter array 26
:sp0 - :sp31 option 30, 50
cnst0-cnst31 statements 15, 26
:sp0 - :sp31 options 51
compilation of a pulse program 3
Numerics composite pulse decoupling 47, 49
conditional pulse program execution 59
4D experiments 78 continuous wave decoupling 6, 47
A cos gradient function 102
cosyph pulse program 83
absolute power of a shaped pulse 31 CPD sequences 49
acquisition scan 7 cpd1-cpd8 statements 47, 50
ADC blanking 68 cpdng1-cpdng8 statements 50
adc statement 39, 67, 70, 71, 72, 73, 76 cpdngs1-cpdngs8 statements 50
amplitude lists 33 cpdngs29 statement 74
AMX spectrometer 3, 8 CPDPRG1 - CPDPRG8 parameters 50
AQ parameter 7, 8, 14, 35, 68 cpds1-cpds8 statements 47, 49, 50
aq statement 15, 35, 39 cpdtim1-cpdtim8 statements 15
AQ_mod parameter 68 currentpower statement 31, 32
AQS rack 4 cw statement 6, 47, 48
AQSEQ parameter 78
aqseq statement 78 D
AQX rack 4 D[0]-D[31] parameter array 35
artefact suppression 7 d0-d31 statements 15, 35, 39, 40, 51
ARX spectrometer 3, 8
I-1
I-2
scan counter 6, 70 U
selno pulse program 71
u option (delay) 35
ser file 76, 77
INDEX up option (pulse) 9, 10
SFO1-SFO8 parameters 16
user defined delay 36
sgrad statement 101
SGU unit 73, 74 INDEX DONEV
shape
V9 parameter 10, 36
file 30, 31
VALIST parameter 29
offset frequency 31
variable list delay 37
Shape Tool 31, 100
vcidx statement 58
shaped
VCLIST parameter 58
gradient 99, 100, 102
vd statement 15, 35, 37
pulse 30
VDLIST parameter 37
shaped pulse
vp statement 9, 11, 13, 15, 31
offset frequency 33
VPLIST parameter 11, 16
sin gradient function 102
sinp gradient function 102 W
solid states experiments 33
sp option (pulse) 9, 10 wr statement 8, 58, 76, 77, 81, 82
SP07 parameter 30, 32 Z
spf0-spf31 statements 33
sslice statement 104 zd statement 6, 23, 69, 70, 71, 74, 76, 82
st command 31, 100 ze statement 5, 6, 7, 23, 69, 70, 71, 74, 76
st statement 58, 75, 76 zg command 3, 58, 61, 76, 82
st0 statement 58, 75, 76 zg pulse program 73
stdisp command 31, 100 zgadc pulse program 73
steady state condition 7 zgcw30 pulse program 4
steady state conditions 65, 69 ZGOPTNS parameter 61
step gradient function 102 zgrad statement 101
suspend command 66 zslice statement 104
syrec statement 68, 73
T
tabRTP 98
TCU unit 63, 65, 96
TD parameter 14, 58, 68, 71, 74, 75, 76, 77
td statement 15
td1 statement 15, 78
td2 statement 15, 78
tr command 8, 68
trigger
events 63
inputs 63
specifiers 64
I-6
INDEX
INDEX DONE