function IRIS_PREP_ALIGN_IMAGE, index, data, params, pdb, $
	measure_fid = measure_fid, shift_fid = shift_fid, $
	measure_wave = measure_wave, shift_wave = shift_wave, $
	measure_aia = measure_aia, shift_aia = shift_aia, $
	obsfit = obsfit, filter_fid = filter_fid, $
	filter_wave = filter_wave, filter_aia = filter_aia, $
	fidmsg = fidmsg, wmsg = wmsg, logdir = logdir, $
	tmid = tmid, loud = loud, pstop = pstop, level1p5 = level1p5, $
	xfiltfail = xfiltfail, yfiltfail = yfiltfail, fitchisq_max = fitchisq_max

;+
;
; Adjusts the interpolation matrix for an IRIS image in order to apply shifts,
; rotations and magnifications. Used by IRIS_PREP.
;
; INPUTS:
;	index	-	The header (a structure) of the FITS file to be aligned
;	data	-	The data (a 2D or 3D array)
;
; INPUT/OUTPUTS:
;	params	-	A structure describing the warping to be applied to the 
; 				image; see IRIS_PREP_GET_GEOWAVE (looked up if not passed in)
;	pdb		-	The pointing database structure from IRIS_MK_POINTDB (looked up
;				if not passed in)
;
; KEYWORDS:
;	fidmsg	-	a string or string array with a message regarding the fiducial
;				shifting to be performed on the image
;	wmsg	-	a string or string array with a message about the wavelength
;				shifting to be performed on the image
;	measure_fid	-	Set if you want to run IRIS_PREP_FID_FINDER to find the 
;					location of the fiducials and write it to a file
;	measure_wave -	Set if you want to run IRIS_PREP_WAVECORR to find the 
;					location of the Ni I NUV line and write it to a file
;	shift_fid	-	Set if you want to apply the shift to put the fiducials in
;					their nominal position. If /measure_fid is set, then
;					the correction is from the real-time measurement of this
;					image; otherwise, it is loaded from the side database
;	shift_wave	-	Set if you want to apply the shift to put the wavelengths in
;					their nominal positions. If /measure_wave is set, then
;					the correction is from the real-time measurement of this
;					image; otherwise, it is loaded from the side database
;	tmid	-	SYSTIME in between fid_finder and wavecorr; only useful for
;				benchmarking pipeline processes
;	[xy]filtfail -	Bit set to 1 if /filter_wave of /filter_fid is set, but
;					the filtered value is not used due to a missing fit
;					or chi-squared filtering
;	fitchisq_max -	Threshold value for the chi-squared on the obs-level fit; 
;					defaults to 2.
;
; RETURNS:
;	result	-	a structure with the same format as params, but with the 
;				warping updated to also perform the desired shifts, rotations
;				and magnifications
;	
;
;-

if not KEYWORD_SET(loud) then loud = 0
if not KEYWORD_SET(logdir) then logdir = 0
if N_ELEMENTS(params) eq 0 then params = IRIS_PREP_GET_GEOWAVE(index[0])
if N_ELEMENTS(pdb) eq 0 then pdb = IRIS_MK_POINTDB(version = pdb_ver)
		
measure_fid = KEYWORD_SET(measure_fid)
measure_wave = KEYWORD_SET(measure_wave)
measure_aia = KEYWORD_SET(measure_aia)
shift_fid = KEYWORD_SET(shift_fid)
shift_wave = KEYWORD_SET(shift_wave)
shift_aia = KEYWORD_SET(shift_aia)

filter_fid = KEYWORD_SET(filter_fid)
filter_wave = KEYWORD_SET(filter_wave)
filter_aia = KEYWORD_SET(filter_aia)
; Hard-coded constants for deciding whether to use filtered results
if N_ELEMENTS(fitchisq_max) eq 0 then fitchisq_max = 2.
fitnum_min = 20
fidsep = 269.5
maxamp = 10
; Initial values for setting iprpofff flags for bad obsfits
xfiltfail = 0
yfiltfail = 0

