How can I avoid offset at start and end of signal when using xcorr-function?

I have two signals:
signal_a, 200 Hz with time time_a
signal_b 40 Hz with time_b.
First I downsampled signal a to the same sampling rate of signal_b.
Then I precut the signals to fit them better, used detrend to make them better compareable.
Finally I used the Xcorr-function to fit the two signals on the x-axis.
I have this lag at the beginning and at the end of the signals . Is there a way to avoid this? (I know this is how xcorr-function works.)
Or do I have to cut the signal in several pieces, then use xcorr and put them back together?
Thank you for your answers!
load('signal_a.mat')
load('signal_b.mat')
load('time_a.mat')
load('time_b.mat')
%--------------------------------------------------------------------------
% calculating sampling rate of signal_a and signal_b
%--------------------------------------------------------------------------
Ts_a = mean(diff(time_a));
Fs_a = 1/Ts_a;
Ts_b = mean(diff(time_b));
Fs_b = 1/Ts_b;
%--------------------------------------------------------------------------
% downsample signal a and detrend both signals
%--------------------------------------------------------------------------
signal_a_downsample = resample(signal_a,time_a,Fs_b);
signal_a_detrend = detrend(signal_a_downsample);
signal_b_detrend = detrend(signal_b);
%--------------------------------------------------------------------------
% cutting the signals to same begin- and end timestamps
%--------------------------------------------------------------------------
sig_a = signal_a_detrend(40:9095)
sig_b = signal_b_detrend(104:9270)
%--------------------------------------------------------------------------
% using xcorrr-function to fit signals on x-axis
%--------------------------------------------------------------------------
[c_a, lag_a] = xcorr(sig_b,sig_a);
c_a = c_a/max(c_a);
[m_a, i_a] = max(c_a);
t_a = lag_a(i_a);
sig_b_offset = sig_b(t_a:end);
%--------------------------------------------------------------------------
% plotting the results
%--------------------------------------------------------------------------
subplot(3,1,1)
plot(time_b, signal_a_detrend)
hold on
plot(time_b, signal_b_detrend)
sgtitle('signal_a and signal_b fitting with xcorr-function')
title('raw data signal_a and signal_b')
legend('signal_a', 'signal_b')
subplot(3,1,2)
plot(time_b(1:length(sig_a)), sig_a)
hold on
plot(time_b(1:length(sig_b)), sig_b)
title('precut, downsample, detrend')
legend('signal_a', 'signal_b')
subplot(3,1,3)
plot(time_b(1:length(sig_a)),sig_a,'b')
hold on
plot(time_b(1:length(sig_b_offset)), sig_b_offset, 'r')
title('precut, downsample, detrend - xcorr-fit -')
legend('signal_a', 'signal_b')

 Respuesta aceptada

hello Simon
I tweaked a bit your code ; see my comments and mods
no more manual cuts needed it's all automatic; also there is one section now that can be removed as it's no more needed
--------------------------------------------------------------------------
% cutting the signals to same begin- and end timestamps
%--------------------------------------------------------------------------
% sig_a = signal_a_detrend(40:9095)
% sig_b = signal_b_detrend(104:9270)
% basically we can skip this section now as the manual cut is no more
% needed
sig_a = signal_a_detrend;
sig_b = signal_b_detrend;
so you can now simplify your code
hope it helps
full code below :
clearvars
load('signal_a.mat')
load('signal_b.mat')
load('time_a.mat')
load('time_b.mat')
%--------------------------------------------------------------------------
% calculating sampling rate of signal_a and signal_b
%--------------------------------------------------------------------------
Ts_a = mean(diff(time_a));
Fs_a = 1/Ts_a;
Ts_b = mean(diff(time_b));
Fs_b = 1/Ts_b;
%--------------------------------------------------------------------------
% downsample signal a and detrend both signals
%--------------------------------------------------------------------------
% signal_a_downsample = resample(signal_a,time_a,Fs_b);
signal_a_downsample = interp1(time_a,signal_a,time_b); % I prefer this method as it will ensure that both data share the same time axis
signal_a_detrend = detrend(signal_a_downsample);
signal_b_detrend = detrend(signal_b);
figure(1)
plot(time_b, signal_a_detrend)
hold on
plot(time_b, signal_b_detrend)
%--------------------------------------------------------------------------
% cutting the signals to same begin- and end timestamps
%--------------------------------------------------------------------------
% sig_a = signal_a_detrend(40:9095)
% sig_b = signal_b_detrend(104:9270)
% basically we can skip this section now as the manual cut is no more
% needed
sig_a = signal_a_detrend;
sig_b = signal_b_detrend;
%--------------------------------------------------------------------------
% using xcorrr-function to fit signals on x-axis
%--------------------------------------------------------------------------
[c_a, lag_a] = xcorr(sig_b,sig_a);
% c_a = c_a/max(c_a); % not needed
[m_a, i_a] = max(c_a);
t_a = lag_a(i_a);
sig_b_offset = sig_b(t_a:end);
time_b_offset = time_b(1:length(sig_b_offset));
sig_a_trunc = sig_a(1:length(sig_b_offset));
%--------------------------------------------------------------------------
% plotting the results
%--------------------------------------------------------------------------
subplot(3,1,1)
plot(time_b, signal_a_detrend)
hold on
plot(time_b, signal_b_detrend)
sgtitle('signal_a and signal_b fitting with xcorr-function')
title('raw data signal_a and signal_b')
legend('signal_a', 'signal_b')
subplot(3,1,2)
% plot(time_b(1:length(sig_a)), sig_a)
plot(time_b, sig_a)
hold on
% plot(time_b(1:length(sig_b)), sig_b)
plot(time_b, sig_b)
title('precut, downsample, detrend')
legend('signal_a', 'signal_b')
% subplot(3,1,3)
% plot(time_b(1:length(sig_a)),sig_a,'b')
% hold on
% plot(time_b(1:length(sig_b_offset)), sig_b_offset, 'r')
% title('precut, downsample, detrend - xcorr-fit -')
% legend('signal_a', 'signal_b')
subplot(3,1,3)
plot(time_b_offset,sig_a_trunc,'b')
hold on
plot(time_b_offset, sig_b_offset, 'r')
title('precut, downsample, detrend - xcorr-fit -')
legend('signal_a', 'signal_b')

