function IRIS_FID_FINDER, index, data, display=display, startval=startval

;+
;
; NAME:   iris_fid_finder.pro
;       
; PURPOSE:  Pipeline version to find the pixel locations of the IRIS fiducial 
;			markers in both SJI and spectra
;
; CATEGORY: Image Calibration
;
; CALLING SEQUENCE: values = iris_fid_finder(index, data)
;
; INPUT ARGUMENTS:  
;       index = Single or array of header structure(s) of image(s) to pass in
;	data = Single or array of image data to pass in
;
; INPUT KEYWORD PARAMETER:
;	/display = Set to make some plots and images showing the results
;	startval = Array specifying the pixel positions to start the
;				slices and calcualtions with. The format should be as follows: 
;				[X1, Y1, X2, Y2].
;
; OUTPUTS: Variable that contains the following information in a structure:
;       T_obs = The time of the observation
;       FSN = The file serial number
;       Type = What SJI or spectra is being processed
;       X1 = The determined X1 value
;       Y1 = The determined Y1 value
;       X2 = The determined X2 value
;       Y2 = The determined Y2 value
;       CHISQ_X1 = The goodness of fit from the X1 slice
;       CHISQ_Y1 = The goodness of fit from the Y1 slice
;       CHISQ_X2 = The goodness of fit from the X2 slice
;       CHISQ_Y2 = The goodness of fit from the Y2 slice
;       Dist = The calcualted distance between the fiducials
;       Ang = The calculated angle 
;
; PROGRAM NOTES: 
;	When measured values are considered bad (the goodness of fit values are large)
;	the value is thrown out by setting it to 0. Keep this in mind when using the 
;	output data.
;
; OTHER PROGRAMS NEEDED:
; 	fid_fitter - Used to fit slices taken to get sub-pixel values for locations
;
; MODIFICATION HISTORY:
;	2013/09/06 Written by Sean McKillop (smckillop@cfa.harvard.edu)
;	2013/10/03 Updated by Paul Boerner
;       2017/08/03 forcing xmin ge 0 to prevent this routine from crashing the pipeline
;
;-

if N_ELEMENTS(index) gt 1 then begin
	for i = 0, N_ELEMENTS(index) - 1 do begin
		this_result = IRIS_FID_FINDER(index[i], data[*,*,i], startval=startval)
		if i eq 0 then result = this_result else result = [[result], [this_result]]
	endfor
	RETURN, result
endif

if KEYWORD_SET(display) then begin
	fidname = ['Bottom', 'Top']
	TVLCT, rr, gg, bb, /get
	LOADCT, 0, /silent
	oldpmulti = !p.multi
	!p.multi = [0,3,2]
	WDEF, display, 1200, 900
endif

type = index.IMG_PATH
spect = STRMID(type, 0, 3) ne 'SJI'
if type eq 'FUV' then begin
	nterms = 4
	pmax = 50
endif else begin
	nterms = 5
	pmax = 200
endelse

x1 = startval[0]
y1 = startval[1]
x2 = startval[2]
y2 = startval[3]
endval = FLTARR(4)
allchisq = FLTARR(4) + 100
 
if spect eq 0 then begin
	;++++++++++++++++++++++++++++++++++++++++++
	;		SJI Fiducials
	;------------------------------------------
	if not KEYWORD_SET(ywidth) then ywidth = 5
	if not KEYWORD_SET(xwidth) then xwidth = 7
	if not KEYWORD_SET(yrange) then yrange = 6	;	How many pixels high the slit-finder should be
	if not KEYWORD_SET(yoff) then yoff = 2		;	How many pixels away from the nominal fiducial
	xsummer = [0.]
;	chisqlim = 500.
	chisqlim = 1.e10
	if STRMID(type, 0, 5) eq 'SJI_2' then pmax = 500
endif else begin
	;++++++++++++++++++++++++++++++++++++++++++
	;		Spectral Fiducials
	;------------------------------------------
	if not KEYWORD_SET(ywidth) then ywidth = 6
	if not KEYWORD_SET(xwidth) then xwidth = 15
	if not KEYWORD_SET(yrange) then yrange = 10	;	How many pixels high the slit-finder should be
	if not KEYWORD_SET(yoff) then yoff = -2		;	How many pixels away from the nominal fiducial
	xsummer = FINDGEN(9) - 4.
;	chisqlim = 10000.
	chisqlim = 1.e10
endelse

