Introduction
I’ve recently been developing some new NMR experiments in TopSpin. I’ve generated many datasets that require tedious processing. In this post, I’ll discuss how Python can be used to automate such tasks in TopSpin.
The older way to automate was to write AU programs, which are based on C. From a programming standpoint, this is cumbersome. Fortunately, we can use Python instead. TopSpin implements Python 2.7 using Jython. This implementation includes standard libraries (e.g. os
or random
). The manual explains that you can also install third-party libraries, but there is no package manager, and hopefully this won’t be necessary for the kinds of basic scripts that I have in mind here.
Getting Started
To get started, use the edpy
command to open the Python editor. You can define new programs here or modify old ones, in a manner analogous to how you typically define pulse sequences. When you run a Python program, a separate thread launches. To terminate a running thread, use the kill
command and find the appropriate Python process.
Syntax and Commands
In addition to the usual Python 2.7 commands, which are all valid, a number of special TopSpin-specific commands have been defined. These new reserved words are always in capital case. Here are some of the most useful ones:
MSG(message, title)
: create a dialog box (user will have to click OK)SHOW_STATUS(message)
: write a string to the TopSpin consoleEXIT()
: terminate the scriptSLEEP(seconds)
: pause for the specified number of secondsXCMD(cmd, wait=WAIT_TILL_DONE or NO_WAIT_TILL_DONE)
: run an arbitrary TopSpin command and wait (or don’t wait) until the command is finishedRE(dataset, show)
: Switch to the specified dataset.dataset
is a list of the form[experiment_name, expno, procno, directory_name]
. This command seems to work better than simpler calls likeXCMD(1)
which can fail to work for some starting states.value=GETPAR2(name)
: retrieve the value of the specified parameter from the current dataset
The Bruker PDF that describes Python automation in TopSpin contains a more comprehensive list of commands.
Example Script
This script takes a series of pseudo-2D experiments, extracts the first spectrum from each one, computes the automatic phase correction, and applies this phase correction to the corresponding dataset.
experiment_name="my_experiment_name"
directory_name="/opt/topspin4.0.5/data/kwaneu/nmr"
procno="1"
# switch to the specified experiment
def recall(expno):
RE([experiment_name, str(expno), procno, directory_name], show="yes")
# keep track of which zero- and first-order phases got used
phase0list=[]
phase1list=[]
# apply these processing commands to experiments 300-340
for exp in range(300,341):
# switch to experiment and apply preliminary processing
recall(exp)
XCMD("1 SI 8")
XCMD("2 BC_mod no")
XCMD("PHC0 0")
XCMD("PHC1 0")
XCMD("xf2")
# extract first row into a temporary dataset
# and apply autophasing
XCMD("rser 1")
XCMD("apk")
# this delay is necessary to allow autophasing
# to complete; otherwise, errors occur
SLEEP(1)
# retrieve and store the optimized phases
phase0 = float(GETPAR2("PHC0"))
phase1 = float(GETPAR2("PHC1"))
phase0list.append("%.0f" % phase0)
phase1list.append("%.0f" % phase1)
# close the temporary dataset
XCMD("close")
# open the original dataset again
recall(exp)
# apply the optimized phases
XCMD("PHC0 %s" % phase0)
XCMD("PHC1 %s" % phase1)
XCMD("xf2")
# tell the user we are done and print out the phases that got used
MSG("%s\n\n%s" % (str(phase0list),str(phase1list)), "phasing complete")
Troubleshooting and Tips
- If you make a mistake in your script, the runtime errors will be reflected in a Java stack trace. This is pretty tedious to read, so if you want to be doing any complicated pure Python, I suggest testing that in a more typical Python environment first.
- Some TopSpin commands seem to ignore the
XCMD
option to wait until finished. For example, callingXCMD("lock cdcl3")
followed byCMD("atma")
can cause tuning to run at the same time. To avoid this, preface your commands with thenoqu
command. For example, useXCMD("noqu lock cdcl3")
andXCMD("noqu atma")
instead. You may also need to add some delays with theSLEEP
command. - For complex scripts, I suggest logging to a file using the usual Python commands for writing strings to disk.
- After processing, I suggest further data analysis within a more modern Python environment via nmrglue, which can read processed data via
read_pdata
.