Evgenii Kovrigin (C) 2022

 



  KovriginNMR:  Classes and commands


  Return to main document

Contents

 

Back to Contents


Introduction

The Python code of KovriginNMR is contained in several files. All class definitions and main service functions are included with the knmr_library.py. In particular, the user will utilize NMR_sample, Sample_Changer, NMR_Experiment, NMR_Workflow, and NMR_Workflow_Report_Log classes. The following sections provide detailed descriptions of each of them.


IMPORTANT TECHNICAL NOTE: To use KovriginNMR code, first, you must display  some experiment in Topspin. The KovriginNMR code will not destroy the current experiment but needs it to extract the path information. Otherwise, due to limitations of Python in Topspin, KovriginNMR cannot determine the user's path.

 

Basic Python usage in Topspin is described in a Bruker manual retrieved from Topspin by clicking on a Help menu item ("?"), selecting Manuals (docs), navigating to Programming Manuals section, and opening Python Programming.

 

Simple approach to debugging of your code is described in Debugging and checking values of variables.

 

Errors triggered upon execution of Python scripts are discussed in Interpretation of Topspin Python errors messages

 

Basic information on Python in Topspin is included in the Help:Manuals (docs): Programming Manuals section. Please, see

 

 

Back to Contents


Description:  NMR_sample class

Intended purpose of this class is to encapsulate all information about specific NMR sample in one object, which includes its formal name, lock solvent, as well as a short code used for marking the tube. For example, a routine chloroform standard labelled with 'CD' on a tube will be entered as:

CD =NMR_sample("Routine CDCl3 standard",    "CDCl3", "CD")
The variable CD on the left encapsulates all this information, which will be accessible through properties of this class: title, solvent, and tube_code. When converted to a string, the object makes a nice printable presentation of its content.

The user can create NMR_sample objects for all his/her NMR samples regardless of whether there is a plan to use them all in a particular workflow. For example, I can create objects for additional standard samples that I have even if I may not need them today:

C= NMR_sample("1% CHCl3", "Acetone", "C") 
C2=NMR_sample("2% CHCl3", "Acetone", "C2") 
E =NMR_sample("0.1% Ethylebenzene", "CDCl3", "E") 

IMPORTANT: Triple-check spelling of the lock solvent in the sample description!  If you misspelled the lock solvent name, it will not be discovered until the solvent name is submitted to the lock system. The error will be triggered at the time of execution and will stall the script.

Back to Contents


 

Description:  Sample_Changer class

KovriginNMR provides most benefit when the instrument is equipped with an automatic sample changer. Yet, the class Sample_Changer is used to handle sample information even when an actual sample changer is absent. In case of a manual insertion, the code will prompt a user to manually insert a specifc sample to the bore when the time comes or you insert wherever you want and just indicate sample as inserted.

 

Making a new Sample_Changer object

The Sample_Changer object holds a database of all samples that will be involved in the current workflow and are currently inserted in the sample changer carousel. To indicate a use of an automatic sample changer and a manual insertion, the object is created with an appropriate argument:

changer = Sample_Changer(AUTOMATIC_CHANGER, changer_capacity=24)

or

changer = Sample_Changer(MANUAL_INSERTION, changer_capacity=24)
      

The second argument is an actual capacity of the changer's carousel. If a manual insertion is used, enter any number larger than the number of samples you intend to utilize in this workflow.

IMPORTANT: the Sample_Changer object does not communicate with an automatic sample changer to know, which positions are occupied by which sample. It is a duty of the user to load correct samples to corresponding positions in the changer carousel and assign the same positions in the Sample_Changer database.

 

 

Adding samples to the database

Addition of a sample to the changer's database is done with add_sample() method. Each NMR_sample object is associated with a specific position number in the database, which is supplied as the second argument of the add_sample() method. The changer object verifies that the samples are associated with positions not yet assigned to other samples.

changer.add_sample(CD,1)
changer.add_sample(C, 2)
changer.add_sample(E, 3)

For a manual insertion, the positions are virtual: just assign all different numbers for the samples.

The Sample_Changer class will not allow adding the same sample twice. If you, indeed, have two identical samples, you will have to create two separate NMR_sample objects for them.

 

Displaying the content of the sample changer database

Current content of the sample database of the changer object may be displayed using confirm_sample_positions() method:

changer.confirm_sample_positions()

The method will pop up a message window in Topspin displaying the current content of the database. A user has to click [Close] button for the Python code to proceed. The same information is available upon conversion of the Sample_Changer object into a string format. The intention is to give the user a chance to confirm that the sample positions in the carousel of the changer are the same that were entered in the KovriginNMR script.

IMPORTANT: This method pauses execution of the KovriginNMR script till the [Close] button is clicked. Comment out this command if you need your script run unattended!

 

Extracting sample information

Any sample in the Sample_Changer database has three pieces of information associated with it: the sample object itself, the tube code, and the position in the changer. You can obtain the tube position and the tube code if you have a sample object as well as find out which sample or the tube code is assigned to a specific position:

sample_object = changer.get_sample_by_tube_code(tube_code='C')
sample_object = changer.get_sample_by_position(position=1)
position = changer.get_position_by_sample(sample=C )
position = changer.get_position_by_tube_code(tube_code='C')