if N_ELEMENTS(index) gt 1 then begin
	; Just call itself recursively; not very efficient but oh well
	; Note that the same params structure is used for each index
	for i = 0, N_ELEMENTS(index)-1 do begin
		thisresult = IRIS_PREP_ALIGN_IMAGE(index[i], data[*,*,i], params, pdb, $
			logdir = logdir, measure_fid = measure_fid, shift_fid = shift_fid, $
			measure_wave = measure_wave, shift_wave = shift_wave, $
			measure_aia = measure_aia, shift_aia = shift_aia, $
			fidmsg = thisfidmsg, wmsg = thiswmsg)
		if i eq 0 then begin
			result = thisresult
			if N_ELEMENTS(thisfidmsg) gt 0 then fidmsg = thisfidmsg
			if N_ELEMENTS(thiswmsg) gt 0 then wmsg = thiswmsg
		endif else begin
			result = [result, thisresult]
			if N_ELEMENTS(thisfidmsg) gt 0 then fidmsg = [fidmsg, thisfidmsg]
			if N_ELEMENTS(thiswmsg) gt 0 then wmsg = [wmsg, thiswmsg]
		endelse 
	endfor
	RETURN, result
endif

lvl1_in = 1
itags = TAG_NAMES(index)
lvlnum_tag = WHERE(itags eq 'LVL_NUM', haslvl)
if haslvl then if index.lvl_num ne 1 then lvl1_in = 0

result = params
pdb_tags = TAG_NAMES(pdb)

if STRMID(index.img_path, 0, 3) eq 'SJI' then type = 'img' else type = 'spec'
sumspat = index.sumspat
sumsptrl = index.sumsptrl
offspat = (sumspat - 1.0) / (sumspat * 2.0)
offsptrl = (sumsptrl - 1.0) / (sumsptrl * 2.0)
if KEYWORD_SET(pstop) then STOP

