Viewing contents of file '../idllib/contrib/buie/getannul.pro'
;+
; NAME:
;    getannul
; PURPOSE: (one line)
;    Extract an annulus from a 2-D array.
; DESCRIPTION:
;
; CATEGORY:
;    CCD data processing
; CALLING SEQUENCE:
;    Getannul, image, xcen, ycen, inradius, outradius, data
;
; INPUTS:
;    image       : CCD image array.
;    xcen,ycen   : Center of annulus.
;    inradius    : Radius of inner circle.
;    outradius   : Radius of outer circle.
;
; OPTIONAL INPUT PARAMETERS:
;
; KEYWORD PARAMETERS:
; OUTPUTS:
;    data        : Array of data from the image array.
;    idx         : Optional output of 1D indices (in image) of data.
;
; COMMON BLOCKS:
;
; SIDE EFFECTS:
;
; RESTRICTIONS:
;
; PROCEDURE:
;
; MODIFICATION HISTORY:
;    Written by Doug Loucks, Lowell Observatory, April, 1993.
;    Reference: getannul.c by Marc Buie.
;    This version is completely different than the previous version and
;    somewhat faster.
;    5/12/93, DWL, Fixed a bug involving fringe pixels.  In certain cases,
;                  the determination of the row indices led to a bad array
;                  subscript range.
;    1/5/94, DWL, Added optional output parameter idx.
;    95/06/12, MWB, Fixed bug, base needed to be LONG for large sky apertures
;-
PRO Getannul, image, xcen, ycen, inradius, outradius, data, idx

data = 0

; Get input image array size.
image_size = SIZE( image )
xsize = image_size[ 1 ]
ysize = image_size[ 2 ]

; Compute the exact area of the annulus and reserve enough space for the pixel
; index arrays.
r1 = inradius
r2 = outradius + 1
npts = LONG( !PI * ( r2*r2 - r1*r1 ) )
x = INTARR( npts )
y = INTARR( npts )
base = 0L

IF ( 0 LE inradius ) AND ( inradius LT outradius ) THEN BEGIN
   ; Compute the y-range limits.
   r2 = outradius
   r1 = inradius
   r2sq = r2 * r2
   r1sq  = r1 * r1
   yp = ycen - r2
   outy0 = FIX( yp )
   IF outy0 LT yp THEN outy0=outy0+1
   yp = ycen + r2
   outy3 = FIX( yp + 1 )
   IF outy3 GT yp THEN outy3=outy3 - 1
   FOR yp = outy0, outy3 DO BEGIN
      ; Step through each row and compute the x-range (or ranges).
      dy = yp - ycen
      dysq = dy * dy
      dx2 = SQRT( r2sq - dysq )
      xp = xcen - dx2
      outx0 = FIX( xp )
      IF outx0 LT xp THEN outx0=outx0+1
      xp = xcen + dx2
      outx3 = FIX( xp + 1 )
      IF outx3 GT xp THEN outx3=outx3-1
      IF dysq GT r1sq THEN BEGIN
         ; No intersection with inner radius.
         n = outx3 - outx0 + 1
         IF n EQ 0 THEN n = 1
         x[ base : base+n-1 ] = outx0 + INDGEN( n )
         y[ base : base+n-1 ] = REPLICATE( yp, n )
         base = base + n
      ENDIF ELSE BEGIN
         ; Passing through the inner circle.  Select two parts.
         dx1 = SQRT( r1sq - dysq )
         xp = xcen - dx1
         inx0 = FIX( xp + 1 )
         IF inx0 GT xp THEN inx0 = inx0 - 1
         xp = xcen + dx1
         inx3 = FIX( xp )
         IF inx3 LT xp THEN inx3=inx3+1
         n1 = inx0 - outx0 + 1
         n2 = outx3 - inx3 + 1
         IF n1 EQ 0 THEN n1 = 1
         IF n2 EQ 0 THEN n2 = 1
         x[ base : base+n1-1 ] = outx0 + INDGEN( n1 )
         y[ base : base+n1-1 ] = REPLICATE( yp, n1 )
         base = base + n1
         x[ base : base+n2-1 ] = inx3 + INDGEN( n2 )
         y[ base : base+n2-1 ] = REPLICATE( yp, n2 )
         base = base + n2
      ENDELSE
   ENDFOR

   ; Final verification and selection.
   t = WHERE( x[0:base-1] LT 0 OR x[0:base-1] GE xsize OR $
              y[0:base-1] LT 0 OR y[0:base-1] GE ysize, count )
   IF count GT 0 THEN BEGIN
      t = WHERE( x[0:base-1] GE 0 AND x[0:base-1] LT xsize AND $
                 y[0:base-1] GE 0 AND y[0:base-1] LT ysize, count )
      data = image[ x[t], y[t] ]
      IF N_PARAMS() EQ 7 THEN idx = x[t] + xsize * y[t]
   ENDIF ELSE BEGIN
      data = image[ x[0:base-1], y[0:base-1] ]
      IF N_PARAMS() EQ 7 THEN idx = x[0:base-1] + xsize * y[0:base-1]
   ENDELSE
ENDIF
END