Insertion of a sample in the magnet bore

The Sample_Changer object controls the automatic sample changer to insert the chosen sample into the magnet bore. Different from initiating sample insertion from Topspin command line, you will use the NMR_Sample object itself instead of a position in the carousel:

changer.insert_sample(sample=C)

Essentially, the Sample_Changer relieves the user from the need to remember the position in the carousel for any particular sample. Instead, you can initiate insertion of a sample by just providing its object name in the script.

NOTE: This is not a recommended way of inserting samples in KovriginNMR. The objects of the NMR_Workflow class provide a more convenient and reliable method.

Completely manual insertion: Indicating that the sample has already been placed in the bore

If you want to handle manual insertion separately from your script, you should still add information for your sample to the changer database and indicate that the sample is already in the bore:

changer = Sample_Changer(MANUAL_INSERTION, changer_capacity=1)
changer.already_inserted(sample = CD)

In this case, the changer object only serves to provide sample information to NMR_Workflow class to include in the experiment titles and the HTML report.

 

 

Finding out what sample is currently in the magnet

You can look up what sample has been last inserted in the magnet from the current_sample property of the Sample_Changer object:

sample  = changer.current_sample

This operation returns an NMR_Sample object for the sample, which was last inserted, or an empty string if no sample has been inserted by the script yet. IMPORTANT: "no sample" does not mean the magnet bore is empty. It simply indicates that the Sample_Changer object has not been instructed to insert any samples into the magnet yet.

 

Obtaining a list of samples in the order of increasing position in the carousel

Sequential-access sample changers will work better (use less time) if the samples are requested for insertion in the order of increasing position number. You can obtain a list of samples ordered by position to use it in a loop as follows:

ordered_sample_list  = changer.sample_list_with_increasing_position()
for sample in ordered_sample_list:     ... insert and acquire...
 

Back to Contents


 

 

Description:  NMR_Experiment class

The NMR_Experiment class makes objects representing individual NMR datasets in a user data folder on a workstation drive (the folders that you see in the Topspin Browser window).

The experiments are prepared for acquisition in two steps: (1) creating an NMR_Experiment object and (2) making an experimental folder on a disk and adjusting its parameter set.

IMPORTANT NOTE: When experiments are created, the existing experiments with the same folder name and EXPNO are overwritten without a warning.

 

Step 1. Make NMR_Experiment object

The first step is to create an object of NMR_Experiment class and give it a folder name for the experiment, EXPNO, and a spinning requirement. For example, below I will create an object for a standard experiment to measure proton line shape while spinning:

proton_lineshape_spinning = NMR_Experiment(
				 name= "1H lineshape with rotation", 
 				experiment_folder= 'My_standard_experiment_for_today', 
 				EXPNO =1, 
 				spinning_mode='yes'  # yes/no/solids
 				)

I indicated a formal name of the experiment, which will be included with the title of the experiment data set to be displayed in the Spectrum tab of the Topspin window. I also supplied a folder name, which to create data set in, and the EXPNO (the numbered folder for the dataset inside the experimental folder).

Spinning_mode controls whether the experiment is a acquired with rotation. It will take 'YES', 'yes', 'y', 'NO', 'no', 'n' as valid settings.

NOTE: For a solid-state NMR, you should set spinning_mode to 'solids' because sample spinning is controlled separately.

 

IMPORTANT NOTE: If I want to use an existing experiment folder and intended to issue zg directly in that folder to overwrite existing data, I'll provide the name of this data set and its EXPNO (see 1. Re-run acquisition in a pre-existing experiment (overwriting the data)). Otherwise, if I intend to make a new data set or a copy from an existing one (a template), I will choose a new name for the experiment_folder and/or EXPNO.

 

Step 2. Choose the source experimental folder and adjust parameters

After the NMR_Experiment object has been created, there are four ways to proceed depending on how you want to make a new dataset:

1. Re-run acquisition in a pre-existing experiment (overwriting the data)


2. Duplicate a pre-existing experiment to make an experiment in a new folder (the pre-existing experiment is preserved)


3. Create a brand new experiment from scratch (using a standard experiment available in a Bruker library to create a "starter" experiment and then modifying its parameters as needed)


4. Duplicate the existing NMR_Experiment object to make a copy in a new folder with adjusted (or not) parameters.


Method 1. Re-run acquisition in a pre-existing experiment (overwriting the data)

You may set up an experiment in Topspin manually and use it in KovriginNMR directly with or without adjustments. This is equivalent to re-running the existing experiment with overwriting the previous data. To set up such dataset for re-use, I will call use_existing_experiment() method:

proton_lineshape_spinning = NMR_Experiment(
				 name= "1H lineshape with rotation", 
 				experiment_folder= 'My_existing_experiment_to_rerun', 
 				EXPNO =1, 
 				spinning_mode='yes'  # yes/no
 				)

proton_lineshape_spinning.use_existing_experiment(
	 title_text="Old experiment to be overwritten today", 
 	adjusted_parameters="""
 		RG 1
 		""")

