;+
;NAME:
;	eis_fitwrap.pro
;PURPOSE:
;	Wrapper containing the block of code that makes and adjusts
;	a multiple Gaussian fit to an EIS data window structure.
;
;INPUTS:
;	windata (struct) == EIS data window created by eis_getwindata.pro ; a rebinned windata will be outputted
;KEYWORDS:
;	offset (fltarr) == array of wavelength offsets ; usually an input, but will be an output if orbit_corr is set
;	bin_xy (int/intarr) == set to perform a spatial binning ; use integer to bin the same in X&Y, or 2D array [X,Y]
;	orbit_corr (/ or flt) == set to perform a wavelength correction for orbit variation using eis_update_fitdata.pro
;		(flt) == set as a wavelength to pass that value (as keyword wvl) to eis_fit_template.pro
;	template (struct or str) == structure or text file created by eis_fit_template/eis_write_template
;	wvl_select (struct or str) == structure or text file created by eis_wvl_select/eis_write_wvl_select
;	no_ui (/) == set to skip all user interface -- i.e. no read input statements and no GUI
;	window_new (int) == window index to use when doing the orbit correction
;OUTPUTS:
;	fitdata (struct) == the Gaussian fit structure created by eis_auto_fit.pro
;OPTIONAL OUTPUT KEYWORDS:
;	line_main (int) == data window's main reference line, set by the user
;	val (flt) == value set by the user when exiting
;
;EXAMPLES:
;IDL> fitdata = eis_fitwrap(windata, bin_xy=2)
;IDL> fitdata = eis_fitwrap(windata, offset=offset_in, line=line, template='fe12_template.txt')
;IDL> fitdata_orbit = eis_fitwrap(windata, offset=offset_orbit, w=4, /orbit)
;
;CONTACT:
;	Gary Kilper (GSFC/ORAU; garyk1@gmail.com)
;	Apr 14, 2011: Initial public version
;-

function eis_fitwrap, windata, offset=offset, bin_xy=bin_xy, orbit_corr=orbit_corr, $
				template=template, wvl_select=wvl_select, no_ui=no_ui, window_new=window_new, $
				line_main=line_main, val=val


;check inputs
if ~tag_exist(windata, 'hdr') then begin
	print, '% EIS_FITWRAP: Error: Input must be an EIS data window from eis_getwindata.pro.'
	return, 0
endif else if windata.hdr.slit_id NE '1"' and windata.hdr.slit_id NE '2"' then begin
	print, '% EIS_FITWRAP: Error: Fitting can only be done on EIS slit data.'
	return, 0
endif


;set initial parameters
windata0 = windata
if keyword_set(offset) then offset1 = offset else offset1 = windata.wave_corr
if n_elements(bin_xy) EQ 1 then begin
	xbin = bin_xy
	ybin = bin_xy
endif else if n_elements(bin_xy) EQ 2 then begin
	xbin = bin_xy(0)
	ybin = bin_xy(1)
endif
if keyword_set(template) then begin
	if size(template, /type) EQ 7 then begin
		if file_test(template, /read) then template0 = eis_read_template(template) $
		else print, '% EIS_FITWRAP: Warning: template file cannot be read: ', template
	endif else if size(template, /type) EQ 8 then template0 = template
endif
if keyword_set(wvl_select) then begin
	if size(wvl_select, /type) EQ 7 then begin
		if file_test(wvl_select, /read) then eis_read_wvl_select, wvl_select, wvl_select0 $
		else print, '% EIS_FITWRAP: Warning: wvl_select file cannot be read: ', wvl_select
	endif else if size(wvl_select, /type) EQ 8 then wvl_select0 = wvl_select
endif
if keyword_set(orbit_corr) then begin
	if orbit_corr GT 100. then wvl = orbit_corr
	no_ui = 0		;must have user interface for orbit correction
	xbin = 0		;shouldn't bin X when doing orbit correction
	y0 = 0		;set as an integer
	y1 = 1		;set as an integer
endif
line_main = 0		;set as an integer