;++++++++++++++++++++++++++++++++++++
; For slit-jaw images...
;------------------------------------
if type eq 'img' then begin

	; Look in pointing database for typical fiducial location/scale/roll for lev1 images
	sji_wv_nm = STRMID(index.img_path, 4, 3)
	if sji_wv_nm eq '160' then sji_wv_nm = 'MIR'
	if sji_wv_nm eq '500' then sji_wv_nm = 'FSI'
	nomx = (pdb.(WHERE(pdb_tags eq 'CPX1_' + sji_wv_nm))-1)/sumsptrl - offsptrl
	nomy1 = (pdb.(WHERE(pdb_tags eq 'CPX2_' + sji_wv_nm)) - 1 - fidsep)/sumspat - offspat
	nomy2 = (pdb.(WHERE(pdb_tags eq 'CPX2_' + sji_wv_nm)) - 1 + fidsep)/sumspat - offspat
	scale = pdb.(WHERE(pdb_tags eq 'CDLT_' + sji_wv_nm))
	roll = pdb.(WHERE(pdb_tags eq 'BE_' + sji_wv_nm))
	rshift = ATAN(roll*!pi/180.) * fidsep	;	X offset of fiducials due to roll

	; Target fiducial location/scale/roll for level 1.5 images
	xref = (pdb.cpx1_1p5 - 1) / sumsptrl - offsptrl
	yref = (pdb.cpx2_1p5 - 1) / sumspat - offspat
	sref = pdb.cdlt_1p5
	rref = 0.
	
	; If operating on lev1.5 images, update fiducial guesses to use targets
	if KEYWORD_SET(level1p5) then begin
		nomx = xref
		rshift = 0.
		nomy1 = yref - fidsep/sumspat
		nomy2 = yref + fidsep/sumspat
	endif 

	; Zeroth-order shifts needed to align image with lev1p5 target
	xshift = xref - nomx
	yfid = MEAN([nomy1, nomy2])
	yshift = yref - yfid
	
	; Measure the image-specific offset of the fiducials from the target positions, 
	; and write to trending databases		
	if measure_fid then fshifter = IRIS_PREP_FID_FINDER(index, data, fidmsg, $
		nomx1 = nomx-rshift, nomx2 = nomx+rshift, nomy1 = nomy1, nomy2 = nomy2, $
		logdir = logdir, loud = loud)
	if loud then PRINT, fidmsg

	; Look up from the temperature relationship how much of a shift is needed to 
	; bring the image back to target values
	shifter = IRIS_PREP_SHIFT_READER(index, nfidmsg, wmsg, nomx = nomx, nomy = yfid)
	if shift_fid then begin
		xshift = (xshift + shifter[0]) * sumsptrl
		yshift = (yshift + shifter[1]) * sumspat
		fidmsg = nfidmsg
	endif

	; Look up from the trending databases how much of a shift is needed to 
	; bring the image back to target values
	if filter_fid then begin
		if FIX(sji_wv_nm) gt 200 then chantype = 'SJIN' else chantype = 'SJIF'
		fitind = WHERE(obsfit.fid.combo_chans eq chantype) 
		fitchisqs = REFORM(obsfit.fid.combo_chisqs[fitind,*])
		fitnum = REFORM(obsfit.fid.combo_numfit[fitind,*])
		offsetindx = WHERE(STRMID(obsfit.fid.combo_tag[fitind,0,*], 0, 8) eq index.img_path $
			and obsfit.fid.combo_flag[fitind,0,*] eq 1, numoffx)
		offsetindy = WHERE(STRMID(obsfit.fid.combo_tag[fitind,1,*], 0, 8) eq index.img_path $
			and obsfit.fid.combo_flag[fitind,1,*] eq 1, numoffy)
		amplitude = REFORM(obsfit.fid.combo_paramvals[fitind,*,0])
		fitgood = fitchisqs lt fitchisq_max and fitnum gt fitnum_min and $
			  [numoffx,numoffy] gt 0 and amplitude le maxamp
		fitparams = REFORM(obsfit.fid.combo_paramvals[fitind,*,*])
		; Correct for y-axis separation of fiducials
		fitparams[1,*] = fitparams[1,*] + [0,0,0,fidsep,-fidsep,fidsep,-fidsep]
		if fitgood[0] eq 1 then begin
			; Good X fit for this OBS
			offset = MEAN(fitparams[0,3 + offsetindx])
			dt = ANYTIM2TAI(index.t_obs)
			xfit = offset + fitparams[0,0] * SIN( (fitparams[0,1] * dt) + fitparams[0,2] )
			xshift = xshift + (xref * sumsptrl - xfit)
			STRPUT, fidmsg, STRING(xshift/sumsptrl, form = '(f9.2)'), 40
		endif else begin
			xfiltfail = 1
		endelse
		if fitgood[1] eq 1 then begin
			; Good Y fit for this OBS
			offset = MEAN(fitparams[1,3 + offsetindy])
			dt = ANYTIM2TAI(index.t_obs)
			yfit = offset + fitparams[1,0] * SIN( (fitparams[1,1] * dt) + fitparams[1,2] )
			yshift = yshift + (yref * sumspat - yfit)
			STRPUT, fidmsg, STRING(yshift/sumspat, form = '(f9.2)'), 49
		endif else begin
			yfiltfail = 1
		endelse
	endif

	mag = scale / sref
	roll = roll - rref
	; Note that applying the summing to the reference coordinates may cause problems
	; when applying filter measurements taken without this correction
	result = IRIS_PREP_ROT(result, mag, roll, xref * sumsptrl, yref * sumspat, $
		xshift, yshift, cx = cx, cy = cy)

