function IRIS_ALIGN_AIA, oindx, afit, msg=msg, flag=flag

;+
; Name    : iris_align_aia
;
; Purpose : corrects the pointing in the IRIS header with the results from
;           an IRIS - AIA image cross-correlation.
;
; Use     : 
;           IDL> nindex = iris_align_aia(oindx,afit,msg=aiamsg)
;
; Input   :
;    oindx = (single) FITS header index structure with old pointing
;    afit   = struct.  Either an obsfit structure or an iris_align_struct.
;             Must be supplied by the calling routine (e.g., iris_prep)
;             obsfit: structure with OBS specific fitting resuls, typically
;                     read via iris_prep_obsfit_reader.pro
;             iris_align_struct: as created by iris_aia_corr.pro
;
; Output  :
;    nindex = FITS header index structure with updated pointing
;               Note that, if it's a full FITS header then the CRVAL and XYCEN
;               keywords are updated; if it's only a partial header, then its 
;               assumed that the calling routine (likely IRISL12_SHIFTAIA) will
;               do those updates, and only the displacements are returned.
;
; Keywords input:
;
; Keywords output:
;    msg = string with pointing info, typically added to the FITS header 
;          as HISTORY lines by the caller (e.g., iris_prep or irisl12_shiftaia)
;   flag = int set to 1 if the result was successful, 0 if it was rejected
;
; Common  :
;
; Restrictions:
;    - Does not check if correction already applied.  Calling routine must
;      make sure the correction hasn't been applied already.
;    - afit must be a structure element, not a vector.
;    - The afit structure is not checked for validity.  The caller must make
;      sure to either supply the obsfit structure for the correct OBS, or
;      the iris_align_struct for this particular image.
;    - Applies the delta from the IRIS-AIA correlation to the pointing in oindx
;    - Assumes that the pointing information in the old header is the same as
;      in the headers of the IRIS images used for the IRIS - AIA correlation
;      That is usually not the case for L1 files: those ought to be processed
;      through iris_isp2wcs WITH THE PROPER TEMPERATURES (via iris_time2hk.pro)
;    - Assumes that the headers of the AIA images used for the IRIS - AIA
;      correlation was correct.  Typically, the AIA headers are based on
;      daily master poiniting data.  The pointing could be further improved
;      by applying the difference between 3-hour and daily AIA pointing data.
;
; Side effects:
;
; Category   : Calibration, iris_prep
;
; Prev. Hist.:
;
; Written    : Jean-Pierre Wuelser                       LMSAL 19-Nov-2018
;
; MODIFICATION HISTORY:
;       2020-03-11: Paul Boerner -- updated interface to always use PC matrix
;
;-

peak_str_min = 3.0                                ; minimum value for peak_str
chisqs_max   = 0.5                                ; maximum for combo chisqs
numfit_min   = 20                                 ; either 0 or gt 20 anyway
offset_max   = 10.0                               ; max. offset in arcsec
slit_rot     = 0.646                              ; iris_mk_pointdb ver=2

; initial values
x_off = 0.
y_off = 0.
good  = 0

; check which input form (single index or time vector)
if size(oindx,/type) ne 8 then begin              ; we now require it to be an index
    PRINT, 'IRIS_ALIGN_AIA no longer accepts non-index inputs'
    STOP
    RETURN, oindx
endif
nindx = oindx
dt    = ANYTIM2TAI(oindx.t_obs)

if size(afit,/type) ne 8 then begin
    PRINT, 'IRIS_ALIGN_AIA requires a structure for the offset fits. Returning...'
    return,nindx
endif

; check for type of input and derive offsets accordingly
if tag_exist(afit,'peak_str',/quiet) then begin   ; -> iris_align_struct
   if afit.peak_str gt peak_str_min then begin
      x_off   = afit.x_off
      y_off   = afit.y_off
      good    = 1
   endif
