; $Id: anomWid.pro,v 1.3 2005/02/09 16:58:01 dimeo Exp $
;###############################################################################
;
; NAME:
;  ANOMWID
;
; 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.
;
;###############################################################################
; ANOMWID.PRO
;
; Application for visualizing the possible spurions when the
; monochromator and analyzer are set to the transmit the same
; wavelengths and the sample scatters elastically.  The spurious
; feature is an apparent shift of an elastic scattering process.
;
; Written by R.M.Dimeo (02/06/02)
; Modified (02/07/02) to work within DAVE. (RMD)
;
;;;;;;;;;;;;;;
pro anomWidCleanup,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 = {anomEvent,$
                   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).ePtr,(*pState).dePtr
ptr_free,pState
return
end
;;;;;;;;;;;;;;
pro anomWidQuit,event
widget_control,event.top,/destroy
return
end
;;;;;;;;;;;;;;
pro anomWidPlot,event
widget_control,event.top,get_uvalue = pState,/no_copy
if n_elements(*(*pState).dePtr) gt 2 then begin

  ymax = 30.0
  ymin = 0.0
  de = *(*pState).dePtr
  e = *(*pState).ePtr
  s = size(de)
  n = s[1] & npts = s[3]
  if (*pState).autoscale eq 1 then begin
    ymax = max(abs(de[0:n-2,0:n-2,*])) & ymin = min(abs(de[0:n-2,0:n-2,*]))
    xmin = min(e) & xmax = max(e)
    dy = ymax-ymin & dx = xmax-xmin
    (*pState).xviewrange = [xmin,xmax]
    (*pState).yviewrange = [0.0,ymax+0.1*dy]
  endif

  wset,(*pState).winPix
  for i = 0,n-1 do begin
    for j = 0,n-1 do begin
      if i eq 0 and j eq 0 then begin
        plot,e,de[i,j,*],psym = 0,yrange = (*pState).yviewrange,ystyle = 1,$
        ytitle = (*pState).ylabel,charsize = 1.5,xtitle = (*pState).xlabel,$
        title = (*pState).title,xrange = (*pState).xviewrange,xstyle = 1,$
        subtitle = (*pState).subtitle
      endif
      if total(de[i,j,*]) gt 0 then begin
        oplot,e,de[i,j,*],linestyle = 0
      endif else begin
        oplot,e,abs(de[i,j,*]),linestyle = 2
      endelse
    endfor
  endfor
  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 anomWidCalc,event
widget_control,event.top,get_uvalue = pState,/no_copy
widget_control,(*pState).group,get_value = value
widget_control,(*pState).order,get_value = order

n = fix(order[0])	; upper limit on the order of beam contamination
nm = 1 + indgen(n)
na = 1 + indgen(n)
nap = fltarr(n,n)
uvec = 1+bytarr(n)

(*pState).n = n