endif else begin
	;++++++++++++++++++++++++++++++++++++
	; For NUV spectra...
	;------------------------------------
	if index.img_path eq 'NUV' then begin

		; Look in pointing database for typical fiducial location/scale/roll for lev1 images
		fnomy1	= pdb.cpx2_nuv - fidsep - 1
		fnomy2	= pdb.cpx2_nuv + fidsep - 1
		fnomy	= pdb.cpx2_nuv - 1
		; Reference spectral pixel location for reference line at level 1 AND 1.5 (really 1.5)
		fnomx	= pdb.cpx1_nuv - 1
		; Reference platescale and roll are not changed for spectra
		scale	= pdb.cdlt2_nu
		roll 	= 0

		; Target fiducial location/reference wave/scale/roll for level 1.5 images
		xref	= (pdb.cpx1_nuv - 1) / sumsptrl - offsptrl
		yref	= (pdb.cpx2_1p5 - 1) / sumspat - offspat
		sref	= pdb.cdlt_1p5
		rref	= 0.

		; Which spatial pixel in the lev1 image maps to the "lev1 typical value" in the lev1.5?
		rnomy1	= params.dmapy[fnomx, fnomy1] + (fnomy1 mod 1)
		rnomy2	= params.dmapy[fnomx, fnomy2] + (fnomy2 mod 1)
		; Approximately invert that to say where pixels on the typical lev1 location will go at 1.5
		nomy1 = 2 * fnomy1 - rnomy1
		nomy2 = 2 * fnomy2 - rnomy2
		; If the fiducials are typical at lev1, where will they go at lev1.5 
		; if we don't apply a shift? (0-order offset)
		yfid = MEAN([nomy1, nomy2])/sumspat - offspat
		yshift0 = yref - yfid
		
		; Which spectral pixel in the lev1 image maps to the target at lev1.5? 
		; (Could be thought of as the REAL lev1 target; this is used as the reference
		; for the time-dependent wavelength correction)
		nomx	= params.dmapx[fnomx, fnomy] + (fnomx mod 1)
		; Pixel offset between the bright line used for fiducial finding (Mg II)
		; and the reference line used for wavelength calibration (Ni I)
		woff	= (659.3 - 535.)
		; Which spectral pixel in the lev1 image has a bright line for fiducial finding?
		nomx1	= params.dmapx[fnomx-woff, fnomy1] + (fnomx mod 1)
		nomx2	= params.dmapx[fnomx-woff, fnomy2] + (fnomx mod 1)

		; If operating on lev1.5 images, update fiducial guesses to use targets
		if KEYWORD_SET(level1p5) then begin
			fnomy1 = pdb.cpx2_1p5 - 1 - fidsep
			fnomy2 = pdb.cpx2_1p5 - 1 + fidsep
			nomx1  = fnomx - woff
			nomx2  = fnomx - woff
		endif 
	
		; Measure the offset of the fiducial and reference line from the target
		; positions, and write to trending databases		
		if measure_fid then fshifter = IRIS_PREP_FID_FINDER(index, data, fidmsg, $
			nomx1 = nomx1/sumsptrl, nomx2 = nomx2/sumsptrl, $
			nomy1 = fnomy1/sumspat, nomy2 = fnomy2/sumspat, $
			logdir = logdir, loud = loud)
		if measure_wave then wshift_str = IRIS_PREP_WAVECORR(index, data, $
			wmsg, logdir = logdir, angstroms_per_pixel = pdb.cdlt1_nu*sumsptrl)
		if loud then PRINT, fidmsg, wmsg
		
		; Look up from the temperature relationship how much of a shift is needed to 
		; bring the image back to target values
		shifter = IRIS_PREP_SHIFT_READER(index, fidmsg_out, wmsg_out, $
;			nomx = nomx / index.sumsptrl, nomy = yfid)
			nomx = nomx / sumsptrl, nomy = fnomy / sumspat)
		if shift_fid then begin
			yshift = shifter[1]
			fidmsg = fidmsg_out
		endif else begin
			yshift = 0.
		endelse
		if shift_wave then begin
			xshift = shifter[0] * sumsptrl
			wmsg = wmsg_out
		endif else begin
			xshift = 0.
		endelse
		yshift = (yshift + yshift0) * sumspat
	
		; Look up from the trending databases how much of a shift is needed to 
		; bring the image fiducials back to target values
		if filter_fid then begin
			fitind = WHERE(obsfit.fid.combo_chans eq 'NUV') 
			fitchisqs = REFORM(obsfit.fid.combo_chisqs[fitind,1])
			fitnum = REFORM(obsfit.fid.combo_numfit[fitind,1])
			offsetind = WHERE(obsfit.fid.combo_flag[fitind,1,*] eq 1, numoff)
			amplitude = obsfit.fid.combo_paramvals[fitind,1,0]
			fitgood = fitchisqs lt fitchisq_max and fitnum gt fitnum_min and $
				numoff gt 0 and amplitude le maxamp
			fitparams = REFORM(obsfit.fid.combo_paramvals[fitind,1,*])
			; Correct for y-axis separation of fiducials
			fitparams = fitparams + [0,0,0,fidsep,-fidsep,fidsep,-fidsep]
			if fitgood eq 1 then begin
				; Good fid fit for this OBS
				offset = MEAN(fitparams[3 + offsetind])
				dt = ANYTIM2TAI(index.t_obs)
				yfit = offset + fitparams[0] * SIN( (fitparams[1] * dt) + fitparams[2] )
				yshift = yshift + (yref * sumspat - yfit)
				yshift_pix = (yshift - yshift0 * sumspat) / sumspat
				STRPUT, fidmsg, STRING(yshift_pix, form = '(f9.2)'), 40
			endif else begin
				xfiltfail = 1
			endelse
		endif
		; Look up from the trending databases how much of a shift is needed to 
		; bring the wavelength back to target values
		if filter_wave then begin
			fitind = WHERE(obsfit.wave.combo_chans eq 'NUV') 
			fitchisqs = REFORM(obsfit.wave.combo_chisqs[fitind])
			fitnum = REFORM(obsfit.wave.combo_numfit[fitind])
			offsetind = WHERE(obsfit.wave.combo_flag[fitind,*] eq 1 and $
				obsfit.wave.combo_paramvals[fitind,3:*] ne 100, numoff)	;	 second part should be redundant but isn't...
			amplitude = obsfit.wave.combo_paramvals[fitind,0]
			fitgood = fitchisqs lt fitchisq_max and fitnum gt fitnum_min and $
				numoff gt 0 and amplitude le maxamp
			fitparams = REFORM(obsfit.wave.combo_paramvals[fitind,*])
			if fitgood eq 1 then begin
				; Good wave fit for this OBS
				offset = MEAN(fitparams[3 + offsetind])
				dt = ANYTIM2TAI(index.t_obs)
				xfit = offset + fitparams[0] * SIN( (fitparams[1] * dt) + fitparams[2] )
				xshift = xshift + (xref * sumsptrl - xfit)
				STRPUT, wmsg, STRING(xshift/sumsptrl, form = '(f9.2)'), 40
			endif else begin
				xfiltfail = 1
			endelse
		endif
	
		;mag = sref / scale
		mag = 1.
		result = IRIS_PREP_ROT(result, mag, roll, xref * sumsptrl, yref * sumspat, xshift, yshift)

	endif else begin
	;++++++++++++++++++++++++++++++++++++
	; For FUV spectra...
	;------------------------------------
	
		; Look in pointing database for typical fiducial location/scale/roll for lev1 images
		fnomy1_s	= pdb.cpx2_fu1 - 1 - fidsep
		fnomy2_s	= pdb.cpx2_fu1 - 1 + fidsep
		fnomy_s		= pdb.cpx2_fu1 - 1
		fnomy1_l	= pdb.cpx2_fu2 - 1 - fidsep
		fnomy2_l	= pdb.cpx2_fu2 - 1 + fidsep
		fnomy_l		= pdb.cpx2_fu2 - 1
		; Reference spectral pixel location for reference line at level 1 AND 1.5 (really 1.5)
		fnomx_s	= pdb.cpx1_fu1 - 1
		xls = 2072.
		fnomx_l	= pdb.cpx1_fu2 - 1 - xls
		; Reference platescale and roll are not changed for spectra
		scale_s = pdb.cdlt2_f1
		scale_l = pdb.cdlt2_f2
		scale = MEAN([scale_s, scale_l])
		roll = 0

		; Target fiducial location/reference wave/scale/roll for level 1.5 images
		xref_s 	= (pdb.cpx1_fu1 - 1) / sumsptrl - offsptrl
		xref_l	= (pdb.cpx1_fu2 - 1) / sumsptrl - offsptrl
		xref	= [xref_s, xref_l]
		yref	= (pdb.cpx2_1p5 - 1) / sumspat - offspat
		yref	= [yref, yref]
		sref	= pdb.cdlt_1p5

		; Which spatial pixel in the lev1 image maps to the "lev1 typical value" in the lev1.5?
		rnomy1_s	= params.fuvs.dmapy[fnomx_s, fnomy1_s] + (fnomy1_s mod 1)
		rnomy2_s	= params.fuvs.dmapy[fnomx_s, fnomy2_s] + (fnomy2_s mod 1)
		rnomy1_l	= params.fuvl.dmapy[fnomx_l, fnomy1_l] + (fnomy1_l mod 1)
		rnomy2_l	= params.fuvl.dmapy[fnomx_l, fnomy2_l] + (fnomy2_l mod 1)
		; Approximately invert that to say where pixels on the typical lev1 location will go at 1.5
		nomy1_s = 2 * fnomy1_s - rnomy1_s
		nomy2_s = 2 * fnomy2_s - rnomy2_s
		nomy1_l = 2 * fnomy1_l - rnomy1_l
		nomy2_l = 2 * fnomy2_l - rnomy2_l
		; If the fiducials are typical at lev1, where will they go at lev1.5 
		; if we don't apply a shift? (0-order offset)
		yfid_s = MEAN([nomy1_s, nomy2_s]) / sumspat - offspat
		yshift0_s = yref[0] - yfid_s
		yfid_l = MEAN([nomy1_l, nomy2_l]) / sumspat - offspat
		yshift0_l = yref[1] - yfid_l

		; Which spectral pixel in the lev1 image maps to the target at lev1.5? 
		; (Could be thought of as the REAL lev1 target; this is used as the reference
		; for the time-dependent wavelength correction)
		nomx_s	= params.fuvs.dmapx[fnomx_s, fnomy_s] + (fnomx_s mod 1)
		nomx_l	= params.fuvl.dmapx[fnomx_l, fnomy_l] + (fnomx_l mod 1)
		; Pixel offset between the bright line used for fiducial finding (C II / Si IV) 
		; and the reference line used for wavelength calibration (O I / Si IV)
		woff_s	= (1840.93 - 219.5)
