From: Ben on
I have a medium to large set of 2D experimental data, which is spaced non-uniformly, and I need to interpolate it to a uniform grid. The size of each 2D field is usually around 2000x30 data points, and I can have as many as 5000 of these 2D fields. The other catch is every field is missing about 30% of it's data. So far, the missing data has always been at the edges, leading to concave and convex regions, but there is no reason why I might not get a large hole in the middle of my data.

At this point, I have a working solution for my data, but it's quite slow, and I don't think it will work well with a large hole in the data. Here is a stripped down version of my code that only has the essential parts in it:

%Cycle thru the fields
for f=1:5000
%Isolate data needed for this for loop
x_in=x_data(:,:,f);
y_in=y_data(:,:,f);
lgc_in=lgc_data(:,:,f);
%Create a Delaunay Triangulation only using the valid data points (lgc_in is a logical that specifies whether a data point is valid or missing)
x=x_in(lgc_in);
y=y_in(lgc_in);
dt = DelaunayTri(x,y);

%Find the circumcenters of the triangles
[cc,cr]=circumcenters(dt); %#ok<ASGLU>
%Find the triangles whose circumcenters are sufficiently small
%(large circumcenter radii indicate large missing areas of data,
%which should not be interpolated over)
tri_ndx=cr<5;
%Create a triangle representation with only the triangles that
%are sufficiently small
tri_edges=dt.Triangulation(tri_ndx,:);
tri=TriRep(tri_edges,x,y);
%Find the free edges of this triangle representation
fe=freeBoundary(tri);
%Add the free edges as a constraint to the Delauney
%Triangulation. (The TriScatteredInterp function below
%cannot use a generic triangle representation. It requires a
%Delauney Triangulation.)
%(A constraint can sometimes cut thru a triangle requiring the
%Delauney triangulation to be reconstructed, but here only
%entire triangles are eliminated by the constraint.)
dt.Constraints=fe;

%Find the limits of the field
AOI_lmt=round([min(x),max(x);min(y),max(y)]);

%Create interpolation list
[xi,yi]=meshgrid((AOI_lmt(1,1):AOI_lmt(1,2))',(AOI_lmt(2,1):AOI_lmt(2,2))');
[i,j]=size(xi);
n_pts=numel(xi);
xi=reshape(xi,n_pts,1);
yi=reshape(yi,n_pts,1);

%Find the triangle index for each xi-yi data point
tri_ndx=pointLocation(dt,xi,yi);
%Find the data points that are within the triangulation region
in_tri=~isnan(tri_ndx);
%Get the list of which triangles are inside constraint boundary
io=dt.inOutStatus();
%Of the points that are inside the triangulation region, some are inside
%triangles that are outside the constraint boundary. Find the points that
%are within the constraint boundary.
in_bndry=in_tri;
in_bndry(in_tri)=io(tri_ndx(in_tri));
%Set the points that are outside the constraint boundary to NaN. (Don't
%remove them since that would produce holes in the grid points, and we
%need a full grid to make a contour plot or image of the field data.)
xi(~in_bndry)=NaN;
yi(~in_bndry)=NaN;

%Find the valid field points
field_in=field_data(:,:,f);
z=field_in(lgc_in);
%Create the interpolation object
F=TriScatteredInterp(dt,z);
%Interpolate at the grid points (regions outside the
%constraint boundary have NaN, so interpolation will result
%in NaN at those data points).
zi=F(xi,yi);
end

I've run profiler on this code and the slowest parts are pointLocation(dt,xi,yi) and TriScatteredInterp(dt,z), which take about 40 seconds each. I guess I have to accept the computation time required for TriScatteredInterp, but I'm hoping that there may be a way to speed up the code associated with pointLocation. As you can see, I'm using a Delauney constraint boundary to specify where I want to interpolate (inside the boundary there is enough data so interpolate; outside the boundary there isn't enough data so do not interpolate). Then I use pointLocation to help me determine whether data points on the interpolation grid are inside or outside the Delauney constraint boundary.

Does anyone know a better (faster) way to do this? Furthermore I'm not sure if the freeBoundary(tri) function call will find a large hole in the data.