In this example, I have created My_existing_experiment_to_rerun/1 manually in Topspin and provided its folder name and EXPNO to the NMR_Experiment class constructor. Then I call the use_existing_experiment() method of the newly made object with title_text and adjusted_parameters arguments. The title_text is an additional line of text you may want to provide, which will be included with the title of the NMR data set. The adjusted_parameters argument is a multi-line Python string containing Topspin commands that allows to set up the NMR experiment appropriately. Please, see Topspin command reference for details.

 

IMPORTANT: Since you have previously set up this experiment, KovriginNMR does NOT issues a 'getprosol' in this folder. If your spectrometer often changes probes, you may still want issuing getprosol before parameters are set. You enter this command as the first line of adjusted_parameters:

	adjusted_parameters="""
		getprosol		
		RG 1
	"""

Yet, remember, that 'getprosol' erases many parameters you may have had adjusted previously!

 


 

Method 2. Duplicate a pre-existing experiment to make a separate experiment in a new folder

This method is equivalent to creating a new data set from the currently displayed data set in Topspin through Start: Create Dataset: and choosing a radio button Use Current Parameters. To perform this operation, we call copy_from_existing_experiment() method of NMR_Experiment object:

proton_lineshape_spinning = NMR_Experiment(
				 name= "1H lineshape with rotation", 
 				experiment_folder= 'New_experiment_from_template', 
 				EXPNO =1, 
 				spinning_mode='yes'  # yes/no
 				)

proton_lineshape_spinning.copy_from_existing_experiment(
	source_experiment_folder_name ='Proton_Lineshape',
	source_experiment_EXPNO=1, 
	title_text='a copy from my disk', 
	adjusted_parameters="""
     	TD 1036
   		""" )
        

Here, I use NMR_Experiment object that I previously made but call a different method: copy_from_existing_experiment().  The first argument, source_experiment_folder_name, should be a name of the data folder with the pre-existing experiment (in your NMR account). The second argument, EXPNO, is the numbered folder actually containing the source data set. The example above will use Proton_Lineshape/1 as a template for creating a new experiment in the folder New_experiment_from_template/1.

The title_text argument allows to enter additional explanatory information. The last argument, adjusted_parameters, is used as described in the previous case. Please, see Topspin command reference for details.

 

IMPORTANT: Since you have previously set up this experiment, KovriginNMR does NOT issues a 'getprosol' in this folder. If your spectrometer often changes probes, you may still want issuing getprosol before parameters are set. You enter this command as the first line of adjusted_parameters:

	adjusted_parameters="""
		getprosol		
		TD 1036
	"""
        

Yet, remember, that 'getprosol' erases many parameters you may have had adjusted previously!



 


Method 3. Create a brand-new experiment from scratch

This method is essentially the same as creating a new experiment through Start : Create Dataset buttons of Topspin, selecting a radio button Experiment, and typing in or selecting the parameter set name.

This method is most reliable because it will always result in the same set of parameters (does not depend on parameters of pre-existing experiments). This is also the most portable method: it will create identical experiments on any spectrometer (except for the field and pulse durations/powers).

Here I am making my proton line shape measurement experiment in New_experiment_from_parameter_set/1 using a standard parameter set and adjusting its parameters:

proton_lineshape_spinning = NMR_Experiment(
				 name= "1H lineshape with rotation", 
 				experiment_folder= 'New_experiment_from_parameter_set', 
 				EXPNO =1, 
 				spinning_mode='yes'  # yes/no
 				)

proton_lineshape_spinning.create_from_parameter_set(
	source_parameter_set = "PROTON", 
	title_text ='New expt from scratch', 
	adjusted_parameters = """ 
		DS 0
		NS 4
		SWH 1001
		AQ 16
		TD 32K
		O1P 8
		SI 16K
		WDW no
		SSB 0
		LB 0
		GB 0
		PC 1
		CY 1000
		MI 100
 	""" )
        

The standard parameter set name is provided as the first argument for the create_from_parameter_set(...)  method. The title_text is an additional line of text you may want to provide, which will be included with the title of the NMR data set. The last argument, adjusted_parameters, is used as described in the previous cases. Please, see Topspin command reference for details.

Once the experiment has been set up, KovriginNMR issues a 'getprosol' command to update probe parameters (pulses and powers), and then applies instructions that you included in adjusted parameters.


 

Method 4. Duplicate the existing NMR_Experiment object to make a copy with adjusted parameters

This is a case when I have already made an experiment in the KovriginNMR script with one of the above methods and now need a nearly identical one. To do this, I will use the duplicate_experiment_object() method. The syntax is similar to creating a new experiment from existing experiment on a hard drive, but it uses an NMR_Experiment object in place of the folder name and EXPNO, for simplicity:

proton_lineshape_spinning.duplicate_experiment_object(
	source_experiment_object = another_experiment, 
	title_text="another copy", 
	adjusted_parameters="""
		TD 1234
	""")

The first argument is the actual object, which represents the experiment that I made previously in my script. All of its parameters will be copied and additional parameter changes are performed through adjusted_parameters