;rebin raster, select fit template and wavelengths
repeat begin
	if keyword_set(xbin) or keyword_set(ybin) then begin
		if keyword_set(offset) then offset1 = offset else offset1 = windata.wave_corr
		if xbin GT 1 and ybin GT 1 then $
			windata = eis_bin_windata(windata0, xbin=xbin, ybin=ybin, offset=offset1) $
		else if xbin GT 1 then $
			windata = eis_bin_windata(windata0, xbin=xbin, offset=offset1) $
		else if ybin GT 1 then $
			windata = eis_bin_windata(windata0, ybin=ybin, offset=offset1)
	endif

	;if desired, skip user interface
	if keyword_set(no_ui) then begin
		if keyword_set(template0) then template1 = template0
		if keyword_set(wvl_select0) then wvl_select1 = wvl_select0
		break
	endif

	SET_TEMPLATE:
	if ~keyword_set(template0) or line_main EQ -2 then begin
		print, 'Set spectral lines for the fitting template.' 
		eis_fit_template, windata, template1, offset=offset1, wvl=wvl
	endif else template1 = template0
	if size(template1, /type) NE 8 then begin
		print, '% EIS_FITWRAP: Error: At least one line must be included.'
		goto, SET_TEMPLATE
	endif
	for n=0, template1.ngauss-1 do print, 'Line:', n, template1.lines(n).centroid, template1.lines(n).peak
	line_range = '0-' + strtrim(template1.ngauss - 1, 2)
	if ~keyword_set(wvl_select0) or line_main EQ -2 then begin
		print, 'De-select any wavelengths to be excluded from the fit.'
		eis_wvl_select, windata, wvl_select1, offset=offset1
	endif else wvl_select1 = wvl_select0

	read, line_main, prompt='Enter index for main spectral line ('+line_range+'; use -1 to rebin, -2 to redo template): '
	if line_main EQ -1 then begin
		read, xbin, prompt='Enter pixel bin size for X direction (1 = no rebinning): '
		read, ybin, prompt='Enter pixel bin size for Y direction (1 = no rebinning): '
	endif
endrep until line_main GE 0


;attempt to fit Gaussians to each position in the raster
eis_auto_fit, windata, fitdata, offset=offset1, wvl_select=wvl_select1, template=template1
if keyword_set(no_ui) then return, fitdata


;set parameters for orbit correction
if keyword_set(orbit_corr) then begin
	print, 'Determine y-range for a quiet Sun region.'
	eis_fit_viewer, windata, fitdata
	print, 'Enter y-range for orbit correction.'
	read, y0, prompt='Enter value for y0 (0-'+strtrim(fitdata.ny-2,2)+'): '
	read, y1, prompt='Enter value for y1 ('+strtrim(y0+1,2)+'-'+strtrim(fitdata.ny-1,2)+'): '
	if keyword_set(window_new) then window, abs(window_new), xsize=500, ysize=500 $
	else window, /free, xsize=500, ysize=500
endif


;view the fit, and allow user to adjust fit parameters
repeat begin
	if keyword_set(orbit_corr) then $			;do orbit correction
		fitdata = eis_update_fitdata(fitdata, line=line_main, yrange=[y0,y1], $
				offset=offset_orbit, fit_error=fit_error, refpix=refpix)
	eis_fit_viewer, windata, fitdata

	print, '% EIS_FITWRAP: Current main/reference spectral line index:', line_main
	if keyword_set(orbit_corr) then begin
		print, '% EIS_FITWRAP: Current y-range for orbit correction update:', y0, y1
		read, val, prompt='Enter value >= 0 to continue (use -1 to switch lines, -2 to redo fit, -3 to reset y-range): '
	endif else read, val, prompt='Enter value >= 0 to continue (use -1 to switch reference lines, -2 to redo fit): '

	if val EQ -1 then $
		read, line_main, prompt='Re-enter index for main spectral line (0-'+strtrim(fitdata.ngauss-1,2)+'): ' $
	else if val EQ -2 then goto, SET_TEMPLATE $
	else if val EQ -3 then begin
		read, y0, prompt='Enter new value for y0 (0-'+strtrim(fitdata.ny-2,2)+'): '
		read, y1, prompt='Enter new value for y1 ('+strtrim(y0+1,2)+'-'+strtrim(fitdata.ny-1,2)+'): '
	endif
endrep until val GE 0


;save parameters from orbit correction
if keyword_set(orbit_corr) then begin
	wdelete, !d.window
	fitdata = create_struct(fitdata, 'fit_error', fit_error, 'refpix', refpix)
	offset = offset_orbit
endif


return, fitdata
end
