Viewing contents of file '../idllib/uit/pro/cntrd.pro'
pro cntrd, img, x, y, xcen, ycen, fwhm, SILENT= silent, DEBUG=debug
;+
; NAME:
; CNTRD
; PURPOSE:
; Compute centroid coordinates of a stellar object using the
; algorithm in the DAOPHOT FIND subroutine.
;
; CALLING SEQUENCE:
; CNTRD, img, x, y, xcen, ycen, [ fwhm , /SILENT, /DEBUG]
;
; INPUTS:
; IMG - Two dimensional image array
; X,Y - Scalar or vector integers giving approximate stellar center
;
; OPTIONAL INPUT:
; FWHM - floating scalar; Centroid is computed using a box of half
; width equal to 1.5 sigma = 0.637* FWHM. CNTRD will prompt
; for FWHM if not supplied
;
; OUTPUTS:
; XCEN - the computed X centroid position, same number of points as X
; YCEN - computed Y centroid position, same number of points as Y
;
; Values for XCEN and YCEN will not be computed if the computed
; centroid falls outside of the box, or if the computed derivatives
; are non-decreasing. If the centroid cannot be computed, then a
; message is displayed and XCEN and YCEN are set to -1.
;
; OPTIONAL OUTPUT KEYWORDS:
; SILENT - Normally CNTRD prints an error message if it is unable
; to compute the centroid. Set /SILENT to suppress this.
; DEBUG - If this keyword is set, then CNTRD will display the subarray
; it is using to compute the centroid.
;
; PROCEDURE:
; Maximum pixel within distance from input pixel X, Y determined
; from FHWM is found and used as the center of a square, within
; which the centroid is computed as the value (XCEN,YCEN) at which
; the derivatives of the partial sums of the input image over (y,x)
; with respect to (x,y) = 0.
;
; MODIFICATION HISTORY:
; Written 2/25/86, by J. K. Hill, S.A.S.C., following
; algorithm used by P. Stetson in DAOPHOT.
; Improved error checking W. Landsman August, 1991
; Allowed input vectors G. Hennessy April, 1992
; Fixed to prevent wrong answer if floating pt. X & Y supplied
; W. Landsman March, 1993
;-
On_error,2 ;Return to caller
if N_params() LT 5 then begin
print,'Syntax: CNTRD, img, x, y, xcen, ycen, [ fwhm, /SILENT, /DEBUG ]'
PRINT,'img - Input image array'
PRINT,'x,y - Input scalars giving approximate X,Y position'
PRINT,'xcen,ycen - Output scalars giving centroided X,Y position'
return
endif else if N_elements(fwhm) NE 1 then $
read,'Enter approximate FWHM of image in pixels: ',fwhm
sz_image = size(img)
if sz_image(0) NE 2 then message, $
'ERROR - Image array (first parameter) must be 2 dimensional'
xsize = sz_image(1)
ysize = sz_image(2)
; Compute size of box needed to compute centroid
nhalf = fix(0.637*fwhm) > 2 ;
nbox = 2*nhalf+1 ;Width of box to be used to compute centroid
nhalfbig = nhalf +3
nbig = nbox + 6 ;Extend box 3 pixels on each side to search for max pixel value
npts = N_elements(x)
xcentroid = fltarr(npts) & ycentroid = xcentroid
xcen = float(x) & ycen = float(y)
ix = fix( x + 0.5 ) ;Central X pixel ;Added 3/93
iy = fix( y + 0.5 ) ;Central Y pixel
for i = 0,npts-1 do begin ;Loop over X,Y vector
pos = strtrim(x(i),2) + ' ' + strtrim(y(i),2)
if ( (ix(i) LT nhalfbig) or ((ix(i) + nhalfbig) GT xsize-1) or $
(iy(i) LT nhalfbig) or ((iy(i) + nhalfbig) GT ysize-1) ) then begin
if not keyword_set(SILENT) then message,/INF, $
'Position '+ pos + ' too near edge of image'
xcen(i) = -1 & ycen(i) = -1
goto, DONE
endif
bigbox = img(ix(i)-nhalfbig : ix(i)+nhalfbig, iy(i)-nhalfbig : iy(i)+nhalfbig)
; Locate maximum pixel in 'NBIG' sized subimage
mx = max( bigbox, mx_pos ) ;Maximum pixel value in BIGBOX
idx = mx_pos mod nbig ;X coordinate of Max pixel
idy = mx_pos / nbig ;Y coordinate of Max pixel
xmax = ix(i) - (nhalf+3) + idx ;X coordinate in original image array
ymax = iy(i) - (nhalf+3) + idy ;Y coordinate in original image array
; Extract smaller 'STRBOX' sized subimage centered on maximum pixel
strbox = img(xmax-nhalf : xmax+nhalf, ymax-nhalf : ymax+nhalf)
if keyword_set(DEBUG) then begin
PRINT,'Subarray used to compute centroid:'
print,strbox
endif
ir = (nhalf-1) > 1
dd = indgen(nbox-1) + 0.5 - nhalf
; Weighting factor W unity in center, 0.5 at end, and linear in between
w = 1. - 0.5*(abs(dd)-0.5)/(nhalf-0.5)
sumc = total(w)
; Find X centroid
deriv = shift(strbox,-1,0) - strbox ;Shift in X & subtract to get derivative
deriv = deriv(0:nbox-2,nhalf-ir:nhalf+ir) ;Don't want edges of the array
deriv = total( deriv, 2 ) ;Sum X derivatives over Y direction
sumd = total( w*deriv )
sumxd = total( w*dd*deriv )
sumxsq = total( w*dd^2 )
if sumxd GT 0 then begin ;Reject if X derivative not decreasing
if not keyword_set(SILENT) then message,/INF, $
'Unable to compute X centroid around position '+ pos
xcen(i)=-1 & ycen(i)=-1
goto,DONE
endif
dx = sumxsq*sumd/(sumc*sumxd)
if ( abs(dx) GT nhalf ) then begin ;Reject if centroid outside box
if not keyword_set(SILENT) then message,/INF, $
'Computed X centroid for position '+ pos + ' out of range'
xcen(i)=-1 & ycen(i)=-1
goto, DONE
endif
xcen(i) = xmax - dx ;X centroid in original array
; Find Y Centroid
deriv = shift(strbox,0,-1) - strbox
deriv = deriv(nhalf-ir:nhalf+ir,0:nbox-2)
deriv = total( deriv,1 )
sumd = total( w*deriv )
sumxd = total( w*deriv*dd )
sumxsq = total( w*dd^2 )
if (sumxd GT 0) then begin ;Reject if Y derivative not decreasing
if not keyword_set(SILENT) then message,/INF, $
'Unable to compute Y centroid around position '+ pos
xcen(i) = -1 & ycen(i) = -1
goto, DONE
endif
dy = sumxsq*sumd/(sumc*sumxd)
if (abs(dy) GT nhalf) then begin ;Reject if computed Y centroid outside box
if not keyword_set(SILENT) then message,/INF, $
'Computed X centroid for position '+ pos + ' out of range'
xcen(i)=-1 & ycen(i)=-1
goto, DONE
endif
ycen(i) = ymax-dy
DONE:
endfor
return
end