;		woff_l	= (3100.00 - 3807.3)	; (Just changing from one Si IV line to another)
		woff_l 	= 0.
		; Which spectral pixel in the lev1 image has a bright line for fiducial finding?
		nomx1_s	= params.fuvs.dmapx[fnomx_s-woff_s, fnomy1_s] + (fnomx_s mod 1)
		nomx2_s	= params.fuvs.dmapx[fnomx_s-woff_s, fnomy2_s] + (fnomx_s mod 1)
		nomx1_l	= params.fuvl.dmapx[fnomx_l-woff_l, fnomy1_l] + (fnomx_l mod 1)
		nomx2_l	= params.fuvl.dmapx[fnomx_l-woff_l, fnomy2_l] + (fnomx_l mod 1)
	
		; If operating on lev1.5 images, update fiducial guesses to use targets
		if KEYWORD_SET(level1p5) then begin
			fnomy1_s = pdb.cpx2_1p5 - 1 - fidsep
			fnomy2_s = pdb.cpx2_1p5 - 1 + fidsep
			fnomy1_l = pdb.cpx2_1p5 - 1 - fidsep
			fnomy2_l = pdb.cpx2_1p5 - 1 + fidsep
			nomx1_s  = fnomx_s - woff_s
			nomx2_s  = fnomx_s - woff_s
			nomx1_l  = fnomx_l - woff_l
			nomx2_l  = fnomx_l - woff_l
		endif 

		; Measure the offset of the fiducial and reference line from the target
		; positions, and write to trending databases		
		if measure_fid then begin
			fshifter_s = IRIS_PREP_FID_FINDER(/fuvs, index, data, fidmsg_s, logdir = logdir, $
				nomx1 = nomx1_s/sumsptrl, nomx2 = nomx2_s/sumsptrl, $
				nomy1 = fnomy1_s/sumspat, nomy2 = fnomy2_s/sumspat, loud = loud)
			if (loud gt 0) then loud = 2
			fshifter_l = IRIS_PREP_FID_FINDER(/fuvl, index, data, fidmsg_l, logdir = logdir, $
				nomx1 = (nomx1_l+xls)/sumsptrl, nomx2 = (nomx2_l+xls)/sumsptrl, $
				nomy1 = fnomy1_l/sumspat, nomy2 = fnomy2_l/sumspat, loud = loud)
			fidmsg = [fidmsg_s, fidmsg_l]
			if (loud gt 0) then loud = 1
		endif
		if measure_wave then begin
			wshift_s = IRIS_PREP_WAVECORR(index, data, wmsg_s, logdir = logdir, $
				angstroms_per_pixel = pdb.cdlt1_f1/sumsptrl, /fuvs)
			wshift_l = IRIS_PREP_WAVECORR(index, data, wmsg_l, logdir = logdir, $
				angstroms_per_pixel = pdb.cdlt1_f2/sumsptrl, /fuvl)
			wmsg = [wmsg_s, wmsg_l]
		endif
		if loud then PRINT, fidmsg, wmsg

		; Look up from the temperature relationship how much of a shift is needed to 
		; bring the image back to target values
		shifter = IRIS_PREP_SHIFT_READER(index, fidmsg_out, wmsg_out, $
;			nomx = nomx_s / index.sumsptrl, nomy = [yfid_s, yfid_l])
			nomx = nomx_s / sumsptrl, nomy = [fnomy_s, fnomy_l] / sumspat)
		if shift_fid then begin
			yshift = shifter[1,*]
			fidmsg = fidmsg_out
		endif else begin
			yshift = [0., 0.]
		endelse
		if shift_wave then begin
			xshift = shifter[0,*] * sumsptrl
			wmsg = wmsg_out
		endif else begin
			xshift = [0., 0.]
		endelse
		yshift = (yshift + [yshift0_s, yshift0_l]) * sumspat
				
		; Look up from the trending databases how much of a shift is needed to 
		; bring the image fiducials back to target values
		if filter_fid then begin
			fitind = WHERE(obsfit.fid.combo_chans eq 'FUV') 
			fitchisqs = REFORM(obsfit.fid.combo_chisqs[fitind,1])
			fitnum = REFORM(obsfit.fid.combo_numfit[fitind,1])
			offsetind = WHERE(obsfit.fid.combo_flag[fitind,1,*] eq 1, numoff)
			amplitude = obsfit.fid.combo_paramvals[fitind,1,0]
			fitgood = fitchisqs lt fitchisq_max and fitnum gt fitnum_min and $
				numoff gt 0 and amplitude le maxamp
			fitparams = REFORM(obsfit.fid.combo_paramvals[fitind,1,*])
			; Correct for y-axis separation of fiducials
			fitparams = fitparams + [0,0,0,fidsep,-fidsep,fidsep,-fidsep]
			if fitgood eq 1 then begin
				; Good fid fit for this OBS
				offset = MEAN(fitparams[3 + offsetind])
				dt = ANYTIM2TAI(index.t_obs)
				yfit = offset + fitparams[0] * SIN( (fitparams[1] * dt) + fitparams[2] )
				yshift = yshift + (yref * sumspat - yfit)
				fidmsg_s = fidmsg[0]
				fidmsg_l = fidmsg[1]
				STRPUT, fidmsg_s, STRING(yshift[0]/sumspat, form = '(f9.2)'), 40
				STRPUT, fidmsg_l, STRING(yshift[1]/sumspat, form = '(f9.2)'), 40
				fidmsg = [fidmsg_s, fidmsg_l]
			endif else begin
				yfiltfail = 1
			endelse
		endif
		; Look up from the trending databases how much of a shift is needed to 
		; bring the wavelength back to target values
		if filter_wave then begin
			fitind = WHERE(obsfit.wave.combo_chans eq 'FUV') 
			fitchisqs = REFORM(obsfit.wave.combo_chisqs[fitind])
			fitnum = REFORM(obsfit.wave.combo_numfit[fitind])
			offsetind = WHERE(obsfit.wave.combo_flag[fitind,0:2] eq 1, numoff)
			amplitude = obsfit.wave.combo_paramvals[fitind,0]
			fitgood = fitchisqs lt fitchisq_max and fitnum gt fitnum_min and $
				numoff gt 0 and amplitude le maxamp
			fitparams = REFORM(obsfit.wave.combo_paramvals[fitind,*])
			if fitgood eq 1 then begin
				; Good wave fit for this OBS
				offset = MEAN(fitparams[3 + offsetind])
				dt = ANYTIM2TAI(index.t_obs)
				xfit = offset + fitparams[0] * SIN( (fitparams[1] * dt) + fitparams[2] )
				xshift = xshift + (xref[0] * sumsptrl - xfit)
				wmsg = wmsg[0]
				STRPUT, wmsg, STRING(xshift[0]/sumsptrl, form = '(f9.2)'), 40
				wmsg = [wmsg, wmsg]
			endif else begin
				xfiltfail = 1
			endelse
		endif

		;mag = sref / scale
		mag = 1.
		result = IRIS_PREP_ROT(result, mag, roll, xref * sumsptrl, yref * sumspat, xshift, yshift)
		
	endelse
endelse

RETURN, result

end
