MATLAB: Interp2 yields undesired results on center daigonal.

cross-spectral matrixinterp2interpolationMATLAB

I am doing cross spectral matrices on some data where they look something like this:
Now when I interpolate using interp2 with 3 times as many points I get this:
[X,Y] = meshgrid(18:33);
[Xq,Yq] = meshgrid(18:1/3:33);
imagesc(18:33,18:33,interp2(X,Y,coMatSimple,Xq,Yq))
set(gca,'YDir','Normal')
colorbar
While this is technically correct, the problem with this is that the diagonal from the bottom left to top right corners should be all 1's (by definition of what I'm doing) and it is for my original data, but when I interpolate it's only 1 at the original data points and not anywhere else on that diagonal.
Is there a way I can get around this problem, maybe another function I can use instead of interp2 or some parameter that I can change to force the center diagonal values to be one and then have the interpolation function take that into account when interpolating?

Best Answer

There is nothing wrong with interp2.
Here is a minimal working example of your situation:
>> interp2([0,1;1,0])
ans =
0.00000 0.50000 1.00000
0.50000 0.50000 0.50000
1.00000 0.50000 0.00000
>>
The middle value is 0.5 (as it should be), because it interpolates between the zero values as well as the one values. There is no reason why the middle value should be one, because the ones do not have some magical higher priority that overrides the zeros, and so the original zeros also have an influence on the interpolated values.
Someone might offer better solutions, but here are two ideas to try:
  1. rotate the data matrix by 45 degrees, interpolate, and then rotate back. You could use the image processing tools to do the rotation. Keep in mind that this will lose some data precision as well.
  2. specify every output point along the antidiagonal and then use a scattered interpolant. This will be slightly more complex to set up (you will have to convert the data matrices into vectors and add the antidiagonal values), but has the advantages that there will be no loss of precision prior to interpolating, and you can specify the antidiagonal values exactly. Here is a demonstration of this:
>> M = [0,1;1,0] % input data
M =
0 1
1 0
>> [Ri,Ci] = ndgrid(0:1,0:1); % input locations
>> Rv = [Ri(:);0.5]; % add antidiagonal location

>> Cv = [Ci(:);0.5]; % add antidiagonal location
>> Mv = [ M(:);1]; % add antidiagonal data value
>> F = TriScatteredInterp(Rv,Cv,Mv);
>> [Ro,Co] = ndgrid(0:0.5:1,0:0.5:1); % output locations
>> F(Ro,Co)
ans =
0 0.5 1
0.5 1 0.5
1 0.5 0
>>
Perfect!