Processing

Processing steps

NMRTools.NMRBase.apodize — Function
apodize(spec, [dim], [window]; inverse=false)

Multiply the time-domain data by a window function. With no dimension argument every Fourier time dimension is apodized; with no window, each dimension's :window metadata is used (no apodization if it has none).

The window's length is set from the acquisition time when it is not given, so Cos2Window() or GeneralSineWindow(0.5, 1, 2) can be used without a tmax. The window starts at t = 0; digital-filter build-up points before t = 0 are left unwindowed. The window applied is recorded in the dimension's :window metadata.

Keywords

  • inverse: divide by the window instead, undoing a previous apodization.

Examples

loadfid("expt/1") |> apodize(ExponentialWindow(5.0)) |> zerofill |> ft
loadfid("hsqc/1") |> apodize(T1Dim, ExponentialWindow(5.0)) |> apodize(T2Dim, Cos2Window())

See also WindowFunction, zerofill.

source
NMRTools.NMRBase.zerofill — Function
zerofill(spec, [dim]; factor=2)

Append zeros to the end of the FID, multiplying the number of points by the integer factor. With no dimension argument every Fourier time dimension is zero-filled. The :tdzf metadata is updated.

Examples

fid |> zerofill |> ft                   # double every Fourier dimension
fid |> zerofill(T1Dim; factor=4) |> ft
source
NMRTools.NMRBase.ft — Function
ft(spec, [dim]; inverse=false)

Fourier transform one dimension, or with no dimension argument every Fourier dimension in order (direct dimension first). A time dimension becomes the corresponding frequency dimension, or the reverse with inverse=true. The transform uses the dimension's imaginary unit (:mcindex), applies no normalisation, as TopSpin does, and refreshes the noise estimate.

The spectrum is ordered from high to low chemical shift, as for data loaded with loadnmr, and ft(ft(spec); inverse=true) recovers spec.

A digital-filter group delay recorded by loadfid (:grpdly) is removed after the transform with a linear phase ramp, which moves the filter's build-up points to negative time. The frequency dimension has no group delay left, so an inverse transform gives a FID whose first point is at t = 0.

Keywords

  • inverse: inverse transform from the frequency domain to the time domain.

Examples

spec = loadfid("expt/1") |> apodize(Cos2Window()) |> zerofill |> ft
spec2 = ft(spec, F1Dim; inverse=true)
source
NMRTools.NMRBase.phase — Function
phase(spec, dim, p0, p1=0; pivot=nothing)
phase(dim, p0, p1=0; pivot=nothing)

Apply a zero-order (p0) and first-order (p1) phase correction, in degrees, along dimension dim. The phase applied to point n of N (counting from 0 at the first, highest-ppm point) is θ = p0 + p1·n/N, multiplied in as exp(-imₖ·θ) with the dimension's imaginary unit. This is TopSpin's convention, so p0 and p1 are its PHC0 and PHC1. Works in the time or frequency domain. The second form returns a function for use with |>.

For a frequency dimension the total correction applied so far is recorded in the dimension's :phase metadata as (p0=…, p1=…), with p0 referred to the first point, and the noise estimate is refreshed.

Keywords

  • pivot: position at which only p0 acts, in ppm for a frequency dimension or seconds for a time dimension. Defaults to the first point.

Examples

spec |> phase(F1Dim, 128.5) |> realest
phase(spec, F1Dim, 40.0, -20.0; pivot=4.7)

See also autophase, autophase0.

source
NMRTools.NMRBase.extract — Function
extract(dim, range)
extract(dim1 => range1, dim2 => range2, ...)

Return a function that selects a region of a spectrum, for use with |>. dim is a dimension type (for example F1Dim) and range an interval (for example 6.0 .. 10.0). The noise estimate (:noise) of the selected region is refreshed.

Outside a pipeline, index the spectrum directly with a chemical shift selector, as spec[F1Dim(6.0 .. 10.0)] or spec[6.0 .. 10.0, :].

