I basicaly understood how the Rubberband/Baseline-correction works.

  1. The given spectrum is divided into (N) ranges.
  2. The lowest points in every range are determined.
  3. The initial baseline is built out of those points.
  4. Now all the points on the spectrum are drawn down by the difference between the lowest point in the current range and the lowest point on the baseline.

There are some nuances, though, that I do not know how to handle. E.g., what if one of the points is exactly on the border between two ranges, etc.

Plus, I have to be able to prove that the algorithm that I am writing is a solid one and can be referenced by other works or scientific papers.

If anyone could give me some reference I would be very pleased.

  • $\begingroup$ Or maybe somebody knows a better or similar way to detect && correct a baseline. $\endgroup$ – チーズパン Jul 3 '12 at 8:45

This can be easily done in R or Python. There are well-tested functions available, so you don't have to worry about any boundaries or nuances. Moreover, both are free and popular among scientists.

Solution for R

There is a special package to handle spectral data, called hyperSpec. The rubberband baseline correction is already implemented there (function spc.rubberband). All details are highlighted in the documentation. The usage is pretty simple:

spc <- read.spe("paracetamol.SPE")
baseline <- spc.rubberband(spc)

corrected <- spc - baseline

enter image description here

Solution for Python

There is no (to the best of my knowledge) out-of-the box solution for python, but you can use scipy.spatial.ConvexHull function to find indices of all points that form a convex hull around your spectrum. Suppose that the spectrum is contained in x and y arrays:

import numpy as np
from scipy.spatial import ConvexHull

def rubberband(x, y):
    # Find the convex hull
    v = ConvexHull(np.array(zip(x, y))).vertices

Array v contains indices of the vertex points, arranged in the CCW direction, e.g. [892, 125, 93, 0, 4, 89, 701, 1023]. We have to extract part where v is ascending, e.g. 0–1023.

    # Rotate convex hull vertices until they start from the lowest one
    v = np.roll(v, -v.argmin())
    # Leave only the ascending part
    v = v[:v.argmax()]

    # Create baseline using linear interpolation between vertices
    return np.interp(x, x[v], y[v])

Now the baseline is corrected like this:

y = y - rubberband(x, y)
  • $\begingroup$ Nice answer, and bilingual, too! :-) $\endgroup$ – Peter K. May 11 '16 at 11:36

There may be many techniques. Your idea seems good to me.

Two other ideas:

  1. Do a FFT of your data and filter out the lowest frequencies. This also removes the baseline modulations. Certainly you have to find the correct filter width by hand or from an educated guess from the data.

  2. Use Cosine functions with multiple long wavelengths and do a linear fit to your data. You could also throw out the peaks via an simple filter or by weighting the data points with their signal strength.


[EDIT 2018/03/24] Since the answer, several uses on spectral data have been recorded

If your spectral peaks are relatively fine, and almost positive above a baseline with a more low-frequency behavior, I suggest to give a try to BEADS (Baseline Estimation And Denoising w/ Sparsity), an algorithm based on the sparsity of the data and soome of its derivatives. It works fine with chromatographic data. Matlab code is available, and the BEADS page gathers R or C++ codes, and known uses. Here you can find uses for Raman spectra, astronomical hyperspectral galaxy spectrum, X-ray absorption spectroscopy (XAS), X-ray diffraction (XRD), and combined XAS/XRD measurements.

Chromatography with simulated baseline

Baseline and noise corrected


Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.