if value[0] eq 1 then begin	; Ef is fixed
  (*pState).xlabel = '!3E!Dfinal!n (meV)'
  for i = 0,n-1 do begin
    nap[i,0:n-1] = (shift(na,n))[i]
  endfor
  nanm = (nap/(uvec#nm))^2-1.0
  npts = 100
  elo = 0.0 & ehi = 100.0
  ef = hfbs_makepoints(xlo = elo,xhi = ehi,npts = npts)
  de = fltarr(n,n,npts)
  for i = 0,npts-1 do begin
    de[*,*,i] = nanm[*,*]*ef[i]
  endfor
  *(*pState).ePtr = ef
  *(*pState).dePtr = de
endif
if value[0] eq 0 then begin	; Ei is fixed
  (*pState).xlabel = '!3E!Dinitial!n (meV)'
  for i = 0,n-1 do begin
    nap[i,0:n-1] = (shift(na,n))[i]
  endfor
  nanm = (nap/(uvec#nm))^2-1.0
  nanm = -1.0*transpose(temporary(nanm))
  npts = 100
  elo = 0.0 & ehi = 100.0
  ei = hfbs_makepoints(xlo = elo,xhi = ehi,npts = npts)
  de = fltarr(n,n,npts)
  for i = 0,npts-1 do begin
    de[*,*,i] = nanm[*,*]*ei[i]
  endfor
  *(*pState).ePtr = ei
  *(*pState).dePtr = de
endif
widget_control,event.top,set_uvalue = pState,/no_copy
return
end
;;;;;;;;;;;;
pro anomWidDraw,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
case event.type of
0:	begin		; button press
	  (*pState).mouse = event.press
	  if (*pState).mouse eq 4 then begin
	    (*pState).autoscale = 1
	  endif
	  if (*pState).mouse eq 1 then begin
	    (*pState).xbox[0] = event.x
	    (*pState).ybox[0] = event.y
	    wset,(*pState).winVis
	    device,copy = [0,0,!d.x_size,!d.y_size,0,0,(*pState).winPix]
	    empty
	    (*pState).autoscale = 0
	  endif
	end
1:	begin	; button release
	  xll = (*pState).xbox[0] < (*pState).xbox[1]
	  yll = (*pState).ybox[0] < (*pState).ybox[1]
	  w = abs((*pState).xbox[1] - (*pState).xbox[0])
	  h = abs((*pState).ybox[1] - (*pState).ybox[0])
	  xur = xll + w
	  yur = yll + h
	  ll = convert_coord(xll,yll,/device,/to_data)
	  ur = convert_coord(xur,yur,/device,/to_data)
	  (*pState).xviewrange = [ll[0],ur[0]]
	  (*pState).yviewrange = [ll[1],ur[1]]
	  wset,(*pState).winPix
	  widget_control,event.top,set_uvalue = pState,/no_copy
	  anomWidPlot,event
	  widget_control,event.top,get_uvalue = pState,/no_copy
	  wset,(*pState).winVis
	  device,copy = [0,0,!d.x_size,!d.y_size,0,0,(*pState).winPix]
	  (*pState).mouse = 0B
	end
2:	begin	; mouse motion
	  if (*pState).mouse eq 1 then begin
	  	(*pState).xbox[1] = event.x
	  	(*pState).ybox[1] = event.y
	  	xc = [(*pState).xbox[0],event.x,event.x,(*pState).xbox[0],(*pState).xbox[0]]
	  	yc = [(*pState).ybox[0],(*pState).ybox[0],event.y,event.y,(*pState).ybox[0]]
	  	wset,(*pState).winVis
	  	device,copy = [0,0,!d.x_size,!d.y_size,0,0,(*pState).winPix]
	  	plots,xc,yc,/device
	  	empty
	  endif else begin
	    coords = convert_coord(event.x,event.y,/device,/to_data)
	    if (coords[0] gt !x.crange[0]) and (coords[0] lt !x.crange[1]) and $
		  (coords[1] gt !y.crange[0]) and (coords[1] lt !y.crange[1]) then begin
	      widget_control,(*pState).efout,set_value = string(coords[0])
	      widget_control,(*pState).deout,set_value = string(coords[1])
	      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
	        n = (*pState).n
	        nn = n*n
	        strout = strarr(nn+1)
	        de = *(*pState).dePtr
	        e = *(*pState).ePtr
	        strout[0] = "(analyzer,monochromator): energy (meV)"
			count = 1
			for i = 0,n-1 do begin
			  for j = 0,n-1 do begin
				  yout = interpol(de[i,j,*],e[*],coords[0])
				  strout[count] = "("+strcompress(string(i+1))+","+$
				                  strcompress(string(j+1))+"): "+$
				                  strcompress(string(yout))
			    count = count + 1
			  endfor
			endfor
			widget_control,(*pState).text,set_value = strout
	    endif

	  endelse
	end
else:
endcase
widget_control,event.top,set_uvalue = pState,/no_copy
return
end
;;;;;;;;;;;;;;
pro anomWid_event,event
widget_control,event.top,get_uvalue = pState,/no_copy
if (event.id eq (*pState).group) or (event.id eq (*pState).order) then begin
  widget_control,(*pState).order,get_value = n
  n = fix(n[0])
  if n le 2 then begin
    out = 'n (order) > 2'
    void = dialog_message(dialog_parent = event.top,out)
    widget_control,event.top,set_uvalue = pState,/no_copy
    return
  endif
  widget_control,event.top,set_uvalue = pState,/no_copy
  anomWidCalc,event
  anomWidPlot,event
  widget_control,event.top,get_uvalue = pState,/no_copy
endif

widget_control,event.top,set_uvalue = pState,/no_copy
return
end
;;;;;;;;;;;;;;
pro anomDesc,event
strout	=	["This program calculates the apparent inelastic scattering",$
			 "due to the elastic scattering of higher order harmonics from",$
			 "the sample.  Drag the cursor around the screen to determine",$
			 "which harmonics result in apparent inelastic features.  The",$
			 "dashed lines indicate a negative apparent energy transfer.",$
			 "The order of the transmission is displayed in the text box",$
			 "at the right as you drag the cursor around the screen."]
void = dialog_message(dialog_parent = event.top,strout,/information)
return
end
;;;;;;;;;;;;;;
pro anomAbout,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 anomWid,NOTIFYIDS = notifyIDs,INPTR = inPtr
; Widget definition module
tvlct,r,g,b,/get
loadct,0,/silent

if not keyword_set(notifyIDs) then notifyIDs = 0
if not keyword_set(inPtr) then inPtr = 0.0

!y.margin = [5.0,3.0]
tlb = widget_base(/col,title = 'Elastic spurion calculator',/tlb_frame_attr,mbar = bar)
filemenu = widget_button(bar,value = 'File')
miscmenu = widget_button(bar,value = 'Misc')
void = widget_button(miscmenu,value = 'Brief description',event_pro = 'anomDesc')
void = widget_button(miscmenu,value = 'About...',event_pro = 'anomAbout')

rowBase1 = widget_base(tlb,/row)
type = ['Ei','Ef']
group = cw_bgroup(rowBase1,type, /row, /exclusive,$
         label_top='Fixed energy',/no_release,$
         frame=1,set_value=0,/return_index)
order = cw_field(rowBase1,value = '4',/string,xsize = 5,title = 'Max order',/return_events,/col)
efout = cw_field(rowBase1,value = "",/string,title = 'Final energy (meV)',xsize = 6,/col)
deout = cw_field(rowBase1,value = "",/string,title = 'Apparent energy transfer (meV)',xsize = 6,/col)

void = widget_button(filemenu,value = 'Quit',event_pro = 'anomWidQuit')
rowBase2 = widget_base(tlb,/row)
winxsize = 550 & winysize = 400
plotWin = widget_draw(rowBase2,xsize = winxsize,ysize = winysize,$
          event_pro = 'anomWidDraw',/button_events,/motion_events)
text = widget_text(rowBase2,xsize = 40,ysize = 20,/scroll)

centertlb,tlb
widget_control,tlb,/realize

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

state = {group:group,$
         plotWin:plotWin,$
         winPix:winPix,$
         winVis:winVis,$
         winxsize:winxsize,$
         winysize:winysize,$
         text:text,$
         ePtr: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",$
         subtitle:"(same monochromator and analyzer setup)",$
         order:order,$
         autoscale:1,$
         xviewrange:[0.0,1.0],$
         yviewrange:[0.0,1.0],$
         xbox:[0,1],$
         ybox:[0,1],$
         mouse:0B,$,
         r:r,g:g,b:b,$
         efout:efout,$
         deout:deout,$
         n:0,$
         notifyIDs:notifyIDs,$
         inPtr:inPtr}

widget_control,tlb,set_uvalue = ptr_new(state,/no_copy)
anomWidCalc,{event,top:tlb,id:text,handler:0l}
anomWidPlot,{event,top:tlb,id:text,handler:0l}

xmanager,'anomWid',tlb,cleanup = 'anomWidCleanup'
return
end