Viewing contents of file '../idllib/astron/contrib/freudenreich/rob_mapfit.pro'
function rob_mapfit,map,ndeg, cc, sig, single=precision, floor=minval
;
;+
; NAME:
; ROB_MAPFIT
;
; PURPOSE:
; Robustly fit a polynomial surface to a 2D floating-point array
;
; CALLING SEQUENCE:
; surface = ROB_MAPFIT( map,ndeg, coefficients, Sigma, [/SINGLE, FLOOR= ])
;
; INPUTS:
; map = array to fit, floating-point
; ndeg= degree of polynomials to be fitted. 1: Z=a+bX+cY
; 2: Z=a+bX+cY+eX^2+eY^2+fXY
; 3: Z=a+bX+cY+eX^2+eY^2+fX^3+gY^3+hX^2Y+iY^2X
; and so on...
; Maximum degree = 7 (35 terms)
;
; OUTPUT:
; ROB_MAPFIT returns the calculated fitted surface at each pixel:
; an array like the input array.
;
; OPTIONAL INPUT KEYWORDS:
; FLOOR = the minimum value allowed. Pixels <= this are considered vacant.
; The default = -1.0e20
; SINGLE if set, single precision is used. This should be done only if
; there is not enough memory for the default double-precision
; calculations.
;
; OPTIONAL OUTPUT:
; coefficients = the coefficients of the fit, in the order [a,b,c,...]
; as above.
; sigma = a robust analog of the std. deviation of the residuals
;
; SUBROUTINES NEEDED:
; Planefit, Robust_planefit, Quarticfit, Rob_Quarticfit, Rob_Checkfit,
; Robust_Sigma, Med, REGRESS (in USERLIB)
;
; NOTES:
; This routine will usually give excellent results as long as no more than
; 25% of the pixels are contaminated. When more than 25% are affected, it
; becomes harder to obtain the underlying shape. However, it will still do
; a pretty good job even if the data is a mess. But try to keep the degree
; of the fit down. Best if #pts >> degree
;
; REVISION HISTORY:
; Written, H.T. Freudenreich, HSTX, 5/20/93
;-
on_error,2
if keyword_set(minval) then empty=minval else empty=1.0e-20
if keyword_set(precision) then singlep=1 else singlep=0
nterms=[1,3,5,9,14,20,27,35]
maxdeg = n_elements(nterms)
if ndeg gt maxdeg then begin
print,' ROB_MAPFIT: Maximum degree = ',maxdeg,'!'
return,map
endif
; Get the needed dimensions:
syz=size(map)
nx=syz(1) & ny=syz(2)
ntot=nx*ny
q=where(map gt empty, ngood )
if ngood lt (nterms(ndeg)+2) then begin
print,'ROB_MAPFIT: Too few points!'
pap=map
return,pap
endif
if ndeg gt 7 then begin
print,'ROB_MAPFIT: Maximum degree in X and Y is 7! Setting degree to 7'
endif
; Obtain (X,Y) coordinates of the pixels:
u=findgen(nx) & v=findgen(ny)
xx=fltarr(nx,ny) & yy=fltarr(nx,ny)
for i=0,ny-1 do xx(*,i)=u & u=0
for i=0,nx-1 do yy(i,*)=v & v=0
x=reform(xx,ntot) & xx=0
y=reform(yy,ntot) & yy=0
z=reform(map,ntot)
; For efficiency, use specialized routines in the case of a plane or surface
; quadratic in X and Y.
if ndeg eq 1 then begin
cc=robust_planefit(x,y,z,zfit,sig,floor=empty)
endif else begin
; Go to double-precision:
if n_params() lt 4 then begin
if singlep eq 0 then begin
x=double(x) & y=double(y) & z=double(z)
endif
endif
if ndeg eq 2 then begin
cc = rob_quarticfit(x,y,z,zfit,sig,floor=empty)
endif else begin
if singlep eq 1 then xxx=fltarr(nterms(ndeg),ntot) else $
xxx=dblarr(nterms(ndeg),ntot)
x2 = x*x & y2 = y*y
xxx(0,*)=x & xxx(1,*)=y
xxx(2,*)=x2 & xxx(3,*)=y2
xxx(4,*)=x*y
xxx(5,*)=x2*x & xxx(6,*)=y2*y
xxx(7,*)=x2*y & xxx(8,*)=y2*x
if ndeg gt 3 then begin
xxx(9,*) =x2*x2 & xxx(10,*)=y2*y2
xxx(11,*)=x2*x*y & xxx(12,*)=y2*y*x
xxx(13,*)=x2*y2
if ndeg gt 4 then begin
xxx(14,*)=x^5 & xxx(15,*)=y^5
xxx(16,*)=x2*x2*y & xxx(17,*)=y2*y2*x
xxx(18,*)=x^3*y2 & xxx(19,*)=y^3*x2
if ndeg gt 5 then begin
xxx(20,*)=x^6 & xxx(21,*)=y^6
xxx(22,*)=x^5*y & xxx(23,*)=y^5*x
xxx(24,*)=x^4*y2 & xxx(25,*)=y^4*x2
xxx(26,*)=x^3*y^3
if ndeg gt 6 then begin
xxx(27,*)=x^7 & xxx(28,*)=y^7
xxx(29,*)=x^6*y & xxx(30,*)=y^6*x
xxx(31,*)=x^5*y2 & xxx(32,*)=y^5*x2
xxx(33,*)=x^4*y^3 & xxx(34,*)=y^4*x^3
endif
endif
endif
endif
cc = robust_regress( xxx,z, zfit, sig, floor=empty )
xxx=0
endelse
; Convert back to single-precision:
cc=float(cc)
zfit=float(zfit)
sig=float(sig)
endelse
; If the fit was made, convert back to 2D:
if n_elements(cc) gt 1 then pap=reform(zfit,nx,ny) else $
pap=map
return,pap
end