How to Correct the baseline shift of the signal

85 views (last 30 days)
I am trying to correct the baseline of the signal (picture attached) by using a single exponential curve fit to adjust the baseline.
The data file is attached as well.

Accepted Answer

Star Strider
Star Strider on 16 May 2018
Edited: Star Strider on 16 May 2018
I always use discrete filters to eliminate baseline drift, baseline offset, and high-frequency noise.
Try this:
[D,S] = xlsread('Book1GA.xls');
Tcl = regexp(S, '(\d\.\d+)', 'match'); % Time Values (Cell Array)
Tch = cell2mat([Tcl{:}]'); % Time Values (Character Array)
Tv = str2num(Tch); % Time Vector (Double)
L = numel(Tv);
Ts = mean(diff(Tv)); % Sampling Interval
Tsd = std(diff(Tv));
Fs = 1/Ts; % Sampling Frequency
Fn = Fs/2; % Nyquist Frequency
Dmd = D - mean(D);
FT_D = fft(Dmd)/L;
Fv = linspace(0, 1, fix(L/2)+1)*Fn; % Frequency Vector
Iv = 1:numel(Fv);
figure(1)
plot(Fv, abs(FT_D(Iv))*2)
grid
axis([0 25 ylim])
set(gca, 'XMinorTick','on')
xlabel('Frequency')
Wp = [2.1 15.0]/Fn; % Passband Frequency (Normalised)
Ws = [1.8 18.0]/Fn; % Stopband Frequency (Normalised)
Rp = 1; % Passband Ripple (dB)
Rs = 50; % Stopband Ripple (dB)
[n,Ws] = cheb2ord(Wp,Ws,Rp,Rs); % Filter Order
[z,p,k] = cheby2(n,Rs,Ws); % Filter Design, Sepcify Bandpass
[sos,g] = zp2sos(z,p,k); % Convert To Second-Order-Section For Stability
figure(2)
freqz(sos, 2^16, Fs) % Filter Bode Plot
D_Filtered = filtfilt(sos, g, D); % Filter Signal
figure(3)
plot(Tv, D_Filtered)
grid
xlabel('Time')
Experiment witht he passband and stopband frequencies to get the result you want. Note that in a bandpass filter, the passband frequency limnits must always be within the stopband frequency limits.
EDIT Adding the plot:
  10 Comments
amirhossein shahriari
amirhossein shahriari on 7 Jun 2018
Thank you so much . I have tried to experiment other sets of my data with savitzky filter but still seems like this band pass filter you design are way better and I can get way better average of my action potentials. So do you know why some other filters like savitzky are not helpful enough for this type of data
Star Strider
Star Strider on 7 Jun 2018
As always, my pleasure.
The Savitzky-Golay filter is primarily used for curve-smoothing (or at least that is my experience). It is quite good for that purpose. However for signal processing, I find it difficult to design functional filters with it, and prefer using frequency-selective filters such as those I use here. The Tips (link) section of the documentation describes the use of the Savitzky-Golay filter much better than I can.
Also, if you have R2018a or later, the bandpass (link) and related functions make filter design significantly easier. If you use the ‘d’ output from it with an IIR filter, remember to use the filtfilt function to do the actual filtering, not the filter function as suggested in the documentation (that I consider to be an error).

Sign in to comment.

More Answers (2)

Image Analyst
Image Analyst on 16 May 2018
You might use fitnlm(), if you have the Statistics and Machine Learning Toolbox
[D, S] = xlsread('Book1GA.xls');
Tcl = regexp(S, '(\d\.\d+)', 'match'); % Time Values (Cell Array)
Tch = cell2mat([Tcl{:}]'); % Time Values (Character Array)
Tv = str2num(Tch); % Thanks to Star for figuring out how to get the time!
plot(Tv, D, 'b-')
grid on;
erodedSignal = imerode(D, ones(51, 1));
hold on;
plot(Tv, erodedSignal, 'r-', 'LineWidth', 2);
X = Tv;
Y = erodedSignal;
% Convert X and Y into a table, which is the form fitnlm() likes the input data to be in.
tbl = table(X, Y);
% Define the model as Y = a + exp(-b*x)
% Note how this "x" of modelfun is related to big X and big Y.
% x((:, 1) is actually X and x(:, 2) is actually Y - the first and second columns of the table.
modelfun = @(b,x) b(1) + b(2) * exp(-b(3)*x(:, 1));
beta0 = [10000, 300, 1]; % Guess values to start with. Just make your best guess.
% Now the next line is where the actual model computation is done.
mdl = fitnlm(tbl, modelfun, beta0);
% Now the model creation is done and the coefficients have been determined.
% YAY!!!!
% Extract the coefficient values from the the model object.
% The actual coefficients are in the "Estimate" column of the "Coefficients" table that's part of the mode.
coefficients = mdl.Coefficients{:, 'Estimate'}
% Create smoothed/regressed data using the model:
yFitted = coefficients(1) + coefficients(2) * exp(-coefficients(3)*X);
% Now we're done and we can plot the smooth model as a red line going through the noisy blue markers.
hold on;
plot(X, yFitted, 'k-', 'LineWidth', 3);
grid on;
title('Exponential Regression with fitnlm()', 'FontSize', fontSize);
xlabel('X', 'FontSize', fontSize);
ylabel('Y', 'FontSize', fontSize);
legendHandle = legend('Original Signal', 'Baseline', 'Fitted Y', 'Location', 'north');
legendHandle.FontSize = 25;
% Set up figure properties:
% Enlarge figure to full screen.
set(gcf, 'Units', 'Normalized', 'OuterPosition', [0 0 1 1]);
% Get rid of tool bar and pulldown menus that are along top of figure.
% set(gcf, 'Toolbar', 'none', 'Menu', 'none');
% Give a name to the title bar.
set(gcf, 'Name', 'Demo by ImageAnalyst', 'NumberTitle', 'Off')
The black line is the exponential fit of the bottoms of the signal.
  2 Comments
amirhossein shahriari
amirhossein shahriari on 17 May 2018
thank you so much for your reply , how can I subtract the exponential fit of the data
Image Analyst
Image Analyst on 18 May 2018
Simply subtract yFitted from D
yCorrected = D - yFitted;

Sign in to comment.


Image Analyst
Image Analyst on 16 May 2018
Well you can try imerode() or movmin(). Or you can try some more sophisticated spectroscopic methods. It would have been easy for people to try things if you had attached your data. Try this link

Categories

Find more on Measurements and Feature Extraction in Help Center and File Exchange

Community Treasure Hunt

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

Start Hunting!