1 view (last 30 days)

Show older comments

I have a slowly varying signal that is always increasing or decreasing in value. I measure this with a descrete device (both signal and time value). I would like to determine the gradient of the true signal and therefore I would like to recover/estimate the true signal first. I have made a simple example which have similar behavior as what I am dealing with. Assuming that I know the signal values my measureing device can give (e.g. integer muliplum of 0.1) can I then recover the real signal with high accuracy in the gradient?

I appreciate any hint help you can give me to go in the right direction.

x = 1:0.01:10;

y = 1./x;

figure

plot(x,y)

hold on

y_discrete = round(y*10)/10;

plot(x,y_discrete,'.')

ylim([0,1])

EDIT:

Based on comments I have added a little extra description and a suggestion for a solution.

Assumptions:

- There is no noise (it will be removed before this step)
- Within each constant value block (the red lines in the plot above) the true value change slowly
- The estimation of the true signal is done as postprocessing so I have the whole dataset available and the calculation time is not an issue.

%Real and discrete sigmal

x = 1:0.01:10;

y = 1./x;

figure

plot(x,y)

hold on

y_discrete = round(y*10)/10;

plot(x,y_discrete,'.')

ylim([0,1])

%Approximation of the real signal using splines assuming that when the

%value of the discrete signal changes a good approximation of the real value

%is the average between the two levels.

idx = diff(y_discrete)';

idx = find(idx ~= 0);

x_intrp = zeros(length(idx)+2,1);

y_intrp = zeros(length(idx)+2,1);

x_intrp(1) = x(1);

y_intrp(1) = y(1);

for i = 1:length(idx)

y_intrp(i+1) = (y_discrete(idx(i))+y_discrete(idx(i)+1))/2;

x_intrp(i+1) = (x(idx(i))+x(idx(i)+1))/2;

end

x_intrp(i+2) = x(end);

y_intrp(i+2) = y(end);

plot(x_intrp,y_intrp,'r*')

m = makima(x_intrp,y_intrp,x); %Akima piecewise cubic Hermite interpolation

plot(x,m)

legend('True signal', 'Discrete signal', 'True nodes estimates', 'Spline estimation')

Bjorn Gustavsson
on 12 Jul 2021

Maybe you get something thats a bit more general (and perhaps?) more robust by simple least-square fitting:

m_fun = @(pars,x) round(interp1(pars(1:2:end),pars(2:2:end),x,'pchip')*10)/10; % 2 slightly different

M_fun = @(pars,x) round(interp1(pars(1:2:end),pars(2:2:end),x,'spline')*10)/10;% rounding model-functions

% you might consider adding arbitrary bells-and-whistles to this...

% Error-function:

err_fcn = @(pars,x,y,fcn) sum((y-fcn(pars,x)).^2);

par0 = [1 1 3 1/3 6 1/6 9 1/9]; % initial guess for 4 node-points for the approximating spline

par1 = fminsearch(@(pars) err_fcn(pars,x,y,m_fun),par0);

Par1 = fminsearch(@(pars) err_fcn(pars,x,y,M_fun),par0);

% disp(Par1) returns:

% Par1 =

% 0.98183 0.82362 2.9534 0.35617 6.6921 0.14992 8.8114 0.12509

% disp(par1) returns:

% par1 =

% 1.0057 0.89591 2.8314 0.33493 6.0081 0.16794 9.7301 0.10913

clf

plot(x,y)

hold on

plot(x,y_discrete,'.')

plot(x,m_fun(par1,x),'b')

plot(x,M_fun(Par1,x),'g')

In any non-artificial case you'll at least have to consider discretization-noise at each jump in the data - regardless of what noise-removal technique you consider...

HTH

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

Start Hunting!