IMPORTANT: Since you have previously set up this experiment, KovriginNMR does NOT issues a 'getprosol' in this folder. If your spectrometer often changes probes, you may still want issuing getprosol before parameters are set. You enter this command as the first line of adjusted_parameters:

	adjusted_parameters="""
		getprosol		
		TD 1234
	"""

Yet, remember, that 'getprosol' erases many parameters you may have had adjusted previously!


 

 

Updating the experiment title

When you make an NMR_Experiment object, it creates a comprehensive title for the experiment including its name, the experiment folder, the spinning mode and your additional title text, which you provided. This information will be displayed in Topspin in the Spectrum window and in the Title tab.

You may update the experiment title at any time using the append_to_title() method of the NMR_Experiment object.

proton_lineshape_spinning.append_to_title("Additional information text")

          

Displaying the experiment in Topspin (making it "current")

Same as when using Topspin directly, to change any parameters of the data set or begin acquisition, a user has to display the data set to make it current. Any NMR experiment objects that you made in the script may be made the current experiment using a make_dataset_current() method:

proton_lineshape_spinning.make_dataset_current()

NOTE: The preferred way to do it is through a display_experiment() method of the  NMR_Workflow class.

 

 

Notes for next steps


Once the experiments are created, you may inspect all their parameters directly in Topspin. In fact, this is the simplest way of using KovriginNMR: only to perform the experiment setup in a consistent manner. Once all the experiments have been created, they may be acquired manually or queued using the Topspin Spooler if desired.

If more a reliable operation is desired, I recommend acquiring experiments with KovriginNMR as described in the following sections. The KovriginNMR environment allows to program complex queues including loops or branching, which Spooler cannot do. The KovriginNMR scripts are prepared in a text editor, which allows to include necessary comments on your decisions, therefore, reducing chance of mistakes and wasted operator's and NMR time. KovriginNMR scripts may be reused for new projects with a very little effort and easily adjusted to new needs. The HTML report also serves as a permanent record of experimenal design with time stamps for all operations, recorded sample and experiment data, and is easily readable in any browser.

 

Read text files from pdata/1

Some Topspin commands record their output in the experiment folder in pdata/1. One example is humpcal, which measures parameters of the resonance line shape (for accessing shimming quality).

The method fetch_text_file(text_file_name) returns a content of a text file from pdata/1:

output = my_experiment.fetch_text_file('knmr_humpcal.txt')

IMPORTANT NOTE: It is recommended to use fetch_text_file_from_current_experiment() of the NMR_Workflow object instead, because it allows for a "dry run" -- to be skipped in "Make experiments only" mode!

 

Back to Contents


 

Description:  Topspin operations

The KovriginNMR environment allows for direct access to Topspin command line as described in the following subsections. 

NOTICE: The direct access to Topspin is provided for convenience but I strongly recommend to control the spectrometer through corresponding methods of the NMR_Workflow class. This class provides for additional benefits such as creating an HTML report of all operations with time stamps, creating comprehensible experiment titles, and allowing for a "dry run": skipping all spectrometer commands to allow your checking of parameter sets directly in Topspin.

VERY IMPORTANT: To use topshim and pulsecal, you must call corresponding methods of the NMR_Workflow class. The reason behind this requirement is an undocumented (by Bruker) behavior of both topshim and pulsecal, which unexpectedly change the current experiment EXPNO without warning when called from a Python script (including KovriginNMR). The corresponding topshim and pulsecal methods of the NMR_Workflow explicitly return Topspin to the current dataset to allow the commands that follow to operate on the intended dataset.

 

Issuing Topspin commands

You may issue any Topspin command in the experiment same way as you do it on a command line after you displayed the dataset in Topspin. To do this, you make the NMR_Experiment object "current" and then issue commands:

test3.make_dataset_current()
run_topspin_commands("""
	NS 24 
	lock D2O
	atma
	rga	
 """ )

NOTE: Please, see Topspin command reference for details on correct synthax of commands for setting parameters.

 

Obtaining and setting parameters with dedicated commands

To get values of parameters of the current dataset use these commands

value_string = get_topspin_parameter(parameter_name)
set_topspin_parameter(parameter_name, value_string)      

NOTE 1: get_topspin_parameter(...) returns a string so you have to convert it to float or int types for calculations. For example:

number_of_scans = int(get_topspin_parameter('NS'))

See my note on parameters like delays and pulses below!

 

NOTE 2: set_topspin_parameter(...) requires a string as a value of parameter, therefore, you should use a Python string conversion operation:

NS=2048
 set_topspin_parameter('NS', str(NS))

Both commands show a Status Message (below Topspin command line) and pause for one second for you to allow you to observe this message and confirm the command issued. However, if you need to set many of parameters like this, it may be slow: you should use run_topspin_commands(...) instead for speed.

 

IMPORTANT NOTE FOR PULSES, POWERS, AND DURATIONS: all arrayed parameters like durations, D, pulses, P, powers,PLW, etc. must be accessed by giving the name and the index separated by a space:


# Getting calibrated P1 value
p1 = float(get_topspin_parameter('P 1'))
# Getting current value of D16
d16 = float(get_topspin_parameter('D 16'))
# setting power PLW1 to zero
plw1 = 0
set_topspin_parameter('PLW 1', str(plw1))

