Skip to content

Understanding phasing

Import the necessary libraries

import sys

from scipy.optimize import curve_fit

sys.path.append("../../src")

from relaxometrynmr.core import T1Functions

import numpy as np

import matplotlib.pyplot as plt

import ipywidgets as widgets

from IPython.display import display

specify path to the data file and ensure that "\\" is appended to the end of the path

  • create an instance t1 of T1Functions
filepath = r"../../data/T1_data/1//"

t1 = T1Functions(filepath)

Read and convert Bruker NMR data to NMRPipe and CSDM formats: read_and_convert_bruker_data.

The function automatically detects and loads the variable delay list (vdlist, vplist, vclist) used in the experiment.

It returns a tuple containing three elements: a list of 1D NMR (spectra), the variable delay list (vd_list), and the complete dataset in CSDM format (csdm_ds)

spectra, vd_list, csdm_ds = t1.read_and_convert_bruker_data(filepath)

Process the returned 1D NMR spectra

  • apply the Gaussian apodisation (fwhm)
  • zero-filling for increased digital resolution (zero_fill_factor)
  • 0th order phase correction (ph0)
  • 1st order phase correction (ph1) -- this phase correction is a bit nuanced and so far, a value of 0 - 0.6 ° has worked quite well
  • Below, pick a spectrum and drag the PH1 slider one value at a time to see how the peak's shape changes -- a wrong PH1 shows up as a distorted, dispersive lineshape (a positive lobe next to a negative one); the right PH1 collapses it into one clean peak
FWHM = "500 Hz"
ZERO_FILL_FACTOR = 10

# sub-region containing the main resonance, shown in the zoomed panel
ZOOM_XLIM = (2000, -1000)

spectrum_selector = widgets.Dropdown(
    options=list(range(len(spectra))), value=0,
    description='Spectrum idx', style={'description_width': 'initial'}
)
ph0_slider = widgets.IntSlider(
    value=50, min=-360, max=360, step=1,
    description='PH0 (°)', continuous_update=False,
    style={'description_width': 'initial'}, layout=widgets.Layout(width='500px')
)
ph1_slider = widgets.FloatSlider(
    value=0.0, min=0.0, max=1.0, step=0.005,
    description='PH1', continuous_update=False, readout_format='.3f',
    style={'description_width': 'initial'}, layout=widgets.Layout(width='500px')
)
out = widgets.Output()

def update_preview(change=None):
    i = spectrum_selector.value
    ph0, ph1 = ph0_slider.value, ph1_slider.value
    exp = t1.process_spectrum(spectra[i], fwhm=FWHM, zero_fill_factor=ZERO_FILL_FACTOR, ph0=ph0, ph1=ph1)
    ppm = exp.dimensions[0].coordinates.value
    y = exp.dependent_variables[0].components[0].real
    with out:
        out.clear_output(wait=True)
        fig, ax = plt.subplots(1, 2, figsize=(9, 3.5))

        ax[0].plot(ppm, y)
        ax[0].invert_xaxis()
        ax[0].set_xlabel('$^{17}$O chemical shift (ppm)')
        ax[0].set_ylabel('Intensity (a.u.)')
        ax[0].set_title('Full spectrum')

        ax[1].plot(ppm, y)
        ax[1].invert_xaxis()
        ax[1].set_xlim(*ZOOM_XLIM)
        ax[1].set_xlabel('$^{17}$O chemical shift (ppm)')
        ax[1].set_title('Zoomed: main resonance')

        fig.suptitle(f'Spectrum {i}  |  PH0 = {ph0}°   PH1 = {ph1:.3f}')
        plt.tight_layout()
        plt.show()

spectrum_selector.observe(update_preview, names='value')
ph0_slider.observe(update_preview, names='value')
ph1_slider.observe(update_preview, names='value')

display(widgets.VBox([spectrum_selector, ph0_slider, ph1_slider, out]))
update_preview()  # draw initial preview
VBox(children=(Dropdown(description='Spectrum idx', options=(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14)…