How can I subtract the baseline to zero?

I need to compare peak heights of several spectra but they do not baseline at zero, is there a way I can revert the baseline to zero using code on MATLAB?
Thanks, Hannah (absolute matlab novice)

 Accepted Answer

If you have the Signal Processing Toolbox you can use a Savitzky-Golay filter and I've attached a demo for that, or medfilt1(). Or if you have the Curve Fitting Toolbox you can use smooth() or lowess() or rloess() or functions like that. (Not sure if I spelled them correctly since I don't have that toolbox.
Attach your data and tell us what toolboxes you have and you might get someone to write you some code.

7 Comments

Alright Hannah, you're going to make me work for it. Try this code. I had to simulate your signal so just replace my y with your actual data. This is just one of many possible ways, but it seems to work pretty good. The "baseline" signal is in red and that signal subtracted from the original is the one at the bottom along the x axis.
clc; % Clear the command window.
close all; % Close all figures (except those of imtool.)
clear; % Erase all existing variables. Or clearvars if you want.
workspace; % Make sure the workspace panel is showing.
format long g;
format compact;
fontSize = 24;
% Create some data
x = 900:1400;
period = 500;
y=100*cos(2*pi*(x-950)/period) + 1200;
% Add noise
y = y + 120 * rand(1, length(y));
% Put in big spikes at x=1050 and 1210
y(150) = 1600;
y(310) = 1600;
% Now plot it.
plot(x, y, 'b-');
ylim([-200,1800]);
grid on;
xlabel('X', 'FontSize', fontSize);
ylabel('Y', 'FontSize', fontSize);
% Put a thick black line along the x axis
line([x(1), x(end)], [0, 0], 'LineWidth', 3, 'Color', 'k');
% Enlarge figure to full screen.
set(gcf, 'Units', 'Normalized', 'OuterPosition', [0 0 1 1]);
% Give a name to the title bar.
set(gcf, 'Name', 'Demo by ImageAnalyst', 'NumberTitle', 'Off')
% Now smooth with a Savitzky-Golay sliding polynomial filter
windowWidth = 101
polynomialOrder = 3
baselineY = sgolayfilt(y, polynomialOrder, windowWidth);
hold on;
plot(x, baselineY, 'r-', 'LineWidth', 2);
title('Signal Smoothed by Savitzky-Golay Filter', 'FontSize', fontSize);
% Now subtract the baseline from the original data
detrendedY = y - baselineY;
% Now plot it.
plot(x, detrendedY, 'b-');
Thanks, this was a great help! Your code worked but I thought I would include my original data here anyway. Hannah
Glad it worked for you. Can you go ahead and mark my Answer as officially "Accepted" then? Thanks.
Done! If you don't mind, could you take me through the code you came up with? Namely, windowWidth and why you choose a polynominal order of 3? Also the variables 'b-' (plot(x, detrendedY, 'b-')) and 'r-' 'LineWidth' & 2 ((plot(x, baselineY, 'r-', 'LineWidth', 2)).
Thanks, Hannah
'b-' means plot a blue line between data elements. 'r-' means plot a blue line between data elements.
I chose a linewidth of 2 just to make it thicker and easier to see, especially since the image I had was full screen and it will be subsampled down to display it here in Answers - I didn't want to lose the line entirely because it got subsampled away.
I just choise a windowWidth to make the trend look about right. I originally started out with a smaller one but the red line was following all the little wiggles in the blue data too closely and the red line wasn't smooth enough so I increased the windowWidth until I though the line was smoothed enough.
Oh so all of those variables were purely for the image for Answers rather than being integral to the code. This may be a silly question but why did you choose a polynomial order of 3? Should I keep an order of 3 for all the spectra or is it dependant on the individual spectra?
Appreciate all the help, Hannah.
Hannah, I don't know what variables you're talking about, but true, about half my code is to just synthesize data because you didn't supply me with any. The main code is just these two lines:
baselineY = sgolayfilt(y, polynomialOrder, windowWidth);
detrendedY = y - baselineY;
Everything else is just to make it fancy or initialize things.
I chose an order of 3 because the curve sort of looked like a sine wave which has orders 1, 3, 5, etc. if you know the Taylor series form of it. But really for the Savitzky-Golay filter you don't want too high an order because it just takes more time and doesn't improve the results any. If you make a higher order it will just follow the noisy wiggles more and you don't want that . A lower order like 1, 2, or 3 will give better smoothing.

Sign in to comment.

More Answers (4)

If you have the Image Processing Toolbox, maybe a median filtering would give a good approximation of the baseline, e.g.,
X-medfilt2(X,[1,3])
I never thought I could easily find the solution to this problem :)...thanks Hannah and image analyst..
Hi image analyst,...could you kindly advise which filter would work with my signal below..im having difficulties with using the filter u suggested to hannah...
thanks a lot in advance
Ella
Ella on 20 Feb 2017
Dear Image Analyst,
Thank you for your help with Hannah's question. I tried this method with my data and obtained a flat line. I was wondering if you might be able to help me out with a general baseline removal. In case this is possible, I have attached an example spectrum in .txt format (TanX and TanY are to be plotted on the x and Y axis and are one above each other in the document). We're only concerned about the peaks which are obvious. It was an x-ray photo-electron spectroscopy measurement. Thank you very much!!

4 Comments

Ella, see m-file attached below this plot it produces:
It estimates where the baseline is (shown in red), then fits a line through them (through the red points only). Then subtracts the line from the signal, and clips it to 0 so there are no negative signals. Then it plots the corrected signal.
Thank you Image Analyst. This is great and I have slightly adapted it to treat an extended signal. Is there anywhere where I can vote this answer up or give you some kind of credit?
Since you didn't start your own question, I couldn't answer it, but you can still give me the same number of reputation points (2) by "Voting" for my answer to Hannah up above (below my avatar). It doesn't matter that it was not directed towards you. Thanks for considering that!
Ah I see! Actually I already voted for your answer when I read it first time because it was the closest I had got to something useful! Okay - then if I have another question one day I'll post it in a seperate question then. Thanks again.

Sign in to comment.

Asked:

on 16 Jan 2015

Commented:

on 23 Feb 2017

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!