Please, see Topspin command reference for details on correct synthax of commands for setting parameters that belong to different dimensions.

 

 

KNOWN GLITCH: Topspin versions below 4 may not update the value of the parameter shown in Topspin window that you have set through the above commands. The values ARE SET just not updated in the window view. You should display experiment again or switch to another tab and come back to Acqpars tab to see the updated values.

 

 

Back to Contents


 

Description:  NMR_Workflow class

NMR_Workflow class has been designed to help create complex NMR workflows. The distinctive feature of this approach is that NMR_Workflow logs all issued commands and spectrometer operations in an HTML report, which is saved on a disk along with the NMR data and serves as a permanent record of the experimental session. This feature eliminates a need for the NMR spectroscopist to write down his/her spectrometer manipulations in the lab notebook.

"Dry run" mode:

To be able to easily verify that the KovriginNMR script operates correctly, the NMR_Workflow session allows for a "dry run": it may skip all commands that control the spectrometer and only execute the Python operations. This mode is used for any new experimental workflow when you want to verify that your Python code does not contain any errors. The issue is that Python is an interpreted language, therefore, if there is other error in the later part of your script, it will not be revealed until the line of code with the error is actually executed, and then the script will be halted by a Python error.

To be able to quickly verify your code without running NMR experiments first, you will temporarily set your NMR_Workflow object to run_mode=MAKE_EXPTS_ONLY. With this setting, the entire script code is executed in just a few seconds because all spectrometer-controlling commands (rga, zg, etc.) are skipped. Once you cleared all Python errors, you can directly check all prepared experiments in Topspin and review the HTML report to confirm that the sequence of NMR operations is indeed what you wanted it to be in your script. 

 

Creating a new NMR_Workflow session

You may think of the NMR_workflow session as of a new chapter in your experimental lab notebook where you will set up, perform and record all NMR experiments related to the current set of NMR samples. First, we will make the class object (session):

working_folder = "My_dataset_folder"   

Bruker800 = NMR_Workflow(project_title='Test NMR workflow project', 
       HTML_report_folder_name=working_folder+'.Report', 
       Probe_Name='TXI', 
       Standard_shim_name='TXI', 
       sample_changer=changer, 
       run_mode=MAKE_EXPTS_ONLY,
       #run_mode=MAKE_EXPTS_AND_RUN,
       )

The class constructor needs a general title of your set of experiments (project), the folder name to place HTML report in, the current probe name, the file name of the standard shimset to load, the Sample_Changer class object that contains all samples you intend to use today, and a run mode.

Run Modes

In the example above, I show two choices for the run_mode line. The first choice sets run_mode to MAKE_EXPTS_ONLY, which forces all NMR_workflow methods that control the spectrometer to automatically skip. This means that all experiments will be set up and displayed in due order but no samples will be inserted, no locking/tuning/shimming will be done and no acquisitions will be initiated. This allows Python to go through your entire code quickly to reveal any Python errors prior to real execution. All operations still leave their records in the HTML report, allowing you to verify the sequence of events in your workflow and catch any logical errors or glitches.

To allow for a normal, fully functional operation, un-comment run_mode=MAKE_EXPTS_AND_RUN and comment out the previous choice.

 

IMPORTANT NOTE: Folder names must not include spaces, because Topspin may have problems with such datasets!

