Save and load peak lists

savepeaks writes a peak list to a file and loadpeaks reads one. The format is chosen from the file extension.

using NMRTools
spec = exampledata("2D_HN")
pks = detectpeaks(spec; snr=20, sign=:positive)
dir = mktempdir()

NMRAnalysis.jl format (.csv)

savepeaks writes a peaklist.csv that NMRAnalysis.jl reads directly:

file = joinpath(dir, "peaklist.csv")
savepeaks(file, pks)
print(join(readlines(file)[1:4], "\n"))
# NMRTools.jl 0.3.1 peak list
label,plane,x (ppm),y (ppm),lwx (Hz),lwy (Hz),intensity
X1,,7.7957671281768794,114.95784886559858,18.70706633504243,18.605996730028355,88641.2707328183
X2,,8.369367522782396,111.26848606171569,20.866290704307087,21.313179224592023,83539.63246055976

The file has one row per peak, with units in the column names. x is the direct dimension and y the indirect one. The blank plane column means the position applies to every plane of a series, which is how NMRAnalysis reads it. Labels identify peaks in NMRAnalysis, so they must be unique; unlabelled peaks are written as X1, X2, ….

loadpeaks reads it back, along with lists written by NMRAnalysis and simple hand-made lists of label x y lines:

loadpeaks(file)[1:3]
3-element Vector{Peak{2}}:
  label  x (ppm)  y (ppm)  lwx (Hz)  lwy (Hz)  intensity
     X1  7.79577  114.958   18.7071    18.606    88641.3
     X2  8.36937  111.268   20.8663   21.3132    83539.6
     X3  8.31883   122.37   19.5823    25.193    71443.8

Sparky format (.list)

Sparky lists the indirect dimension first, the reverse of NMRTools' order. Passing the spectrum to loadpeaks checks the order against where the shifts fall, so a list written the other way round is still read correctly:

sparky = joinpath(dir, "hsqc.list")
savepeaks(sparky, pks)
print(join(readlines(sparky)[1:4], "\n"))
       Assignment         w1         w2   Data Height

               X1    114.958      7.796       88641.3
               X2    111.268      8.369       83539.6
loadpeaks(sparky, spec)[1:3]
3-element Vector{Peak{2}}:
  label  x (ppm)  y (ppm)  lwx (Hz)  lwy (Hz)  intensity
     X1    7.796  114.958        NA        NA    88641.3
     X2    8.369  111.268        NA        NA    83539.6
     X3    8.319   122.37        NA        NA    71443.8

Quantities that Sparky lists don't record, such as linewidths, are NaN after loading.

As tables

A peak list is a Tables.jl table, so it converts to a DataFrame or any other table type:

using DataFrames
df = DataFrame(pks)

In a pipeline

pks |> savepeaks("peaklist.csv")
detectpeaks(spec) |> savepeaks("peaklist.csv")