; $Id: anomIeWid.pro,v 1.3 2005/02/09 16:58:01 dimeo Exp $
;###############################################################################
;
; NAME:
;  anomIeWid
;
; PURPOSE:
;  See description below.
;
; CATEGORY:
;  DAVE, HFBS
;
; 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.
;
;###############################################################################
; ANOMIEWID.PRO
;
; Application for visualizing the possible spurions that occur
; when the monochromator and analyzer can transmit higher order
; harmonics and the sample scatters inelastically.  The inelastic
; process will be shifted to a lower energy in general.
;
; External program requirements:
;			TVIMAGE.PRO (Fanning)
;			HFBS_MAKEPOINTS.PRO (Dimeo)
;
; Written by R.M.Dimeo (02/07/02)
; Modified to work within DAVE (RMD)
;
;;;;;;;;;;;;;;
pro anomIeWidCleanup,tlb
widget_control,tlb,get_uvalue = pState,/no_copy

s = size((*pState).notifyIDs)
if n_elements((*pState).notifyIDs) gt 1 then begin
  if s[0] eq 1 then count = 0 else count = s[2] - 1
  for j = 0,count do begin
    pseudoEvent = {anomieEvent,$
                   ID:(*pState).notifyIDs[0,j],$
                   top:(*pState).notifyIDs[1,j],$
                   handler:0l,$
                   inPtr:ptr_new(*(*pState).inPtr)}
    if widget_info((*pState).notifyIDs[0,j],/valid_id) then $
       widget_control,(*pState).notifyIDs[0,j],send_event = pseudoEvent,/no_copy
  endfor
endif

tvlct,(*pState).r,(*pState).g,(*pState).b
!x.margin = [10.0,3.0]
!y.margin = [4.0,2.0]
wdelete,(*pState).winPix
ptr_free,(*pState).efPtr,(*pState).dePtr,(*pState).eaPtr
ptr_free,pState
return
end
;;;;;;;;;;;;;;
pro anomIEWidQuit,event
widget_control,event.top,/destroy
return
end
;;;;;;;;;;;;;;
pro anomIEWidPlot,event
widget_control,event.top,get_uvalue = pState,/no_copy
if n_elements(*(*pState).dePtr) gt 2 then begin
  ymin = min(*(*pState).eaPtr) & ymax = max(*(*pState).eaPtr)
  xmin = min(*(*pState).efPtr) & xmax = max(*(*pState).efPtr)
  wset,(*pState).winPix
  position = [0.2,0.15,0.9,0.9]
  erase
  tvimage,bytscl(*(*pState).dePtr),position = position

  plot,*(*pState).efPtr,*(*pState).eaPtr,/nodata,/noerase,$
       position = position,title = (*pState).title,$
       xtitle = (*pState).xlabel,ytitle = (*pState).ylabel,$
       charsize = 1.5,xrange = [xmin,xmax],xstyle = 1,$
       yrange = [ymin,ymax],ystyle = 1

  wset,(*pState).winVis
  device,copy = [0,0,!d.x_size,!d.y_size,0,0,(*pState).winPix]
endif

widget_control,event.top,set_uvalue = pState,/no_copy
return
end
;;;;;;;;;;;;;;
pro anomIEWidCalc,event
widget_control,event.top,get_uvalue = pState,/no_copy
widget_control,(*pState).n,get_value = n
widget_control,(*pState).na,get_value = na
widget_control,(*pState).nm,get_value = nm
widget_control,(*pState).eflo,get_value = eflo & eflo = float(eflo[0])
widget_control,(*pState).efhi,get_value = efhi & efhi = float(efhi[0])
widget_control,(*pState).ealo,get_value = ealo & ealo = float(ealo[0])
widget_control,(*pState).eahi,get_value = eahi & eahi = float(eahi[0])

nm = fix(nm[0])
n = fix(n[0])	; upper limit on the order of beam contamination
na = fix(na[0])

(*pState).xlabel = '!3E!Dfinal!n (meV)'
n1pts = 200 & n2pts = 220

