1

I have some 'n' experimental curves for the same experimental conditions. Due to the inherent thermal drift in the system, the data sets are not exactly aligned with each other. I am looking for a robust algorithm that would align the data-curves for me.

This is what I tried so far:

x = linspace(1,100,1000);
y = tanh(0.09*x) ; figure; plot(x,y)
y1 = tanh(0.09*(x+10)) ; hold on; plot(x,y1)
y2 = tanh(0.09*(x-10)) ; hold on; plot(x,y2)

The curves look like this:

enter image description here

and this is what I would like to get:

Expected output

(Here I have aligned the curves y1 and y2 on top of the curve y)


I thought cross-correlation might help me align the data. So I tried:

[cc,lag] = xcorr(y,y1,'none');
[~,ind] = max(cc);
sh = lag(ind);

But this gave me sh=0.

Is there a better way of doing this?

Dev-iL
  • 23,742
  • 7
  • 57
  • 99
Backspace
  • 23
  • 3
  • Since the curves are monotone, it seems difficult to even define when they are aligned – Luis Mendo Jul 11 '18 at 10:15
  • Please explain what you would like to get. They already seem aligned in some sense. What features are the curves supposed to share? – Dev-iL Jul 11 '18 at 10:20
  • @Dev-iL : I would like to align the curves in the x direction i.e I want them to lie on top of each other (particularly the part at the beginning of the curve). – Backspace Jul 11 '18 at 11:04
  • @LuisMendo : Sorry, I don't understand your statement. Are monotonic curves difficult to align? Can you please explain your comment? – Backspace Jul 11 '18 at 11:17
  • @Backspace If the curves were for example [unimodal](https://en.wikipedia.org/wiki/Unimodality) you could define alignment more easily. Visually it would be clear how to horizontally shift one to make it more aligned with the other. With monotone functions I don't see how to do that – Luis Mendo Jul 11 '18 at 11:26
  • Actually, your edit makes it clerarer – Luis Mendo Jul 11 '18 at 11:27

1 Answers1

2

Here's my idea on how to approach this, using "reverse" interpolation (reverse in the sense that usually we want to find y values that correspond to some x, but here it's the other way around):

function q51282667
%% Generate data:
x = linspace(1,100,1000);
y{1} = tanh(0.09*x) ; 
y{2} = tanh(0.09*(x+10));
y{3} = tanh(0.09*(x-10));
% ^ y,y1,y2 are not necessarily the same length so I used a cell and not a numeric array

%% Find alignment:
% Establish a baseline: the curve with the largest vertical extent:
[~,mxi] = sort(cellfun(@max,y) - cellfun(@min,y), 'descend');
% Reverse interpolation using y-values:
ny = numel(y);
deltaX = zeros(ny,1);
for indY = 1:ny
  deltaX(indY) = interp1(y{mxi(1)}, x, y{indY}(1)) - x(1);
end

%% Plot:
% Original:
figure(); plot(x, y{1}, x, y{2}, x, y{3}); % this is the same as your example
% Shifted:
figure(); plot(x + deltaX(mxi(1)), y{mxi(1)}, ...
               x + deltaX(mxi(2)), y{mxi(2)}, ...
               x + deltaX(mxi(3)), y{mxi(3)});

resulting in:

deltaX = 

  10.0000063787562
  20.0000993310027
  0

and:

Desired output

Dev-iL
  • 23,742
  • 7
  • 57
  • 99
  • Thanks a lot! That worked like a charm! I must add that I have checked the algorithm with a noisy data(such as `y{1} = tanh(0.09*x); y{1} = awgn(y{1},35);`) and the algorithm seems to be robust. – Backspace Jul 11 '18 at 14:44