The source files for all examples can be found in /examples.

Processing data

In this notebook, we reproduce the typical steps here for processing spectra

For this example, we create two Gaussian signals randomly sampled along two different X axis, with noise and increasing backgrounds. One of them will also have a strong spike!

Signal creation

using Spectra, Plots

# we create a fake signal with
x_1 = rand(1000)*100
x_2 = rand(1000)*100

# create a signal that is the combination of two gaussian peaks plus a background
background_1 = 0.08 * x_1
background_2 = 0.03 * x_2

# some noise
noise_1 = 0.5*randn(1000)
noise_2 = 0.3*randn(1000)

# the full toy signals
y_1 = gaussian(x_1, 10.0, 40., 5.) .+ background_1 .+ noise_1
y_2 = gaussian(x_2, 20.0, 60., 9.) .+ background_2 .+ noise_2

# one of them will have a spike!
y_1[600] = 250.0

# make a plot of our two spectra
scatter(x_1, y_1)
scatter!(x_2, y_2)
Example block output

First possible steps

We can do the following steps (not necessarily in this order):

  • the X values are randomly sorted, we can solve that using flipsp
  • We may like to get our spectra on the same X axis for convenience using resample
  • Spikes are present: we can remove them using despiking
  • Backgrounds are present: we can remove them using baseline
  • Signals are noisy: we can smooth them using smooth
  • We can correct for temperature and laser wavelength using tlcorrection
  • We can normalize the spectra using normalise
  • We can fit the peaks using fit_peaks

Let's do it!

Sort X Axis

We can sort the data by passing an array of spectra. After that we should have not problem plotting things with lines for instance!

spectrum_1 = flipsp([x_1 y_1])
spectrum_2 = flipsp([x_2 y_2])
plot(spectrum_1[:,1], spectrum_1[:, 2])
plot!(spectrum_2[:,1], spectrum_2[:, 2])

Remove spikes

OK, the plot above reveals a strong spike in one of the signals. We will treat actually both signals with despiking to remove possible spikes from the signals, using the default parameters. In summary, with the default settings, despiking checks if any points in a spectrum differ by more than 3 sigma from the mean value of the 4 neighboring points. You can change the default values to adjust the threshold (for more or less than 3-sigma), or to modify the number of neighboring points considered.

y_1 = despiking(x_1, y_1)
y_2 = despiking(x_2, y_2)
1000-element Vector{Float64}:
 22.233205773835333
  0.11829024781265957
  0.6377230276721132
  6.291937607691641
  2.976536881402551
  3.236070842017602
  0.9851497122272481
  3.475018082756437
  3.414925860073212
  2.4895639034216255
  ⋮
  0.5822391739371656
  3.4564839618884804
  0.855787817256738
  9.478968614430917
  1.3444424725831579
  2.8263112896384697
  0.6692099948825339
 14.942255389156047
  1.355610836976348

Resample to have everything on the same X axis

Using resample, we get everything on the same X axis. As we have two spectra with two different X axis, we simply provide them in a Vector like this:

x_new = collect(0.:0.5:100)
spectra_ = [[x_1 y_1], [x_2 y_2]]
spectra_same_x = resample(spectra_, x_new)
plot(x_new, spectra_same_x)

We see tiny problems with the interpolation, we can solve them using another method from DataInterpolations.jl, such as Linear:

spectra_same_x = resample(spectra_, x_new, method="LinearInterpolation")
plot(x_new, spectra_same_x)

Remove a background

Now we can remove a background using the baseline function. Similarly to the other functions, you can pass x and y vectors or a x vectors and an array of y spectra. We will do that here:

ys_corrected, ys_baselines = baseline(x_new, spectra_same_x, method="arPLS")
p1 = plot(x_new, spectra_same_x)
plot!(x_new, ys_baselines, labels=["background 1" "background 2"])

Measure peak parameters

We can now measure the parameters of each peak, for instance their centroid:

println("Centroids are:")
println(centroid(x_new, ys_corrected))
Centroids are:
[40.69442826386072, 59.922297613692244]

The peakmeas function to get access to a bunch of parameters: intensity, position, hwhm, centroïd

println("intensity, position, hwhm, centroïd are:")
println(peakmeas(x_new, ys_corrected[:,1]))
intensity, position, hwhm, centroïd are:
(10.020269070307508, 40.0, 4.75, 40.655297006277856)

If multiple peaks with a background are present, the best is to use the findpeaks() function It can even make a nice plot. Beware that you may have to tweak the windowsize, minwidth, minheight to detect only the main peaks... See the documentation of find_peaks for details. for more precise usage, also see the Peaks.jl package.

result = find_peaks(x_new, ys_corrected[:,1], window_size=1, min_width=2., min_height=2.0, smoothing=true)
println("Peak positions: ", result.peak_positions)
println("Peak heights: ", result.peak_heights)
println("Peak HWHMs: ", result.peak_hwhms)
println("Peak centroids: ", result.peak_centroids)
result.plot_peaks
Example block output

Peak fitting!

We can retrieve the parameters of the two peaks using peak fitting too! We do a quick fit with very loose prior uncertainties on the peak parameters, and unrestrictive lowerbounds and upperbounds. Those informations are provided in a vector of tuples, one tuple per peak: (type, initialparams, prior uncertainties, lowerbounds, upper_bounds)

peaks_info = [
        (:gaussian, [10.5, 50.0, 5.0], [100.0, 100.0, 100.0], [0., 0., 0.], [Inf, Inf, Inf]),
    ]
1-element Vector{Tuple{Symbol, Vararg{Vector{Float64}, 4}}}:
 (:gaussian, [10.5, 50.0, 5.0], [100.0, 100.0, 100.0], [0.0, 0.0, 0.0], [Inf, Inf, Inf])

we declare the context and fit the signals

ctx_1 = prepare_context(x_new, ys_corrected[:,1], peaks_info)
ctx_2 = prepare_context(x_new, ys_corrected[:,2], peaks_info)
result_1 = fit_peaks(ctx_1, backend=:Optim)
result_2 = fit_peaks(ctx_2, backend=:Optim)

println("Parameters and fit for the first signal:")
print_params(result_1.peak_results)
plot_fit(ctx_1, result_1.peak_results)
Parameters and fit for the first signal:
Peak 1 (gaussian):
  amplitude: 9.68 ± 0.32
  center: 40.07 ± 0.16
  width: 4.92 ± 0.18
  area: 101.3 ± 3.3

println("Parameters and fit for the second signal:")
print_params(result_2.peak_results)
plot_fit(ctx_2, result_2.peak_results)
Parameters and fit for the second signal:
Peak 1 (gaussian):
  amplitude: 19.71 ± 0.24
  center: 59.94 ± 0.1
  width: 8.82 ± 0.12
  area: 370.0 ± 4.4


This page was generated using Literate.jl.