When this code runs, it will ask you to verify that "automatic command spooling" is turned off in Topspin. This is critical because Spooler interferes with KovriguinNMR operation. This checkbox is found in Manage : Preferences of the Topspin window (see Getting Started: Disable automatic command spooling

 

If a silent run is needed

When the NMR_Workflow object is made with the above code, it pops up a window requiring a user to confirm that "Automatic command spooling is off". If you have already verified that option on your account and you need this code to run in full automation (unattended), you should add an additional argument to the constructor:


Bruker800 = NMR_Workflow(project_title='Test NMR workflow project', 
       HTML_report_folder_name=working_folder+'.Report', 
       Probe_Name='TXI', 
       Standard_shim_name='TXI', 
       sample_changer=changer, 
       # run_mode=MAKE_EXPTS_ONLY,
       run_mode=MAKE_EXPTS_AND_RUN,    
		spooler_check='no'
       )

NOTE: It is strongly recommended to keep automatic spooling check performed at all times, except where you need to start the script unattended. Interference of Spooler with KovriginNMR is difficult to diagnoze!

 

HTML report

The HTML report is placed in a folder separate from experimental folders with your data because NMR_Workflow session allows acquiring multiple experiments from different arbitrary folders (as defined by experiments themselves). Therefore, NMR_Workflow creates a separate folder for the report. I suggest to use the same name as your folder for the most important data and give it an extension like ".Report" for easy reference (see example above).

 

 

Inserting a sample

To insert a sample into the magnet, you call the insert_sample() method of the NMR_Workflow session and give it the NMR_Sample object as an argument along with a time (in minutes) to allow for temperature equilibration:

Bruker800.insert_sample(sample = CD, sleep_time_min = 5)    

NOTE: It is strongly recommended to set sleep_time_min to, at least, two minutes for equilibration after inserting a sample even if you are working at ambient temperature. If the sample has not fully equilibrated with the probe, your locking, shimming, and acquisition resolution and sensitivity may be bad! A healthy equilibration time is 5 (five) minutes (as in the example above). Sample that was kept in a fridge needs 15 minutes to equilibrate. If you use temperatures significantly different from room temperature, your equilibration time must be much longer (up to 1 hour at the temperature extremes, per Bruker manuals).

 

This method will be skipped if the run_mode was set to MAKE_EXPTS_ONLY but will leave a record in HTML report. It will also make a new sample assigned as a current sample for proper reporting of the samples in the HTML output of the following commands.

 

NOTE: If you do NOT want software to control insertion at all, you should NOT use the insert_sample command but follow these instructions instead: Completely manual insertion: Indicating that the sample has already been placed in the bore

 

Displaying the experiment (making it current)

The first thing to do after insertion of the sample is to display the experiment we plan to use. This action will bring it up on Topspin screen and will allow shimming and tuning procedures to operate correctly. The NMR experiment object should have been defined before experiment may be displayed:

proton_lineshape_spinning = NMR_Experiment(...
...

Bruker800.display_experiment(experiment = proton_lineshape_spinning)    

This method will work at all times, irrespective of the run_mode setting.

NOTE: If desired, you can explicitly issue 'getprosol'  after you displayed experiment with getprosol() method:

Bruker800.getprosol()

This option is provided just in case, because a proper time of issuing getprosol is after making NMR_Experiment objects.

 

Loading a shim set

Before we can lock and shim, we have to load a good shim set. To do it, call the load_standard_shimset() or load_shimset() methods of the NMR_Workflow session.

If you use only one kind of tubes in your session, you need to load the standard shimset only once:

Bruker800.load_standard_shimset()

This command will use the standard shimset name that you gave to the NMR_Workflow object (here, Bruker800) when it was created.

 

If you plan to use normal tubes and Shigemi tubes in the same workflow, you need to load a specific shimset for each kind of tube. Then, you use

Bruker800.load_shimset("name-of-corresponding-good-shim-set") 

 

This method will NOT be skipped if the run_mode was set to MAKE_EXPTS_ONLY because loading shims allows for checking whether the shim name you provided is correct.

 

Locking

To lock the spectrometer we use a lock() method. The solvent name to use for locking is known to the NMR_Workflow object from the current sample description: the lock() will look it up automatically.

Bruker800.lock()    

This method will be skipped if the run_mode was set to MAKE_EXPTS_ONLY.

IMPORTANT: Triple-check spelling of the lock solvent in the sample description! If you misspelled the lock solvent name, it will not be discovered in a dry run because the solvent name will not be submitted to the lock system. The error will be triggered at the time of execution and will stall the script.

 

Tuning

The atma() method of the NMR_Workflow object uses 'atma' command for tuning. You must have displayed the necessary experiment first, prior to issuing atma() command, because atma will look up the channels to tune in the parameter set of the currently displayed experiment:

Bruker800.atma()

This method will be skipped if the run_mode was set to MAKE_EXPTS_ONLY.

 

 

Controlling rotation in solution NMR

Simple spinning may be controlled by rotation_on() or ro_on() and rotation_off() or ro_off() methods:

Bruker800.rotation_on()  # start spinning
...
Bruker800.rotation_off()   # stop spinning
...

      

Bruker800.ro_on()  # start spinning
...
Bruker800.ro_off()  # stop spinning

These methods will be skipped if the run_mode was set to MAKE_EXPTS_ONLY.

 

NOTE: an acquisition started with the zg() method controls rotation independently according to the spinning_mode of the current experiment. It will override the rotation status set up by above methods.

 

IMPORTANT: (if sample rotation in solution NMR experiments is important to you) As of 4/30/2023, I don't have means to record whether the sample was actually spinning. This means, if the spinning failed on some sample, I don't have a record in the HTML report reflecting that. Sometimes, spinning fails temporarily and the error window reporting failure of spinning remains on a screen. It may or may not mean your sample was acquired without spinning. You should be checking the Topspin screen for the spinning icon to verify that!

 

Shimming

The topshim() method of NMR_Workflow object calls topshim for shimming of the sample. The topshim_command_line argument allows to include any options you want to pass to topshim.

This method will be skipped if the run_mode was set to MAKE_EXPTS_ONLY.

 

One-dimensional shimming

One-dimensional shimming along the Z-axis is a routine procedure for shimming of all NMR samples.

NOTE: Sample spinning is required for one-dimensional shimming :

Bruker800.rotation_on()
Bruker800.topshim()
Bruker800.rotation_off()

Calling topshim() without arguments is equivalent to 'topshim' entered on a Topspin command line. You may provide any shimming options by supplying topshim_command_line parameter. Here is an example of a complex topshim command for a sample in a Shigemi tube:

complex_topshim_options = "1d ordmax=8 ls convcomp tunea tuneb shigemi"
Bruker800.topshim(topshim_command_line = complex_topshim_options)

      

NOTE: I recommend performing 1D shimming twice on any sample. In a small fraction of cases, first shimming pass does not achieve good results. Having two passes by default gives a better chance of getting the sample shimmed well in an unattended operation.

 

Three-dimensional shimming

To perform 3D shimming on proton (with 90% H2O sample), I must stop spinning and use the corresponding additional topshim options:

Bruker800.rotation_off()
Bruker800.topshim(topshim_command_line = '3d ordmax=8,7 ss convcomp tunea tuneb 1h')

which uses a command line equivalent to

 topshim 3d ordmax=8,7 ss convcomp tunea tuneb 1h

 

Shimming report

The output of topshim procedure is included in the HTML report compiled by the NMR_workflow object. Checking the topshim output allows to confirm that topshim successfully achieved its criteria of convergence. However, the real spectral resolution has to be checked separately by acquiring a trial 1D proton experiment and observing practical line shapes and line widths.

 

Pulse calibration

All standard parameters appropriate for the probe have already been set up when you issued getprosol on Topspin command line in your experient or created the NMR_Experiment object with create_from_parameter_set(...) method (see NMR_Experiment class). Getprosol looks up pulse and power parameters appropriate for your probe in a prosol table and enters them in the currently displayed parameter set. All prosol parameters are generally appropriate for use in any standard Bruker experiments.

IMPORTANT NOTE: If your solvent is significantly different from the one used to determine prosol values, the proton pulse length may be significantly different. This is unimportant for 1D proton detection but any multi-pulse experiments will require accurate calibration as described below.

 

Proton calibration

The pulsecal() AU program in Topspin performs an automatic pulse calibration.  When this method is called without parameters, it will calibrate a proton pulse:

Bruker800.pulsecal()

IMPORTANT NOTE: You must display the experiment you want to calibrate pulses for before calling pulsecal(), because it will insert the newly determined values into the data set, which is currently displayed.

 

Other nuclei

It is possible to pass any nucleus name known to pulsecal in Topspin to the pulsecal() method:

Bruker800.pulsecal(pulsecal_nucleus = '13C')

NOTE: Calibration of pulses for any nucleus requires a sample with high concentration of the magnetically active isotope. Therefore, calibrations of carbon-13 and nitrogen-15 would require isotopically enriched samples. The hydrogen-1, fluorine-19, and phosphorus-31 are naturally abundant, therefore, calibrations may be done on samples with natural abundance of these nuclei.

NOTE 2: For all nuclei except proton, a concentration of the compound containing the nucleus to calibrate must exceed millimolar levels for a sufficient signal. In case of a proton, pulsecal() will use either your compound or the residual protonated solvent in your deuterated solvent whichever gives taller signal.

 

This method will be skipped if the run_mode was set to MAKE_EXPTS_ONLY.

 

 

Gain adjustment

Gain adjustment method rga() issues rga and saves the found RG value into a currently displayed experiment.

Bruker800.rga()

This method will be skipped if the run_mode was set to MAKE_EXPTS_ONLY.

 

Acquisition

The zg() method starts acquisition in the currently displayed experiment:

Bruker800.zg()

This is equivalent to issuing zg yes on the command line of Topspin, which overwrites the existing data without warning. Prior to starting acquisition, the zg() method turns on rotation if spinning_mode is set to 'yes' in the current experiment or turns it off if spinning_mode is 'no'.

NOTE: For solid-state NMR, the spinning_mode should be set to 'ignore' when creating the experiment: Description:  NMR_Experiment class, which will make zg() method to ignore sample rotation status and not attempt to control it.

The zg() method automatically appends the current sample name to the dataset title.

This method will be skipped if the run_mode was set to MAKE_EXPTS_ONLY.

 

Processing (executing Topspin commands)

The run_topspin_commands(topspin_commands) method will execute any Topspin commands as if you are issuing them on a command line. Its argument may be a single- or multi-line Python string with commands. The commands will be applied to a currently displayed experiment. The commands will also be logged in HTML report. Here is an example of a multi-line string:

Bruker800.run_topspin_commands(topspin_commands ="""
efp
apk
abs
""")

 

This method will be skipped if the run_mode was set to MAKE_EXPTS_ONLY.

 

Read text output of processing programs from pdata/1

Processing steps with AU programs often make text files with their output in the pdata/1 folder. The method fetch_text_file_from_current_experiment() allows to read their content. For example, below I am launching the knmr_humpcal AU program, which makes a text file knmr_humpcal.txt. I want to add its content to the current experiment title and to the HTML report:

Bruker800.run_topspin_commands( topspin_commands ="""knmr_humpcal""")
humpcal_output = spect.fetch_text_file_from_current_experiment('knmr_humpcal.txt')
Bruker800.current_experiment.append_to_title(humpcal_output)
Bruker800.report.add_to_report("Humpcal analysis results:\n\n%s" % humpcal_output)

This method will be skipped if the run_mode was set to MAKE_EXPTS_ONLY.

 

Issuing 'getprosol'

Normally, 'getprosol' command is necessary in any new experiment made from a parameter set. However, the NMR_Experiment class method create_from_parameter_set() will issue 'getprosol' automatically. All other methods assume that 'getprosol' has been issued at the time the existing experiment or template were created. Just for convenience, if you need to do it manually and record its action in HTML, I am including 'getprosol' functions with NMR_Workflow class:

 

Bruker800.getprosol()

 

This method will NOT be skipped when the run_mode was set to MAKE_EXPTS_ONLY.

 

Back to Contents


Description: NMR_Workflow_Report_Log

The major advantage of using KovriginNMR for controlling a Bruker NMR spectrometer is that all commands issued by KovriginNMR script are recorded in an HTML report along with the timestamps and additional messages. The HTML report is conveniently located in the user data folder and maybe open with a single click of a button on KovriginNMR toolbar [Show Most Recent Report] or directly from the file browser.

The HTML report summarizes all information you provided to NMR workflow object when you created it. The list of samples in the sample changer database is displayed. All experiments started in the session are recorded with the corresponding timestamps. Results of the topshim are also captured for inspection.

 

NOTE: The HTML report is made regardles of the run_mode of the NMR_Workflow  session. Therefore, when run_mode is set to MAKE_EXPTS_ONLY, the HTML report will record the sequence NMR experiments as they are displayed in preparation for acquisition. This allows you to verify the flow of logic in your script before actually initiating a long NMR experiment sequence.

 

Adding more information to the report

You can add any additional information to the report at any place in the script by using NMR_Workflow class method add_to_report()

Bruker800.add_to_report("This is an additional text for demonstrating NMR_Workflow_Report_Log functionality")

The method takes a Python string as an argument. You may use a newline character '\n' to start a new line. The method intelligently converts your string into the HTML text for display with the report.

 

Back to Contents


Topspin parameter synthax reference

To adjust dataset parameters with run_topspin_commands() and NMR_Experiment class methods, you should note a proper synthax that the Topspin requires to discriminate NMR dimensions.

NOTE: For using get_topspin_parameter(...) and set_topspin_parameter(...) commands, please, see additional notes on arrayed parameters in Obtaining and setting parameters with dedicated commands

 

How to determine Topspin command line synthax for any parameter

When you change any parameter in the AcqPars (or ProcPars) tab, the Topspin issues commands looking like this: '1 TD 128'. The first number is stands for the NMR dimension the parameter belongs to, the second word is the name of a parameter, and the third is the value of a parameter. For example, changing number of points to 2048 in a direct dimension in a 1D proton experiment would be '1 TD 2048'. In the 2D experiment, the dimension '1' is indirect, therefore, the same operation would need '2 TD 2048' for 2048 points in proton. For parameters, which are not associated with dimensions (like D1, etc.) use '1' for the first number or omit it altogether.

To look up the exact command in Topspin to change a specific parameter:

General parameters do not need a dimension

The following parameters need just a name and a new value you want to assign to them:

Parameters Parameter string Action
NS, DS, PULPROG
'NS 24'
'DS 8' 'PULPROG zg30'

set number of scans to 24
set dummy scans to 8
set pulseprogram name to zg30

all durations D, in seconds
'D1 5'
set pre-scan delay to 5 seconds
all durations P, in microseconds
'P1 10.1'
set pulse P1 to 10.1 microseconds
acquisition time AQ, in sec
'AQ 4'
set acquisition time to 4 seconds
receiver gain, RG
'RG 1'
set receiver gain to 1

 

NOTE: You still may issue them with an explicit first dimension, which achieves the same result:

'1 NS 24'
'1 D1 5'
...
    

1D data spectral parameters: no need for a dimension

Parameters of one-dimensional experiment do NOT need explicit dimension:

Parameters Parameter string Action
TD
'TD 32K'
Set number of points in the fid to 32768
spectral width in PPM:  SW
'SW 20'
Set spectral width to 20 ppm
spectral width in Hz: SWH
'SWH 1500'
Set spectral width to 1500 Hz
carrier frequency in PPM:  O1P
'O1P 8.0'
Set center frequency to 8.0 ppm
carrier frequency in Hz:  O1
'O1 1600'
Set center frequency to 1600 Hz

NOTE: You still may issue them with an explicit first dimension as in the example above.

NOTE 2: Pay attention to a difference in naming between SW and SWH, and O1P and O1!

 

 

 

2D dataset: use explicit dimensions

Recommended forms of commands for parameter-setting in two-dimensional datasets are shown in the table below. Topspin allows other ways of setting the same parameters but I recommend these forms to avoid confusion and subsequent errors.

Parameters Parameter string Action
Direct dimension points
'2 TD 2048'
Set direct dimension, F2, to 2048 points
Inirect dimension points
'1 TD 256'

Set indirect dimension, F1, to 256 points
(meaning 128 complex points, or increments in 2D)

Direct dimension spectral width
'2 SW 20'
Set spectral width in direct dimension to 20 ppm
Indirect dimension spectral width
'1 SW 8'
Set indirect dimension to 8ppm
Carrier frequency, direct dim
'2 O1P 8.0'
Set carrier in direct dimension at 8.0 ppm
Carrier frequency, indirect dim
'1 O1P 6.0'
Set carrier in indirect dim at 6.0 ppm

 

Status parameters

Status parameters are the ones that get their values during execution of the commands. You cannot set them but may obtain them by indicating their dimension ending with 's':

'1s TD'

 

 

 

 

 

Back to Contents


 


Evgenii Kovrigin (C) 2022