; Loop through top and bottom fiducials
for i = 0, 1 do begin
	; Select a box around the expected fiducial and check to make sure the data are good
	thisx = startval[i*2]
	thisy = startval[i*2+1]
	totdata = data[thisx-xwidth:thisx+xwidth,thisy+yoff:thisy+yoff+yrange]
	nans = WHERE(FINITE(totdata) eq 0, numnan)
	if numnan ne 0 then goto, skiploop			;	Good data around this fiducial
	
	; Just look for the min/max value as a rough estimate of the slit/line location
	rough_slitprof = TOTAL(totdata, 2)
	if spect then rough_slitprof = 0 - rough_slitprof	;	Sign reversed for spectra
	slitoff = WHERE(rough_slitprof eq MIN(rough_slitprof)) - xwidth
	xmin = thisx - xwidth + slitoff[0]
        xmin = xmin > 0 ; to keep next line from crashing the pipeline (JPW 20170803)
	totdata = data[xmin:xmin + 2*xwidth, thisy+yoff:thisy+yoff+yrange]
	nans = WHERE(FINITE(totdata) eq 0, numnan)
	if numnan ne 0 then goto, skiploop
	; Pass the profile (re-centered on the slit/line) to the Gaussian fitter
	fine_slitprof = TOTAL(totdata, 2)
	fine_slitxax = xmin + INDGEN(2*xwidth + 1)
	xvalues = IRIS_FID_FITTER(fine_slitxax, fine_slitprof, xmin, $
		xval=(1-spect), yval = spect, nterms = nterms)
	if (xvalues.chisq le chisqlim) and ((xvalues.coeff[1] - thisx) le (2*xwidth)) then begin
		; Found a good X slit location; save it, and look for the Y location of the fiducial
		endval[i*2] = xvalues.coeff[1]
		allchisq[i*2] = xvalues.chisq
		rough_fidprof = TOTAL(data[endval[i*2]+xsummer, thisy-ywidth : thisy+ywidth], 1)
		if spect then rough_fidprof = 0 - rough_fidprof	;	Sign reversed for spectra
		fidoff = WHERE(rough_fidprof eq MAX(rough_fidprof)) - ywidth
		ymin = thisy - ywidth + fidoff[0]
		fine_fidprof = TOTAL(data[endval[i*2]+xsummer, ymin:ymin+2*ywidth], 1)
		nans = WHERE(FINITE(fine_fidprof) eq 0, numnan)
		if numnan ne 0 then goto, skiploop
		fine_fidyax = ymin + INDGEN(2*ywidth + 1)
		yvalues = IRIS_FID_FITTER(fine_fidyax, fine_fidprof, ymin, $
			yval=(1-spect), xval = spect)
		if (yvalues.chisq le chisqlim) and (yvalues.coeff[1] - thisy le (2*ywidth)) then begin
			endval[i*2+1] = yvalues.coeff[1]
			allchisq[i*2+1] = yvalues.chisq
		endif
		if KEYWORD_SET(display) and endval[i*2] gt 0 then begin
			xtitle = 'X-Direction Slice of ' + fidname[i] + ' Fiducial at Y= ' $
				+ STRTRIM(thisy+yoff+yrange/2, 2)
			PLOT, fine_slitxax, fine_slitprof, xtitle='X-Pixel Positions', $
				ytitle='Intensity', title=xtitle, chars = 1.5, $
				yrange=LIMITS(fine_slitprof) + [-100, 100], /xstyle, /ystyle
			OPLOT, fine_slitxax, xvalues.yfit, color = FSC_COLOR('red')
			ytitle = 'Y-Direction Slice of ' + fidname[i] + ' Fiducial at X= ' $
				+ STRTRIM(endval[i*2], 2)
			PLOT, fine_fidyax, fine_fidprof, xtitle='Y-Pixel Positions', $
				ytitle='Intensity', title=ytitle, chars = 1.5, $
				yrange=LIMITS(fine_fidprof) + [-100, 100], /xstyle, /ystyle
			OPLOT, fine_fidyax, yvalues.yfit, color = FSC_COLOR('red')
			PLOT, INDGEN(61) - 30 + thisx, INDGEN(61) - 30 + thisy, /xstyle, /ystyle, $
				yrange = thisy+[-30,30], title = fidname[i] + ' Fiducial', chars = 1.5
			corners = CONVERT_COORD([thisx-30,thisx+30], [thisy-30,thisy+30], /data, /to_dev)
			xsize = corners[0,1] - corners[0,0]
			ysize = corners[1,1] - corners[1,0]
			TV, BYTSCL(CONGRID(data[thisx-30:thisx+30,thisy-30:thisy+30], xsize, ysize), $
				min = 0, max = pmax), corners[0,0], corners[1,0], /dev
			PLOTS, endval[i*2]+[0,0], thisy+[-30,30], color = FSC_COLOR('red'), /data
			PLOTS, thisx+[-30,30], endval[i*2+1]+[0,0], color = FSC_COLOR('red'), /data
		endif
	endif
	skiploop: 
endfor

if KEYWORD_SET(display) then begin
	TVLCT, rr, gg, bb
	!P.Multi = oldpmulti
endif

; Return the x1, x2, y1, y2, all chisq, distance and angle values
; determined in a structure format.
if MIN(endval) gt 0 then begin
	fiddist = SQRT( (endval[2]-endval[0])^2 + (endval[3]-endval[1])^2 )
	ang = ATAN(endval[3]-endval[1], endval[2]-endval[0]) * !radeg
endif else begin
	fiddist = 0.
	ang = 0.
endelse

values = {t_obs:index.t_obs, fsn:index.fsn, type:type, sumspat:index.sumspat, $
	x1:endval[0], y1:endval[1], x2:endval[2], y2:endval[3], chisq_x1:allchisq[0], $
	chisq_y1:allchisq[1], chisq_x2:allchisq[2], chisq_y2:allchisq[3], $
	dist:fiddist, ang:ang, sumsptrl:index.sumsptrl, exptime:index.exptime}

RETURN, values

end
