;$Id: create_gauss_res_fun.pro,v 1.5 2006/07/26 15:05:33 azuah Exp $
;###############################################################################
;
; NAME:
;  CREATE_GAUSS_RES_FUN
;
; PURPOSE:
;  UI for creation of gaussian resolution function.
;
; CATEGORY:
;  DAVE, Data Analysis, RAINS, surface fitting
;
; AUTHOR:
;   Robert M. Dimeo, Ph.D.
;   NIST Center for Neutron Research
;   100 Bureau Drive
;   Gaithersburg, MD 20899
;   Phone: (301) 975-8135
;   E-mail: robert.dimeo@nist.gov
;   http://www.ncnr.nist.gov/staff/dimeo
;
; LICENSE:
;  The software in this file is written by an employee of
;  National Institute of Standards and Technology
;  as part of the DAVE software project.
;
;  The DAVE software package is not subject to copyright protection
;  and is in the public domain. It should be considered as an
;  experimental neutron scattering data reduction, visualization, and
;  analysis system. As such, the authors assume no responsibility
;  whatsoever for its use, and make no guarantees, expressed or
;  implied, about its quality, reliability, or any other
;  characteristic. The use of certain trade names or commercial
;  products does not imply any endorsement of a particular product,
;  nor does it imply that the named product is necessarily the best
;  product for the stated purpose. We would appreciate acknowledgment
;  if the DAVE software is used of if the code in this file is
;  included in another product.
;
;###############################################################################
;+
; NAME:
;       CREATE_GAUSS_RES_FUN
;
; PURPOSE:
;
;		This function creates a Gaussian resolution function based
;		on the input data (a required parameter of an object of the
;		class MODEL_DATA.
;
; AUTHOR:
;
;       Robert M. Dimeo, Ph.D.
;		NIST Center for Neutron Research
;       100 Bureau Drive
;		Gaithersburg, MD 20899
;       Phone: (301) 975-8135
;       E-mail: robert.dimeo@nist.gov
;       http://www.ncnr.nist.gov/staff/dimeo
;
; CATEGORY:
;
;       Utility, DAVE_REFINE application, DAVE project
;
; CALLING SEQUENCE:
;
;
; INPUT PARAMETERS (REQUIRED)
;
;		ODATA:		object of class MODEL_DATA
;
; COMMON BLOCKS:
;
;		None
;
; DEPENDENCIES:
;
;		TVIMAGE
;
; REQUIREMENTS:
;
;	Written using IDL 5.6.  I cannot ensure that it will work with previous
;	releases.
;
; MODIFICATION HISTORY:
;
;       Written by Rob Dimeo, April 14, 2003
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
function cgrf_gaussian,x,y,area,center,fwhm
sig = (fwhm/2.354)
ny = n_elements(y) & uy = 1+bytarr(ny)
gauss = (area/sqrt(2.0*!dpi*sig^2))*exp(-0.5*((x#uy-center)/sig)^2)
return,gauss
end
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
pro cgrf_display_plot,event
widget_control,event.top,get_uvalue = pstate
slider_id = widget_info(event.top,find_by_uname = 'GROUP_SLIDER')
widget_control,slider_id,get_value = val & val = val[0]
xval = (*(*pstate).xPtr)
zval = (*(*pstate).zPtr)[*,val]

plot,xval,zval,psym = 4,/xsty,/ysty
end
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
pro cgrf_refresh_plot,event
widget_control,event.top,get_uvalue = pstate
wset,(*pstate).plot_pix
cgrf_display_plot,event
wset,(*pstate).plot_vis
device,copy = [0,0,!d.x_size,!d.y_size,0,0,(*pstate).plot_pix]
end
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
pro cgrf_display_image,event
widget_control,event.top,get_uvalue = pstate
pos = [0.15,0.15,0.9,0.9]

xval = (*(*pstate).xPtr)
yval = (*(*pstate).yPtr)
zval = (*(*pstate).zPtr)

erase
tvimage,bytscl(zval),position = pos
xrange = [min(xval),max(xval)]
yrange = [min(yval),max(yval)]
print,'image:xrange=',xrange
print,'image:yrange=',yrange
plot,xval,yval,xrange = xrange,yrange = yrange,/nodata,/noerase, $
     position = pos,/xsty,/ysty
end
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
pro cgrf_refresh_image,event
widget_control,event.top,get_uvalue = pstate

wset,(*pstate).im_pix
cgrf_display_image,event
wset,(*pstate).im_vis
device,copy = [0,0,!d.x_size,!d.y_size,0,0,(*pstate).im_pix]
end
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
pro cgrf_calc_resolution,event
widget_control,event.top,get_uvalue = pstate

wid = widget_info(event.top, find_by_uname='XMIN')
widget_control, wid, get_value=xmin
wid = widget_info(event.top, find_by_uname='XMAX')
widget_control, wid, get_value=xmax
wid = widget_info(event.top, find_by_uname='XBIN')
widget_control, wid, get_value=xbin
xmin = float(xmin[0])
xmax = float(xmax[0])
xbin = float(xbin[0])

nx = fix((xmax - xmin)/xbin) + 1
(*(*pstate).xPtr) = xmin + findgen(nx)*xbin

x = (*(*pstate).xPtr)
y = (*(*pstate).yPtr)

fwhm_id = widget_info(event.top,find_by_uname = 'FWHM')
center_id = widget_info(event.top,find_by_uname = 'CENTER')
widget_control,fwhm_id,get_value = fwhm_string & fwhm_string = fwhm_string[0]
widget_control,center_id,get_value = center_string
center_string = center_string[0]
cen_expr = 'ycen='+center_string
wid_expr = 'ywid='+fwhm_string
rcen = execute(cen_expr,1)
if rcen ne 1 then begin
	strout = 'Error evaluating expression for center'
	void = dialog_message(strout,dialog_parent = event.top)
	return
endif
rwid = execute(wid_expr,1)
if rwid ne 1 then begin
	strout = 'Error evaluating expression for width'
	void = dialog_message(strout,dialog_parent = event.top)
	return
endif

nx = n_elements(x) & ny = n_elements(y)
ux = 1+bytarr(nx) & uy = 1+bytarr(ny)
scen = size(ycen)
if scen[0] eq 0 then begin
	ycen = ux#ycen#uy
endif
if scen[0] eq 1 then begin
	ycen = ux#ycen
endif
swid = size(ywid)
if swid[0] eq 0 then begin
	ywid = ux#ywid#uy
endif
if swid[0] eq 1 then begin
	ywid = ux#ywid
endif
res = cgrf_gaussian(x,y,ux#uy,ycen,ywid)

(*(*pstate).zPtr) = res

cgrf_refresh_plot,event
cgrf_refresh_image,event
end
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
pro cgrf_event,event
widget_control,event.top,get_uvalue = pstate
uname = widget_info(event.id,/uname)
case uname of
   'XMIN': cgrf_calc_resolution,event

   'XMAX': cgrf_calc_resolution,event

   'XBIN': cgrf_calc_resolution,event

   'FWHM': cgrf_calc_resolution,event

   'CENTER': cgrf_calc_resolution,event
   
   'REFRESH': cgrf_calc_resolution,event

   'ACCEPT': begin
      cgrf_calc_resolution,event

;      x = (*(*pstate).xPtr)
;      (*(*(*pstate).info_ptr).resptr).x = x
;      (*(*(*pstate).info_ptr).resptr).y = (*(*pstate).yPtr)
;      (*(*(*pstate).info_ptr).resptr).z = (*(*pstate).zPtr)
;      (*(*(*pstate).info_ptr).resptr).xrange = [min(x),max(x)]

      (*(*(*pstate).info_ptr).resptr) = {x:(*(*pstate).xPtr),y:(*(*pstate).yPtr),z:(*(*pstate).zPtr)}

      (*(*pstate).info_ptr).cancel = 0
      widget_control,event.top,/destroy
   end

   'CANCEL': begin
      (*(*pstate).info_ptr).cancel = 1
      widget_control,event.top,/destroy
   end

   'GROUP_SLIDER': begin
      cgrf_refresh_plot,event
   end
   
   else:
endcase
end
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
function create_gauss_res_fun,odata,	group_leader = group_leader,	$
										cancel = cancel
; Widget definition module
tvlct,r,g,b,/get
device,decomposed = 0
loadct,15,/silent
register_name = 'cgrf'
if n_params() eq 0 then return,0
if not obj_valid(odata) then return,0
ret = odata->get(nx = nx,ny = ny,xvals = x,yvals = y)
xmin = min(x,max=xmax)
x = xmin + findgen(nx)*(xmax-xmin)/(nx-1)
resolution = fltarr(nx,ny)
if n_elements(group_leader) eq 0 then begin
	group_leader = 0L
	modal = 0
endif else begin
	modal = 1
endelse
tlb = widget_base(/col,title = 'Gaussian Instrumental Resolution Generator',	$
	group_leader = group_leader,modal = modal,/tlb_frame_attr,/base_align_center)
;row = widget_base(tlb,/row)
row1 = widget_base(tlb,/row,/base_align_center)
void = cw_field(row1,title = 'FWHM(Y),e.g. 0.7+0.0*Y', $
	value = '0.7+0.0*Y',/return_events,uname = 'FWHM')
void = cw_field(row1,title = 'Center(Y),e.g. 0.0*Y', $
	value = '0.0*Y',/return_events,uname = 'CENTER')

row2 = widget_base(tlb,/row,/base_align_center)
;void = cw_field(row2,title = 'X min',value=min(x),/return_events,uname='XMIN',/float)
;void = cw_field(row2,title = 'X max',value=max(x),/return_events,uname='XMAX',/float)
;void = cw_field(row2,title = 'X bin',value=x[1]-x[0],/return_events,uname='XBIN',/float)

prec=3
xmin = min(float(x),max=xmax)
nx = n_elements(x)
xbin = (xmax - xmin)/(nx -1)
void = fsc_field(row2,title='X Min',decimal=prec,value=xmin,uname='XMIN' $
                 ,/highlight,/cr_only,event_pro='cgrf_event')
void = fsc_field(row2,title='X Max',decimal=prec,value=xmax,uname='XMAX' $
                 ,/highlight,/cr_only,event_pro='cgrf_event')
void = fsc_field(row2,title='X Bin',decimal=prec,value=xbin,uname='XBIN' $
                 ,/highlight,/cr_only,event_pro='cgrf_event')


xsize = 400 & ysize = 400
void = widget_slider(tlb,title='Group',value=0,min=0,max=ny-1,uname='GROUP_SLIDER',xsize=1.5*xsize)
plot_row = widget_base(tlb,/row)
im_win = widget_draw(plot_row,xsize = xsize,ysize = ysize)
plot_win = widget_draw(plot_row,xsize = xsize,ysize = ysize)

col2 = widget_base(tlb,/row,/base_align_center)
void = widget_button(col2,value = 'REFRESH',uname = 'REFRESH')
void = widget_button(col2,value = 'ACCEPT',uname = 'ACCEPT')
void = widget_button(col2,value = 'CANCEL',uname = 'CANCEL')

widget_control,tlb,/realize
widget_control,im_win,get_value = im_vis
widget_control,plot_win,get_value = plot_vis
window,/free,/pixmap,xsize = xsize,ysize = ysize
im_pix = !d.window
window,/free,/pixmap,xsize = xsize,ysize = ysize
plot_pix = !d.window
info = {cancel:1 $
        ,resptr:ptr_new({x:x $
                         ,y:y $
                         ,z:resolution $
 ;                        ,xrange:[0.0,0.0] $
 ;                        ,yindex:[0,ny-1] $
                        }) $
       }
info_ptr = ptr_new(info)
state =	{	info_ptr:info_ptr,			$
                im_vis:im_vis,				$
                plot_vis:plot_vis,			$
                im_pix:im_pix,				$
                plot_pix:plot_pix,			$
                xptr:ptr_new(x),			$
                yptr:ptr_new(y),				$
                zPtr:ptr_new(resolution), $
                rptr:ptr_new(r),			$
                gptr:ptr_new(g),			$
                bptr:ptr_new(b)			$
        }

pState = ptr_new(state)
widget_control,tlb,set_uvalue = pstate
pseudo_event = {top:tlb,id:void,handler:0L}
cgrf_calc_resolution,pseudo_event
xmanager,register_name,tlb,event_handler = 'cgrf_event'

; Get everything out and clean it up
tvlct,*(*pstate).rptr,*(*pstate).gptr,*(*pstate).bptr
info = *(*pstate).info_ptr
ptr_free,(*pstate).info_ptr
cancel = info.cancel
;ptr_free,(*pstate).xptr,(*pstate).yptr
ptr_free,(*pstate).rptr,(*pstate).gptr,(*pstate).bptr
wdelete,(*pstate).im_pix
wdelete,(*pstate).plot_pix
ptr_free,pstate

return,info
end
