>
> I have a set of irregularly gridded data (x,y,z) and I am trying to create 
> an interpolating surface using Thin Plate Splines. I couldn't find any 
> existing Julia routines so I thought I'd just do it my self. Here is my 
> implementation 
> <http://nbviewer.ipython.org/urls/gist.githubusercontent.com/lstagner/89964e63557ddb831e72/raw/49049103742450d80ee28d8876fa1a8b8037f970/tps.ipynb>.
>  
> As you can see its wrong. I been staring at it for a while now and I am 
> beginning to think I must be hitting some sort of bug or quirk of the 
> language. It either that or I did something wrong. If I get this to work I 
> was thinking about incorporating it into one of the existing interpolation 
> packages.
>
> Can anyone figure out why this is not working?
>
>
 Hello. I have never seen the formulas you are using to find 'a' and 'b' 
and I do not have the time to check. Provided they are correct, I would 
suspect numerical problems - it is often not a good idea to calculate a 
matrix inverse explicitely and the TPS matrix is ill-conditioned for even a 
moderate number of points. I am attaching my Matlab implementation - you 
see that I am solving the linear system by SVD, which is more stable. It 
should be trivial to translate to Julia. Hope this helps.

Jan
function [c,cnd]=lndthscoef(x,z) ;
% Calculate coefficients for thin-plate spline interpolation
% Calculates coefficients (usable e.g. by lndthseval) to interpolate
% function having values z at points x
%
% Usage: c=lndthscoef(x,z) 
%
% $Id: lndthscoef.m,v 1.3 2000/01/27 18:11:53 jkybic Exp $
% Jan Kybic, 1999

n=length(z) ;
A=zeros(n+3) ;

for i=1:n,
  for j=1:n,
    r2=(x(i,1)-x(j,1))^2+(x(i,2)-x(j,2))^2 ;
    if r2==0,
      A(i,j)=0 ;
    else
      A(i,j)=r2*log(r2) ; % actually twice as much as r^2 ln(r) 
    end ;
  end ;
  A(i,n+1:n+3)=[ x(i,1:2) 1 ] ; 
end ;

A(n+1,1:n)=x(:,1)' ;
A(n+2,1:n)=x(:,2)' ;
A(n+3,1:n)=ones(1,n) ;

% Solve using SVD techniques
[u,s,v]=svd(A) ;
s=diag(s) ; 
cnd=s(1)/s(n+1) ;
q=(s(1)*1e-20+1e-50) ; % the q-value is sensitive !!!
for i=1:n+3,
  if s(i)<q, s(i)=0 ; 
  else s(i)=1/s(i) ; end ;
end ;

c=v*diag(s)*u'*[z(:) ; 0 ; 0 ; 0 ] ;

Reply via email to