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 console
  • EXIT(): terminate the script
  • SLEEP(seconds): pause for the specified number of seconds
  • XCMD(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 finished
  • RE(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 like XCMD(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, calling XCMD("lock cdcl3") followed by CMD("atma") can cause tuning to run at the same time. To avoid this, preface your commands with the noqu command. For example, use XCMD("noqu lock cdcl3") and XCMD("noqu atma") instead. You may also need to add some delays with the SLEEP 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.