Avoid nans in 2D cubic spline interpolation

I have XYZ data (X and Y are the coordinates of Z values). Intermintently, the Z values have NaNs.The data is a radar line with gaps in the data (hence the NaNs) and uneven spacing between each points (see figure, blue is the existing values, orange is the NaN values). What I would like is to interpolate the non-nan values on a regular spacing and leave the nans as they are. My XYZ array is +40k rows and contains approximately +5k of NaNs, sometimes consecutive and sometimes spread out.
I am using the interparc function from John (https://uk.mathworks.com/matlabcentral/fileexchange/34874-interparc) to interpolate my points as I am working with a curved line and do not want to create a meshgrid, but I get an error message every time:
Warning: All data points with NaN as their site will be ignored.
> In chckxy (line 37)
In spline (line 53)
In interparc (line 316)
Error using chckxy (line 42)
There should be at least two data points.
I have tried to replace the NaNs by an arbitrary value (999) and make each value unique, as per (https://uk.mathworks.com/matlabcentral/answers/344604-how-to-change-duplicate-values-so-that-every-value-is-unique)
% replace nans by value
new2_dpth(isnan(new2_dpth)) = 999;
% create unique values for NaNs
a = new2_dpth;
[uvals, ~, uidx] = unique(a, 'stable');
b = a;
for K = 1 : length(uvals)
mask = uidx == K;
b(mask) = uvals(K) + (0 : nnz(mask) - 1) * 0.01;
end
I can then interpolate this and remove any value above a certain threshold, but get very strange results (see second figure).
I have also tried to remove the nan's from the interpolation using a for and if loop, but this is time consuming and does not seem to work either (see below)
f=[];
for i = 1:length(b)
if b (i) ~= -999
f = interparc (100,new2_x,new2_y,b);
else
continue
end
end
Any help would be really appreciated! Thanks.

2 commentaires

darova
darova le 24 Fév 2020
Is this correct?
icylab
icylab le 25 Fév 2020
Hi Darova,
Thanks for your help. Yes I guess this is similar to what I need. However, I already know how to interpolate data on a regular grid. I just need this interpolation to stop before and start after the nans (and not interpolate them). I'm not sure your figure does that?

Connectez-vous pour commenter.

Réponses (1)

darova
darova le 26 Fév 2020
Here is what i tried: Created new mesh and place there NaN (red points_
clc,clear
% generate random data
x = sort(rand(1,20)*5);
y = sin(x);
z = x.^2;
ix = [2 7 12 18]; % indices of NaN's
plot3(x,y,z,'.-b')
hold on
plot3(x(ix),y(ix),z(ix),'ok')
hold off
t = [0 cumsum(sqrt(diff(x).^2+diff(y).^2+diff(z).^2))];
ti = linspace(0,t(end),15); % new mesh
[tt,in] = sort([t(ix) ti]); % sort new mesh and NaN points
[~,ii] = sort(in); % sort indices to get places of NaN
% interpolate data with mesh
xx = spline(t,x,tt);
yy = spline(t,y,tt);
zz = spline(t,z,tt);
i1 = ii(1:length(ix)); % first indices are NaN
hold on
plot3(xx,yy,zz+3,'.:r')
plot3(xx(i1),yy(i1),zz(i1)+3,'ok')
zz(i1) = nan; % place NaN in data to create breaks
plot3(xx,yy,zz+3,'-r','linewidth',2)
hold off
axis vis3d

6 commentaires

darova
darova le 26 Fév 2020
I get general idea of interpolation from HERE
Thanks Darova!
I have tried your solution but keep getting the error message:
Error using chckxy (line 51)
The data sites should be distinct.
Error in spline (line 53)
[x,y,sizey,endslopes] = chckxy(x,y);
Here is the code I adapted:
ix = isnan(new2_dpth); % get logical (1 = nan values)
ix_dpth = new2_dpth(~ix); % take nans out
new2_xx = reshape(new2_x,[1,43885]); % reshape arrays in horizontal direction (previously [43885,1])
new2_yy = reshape(new2_y,[1,43885]); % reshape arrays in horizontal direction (previously [43885,1])
new2_dd = reshape(new2_dpth,[1,43885]); % reshape arrays in horizontal direction (previously [43885,1])
t = [0 cumsum(sqrt(diff(new2_xx).^2+diff(new2_yy).^2))];
ti = linspace(0,t(end),43885); % new mesh
[tt,in] = sort([t(ix) ti]); % sort new mesh and NaN points
[~,ii] = sort(in); % sort indices to get places of NaN
xx = spline(t,new2_xx,tt);
yy = spline(t,new2_yy,tt);
zz = spline(t,new2_dd,tt);
icylab
icylab le 2 Mar 2020
Also, second figure in my initial example was simply connecting each point in the figure with a line, hence the weird blue filled sections in the figure. Just replace '-o' by 'o' when calling plot and this fixes it. Sorry about that.
darova
darova le 2 Mar 2020
You have NaN only in new2_dd? Or x and y?
icylab
icylab le 2 Mar 2020
Only in new2dd
Try this
zz = spline(t(~ix),new2_dd(~ix),tt); % take only number (without NaN)
I gave you incorrect example above
t = [0 cumsum(sqrt(diff(x).^2+diff(y).^2+diff(z).^2))];
Because z in your case have NaN's. You can't use it

Connectez-vous pour commenter.

Catégories

En savoir plus sur Interpolation dans Centre d'aide et File Exchange

Question posée :

le 24 Fév 2020

Commenté :

le 2 Mar 2020

Community Treasure Hunt

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

Start Hunting!

Translated by