The NMRData model

Every spectrum, FID or series in NMRTools is an NMRData: an array of data points, a set of dimensions describing its axes, and a dictionary of metadata. Loading, processing, plotting and peak picking all take and return NMRData.

using NMRTools
spec = exampledata("2D_HN")
size(spec), eltype(spec)
((1216, 512), Float64)

An array with axes

NMRData is a subtype of AbstractDimArray from DimensionalData.jl. It behaves like an ordinary Julia array: it can be indexed, sliced, broadcast and passed to functions that expect an AbstractArray. The difference is that each axis carries its coordinates, so the array also answers questions about chemical shift, time or gradient strength:

dims(spec)
(↓ F1Dim Sampled{Float64} LinRange{Float64}(11.07119, 5.722488424064256, 1216) ReverseOrdered Regular Points,
→ F2Dim Sampled{Float64} LinRange{Float64}(128.9998, 107.04307400088886, 512) ReverseOrdered Regular Points)

Indexing by position and indexing by value use the same square brackets. Value-based selectors come from DimensionalData: Near(x) for the nearest point, At(x) for an exact match, and a .. b for a closed interval:

spec[Near(8.5), 120 .. 121]
┌ 23-element NMRData{Float64, 1} ┐
├────────────────────────────────┴─────────────────────────────────────── dims ┐
  ↓ F2Dim Sampled{Float64} LinRange{Float64}(120.96475545629396, 120.01945609821092, 23) ReverseOrdered Regular Points
├──────────────────────────────────────────────────────────────────── metadata ┤
  Dict{Symbol, Any} with 20 entries:
  :filename         => "/home/runner/.julia/artifacts/278430abd2b28a265273e7074…
  :channels         => Dict{Symbol, Any}(:f1=>Dict{Symbol, Any}(:offsethz=>2819…
  :label            => "13C,15N ubiquitin"
  :ns               => 2
  :temperature      => 276.999
  :experimentfolder => "/home/runner/.julia/artifacts/278430abd2b28a265273e7074…
  :pulseprogram     => "sfhmqcf3gpph.cw"
  :ndim             => 2
  :acqusfilename    => "/home/runner/.julia/artifacts/278430abd2b28a265273e7074…
  :title            => "13C,15N ubiquitin\n500 uM in 10% D2O, 20 mM Pi pH 6.5, …
  :acqus            => Dict{Symbol, Any}(:fcuchan=>Dict(0=>0, 4=>0, 5=>0, 6=>0,…
  :field            => 14.0967
  :format           => :pdata
  :noise            => 502.842
  :solvent          => "H2O+D2O"
  :nuclei           => Set(Nucleus[H1, N15])
  :topspin          => v"6.0.0"
  :acqu2s           => Dict{Symbol, Any}(:origin=>nothing, :sw=>21.9971, :sw_h=…
  :date             => DateTime("2019-11-20T19:41:09")
  :rg               => 203
└──────────────────────────────────────────────────────────────────────────────┘
 ⋮      ⋱  

The result of slicing is another NMRData, with its axes cut to match. A slice through a 2D spectrum is a 1D spectrum that can be plotted, phased or peak-picked like any other.

data(spec) returns the plain array underneath, and data(spec, dim) the plain vector of axis coordinates.

Operations preserve structure

Arithmetic and broadcasting return NMRData with the same axes and metadata:

spec2 = 2 * spec .+ 1
typeof(spec2) == typeof(spec)
true

Reductions over a dimension, such as sum(spec; dims=F1Dim), keep the remaining dimensions. To build a new NMRData with different data but the same axes and metadata, use rebuild:

rebuild(spec, newdata)
Shared metadata

Slices and copies of an NMRData share the same metadata dictionary as the original, so changing metadata on one changes it on all of them. Use deepcopy to make an independent copy. Acquisition metadata (:acqus, :td, …) describe the experiment as acquired and are not updated when data are sliced.

Element types

The element type records what kind of data an NMRData holds:

Element typeMeaningProduced by
Float64real spectrumloadnmr (default), autoprocess, real, realest
Multicomplex{Float64,1,2}complex in one dimensionloadfid on a 1D or pseudo-2D, loadnmr(...; allcomponents=true) on 1D data
Multicomplex{Float64,2,4}complex in two dimensionsloadfid on a 2D
Multicomplex{Float64,3,8}complex in three dimensionsloadfid on a 3D

Processing keeps the element type unchanged from loadfid to the final phase correction, and realest at the end gives a real spectrum. See Multicomplex numbers and quadrature.

Metadata

Metadata are attached at two levels: to the spectrum as a whole (spec[:ns]) and to each dimension (spec[F1Dim, :bf]). See Metadata.