ef = hfbs_makepoints(xlo = eflo,xhi = efhi,npts = n1pts)
ea = hfbs_makepoints(xlo = ealo,xhi = eahi,npts = n2pts)
de = fltarr(n1pts,n2pts)
eavec = 1+bytarr(n2pts)
efvec = 1+bytarr(n1pts)
; Now use array operations (multiplication) to eliminate
; loops and make this go faster.
de = (nm^2)*(efvec#ea) + (nm^2-na^2)*(ef#efvec)

*(*pState).efPtr = ef
*(*pState).eaPtr = ea
*(*pState).dePtr = de

widget_control,event.top,set_uvalue = pState,/no_copy
return
end
;;;;;;;;;;;;
pro anomIEWidDraw,event
widget_control,event.top,get_uvalue = pState,/no_copy
if n_elements(*(*pState).dePtr) lt 2 then begin
  widget_control,event.top,set_uvalue = pState,/no_copy
  return
endif
widget_control,(*pState).na,get_value = na & na = fix(na[0])
widget_control,(*pState).nm,get_value = nm & nm = fix(nm[0])
de = *(*pState).dePtr
ef = *(*pState).efPtr & eflo = min(ef)
efhi = max(ef) & def = ef[1] - ef[0]
ea = *(*pState).eaPtr & ealo = min(ea)
eahi = max(ea) & dea = ea[1] - ea[0]
n1pts = n_elements(ef) & n2pts = n_elements(ea)

case event.type of
2:	begin	; mouse motion
	    coords = convert_coord(event.x,event.y,/device,/to_data)
	    x = coords[0] & y = coords[1]
	    if (x gt !x.crange[0]) and (x lt !x.crange[1]) and $
		  (y gt !y.crange[0]) and (y lt !y.crange[1]) then begin
		  x1index = (x-ef[0])/def
		  x2index = (y-ea[0])/dea
		  yout = interpolate(de,x1index,x2index);,/grid,/cubic)
		  widget_control,(*pState).ef,set_value = $
		         strcompress(string(x,format = (*pState).fcode))
		  widget_control,(*pState).ea,set_value = $
		         strcompress(string(y,format = (*pState).fcode))
		  widget_control,(*pState).de,set_value = $
		         strcompress(string(yout,format = (*pState).fcode))

	      wset,(*pState).winVis
	      device,copy = [0,0,!d.x_size,!d.y_size,0,0,(*pState).winPix]
	      plots,[coords[0],coords[0]],!y.crange,linestyle = 0,thick = 1.5,/data
	      plots,!x.crange,[coords[1],coords[1]],linestyle = 0,thick = 1.5,/data
	    endif
	end
else:
endcase
widget_control,event.top,set_uvalue = pState,/no_copy
return
end
;;;;;;;;;;;;;;
pro anomIEWid_event,event
widget_control,event.top,get_uvalue = pState,/no_copy
if (event.id eq (*pState).ef) or (event.id eq (*pState).ea) then begin
  widget_control,(*pState).ef,get_value = ef & ef = float(ef[0])
  widget_control,(*pState).ea,get_value = ea & ea = float(ea[0])
  widget_control,(*pState).nm,get_value = nm & nm = float(nm[0])
  widget_control,(*pState).na,get_value = na & na = float(na[0])
  de = (nm^2)*ea + (nm^2-na^2)*ef
  widget_control,(*pState).de,set_value = $
         strcompress(string(de,format = (*pState).fcode))
  wset,(*pState).winVis
  device,copy = [0,0,!d.x_size,!d.y_size,0,0,(*pState).winPix]
  plots,[ef,ef],!y.crange,linestyle = 0,thick = 1.5,/data
  plots,!x.crange,[ea,ea],linestyle = 0,thick = 1.5,/data

  empty
endif

if (event.id eq (*pState).n) then begin
  widget_control,(*pState).n,get_value = n & n = fix(n[0])
  widget_control,(*pState).na,set_slider_max = n
  widget_control,(*pState).nm,set_slider_max = n
endif
if (event.id eq (*pState).n) or (event.id eq (*pState).nm) or $
  (event.id eq (*pState).na) or (event.id eq (*pState).eflo) or $
  (event.id eq (*pState).efhi) or (event.id eq (*pState).ealo) or $
  (event.id eq (*pState).eahi) then begin
  widget_control,(*pState).n,get_value = n
  n = fix(n[0])
  widget_control,event.top,set_uvalue = pState,/no_copy
  anomIEWidCalc,event
  anomIEWidPlot,event
  widget_control,event.top,get_uvalue = pState,/no_copy
endif

widget_control,event.top,set_uvalue = pState,/no_copy
return
end
;;;;;;;;;;;;;;
pro anomIEDesc,event
strout	=	["This program calculates the actual inelastic scattering",$
			 "processes that can cause apparent inelastic features at",$
			 "lower energy transfers.  Move the cursor over the image",$
			 "to observe how the actual process changes with apparent",$
			 "energy transfer and the fixed final energy.  Change the",$
			 "position of the slider bars to change the order of the ",$
			 "transmitted neutron wavelength at the monochromator",$
			 "and/or the analyzer."]
