1. Working with SpectData
SpectData is the central data structure in NMRflux.jl. It stores an N-dimensional numerical data array, and one coordinate vector for each dimension, and is defined as a subtype of AbstractArray{T,N}. This means that SpectData behaves like a regular Julia array in most contexts: it supports indexing, slicing, broadcasting, and can be passed to most numerical functions that expect an array.
For reference, the type is defined as:
struct SpectData{T,N} <: AbstractArray{T,N}
dat::AbstractArray{T,N}
coord::NTuple{N,AbstractVector}
end1.1 Loading a simple JOEL dataset
using NMRflux
using NMRflux.Examples
using Plots
data_jeol = NMRflux.Examples.Data["Spheroid culture medium"]
jdf_file = joinpath(data_jeol["path"], "yp-5-fu-2.5-100.jdf")
params_jeol, data_td_jeol = NMRflux.load(jdf_file, :JEOL)
t_jeol = data_td_jeol.coord[1] # time axis (s)
y_jeol = real.(data_td_jeol.dat) # real part
plot(t_jeol, y_jeol;
xlabel = "time / s",
ylabel = "signal (a.u.)",
title = "JEOL FID (real part)")
savefig("jeol_fid_plot.svg"); nothingThe returned data from above is of type SpectData:
typeof(data_td_jeol)SpectData{ComplexF64, 1}1.2 Basic indexing
SpectData can be indexed just like a normal array. When you index with a range, you obtain a SpectData view with the corresponding subset of the data and coordinates:
data_td_jeol[1:5] # SpectData containing the first 5 complex points5-element SpectData{ComplexF64, 1} with coords:(0.0:8.879999999999999e-5:0.00035519999999999996,):
-2.1497944882665717e-7 - 7.707002455031156e-6im
-0.00013950422110987898 - 0.00017234635428217768im
-0.0051844162649977935 - 0.05157299135423599im
-0.08807038729465194 - 0.21358801463142338im
-0.08907652978845076 + 0.1320968426880609imTo access the underlying numerical values directly, you can use the dat field or broadcasted operations:
data_td_jeol.dat[1:5] # first 5 complex values as a plain array
real.(data_td_jeol)[1:5] # real part of first 5 points
imag.(data_td_jeol)[1:5] # imaginary part of first 5 points5-element SpectData{Float64, 1} with coords:(0.0:8.879999999999999e-5:0.00035519999999999996,):
-7.707002455031156e-6
-0.00017234635428217768
-0.05157299135423599
-0.21358801463142338
0.1320968426880609Multi dimensional SpectData objects behave analogously, with size and indexing following standard Julia conventions.
1.3 Internal structure
For a 1D SpectData object such as data_td_jeol, the two fields are:
data_td_jeol.datthe underlying AbstractArray{T,1} holding the numerical data values
(e.g. a complex FID or spectrum)
data_td_jeol.coorda 1-tuple of coordinate vectors, one per dimension. For 1D data,
coord[1] is the time axis (for FIDs) or frequency axis (for spectra)
For a 1D time domain FID:
data_array = data_td_jeol.dat # numerical array (complex FID)
t_axis = data_td_jeol.coord[1] # time axis
(first(t_axis), last(t_axis))(0.0, 2.0487048)In higher dimensions (e.g. 2D or 3D spectra), dat becomes an N-dimensional array, and coord[k] stores the coordinate vector (time, frequency, ppm, etc.) for the k-th dimension. Thus SpectData always keeps the numerical values and their physical axes together in a single coherent object. Conversion to frequency domain spectra (FFT, shifting, phasing, etc.) is handled by the processing tools described in the following sections.