4 comentarios

Hello Mathieu NOE
I also tried the method with interp1, but the result is the same as it is with the resample-function.
The two signals fade away from each other at the beginning and the end. The middle part matches pretty good.
I just wanted to know if it is possible to fit them better on the x-axis.
Greetings,
Simon
hello Simon
check this new update
clearvars
load('signal_a.mat')
load('signal_b.mat')
load('time_a.mat')
load('time_b.mat')
%--------------------------------------------------------------------------
% calculating sampling rate of signal_a and signal_b
%--------------------------------------------------------------------------
Ts_a = mean(diff(time_a));
Fs_a = 1/Ts_a;
Ts_b = mean(diff(time_b));
Fs_b = 1/Ts_b;
%--------------------------------------------------------------------------
% downsample signal a and detrend both signals
%--------------------------------------------------------------------------
% signal_a_downsample = resample(signal_a,time_a,Fs_b);
signal_a_downsample = interp1(time_a,signal_a,time_b); % I prefer this method as it will ensure that both data share the same time axis
signal_a_detrend = detrend(signal_a_downsample);
signal_b_detrend = detrend(signal_b);
% figure(1)
% plot(time_b, signal_a_detrend,'b',time_b, signal_b_detrend,'r')
%--------------------------------------------------------------------------
% cutting the signals to same begin- and end timestamps
%--------------------------------------------------------------------------
% sig_a = signal_a_detrend(40:9095)
% sig_b = signal_b_detrend(104:9270)
% basically we can skip this section now as the manual cut is no more
% needed
sig_a = signal_a_detrend;
sig_b = signal_b_detrend;
%--------------------------------------------------------------------------
% using xcorrr-function to fit signals on x-axis
%--------------------------------------------------------------------------
% do the xcorr on data buffer to get a delay trend vs time
buffer = 256*8;
Overlap = 0.75;
[time,t_a] = myxcorr(sig_b,sig_a, Fs_b, buffer, Overlap);
t_aa = interp1(time,t_a,time_b,'linear','extrap'); % variable time delay must be computed for all time values
new_time = time_b+t_aa;
[new_time,ind] = sort(new_time); % sort new_time in ascending order
sig_a = sig_a(ind); % apply to sig_a too
sig_b = interp1(time_b,sig_b,new_time); % make sure sig b shares same time vector as signal a
% remove signals sections when there are NaNs (introduced by interp1)
inda = isnan(sig_a);
sig_b(inda) = NaN;
indb = isnan(sig_b);
sig_a(indb) = NaN;
%--------------------------------------------------------------------------
% plotting the results
%--------------------------------------------------------------------------
figure(2)
subplot(211),plot(time_b, signal_a_detrend,'b',time_b, signal_b_detrend,'r')
title('downsample, detrend')
legend('signal_a', 'signal_b')
subplot(212),plot(new_time, sig_a,'b',new_time, sig_b,'r')
title('downsample, detrend - xcorr-fit -')
legend('signal_a', 'signal_b')
function [time,t_a] = myxcorr(x,y, Fs, buffer, Overlap)
% FFT peak spectrogram of signal (example sinus amplitude 1 = 0 dB after fft).
% x,y - input signals,
% Fs - Sampling frequency (Hz).
% buffer - buffer size
% Overlap - buffer overlap % (between 0 and 0.95)
samples = length(x);
% compute running xcorr with overlap
offset = fix((1-Overlap)*buffer);
segments = 1+ fix((samples-buffer)/offset); % Number of windows
for ci=1:segments
start = 1+(ci-1)*offset;
stop = start+buffer-1;
[c_a, lag_a] = xcorr(x(start:stop),y(start:stop));
% % c_a = c_a/max(c_a); % not needed
[m_a, i_a] = max(c_a);
t_a(ci) = lag_a(i_a)/Fs; % lag in seconds
end
% time vector
% time stamps are defined in the middle of the buffer
time = ((0:segments-1)*offset + round(offset/2))/Fs;
end
Hi Mathieu NOE,
thank your very much. This is what I was looking for.
I have to dive more into programming with MATLAB I guess to achieve what I actually want.
Greetings,
Simon
Glad I could be of some help
Helping the others is also a way for me to improve my skills ...

Iniciar sesión para comentar.

Más respuestas (0)

Productos

Versión

R2021a

Preguntada:

el 23 de Abr. de 2021

Comentada:

el 26 de Abr. de 2021

Community Treasure Hunt

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

Start Hunting!

Translated by