void = dialog_message(dialog_parent = event.top,strout,/information)
return
end
;;;;;;;;;;;;;;
pro anomIEAbout,event
strout	=	["Written by R.M.Dimeo (02/07/02)",$
			 "NIST Center for Neutron Research"]
void = dialog_message(dialog_parent = event.top,strout,/information)
return
end
;;;;;;;;;;;;;;
pro anomIEWid,NOTIFYIDS = notifyIDs,INPTR = inPtr
; Widget definition module
; Check if we are calling this program from another
if not keyword_set(notifyIDs) then notifyIDs = 0
if not keyword_set(inPtr) then inPtr = 0.0
tvlct,r,g,b,/get
device,decomposed = 0
loadct,3,/silent
!y.margin = [5.0,3.0]
tlb = widget_base(/col,title = 'Inelastic spurion calculator',mbar = bar,/tlb_frame_attr)
filemenu = widget_button(bar,value = 'File')
miscmenu = widget_button(bar,value = 'Misc')
void = widget_button(miscmenu,value = 'Brief description',event_pro = 'anomIEDesc')
void = widget_button(miscmenu,value = 'About...',event_pro = 'anomIEAbout')
rowBase1 = widget_base(tlb,/row)
n = cw_field(rowbase1,title = 'Max order',value = '4',xsize = 4,/return_events,/col)
eflo = cw_field(rowbase1,title = 'Efinal min',value = '0.0',xsize = 6,/return_events,/col)
efhi = cw_field(rowbase1,title = 'Efinal max',value = '30.0',xsize = 6,/return_events,/col)
ealo = cw_field(rowbase1,title = 'Eapp min',value = '0.0',xsize = 6,/return_events,/col)
eahi = cw_field(rowbase1,title = 'Eapp max',value = '30.0',xsize = 6,/return_events,/col)
rowBase2 = widget_base(tlb,/row)

nm = widget_slider(rowbase2,value = 2,min = 1,max = 4,title = 'Monochromator order')
na = widget_slider(rowbase2,value = 1,min = 1,max = 4,title = 'Analyzer order')

void = widget_button(filemenu,value = 'Quit',event_pro = 'anomIEWidQuit')
;rowBase3 = widget_base(tlb,/row)
ef = cw_field(rowBase2,value = "",title = "Efinal",/col,/return_events,xsize = 8)
ea = cw_field(rowBase2,value = "",title = "Eapparent",/col,/return_events,xsize = 8)
de = cw_field(rowBase2,value = "",title = "Eactual",/col,xsize = 8)

winxsize = 550 & winysize = 400
plotWin = widget_draw(tlb,xsize = winxsize,ysize = winysize,$
          event_pro = 'anomIEWidDraw',/button_events,/motion_events)

centertlb,tlb
widget_control,tlb,/realize

window,/free,/pixmap,xsize = winxsize,ysize = winysize
winPix = !d.window
widget_control,plotWin,get_value = winVis

state = {plotWin:plotWin,$
         winPix:winPix,$
         winVis:winVis,$
         winxsize:winxsize,$
         winysize:winysize,$
         eflo:eflo,$
         efhi:efhi,$
         ealo:ealo,$
         eahi:eahi,$
         ef:ef,$
         ea:ea,$
         de:de,$
         r:r,g:g,b:b,$
         efPtr:ptr_new(/allocate_heap),$
         eaPtr:ptr_new(/allocate_heap),$
         dePtr:ptr_new(/allocate_heap),$
         ylabel:"!3!sh!r!e/!n !4x!3!Dapparent!n (meV)",$
         xlabel:"",$
         title:"False Peak Conditions",$
         n:n,$
         na:na,$
         nm:nm,$
         fcode:"(f15.2)",$
         autoscale:1,$
         subtitle:"",$
         xviewrange:[0.0,1.0],$
         yviewrange:[0.0,1.0],$
         xbox:[0,1],$
         ybox:[0,1],$
         mouse:0B,$
         notifyIDs:notifyIDs,$
         inPtr:inPtr}

widget_control,tlb,set_uvalue = ptr_new(state,/no_copy)

anomIEWidCalc,{event,top:tlb,id:na,handler:0L}
anomIEWidPlot,{event,top:tlb,id:na,handler:0L}

xmanager,'anomIEWid',tlb,cleanup = 'anomIEWidCleanup'
return
end