loadfid("1/ser") |> ft |> extract(F1Dim, 6.0 .. 10.0) |> phase(F1Dim, -50) |> realest
loadfid("2/ser") |> ft |> extract(F1Dim => 6.0 .. 10.0, F2Dim => 105 .. 135)
source
NMRTools.NMRBase.frequencyshift — Function
frequencyshift(spec, dim, Δ)
frequencyshift(dim, Δ)

Shift time-domain data in frequency by Δ Hz, by multiplying the FID by exp(-imₖ·2π·Δ·t): a signal at +Δ Hz moves to the carrier. solventfilter uses this to suppress signals away from the carrier; it is also useful for re-referencing in the time domain. The second form returns a function for use with |>.

Examples

fid |> frequencyshift(T1Dim, 250.0) |> ft
source
NMRTools.NMRBase.linearpredict — Function
linearpredict(spec, [dim]; npoints=nothing, factor=2, order=:auto, direction=:forward,
              replace=0, rootfix=true, pool=true)

Extend a time dimension by linear prediction, or rebuild its first points.

Linear prediction models each FID as a sum of decaying oscillations, using the autoregressive coefficient method of nmrPipe and nmrglue, and extrapolates it by recurrence. Forward extension uses the Zhu–Bax scheme: it fits backward coefficients, reflects the roots of the prediction polynomial inside the unit circle, and builds forward coefficients from them, which keeps the extrapolation stable.

With no dimension argument, every indirect Fourier dimension is extended. Prediction uses the FID from t = 0; digital-filter build-up points before t = 0 are left unchanged.

Keywords

  • npoints: length after prediction. Defaults to factor times the current length.
  • factor: length multiplier used when npoints is not given.
  • order: number of prediction coefficients. :auto uses clamp(td ÷ 2, 8, 32).
  • direction: :forward appends points; :backward prepends them and moves the start of the time axis back. Backward extension rebuilds points missing at the start of a FID that begins after t = 0 (see loadfid).
  • replace: if greater than 0, replace that many points from t = 0 by backward prediction, keeping the length unchanged. Overrides npoints and direction.
  • rootfix: reflect unstable roots so that the extrapolation cannot grow.
  • pool: estimate one set of coefficients from the strongest vectors and apply it to all of them. Vectors along one dimension share the same frequencies, so this is valid and much faster than fitting each vector separately (pool=false, as nmrglue does).

Use on time-domain data, before apodize. The :td metadata is updated.

Examples

fid |> linearpredict(T2Dim) |> apodize |> zerofill |> ft     # double the indirect dimension
linearpredict(fid, T1Dim; replace=2)                          # rebuild the first two points
source
NMRTools.NMRBase.solventfilter — Function
solventfilter(spec, [dim]; shift=:carrier, method=:lowpass, width=40.0, shape=:sine,
              band=nothing, ncoef=:auto)

Suppress a solvent signal, or any narrow signal, in the time domain. With no dimension argument the direct dimension is filtered.