Thanks for any help you can lend.
From: us on
"Ben " <breedlun(a)hotmail.com> wrote in message <i1hoju$p2$1(a)fred.mathworks.com>...
> I have a medium to large set of 2D experimental data, which is spaced non-uniformly, and I need to interpolate it to a uniform grid. The size of each 2D field is usually around 2000x30 data points, and I can have as many as 5000 of these 2D fields. The other catch is every field is missing about 30% of it's data. So far, the missing data has always been at the edges, leading to concave and convex regions, but there is no reason why I might not get a large hole in the middle of my data.
>
> At this point, I have a working solution for my data, but it's quite slow, and I don't think it will work well with a large hole in the data. Here is a stripped down version of my code that only has the essential parts in it:
>
> %Cycle thru the fields
> for f=1:5000
> %Isolate data needed for this for loop
> x_in=x_data(:,:,f);
> y_in=y_data(:,:,f);
> lgc_in=lgc_data(:,:,f);
> %Create a Delaunay Triangulation only using the valid data points (lgc_in is a logical that specifies whether a data point is valid or missing)
> x=x_in(lgc_in);
> y=y_in(lgc_in);
> dt = DelaunayTri(x,y);
>
> %Find the circumcenters of the triangles
> [cc,cr]=circumcenters(dt); %#ok<ASGLU>
> %Find the triangles whose circumcenters are sufficiently small
> %(large circumcenter radii indicate large missing areas of data,
> %which should not be interpolated over)
> tri_ndx=cr<5;
> %Create a triangle representation with only the triangles that
> %are sufficiently small
> tri_edges=dt.Triangulation(tri_ndx,:);
> tri=TriRep(tri_edges,x,y);
> %Find the free edges of this triangle representation
> fe=freeBoundary(tri);
> %Add the free edges as a constraint to the Delauney
> %Triangulation. (The TriScatteredInterp function below
> %cannot use a generic triangle representation. It requires a
> %Delauney Triangulation.)
> %(A constraint can sometimes cut thru a triangle requiring the
> %Delauney triangulation to be reconstructed, but here only
> %entire triangles are eliminated by the constraint.)
> dt.Constraints=fe;
>
> %Find the limits of the field
> AOI_lmt=round([min(x),max(x);min(y),max(y)]);
>
> %Create interpolation list
> [xi,yi]=meshgrid((AOI_lmt(1,1):AOI_lmt(1,2))',(AOI_lmt(2,1):AOI_lmt(2,2))');
> [i,j]=size(xi);
> n_pts=numel(xi);
> xi=reshape(xi,n_pts,1);
> yi=reshape(yi,n_pts,1);
>
> %Find the triangle index for each xi-yi data point
> tri_ndx=pointLocation(dt,xi,yi);
> %Find the data points that are within the triangulation region
> in_tri=~isnan(tri_ndx);
> %Get the list of which triangles are inside constraint boundary
> io=dt.inOutStatus();
> %Of the points that are inside the triangulation region, some are inside
> %triangles that are outside the constraint boundary. Find the points that
> %are within the constraint boundary.
> in_bndry=in_tri;
> in_bndry(in_tri)=io(tri_ndx(in_tri));
> %Set the points that are outside the constraint boundary to NaN. (Don't
> %remove them since that would produce holes in the grid points, and we
> %need a full grid to make a contour plot or image of the field data.)
> xi(~in_bndry)=NaN;
> yi(~in_bndry)=NaN;
>
> %Find the valid field points
> field_in=field_data(:,:,f);
> z=field_in(lgc_in);
> %Create the interpolation object
> F=TriScatteredInterp(dt,z);
> %Interpolate at the grid points (regions outside the
> %constraint boundary have NaN, so interpolation will result
> %in NaN at those data points).
> zi=F(xi,yi);
> end
>
> I've run profiler on this code and the slowest parts are pointLocation(dt,xi,yi) and TriScatteredInterp(dt,z), which take about 40 seconds each. I guess I have to accept the computation time required for TriScatteredInterp, but I'm hoping that there may be a way to speed up the code associated with pointLocation. As you can see, I'm using a Delauney constraint boundary to specify where I want to interpolate (inside the boundary there is enough data so interpolate; outside the boundary there isn't enough data so do not interpolate). Then I use pointLocation to help me determine whether data points on the interpolation grid are inside or outside the Delauney constraint boundary.
>
> Does anyone know a better (faster) way to do this? Furthermore I'm not sure if the freeBoundary(tri) function call will find a large hole in the data.
>
> Thanks for any help you can lend.

a hint:
- look at these two great FEX contributions by john d'errico

http://www.mathworks.com/matlabcentral/fileexchange/4551-inpaintnans

http://www.mathworks.com/matlabcentral/fileexchange/8998-surface-fitting-using-gridfit

us
From: Ben on
> a hint:
> - look at these two great FEX contributions by john d'errico
>
> http://www.mathworks.com/matlabcentral/fileexchange/4551-inpaintnans
>
> http://www.mathworks.com/matlabcentral/fileexchange/8998-surface-fitting-using-gridfit
>
> us

Thanks for the reply, but I believe inpaintnans is for interpolating to fill in holes in your data and gridfit is for smoothing/extropolating your data. I do not want to interpolate/extrapolate into the areas where I have missing data. I only want to interpolate if I have enough data points nearby. Sorry if I was not clear above.