endif else begin                                  ; -> obsfit
   if tag_exist(afit,'aia') then begin
      ; calculate offset(s) and determine whether data good or not
      good = sqrt(total(afit.aia.combo_chisqs^2)) lt chisqs_max and $
             min(afit.aia.combo_numfit) gt numfit_min
      if good then begin
         params  = afit.aia.combo_paramvals
         x_off   = params[0,3]+params[0,0]*SIN(params[0,1]*dt+params[0,2])
         y_off   = params[1,3]+params[1,0]*SIN(params[1,1]*dt+params[1,2])
         if max(abs([x_off,y_off])) gt offset_max then good=0
      endif
   endif
endelse



;++++++++++++++++++++++++++++++++++++++++++++
; PB 2020-03-11
; This section seems weird; why not use the 
; same approach used in iris_aia_corr?
; Commenting out and replacing with different
; roll handling.
;--------------------------------------------

;x_off,y_off are in arcsec in IRIS-SJI framework.  Transform to CRVALi
;really needed PC matrix for SJI, but this is a reasonable approximation:
;
;if good then begin
;  if size(oindx,/type) eq 8 then sat_rot=oindx.sat_rot
;  crotarad = ((-slit_rot-sat_rot)/!radeg)
;  crvalx_o = x_off*cos(crotarad) - y_off*sin(crotarad)
;  crvaly_o = x_off*sin(crotarad) + y_off*cos(crotarad)
;  msg = msg + STRING(crvalx_o,form='(f9.2)') + STRING(crvaly_o,form='(f9.2)')
;  if size(oindx,/type) eq 8 then begin          ; index input form
;    update CRVALi, CRVALiA, XCEN,YCEN
;    nindx.crval2  = oindx.crval2  + crvaly_o
;    nindx.crval2a = oindx.crval2a + crvaly_o
;    nindx.xcen    = oindx.xcen    + crvalx_o
;    nindx.ycen    = oindx.ycen    + crvaly_o
;    if oindx[0].instrume eq 'SJI' then begin
;      nindx.crval1  = oindx.crval1  + crvalx_o
;      nindx.crval1a = oindx.crval1a + crvalx_o
;    endif else begin
;      nindx.crval3  = oindx.crval3  + crvalx_o
;      nindx.crval3a = oindx.crval3a + crvalx_o
;    endelse
;  endif else begin                              ; tvec input form
;    nindx[0,*] = crvalx_o
;    nindx[1,*] = crvaly_o
;  endelse
;endif

; The correlation returns both xoff, yoff and crval1, crval2
; We're going to reproduce the calculation that resulted in making
; crval1 and crval2 out of xoff and yoff (since xoff and yoff are
; the parameters that are filtered for each OBS.)
;
if good then begin
    xdisp_rot = x_off*oindx.pc1_1 + y_off*oindx.pc1_2
    ydisp_rot = x_off*oindx.pc2_1 + y_off*oindx.pc2_2    
    msg = 'Pointing corr. w/AIA correl (solar x,y):' + $
            STRING(xdisp_rot,form='(f9.2)') + STRING(ydisp_rot,form='(f9.2)')
    ; if you have a header stub (used by irisl12_shiftaia), then you're done
    if TAG_EXIST(nindx, 'ycen') then begin
        nindx.ycen    = oindx.ycen    + ydisp_rot
        nindx.crval2  = oindx.crval2  + ydisp_rot
        nindx.crval2a = oindx.crval2a + ydisp_rot
        nindx.xcen    = oindx.xcen    + xdisp_rot
        if oindx[0].instrume eq 'SJI' then begin
            nindx.crval1  = oindx.crval1  + xdisp_rot
            nindx.crval1a = oindx.crval1a + xdisp_rot
        endif else begin
            nindx.crval3  = oindx.crval3  + xdisp_rot
            nindx.crval3a = oindx.crval3a + xdisp_rot
        endelse
    endif else begin
        nindx.xdisp_rot = xdisp_rot
        nindx.ydisp_rot = ydisp_rot
    endelse
    flag = 1
endif else begin
    flag = 0
    msg = 'Pointing corr. w/AIA requested but not applied'
endelse

return, nindx

end
