Viewing contents of file '../idllib/astron/contrib/freudenreich/robust_regress.pro'
 FUNCTION ROBUST_REGRESS,X,Y,YFIT,SIG, NUMIT=THIS_MANY, FLOOR=MINVAL
;+
; NAME:
;	ROBUST_REGRESS
;
; PURPOSE:
;	An outlier-resistant linear regression. Calls REGRESS.
;
; CALLING SEQUENCE:
;	COEFF = ROBUST_REGRESS(X,Y, YFIT,SIG, [ NUMIT = , FLOOR = ] )
;
; INPUTS:
;	X = Matrix of independent variable vectors, dimensioned 
;		(NUM_VAR,NUM_PTS), as in REGRESS
;	Y = Dependent variable vector. All Y<MINVAL are ignored.
;
; RETURNS:
;	Function result = coefficient vector. 0th element contains the constant
;	Either floating point or double precision. If the fit failed, COEFF=0.0
;	0.0 is returned; if the fit is dubious, a zero is appended to the 
;	vectors, so that is has NVAR+2 elements.
;
; OPTIONAL OUTPUT PARAMETERS:
;	YFIT = Vector of calculated y's
;	SIG  =  a robust measure of the standard deviation of the residuals
;
; OPTIONAL INPUT KEYWORDS:
;	NUMIT = the max. number of iterations. Default = 20
;	FLOOR = minimum Y value accepted. Y<FLOOR ignored. Default =-1.0e20
;
; RESTRICTIONS:
;	Should have >> NVAR+1 points for the fit to be truly outlier-resistant.
;
; PROCEDURE:
;	This iteratively: calls REGRESS, checks the dispersion of the
;	residuals, and computes weights (biweights). 
;	This is done until the standard deviation, also calculated using 
;	biweights, begins to grow or changes by less than CLOSE_ENOUGH, now set
;	to .03 X [uncertainty of the standard deviation of a normal 
;	distribution]
;
; REVISION HISTORY:
;	Written, H. Freudenreich, STX, 5/19/93
;	H.F. 3/94 --add FLOOR keyword and related modifications.
;-

  ON_ERROR,2

  DEL = 5.0E-07
  EPS = 1.0E-20
  QUESTIONABLE = 0
  IF N_ELEMENTS(THIS_MANY) GT 0 THEN ITMAX=THIS_MANY ELSE ITMAX=20
  IF N_ELEMENTS(MINVAL) GT 0    THEN EMPTY=MINVAL    ELSE EMPTY=-1.0e20

  SYZ = SIZE(X)
  NVAR = SYZ(1)
  NPTS = SYZ(2)

  QGOOD= WHERE( Y GT EMPTY, NGOOD )
  IF NGOOD LT (NVAR+1) THEN BEGIN
     PRINT,'ROBUST_REGRESS: Too Few Points!'
     RETURN,0.
  ENDIF

  CLOSE_ENOUGH = .03*SQRT(.5/(NGOOD-1)) > DEL

; Move X and Y to their centers of gravity:
  X0 = FLTARR(NVAR,NPTS)
  U=X  & V=Y

  FOR I=0,NVAR-1 DO BEGIN
    X0(I)=TOTAL(U(I,QGOOD))/NGOOD
    U(I,*)=U(I,*)-X0(I)
  ENDFOR
  Y0=TOTAL(V(QGOOD))/NGOOD
  V=V-Y0

  W=FLTARR(NPTS)
  W(*)=1.
  QBAD=WHERE( Y LE EMPTY, NBAD )
  IF NBAD GT 0 THEN W(QBAD)=0.
  CC = FLTARR(NVAR+1)

; The initial estimate.
  IF NBAD EQ 0 THEN COEF=REGRESS(U,V,W,YFIT,A0,RELATIVE_WEIGHT=1) $
               ELSE COEF=REGRESS(U,V,W,YFIT,A0) 
  CC=[A0,REFORM(COEF)] 

; The std. deviation of the residuals and weights:
  ISTAT=ROB_CHECKFIT(V(QGOOD),YFIT(QGOOD),EPS,DEL,  SIG,FRACDEV,IGOOD,IW)
  IF ISTAT EQ 0 THEN GOTO,AFTERFIT
  IF IGOOD LT (NVAR+1) THEN BEGIN
     PRINT,'ROBUST_REGRESS: Unable to fit this data. Returning 0'
     RETURN,0.
  ENDIF  
; Incorporate the weights returned by ROB_CHECKFIT:
  W(QGOOD)=IW

; Loop until we converge, or give up:
  SIG_1 = (100.*SIG) < 1.0E20
  DIFF = 1.0E10
  NUM_IT = 0
  WHILE( (DIFF GT CLOSE_ENOUGH) AND (NUM_IT LT ITMAX) ) DO BEGIN
     NUM_IT = NUM_IT + 1
     SIG_2 = SIG_1
     SIG_1 = SIG

     COEF=REGRESS(U,V,W,YFIT,A0) 
     CC=[A0,REFORM(COEF)] 

     ISTAT=ROB_CHECKFIT(V(QGOOD),YFIT(QGOOD),EPS,DEL, SIG,FRACDEV,IGOOD,IW)
     IF ISTAT EQ 0 THEN GOTO,AFTERFIT
     IF IGOOD LT (NVAR+1) THEN BEGIN
        PRINT,'ROBUST_REGRESS: Questionable Fit.'
        QUESTIONABLE = 1
        GOTO,AFTERFIT
     ENDIF  
     W(QGOOD)=IW
     DIFF = (ABS(SIG_1-SIG)/SIG) < (ABS(SIG_2-SIG)/SIG)
  ENDWHILE
;  IF NUM_IT GE ITMAX THEN PRINT,$
;    '   ROBUST_REGRESS did not converge in',ITMAX,' iterations!'

  AFTERFIT:
; Shift the surface back from its center of gravity:
  YFIT = YFIT + Y0
  FOR I=0,NVAR-1 DO CC(0)=CC(0)-CC(I+1)*X0(I)
  CC(0)=CC(0)+Y0
  IF QUESTIONABLE EQ 1 THEN CC=[CC,0.]

  IF NPTS LT N_ELEMENTS(Y) THEN BEGIN
     YFIT=FLTARR(NPTS)
     YFIT(*)=CC(0)
     FOR I=1,NVAR DO YFIT(*)=YFIT(*)+CC(I)*X(I-1,*)
  ENDIF

  RETURN,CC
END