Keywords

  • shift: :carrier, or the chemical shift (ppm) of the signal to remove. A signal away from the carrier is moved to it with frequencyshift, filtered, and moved back.
  • method: :lowpass subtracts a low-pass filtered copy of the FID (the convolution difference method of nmrPipe's SOL). It is fast and suits multidimensional data. :hsvd fits the FID with decaying oscillations and subtracts those within band of the target, which disturbs nearby peaks less but fits each FID separately, so it suits 1D data.
  • width: approximate width (Hz) of the region suppressed by :lowpass. A larger value suppresses a wider region.
  • shape: low-pass window for :lowpass: :boxcar, :sine or :sine².
  • band: width (Hz) of the region removed by :hsvd. Defaults to width.
  • ncoef: number of oscillations fitted by :hsvd. :auto uses clamp(td ÷ 16, 16, 48).

Use on time-domain data, before apodize. The digital-filter group delay recorded by loadfid is taken into account: the FID is filtered from t = 0, with the build-up points before t = 0 treated as negative time, as in ft.

Examples

fid |> solventfilter |> apodize |> zerofill |> ft
solventfilter(fid; shift=4.7, method=:hsvd, band=60)
source
NMRTools.NMRBase.autoprocess — Function
autoprocess(fid; window=Cos2Window(), zerofill=2, solvent=:auto, phase=:auto, rebuild=false,
            real=true)
autoprocess(; kw...)

Process time-domain data from loadfid into a spectrum in one step. The second form returns a function for use with |>. The steps, in order:

  1. With rebuild=true, rebuild points missing at the start of a FID that begins after t = 0 (as loadfid reports for data modified by TopSpin's cryoproc1d), by backward linearpredict.
  2. Suppress the water signal in the direct dimension with solventfilter.
  3. In each Fourier dimension: apodize, zerofill and ft.
  4. Phase each frequency dimension, direct dimension first, with autophase or given phases. A dimension in which autophase finds no lines is left unphased, with a warning. When the solvent was filtered from a 1D spectrum, its phase is estimated from the unfiltered spectrum, leaving out ±0.2 ppm around the solvent: the solvent's dispersion tails at the edges of the spectrum help the estimate, and the filter removes them.

The result is the real spectrum (Float64, real in every dimension, as from realest). Pass real=false to keep the Multicomplex spectrum, for example to phase it further. Non-Fourier dimensions (relaxation delays, offsets, …) are left unchanged.

Keywords

  • window: window function, for example ExponentialWindow(2.0) or GeneralSineWindow(0.33, 1, 2).
  • zerofill: zero-filling factor (1 for none).
  • solvent: :auto suppresses water in ¹H spectra whose solvent contains H₂O; true suppresses a signal at the carrier, a number suppresses one at that chemical shift (ppm), and false skips suppression.
  • phase: :auto runs autophase; a tuple (p0, p1), or a single p0, applies those phases (degrees); nothing skips phasing.
  • real: return the real spectrum (default) rather than the Multicomplex one.
  • rebuild: rebuild points missing after t = 0 by backward linear prediction. Missing points leave a ripple around strong lines; rebuilding them removes it, but can add a broad baseline distortion when the FID contains fast-decaying signals, so it is off by default.

window, zerofill and phase can also be given per dimension as a dictionary keyed by dimension number or type (T1Dim and F1Dim both mean the first dimension). Dimensions missing from a dictionary get the default.

Examples

spec = loadfid("expt/1") |> autoprocess
spec = loadfid("expt/1") |> autoprocess(window=ExponentialWindow(1.0), solvent=false)
spec = autoprocess(loadfid("hsqc/1"); window=Dict(T1Dim => Cos2Window(), T2Dim => Cos2Window()),
                   phase=Dict(F2Dim => (0.0, 0.0)))

See also autophase, apodize, zerofill, ft.

source

Automatic phasing and pole models

NMRTools.NMRBase.autophase — Function
autophase(spec, [dim]; kw...)

Estimate the phase correction of dimension dim with estimatephase and apply it with phase. Without dim, every frequency dimension is phased in turn, direct dimension first; a dimension in which no lines are found is left unphased, with a warning. The total correction applied is recorded in each dimension's :phase metadata, and the estimate is logged at debug level. Keywords are passed to estimatephase, for example order=0 for zero-order only, or exclude=[4.6 .. 4.9] to ignore water; without dim they apply to every dimension.

For multidimensional data the correction is estimated from traces along dim through the strongest cross peaks, pooled into one fit, and applied to the whole dataset. The traces combine the components of the other dimensions so that they do not depend on how those dimensions are phased.

spec = loadfid("expt/1") |> apodize(ExponentialWindow(1.0)) |> zerofill |> ft |> autophase |> realest
source
NMRTools.NMRBase.autophase0 — Function
autophase0(spec, [dim]; exclude=())

Correct the zero-order phase of dimension dim of a frequency-domain spectrum, or without dim of every frequency dimension in turn. p0 is chosen so that the integral of the dispersion mode over the spectrum is zero and the integral of the absorption mode is positive: it is the phase of the integral of the complex spectrum, which equals the phase of the first point of the FID. Points in the chemical-shift intervals exclude, for example [4.6 .. 4.9], are left out of the integral. No first-order correction is applied.

The integral includes everything in the spectrum, so baseline offsets, broad background signals and corrupted first FID points all bias the result. For multidimensional data the correction is estimated from a single trace along dim (see estimatepoles) and applied to the whole dataset. The correction is recorded in the dimension's :phase metadata.

See also autophase, phase.

source
NMRTools.NMRBase.estimatephase — Function
estimatephase(spec, [dim]; order=1, p1=nothing, maxdelay=20e-6, pivot=nothing, snr=10,
              coupling=20, maxwidthratio=3, maxresidual=30, λ=20, edges=0.01, kw...)
    -> NamedTuple
estimatephase([dim]; kwargs...)

Estimate the zero- and first-order phase correction (degrees) for dimension dim (default: the direct dimension) of a frequency-domain spectrum. Returns (p0, p1, pivot, residual, nlines, rejected, edges), where phase(spec, dim, p0, p1; pivot) applies the correction, residual is the weighted rms phase error (degrees) of the observations used, nlines the number of line groups used, rejected lists the line groups left out of the fit as (shift, residual, relsnr), strongest first, where relsnr is the signal-to-noise ratio relative to the strongest group used, and edges lists the edge observations as (edge, snr, residual, used). A large residual, a small number of groups, or a strong rejected group means the estimate should not be trusted. autophase warns when strong groups are rejected.

The forms without the data argument return a function for use with |>.

For a multidimensional spectrum, the lines are taken from 1D traces along dim through the strongest cross peaks, and pooled into one fit. Each trace combines the components real and imaginary in the other dimensions so that it does not depend on how those dimensions are phased, and ridges such as t₁ noise from residual solvent are left out.

Lines are found with estimatepoles. Poles within a coupling constant of each other are grouped, because the lines of a multiplet can carry antiphase dispersive components that cancel only in the sum. Each group's phase is the argument of the integral of the spectrum over a window around the group (up to four linewidths beyond its outer lines, and no more than halfway to the next group), less a linear baseline through the ends of the window. Poles much broader than the typical linewidth are ignored when they overlap a narrower line, since they then model its tails or the baseline. The correction is the weighted circular regression of group phase against position, taken modulo 180° so that negative peaks are not treated as phase errors. Groups with a residual above maxresidual degrees are discarded and the fit repeated. The 180° ambiguity is resolved by a majority vote of the groups, so that most lines are positive.

The edges of the spectrum add two observations. With the correct phase the real part is flat far from the lines, while the imaginary part carries the dispersion tails of the strong lines; the phase at which the real part of each edge region vanishes is used as a further observation, weighted by its signal-to-noise ratio. These are most informative for spectra with strong or broad signals, such as protein spectra with residual water. They are skipped when their signal-to-noise ratio is below snr, and used only if they agree with the fit to the line groups within three times the combined uncertainty of the groups' scatter and the edge's own 2° (and maxresidual), so that they refine the line-based estimate rather than override it. Observations are weighted by inverse variance, combining their signal-to-noise ratio with a systematic uncertainty: the scatter of the line groups about the fit (a scaled median absolute residual, so that a few noise groups do not inflate it), or 2° for an edge.

Keywords

  • order: 1 fits p0 and p1; 0 fits p0 only, with the first-order phase fixed at p1.
  • p1: expected first-order phase (degrees). By default 0 for the direct dimension, which is close to zero once the digital-filter group delay has been removed; for an indirect dimension both 0 and -180° (a first point sampled half a dwell time after t = 0) are tried and the better fit is kept.
  • maxdelay: largest timing error (seconds) to allow for. A first-order phase is a shift of the time origin: an error of τ gives a first-order phase of 360°·SW·τ across the spectral width SW, so the search covers p1 ± 360·SW·maxdelay degrees. The default of 20 µs covers the residual dead-time and receiver delays of most experiments; it gives ±100° for a 14 kHz ¹H spectrum and ±950° for a 130 kHz ¹⁹F spectrum. If the best fit lies at the limit of this range, five times the range is searched and the wider result kept if it fits better.
  • pivot: chemical shift (ppm) at which p0 is reported. Defaults to the first point, as for TopSpin's PHC0/PHC1.
  • snr: minimum signal-to-noise ratio of lines used.
  • coupling: poles closer than this (Hz, plus their mean linewidth) are grouped as one multiplet.
  • maxwidthratio: poles broader than this multiple of the median linewidth are ignored when a narrower line lies within their linewidth.
  • maxresidual: groups further than this (degrees) from the fitted phase are discarded.
  • λ: strength of the prior pulling the first-order phase towards p1. It is scaled by the variance of the phase residuals and divided by the effective number of observations, so it matters when few observations determine the fit or their phases scatter, and not when many agree closely. Increase it when the lines cover only a small part of the spectrum, so p1 is poorly determined.
  • edges: fraction of the spectrum at each end used as an edge observation; 0 disables them. Points within four linewidths of a line are excluded.
  • Other keywords (exclude, bandwidth, …) are passed to estimatepoles. Use exclude to drop solvent or buffer lines.

See also autophase, phase.

source
NMRTools.NMRBase.estimatepoles — Function
estimatepoles(spec, [dim]; bandwidth=:auto, ncoef=16, snr=5, maxlinewidth=nothing, exclude=())
    -> Vector{Pole}
estimatepoles([dim]; kwargs...)

Model a frequency-domain spectrum along dim (default: the direct dimension) as a sum of Lorentzian lines, by band-wise harmonic inversion (HSVD), and return one Pole per line, sorted by decreasing chemical shift. The spectrum may be unphased: the phase of each line is part of the result.

The forms without the data argument return a function for use with |>.

The spectrum is split into overlapping bands of bandwidth points. Each band is inverse Fourier transformed to a short time signal (using only the part covering acquired, not zero-filled, points) and fitted with ncoef damped exponentials. Poles are kept from the central half of each band only, to avoid edge artefacts; bands wrap around the ends of the spectrum, which is periodic. Bands with no signal above the threshold are skipped.

For multidimensional data, the trace along dim takes the first point of every other time dimension, sums every other frequency dimension over the points that carry signal, and sums any remaining dimensions.

Keywords

  • bandwidth: band size in points. :auto uses n ÷ 32 (a power of two between 256 and 4096) for an n-point spectrum.
  • ncoef: number of exponentials fitted per band.
  • snr: minimum signal-to-noise ratio (peak height / noise) for a pole to be kept.
  • maxlinewidth: largest linewidth (Hz) kept; broader poles model baseline rather than lines. Defaults to an eighth of the band width in Hz.
  • exclude: chemical-shift intervals (ppm) to ignore, for example [4.6 .. 4.9] to drop water.

See also estimatephase, autophase.

source
NMRTools.NMRBase.Pole — Type
Pole

One damped complex exponential (a Lorentzian line) from a harmonic-inversion model of a spectrum, as returned by estimatepoles.

Fields

  • shift: chemical shift (ppm)
  • linewidth: full width at half height (Hz)
  • amplitude: complex amplitude. abs(amplitude) is the line integral (spectrum intensity × points) and angle(amplitude) its phase, which is zero for a positive absorption line
  • height: absorption peak height (spectrum intensity units)
  • snr: height divided by the noise level
source

Referencing

NMRTools.NMRBase.reference — Function
reference(spec; indirect=true, aqueous=:auto, temperature=nothing)
reference(; kwargs...)

Reference a spectrum to water based on the sample temperature.

The forms without the data argument return a function for use with |>.

This method is used when no explicit reference shift is provided. It calculates the expected water chemical shift from the temperature and applies a correction relative to the Bruker default of 4.7 ppm.

Arguments

  • spec: NMRData object to reference
  • indirect=true: If true, also reference heteronuclear dimensions using Xi ratios
  • temperature=nothing: Temperature in Kelvin. If nothing, reads from metadata.

Returns

  • New NMRData object with referenced chemical shifts

Only works for aqueous solvents (D2O, H2O, H2O+D2O).

See also reference(spec, dim, pair), xi_ratio.

source
reference(spec, dim, pair::Pair; indirect=true, aqueous=:auto)
reference(dim, pair::Pair; kwargs...)

Reference a spectrum dimension by specifying an old and new chemical shift.

The forms without the data argument return a function for use with |>.

Arguments

  • spec: NMRData object to reference
  • dim: Dimension to reference (Int, dimension type like F1Dim, or Nucleus like H1)
  • pair: A pair old_shift => new_shift specifying the reference point
  • indirect=true: If true, reference other frequency dimensions using Xi ratios
  • aqueous=:auto: Solvent type for Xi ratio selection (:auto, true, or false)

Examples

# Reference 1H dimension
spec2 = reference(spec, 1, -0.12 => 0.0)
spec2 = reference(spec, F1Dim, -0.12 => 0.0)
spec2 = reference(spec, H1, -0.12 => 0.0)

# Reference without indirect referencing of other dimensions
spec2 = reference(spec, H1, -0.12 => 0.0; indirect=false)

See also shiftdim, xi_ratio.

source
reference(spec, dims, pairs; indirect=true, aqueous=:auto)
reference(dims, pairs; kwargs...)

Reference multiple spectrum dimensions simultaneously.

The forms without the data argument return a function for use with |>.

Arguments

  • spec: NMRData object to reference
  • dims: Collection of dimensions to reference
  • pairs: Collection of old_shift => new_shift pairs (same length as dims)
  • indirect=true: If true, reference remaining frequency dimensions using Xi ratios
  • aqueous=:auto: Solvent type for Xi ratio selection

Examples

# Reference both 1H and 15N dimensions
spec2 = reference(spec, [F1Dim, F2Dim], [4.7 => 4.8, 120.0 => 119.5])
spec2 = reference(spec, (H1, N15), (4.7 => 4.8, 120.0 => 119.5))

See also xi_ratio.

source
NMRTools.NMRBase.isaqueous — Function
isaqueous(spec) -> Bool

Determine whether a spectrum was acquired in an aqueous solvent.

Arguments

  • spec: NMRData object

Checks against the metadata field :solvent.

source
NMRTools.NMRBase.watershift — Function
watershift(temperature_K)

Calculate the chemical shift of water at a given temperature using the empirical formula:

δ(H₂O) = 7.83 − T / 96.9

where T is the temperature in Kelvin.

Arguments

  • temperature_K: Temperature in Kelvin

Returns

  • Chemical shift of water in ppm

References

Bruker uses 4.7 ppm as the default water reference when locking (with SR=0).

source

Noise, scaling and decimation

NMRTools.NMRBase.estimatenoise — Function
estimatenoise(nmrdata) -> NMRData

Estimate the rms noise level in the data and update :noise metadata. Returns the NMRData object with noise estimate stored in metadata.

If called on an Array of data, each item will be updated.

Algorithm

Data are sorted into numerical order, and the highest and lowest 12.5% of data are discarded (so that 75% of the data remain). These values are then fitted to a truncated gaussian distribution via maximum likelihood analysis.

The log-likelihood function is:

\[\log L(\mu, \sigma) = \sum_i{\log P(y_i, \mu, \sigma)}\]

where the likelihood of an individual data point is:

\[\log P(y,\mu,\sigma) = \log\frac{ \phi\left(\frac{x-\mu}{\sigma}\right) }{ \sigma \cdot \left[\Phi\left(\frac{b-\mu}{\sigma}\right) - \Phi\left(\frac{a-\mu}{\sigma}\right)\right]}\]

and $\phi(x)$ and $\Phi(x)$ are the standard normal pdf and cdf functions.

Examples

spec = loadnmr("experiment/1/pdata/1")
spec = estimatenoise(spec)  # Estimate and store noise level
spec[:noise]  # Access the noise estimate
source
NMRTools.NMRBase.scale — Function
scale(d::AbstractNMRData)

Return a scaling factor for the data combining the number of scans, receiver gain, and, if specified, the sample concentration.

\[\mathrm{scale} = \mathrm{ns} \cdot \mathrm{rg} \cdot \mathrm{conc}\]

source
NMRTools.NMRBase.decimate — Function
decimate(data, n dims=1)
decimate(n)

Decimate NMR data into n-point averages along the specified dimension. Note that data are averaged and not summed. Noise metadata is not updated.

The forms without the data argument return a function for use with |>.

source