; $Id: neut_calc.pro,v 1.12 2006/06/28 09:09:49 tregenna Exp $
; NEUT_CALC.PRO
;
; Calculates various quantities related to the neutron based on the
; user's input.  Also plots the accessible region of Q-E space for
; direct (indirect) geometry instruments based on the low-high detector
; angles and the fixed initial (final) neutron energy.
;
; Written by R.M.Dimeo (10/4/2000)
;
; Modified 10/11/2000:  fixed the problem with running the first time through
; Modified 10/26/2000:  fixed bug caused by imaginary q vectors in updateNeutronValues
; Modified 10/27/2000:  fixed bug that occurred when typing in an energy value
;            in the meV field.
; Modified 12/12/2000:  fixed "double-event" bug occurring in the cw_bgroup button group.
; Modified 11/1/2001:   modified to work within DAVE.
; Modified 12/13/2001:  added capability to display phase space upon realization of widget
;            but before invoking the xmanager.
; Modified 09/09/2005:  by Philip Tregenna-Piggott:  updated conversion constnts and changed
;   default detector angles to reflect those of the FOCUS instrument at PSI
; Modified 28/06/2006:  by Philip Tregenna-Piggott:  Added key word 'LambdaEntry''
; to allow the default values to be specified upon initialisation of the program.
;
;###############################################################################
; 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 or if the code in this file is
;  included in another product.
;
;###############################################################################
;;;;;;;;;;;;;;;;;;;;;;;;;;
pro neut_calcCleanup,tlb
widget_control,tlb,get_uvalue = pState,/no_copy
tvlct,(*pState).rorig,(*pState).gorig,(*pState).borig
s = size((*pState).notifyIDs)
if s[0] eq 1 then count = 0 else count = s[2] - 1
for j = 0,count do begin
  pseudoEvent = {neutCalcEvent,$
                         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
wdelete,(*pState).winPix
ptr_free,pState
return
end
;;;;;;;;;;;;;;;;;;;;;;;;;;
pro NeutCalcDone,event
widget_control,event.top,get_uvalue = pState,/no_copy
s = size((*pState).notifyIDs)
if s[0] eq 1 then count = 0 else count = s[2] - 1
for j = 0,count do begin
  pseudoEvent = {neutCalcEvent,$
                         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
widget_control,event.top,set_uvalue = pState,/no_copy
widget_control,event.top,/destroy
return
end
;;;;;;;;;;;;;;;;;;;;;;;;;;
pro neut_calcSolveTriangle,event,initvals = initvals

if n_elements(initvals) eq 0 then begin
  widget_control,event.top,get_uvalue = pState,/no_copy
endif
if n_elements(initvals) eq 0 then begin
  widget_control,(*pState).philo,get_value = philo
  widget_control,(*pState).phihi,get_value = phihi
  widget_control,(*pState).energymeV,get_uvalue = eo
  widget_control,(*pState).specType,get_value = geom

  eo = double(eo[0])
  philo = double(philo[0])
  phihi = double(phihi[0])
  alpha = 2.072099427
endif else begin
  eo = double(initvals.emeV)
  philo = double(initvals.anglo)
  phihi = double(initvals.anghi)
  colors = initvals.colors
  alpha = 2.072099427
  geom = 0
endelse

if geom eq 0 then begin ; direct geometry
  npts = 200
  e_hi = eo
  e_lo = -3.0*e_hi
  energy = hfbs_makepoints(xlo = e_lo,xhi = e_hi,npts = npts)
  disc_hi = ((1.0/alpha)*(2.0*eo-energy-2.0*sqrt(eo*(eo-energy))*cos(phihi*!dtor)))
  disc_lo = ((1.0/alpha)*(2.0*eo-energy-2.0*sqrt(eo*(eo-energy))*cos(philo*!dtor)))
  ;disc_hi = ((1.0/alpha^2)*(2.0*eo-energy-2.0*sqrt(eo*(eo-energy))*cos(phihi*!dtor)))
  ;disc_lo = ((1.0/alpha^2)*(2.0*eo-energy-2.0*sqrt(eo*(eo-energy))*cos(philo*!dtor)))
  ;print,'sqrt(min(disc_lo)) =',sqrt(min(disc_lo))
  ;
  lo_wherefinite = where(disc_lo ge 0.0,counthi)
  hi_wherefinite = where(disc_hi ge 0.0,countlo)
  q_hi = dblarr(counthi)
  q_lo = dblarr(countlo)
  qnew = dblarr(counthi+countlo)
  enew = dblarr(counthi+countlo)
  q_hi=sqrt(disc_hi[hi_wherefinite])


  q_lo=sqrt(disc_lo[hi_wherefinite])
  ;print,'min(q_lo) =',min(q_lo)
  ;print,min(q_hi)
  qnew=[q_lo,reverse(q_hi)]
  enew=[energy,reverse(energy)]
endif else begin  ; inverse geometry
  npts = 200
  e_hi = 3.0*eo
  e_lo = -eo
  ef = eo
  energy = hfbs_makepoints(xlo = e_lo,xhi = e_hi,npts = npts)
  e_lo=-eo
  disc_hi = ((1.0/alpha)*(2*ef+energy-2*sqrt(ef*(ef+energy))*cos(phihi*!dtor)))
  disc_lo = ((1.0/alpha)*(2*ef+energy-2*sqrt(ef*(ef+energy))*cos(philo*!dtor)))
  ;disc_hi = ((1.0/alpha^2)*(2*ef+energy-2*sqrt(ef*(ef+energy))*cos(phihi*!dtor)))
  ;disc_lo = ((1.0/alpha^2)*(2*ef+energy-2*sqrt(ef*(ef+energy))*cos(philo*!dtor)))
  lo_wherefinite = where(disc_lo ge 0.0,counthi)
  hi_wherefinite = where(disc_hi ge 0.0,countlo)
  q_hi = dblarr(counthi)
  q_lo = dblarr(countlo)
  qnew = dblarr(counthi+countlo)
  enew = dblarr(counthi+countlo)
  q_hi=sqrt(disc_hi[hi_wherefinite])
  q_lo=sqrt(disc_lo[hi_wherefinite])
  qnew=[q_lo,reverse(q_hi)]
  enew=[energy,reverse(energy)]
endelse

if n_elements(initvals) gt 0 then begin
    qmin = min([min(q_hi),min(q_lo)])
    qmax = max([max(q_hi),max(q_lo)])
    xlo = qmin[0] & xhi = qmax[0]
    ylo = e_lo & yhi = e_hi
endif else begin
 if (*pState).autoscale then begin
    qmin = min([min(q_hi),min(q_lo)])
    qmax = max([max(q_hi),max(q_lo)])
    xlo = qmin[0] & xhi = qmax[0]
    ylo = e_lo & yhi = e_hi
    (*pState).xlo = xlo
    (*pState).xhi = xhi
    (*pState).ylo = ylo
    (*pState).yhi = yhi
 endif else begin
    xlo = (*pState).xlo
    ylo = (*pState).ylo
    xhi = (*pState).xhi
    yhi = (*pState).yhi
 endelse
endelse

if n_elements(initvals) eq 0 then begin
  wset,(*pState).winPix
  lin = 0
  plot,qnew,enew,psym = 0,xtitle = 'Q (!6!sA!r!u!9 %!6!n!E-1!N)',$
     ytitle = '!6Energy Transfer (meV)',xrange = [xlo,xhi],yrange = [ylo,yhi],$
     xstyle = 1,ystyle = 1,/nodata,color = (*pState).white,$
     background = (*pState).black,title = (*pState).title
  polyfill,qnew,enew,/data,color = (*pState).red,$
         CLIP=[xlo,ylo,xhi,yhi], noclip = 0
  wset,(*pState).winVis
  device,copy = [0,0,(*pState).winxsize,(*pState).winysize,0,0,(*pState).winPix]
  (*pState).neutcalc = 1
  widget_control,event.top,set_uvalue = pState,/no_copy
endif else begin
  lin = 0
  plot,qnew,enew,psym = 0,xtitle = 'Q (!6!sA!r!u!9 %!6!n!E-1!N)',$
     ytitle = '!6Energy Transfer (meV)',xrange = [xlo,xhi],yrange = [ylo,yhi],$
     xstyle = 1,ystyle = 1,/nodata,color = colors.white,$
     background = colors.black;title = (*pState).title
  polyfill,qnew,enew,/data,color = colors.red,$
        CLIP=[xlo,ylo,xhi,yhi], noclip = 0
endelse
return
end
;;;;;;;;;;;;;;;;;;;;;;;;;;
pro updateNeutronValues,event
widget_control,event.top,get_uvalue = pState,/no_copy
widget_control,(*pState).energymeV,get_uvalue = energymeV
energymeV = double(energymeV[0])
lambda = double(sqrt(81.80320651/energymeV))
formatType = '(F15.5)'
widget_control,(*pState).waveLength,set_value = string(lambda,format = formatType)
widget_control,(*pState).waveLength,set_uvalue = lambda
k = 2.0*!dpi/lambda
widget_control,(*pState).waveVector,set_value = string(k,format = formatType)
widget_control,(*pState).waveVector,set_uvalue = k
widget_control,(*pState).energyueV,set_value = string(1.0e3*energymeV,format = formatType)
widget_control,(*pState).energyueV,set_uvalue = 1.0d3*energymeV
widget_control,(*pState).energymeV,set_value = string(energymeV,format = formatType)
widget_control,(*pState).energymeV,set_uvalue = energymeV
widget_control,(*pState).energyTHz,set_value = string(energymeV*0.2417989052,format = formatType)
widget_control,(*pState).energyTHz,set_uvalue = energymeV*0.2417989052
widget_control,(*pState).energyGHz,set_value = string(energymeV*241.7989052,format = formatType)
widget_control,(*pState).energyGHz,set_uvalue = energymeV*241.7989052
widget_control,(*pState).energyinvcm,set_value = string(energymeV*8.06554097,$
               format = formatType)
widget_control,(*pState).energyinvcm,set_uvalue = energymeV*8.06554097
widget_control,event.top,set_uvalue = pState,/no_copy
return
end
;1 meV = 241.7989052 GHz
;1 meV = 8.06554097 cm-1
;1 meV = 2.072099427*k^2
;1 meV = 81.80320651 / lambda^2
;;;;;;;;;;;;;;;;;;;;;;;;;;
pro neut_calcWinDraw,event
!except = 0
widget_control,event.top,get_uvalue = pState,/no_copy
if not (*pState).neutcalc 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
     widget_control,event.top,set_uvalue = pState,/no_copy
       neut_calcSolveTriangle,event
     widget_control,event.top,get_uvalue = pState,/no_copy
        (*pState).mouse = 0
        widget_control,event.top,set_uvalue = pState,/no_copy
     return
   endif
   (*pState).xp1 = event.x
   (*pState).yp1 = event.y
   wset, (*pState).winVis
   device, copy = [0,0,(*pState).winxsize,(*pState).winysize,0,0,(*pState).winPix]
   end
1: begin ; button release
   if ((*pState).mouse eq 1) then begin
     x = (*pState).xp1 < (*pState).xp2
     y = (*pState).yp1 < (*pState).yp2
     w = abs((*pState).xp1 - (*pState).xp2)
     h = abs((*pState).yp1 - (*pState).yp2)
     x2 = x+w
     y2 = y+h
     lc = convert_coord(x, y, /device, /to_data)
     uc = convert_coord(x2, y2, /device, /to_data)
     wset,(*pState).winVis
     (*pState).xlo = lc[0] & (*pState).xhi = uc[0]
     (*pState).ylo = lc[1] & (*pState).yhi = uc[1]
     (*pState).autoscale = 0
        widget_control,event.top,set_uvalue = pState,/no_copy
        neut_calcSolveTriangle,event
        widget_control,event.top,get_uvalue = pState,/no_copy
     widget_control,event.top,/clear_events
   endif
   (*pState).mouse = 0
   end
2: begin ; mouse motion
    if ((*pState).mouse eq 1) then begin
      (*pState).xp2 = event.x
      (*pState).yp2 = event.y
      xc = [(*pState).xp1, event.x, event.x, (*pState).xp1, (*pState).xp1]
      yc = [(*pState).yp1, (*pState).yp1, event.y, event.y, (*pState).yp1]
      wset, (*pState).winVis
      device, copy = [0,0,(*pState).winxsize,(*pState).winysize,0,0,(*pState).winPix]
      plots, xc, yc, /device,color = (*pState).yellow,linestyle = 0
    endif else begin
; display the cursor coordinates when within the phase space region
      coords = convert_coord(event.x, event.y, /device, /to_data)
      if (coords[0] le (*pState).xhi) and (coords[0] ge (*pState).xlo) and $
         coords[1] le (*pState).yhi and coords[1] ge (*pState).ylo then begin
        (*pState).title = '!6Q='+strtrim(string(coords[0],format = '(F6.3)'),2)+$
                          ' !6!sA!r!u!9 %!6!n!E-1!N, !6E='+$
                           strtrim(string(coords[1],format = '(F6.3)'),2)+' meV'

      endif
        widget_control,event.top,set_uvalue = pState,/no_copy
        neut_calcSolveTriangle,event
        widget_control,event.top,get_uvalue = pState,/no_copy
    endelse
   end
else:
endcase
  widget_control,event.top,set_uvalue = pState,/no_copy
return
end
;;;;;;;;;;;;;;;;;;;;;;;;;;
pro neut_calc_event,event
; Main event handler
if dave_set_focus(event) then return
;ret = dave_set_focus(event)
widget_control,event.top,get_uvalue = pState,/no_copy

if (*pState).firstTime then begin
            widget_control,event.top,set_uvalue = pState,/no_copy
            updateNeutronValues,event
               neut_calcSolveTriangle,event
            widget_control,event.top,get_uvalue = pState,/no_copy
  (*pState).firstTime = 0
endif

case event.id of
(*pState).waveLength:  begin
            widget_control,(*pState).waveLength,get_value = lambda
            widget_control,(*pState).waveLength,set_uvalue = lambda
            lambda = double(lambda[0])
            energymeV = 81.80320651/(lambda^2)
            widget_control,(*pState).energymeV,set_value = energymeV
            widget_control,(*pState).energymeV,set_uvalue = energymeV
            widget_control,event.top,set_uvalue = pState,/no_copy
            updateNeutronValues,event
               neut_calcSolveTriangle,event
            widget_control,event.top,get_uvalue = pState,/no_copy
                       end
(*pState).waveVector:  begin
            widget_control,(*pState).waveVector,get_value = k
            widget_control,(*pState).waveVector,set_uvalue = k
            k = double(k[0])
            lambda = 2.0*!dpi/k
            energymeV = 81.80320651/(lambda^2)
            widget_control,(*pState).energymeV,set_value = energymeV
            widget_control,(*pState).energymeV,set_uvalue = energymeV
            widget_control,event.top,set_uvalue = pState,/no_copy
            updateNeutronValues,event
               neut_calcSolveTriangle,event
            widget_control,event.top,get_uvalue = pState,/no_copy
                       end
(*pState).energyueV:  begin
            widget_control,(*pState).energyueV,get_value = energyueV
            widget_control,(*pState).energyueV,set_uvalue = energyueV
            energymeV = 1.0e-3*energyueV
            widget_control,(*pState).energymeV,set_value = energymeV
            widget_control,(*pState).energymeV,set_uvalue = energymeV
            widget_control,event.top,set_uvalue = pState,/no_copy
            updateNeutronValues,event
               neut_calcSolveTriangle,event
            widget_control,event.top,get_uvalue = pState,/no_copy
                       end
(*pState).energymeV:  begin
            widget_control,(*pState).energymeV,get_value = energymeV
            energymeV = double(energymeV)
            widget_control,(*pState).energymeV,set_uvalue = energymeV
                        widget_control,event.top,set_uvalue = pState,/no_copy
            updateNeutronValues,event
               neut_calcSolveTriangle,event
            widget_control,event.top,get_uvalue = pState,/no_copy
                       end
(*pState).energyTHz:  begin
            widget_control,(*pState).energyTHz,get_value = energyTHz
            widget_control,(*pState).energyTHz,set_uvalue = energyTHz
            energymeV = energyTHz/0.2417989052
            widget_control,(*pState).energymeV,set_value = energymeV
            widget_control,(*pState).energymeV,set_uvalue = energymeV
            widget_control,event.top,set_uvalue = pState,/no_copy
            updateNeutronValues,event
               neut_calcSolveTriangle,event
            widget_control,event.top,get_uvalue = pState,/no_copy
                       end
(*pState).energyGHz:  begin
            widget_control,(*pState).energyGHz,get_value = energyGHz
            widget_control,(*pState).energyGHz,set_uvalue = energyGHz
            energymeV = energyGHz/241.7989052
            widget_control,(*pState).energymeV,set_value = energymeV
            widget_control,(*pState).energymeV,set_uvalue = energymeV
            widget_control,event.top,set_uvalue = pState,/no_copy
            updateNeutronValues,event
               neut_calcSolveTriangle,event
            widget_control,event.top,get_uvalue = pState,/no_copy
                       end
(*pState).energyinvcm:  begin
            widget_control,(*pState).energyinvcm,get_value = energyinvcm
            widget_control,(*pState).energyinvcm,set_uvalue = energyinvcm
            energymeV = energyinvcm/8.06554097
            widget_control,(*pState).energymeV,set_value = energymeV
            widget_control,(*pState).energymeV,set_uvalue = energymeV
            widget_control,event.top,set_uvalue = pState,/no_copy
            updateNeutronValues,event
               neut_calcSolveTriangle,event
            widget_control,event.top,get_uvalue = pState,/no_copy
                       end
(*pState).philo:       begin
                            widget_control,event.top,set_uvalue = pState,/no_copy
               neut_calcSolveTriangle,event
               widget_control,event.top,get_uvalue = pState,/no_copy
            end
(*pState).phihi:       begin
                            widget_control,event.top,set_uvalue = pState,/no_copy
               neut_calcSolveTriangle,event
               widget_control,event.top,get_uvalue = pState,/no_copy
            end
(*pState).specType:       begin
                            widget_control,event.top,set_uvalue = pState,/no_copy
               neut_calcSolveTriangle,event
               widget_control,event.top,get_uvalue = pState,/no_copy
            end
else:
endcase
widget_control,event.top,set_uvalue = pState,/no_copy
return
end
;;;;;;;;;;;;;;;;;;;;;;;;;;
pro neut_calc,notifyIDs,inPtr,group_leader = group_leader,LambdaEntry = LambdaEntry
; Widget definition module
; First get the colors upon entering this program
tvlct,rorig,gorig,borig,/get
tlb = widget_base(/row,title = 'Neutron Calculator and Unit Converter')
buttonBase1 = widget_base(tlb,/col)
buttonBase2 = widget_base(tlb,/col)
plotBase = widget_base(tlb,/col)
fieldSize = 15

strvalue = strarr(2)
strvalue = ['Type a number in any of','the fields and hit enter']
textField = widget_text(buttonBase1,xsize = 20,ysize = 2,value = strvalue)


IF n_elements(LambdaEntry) EQ 0 THEN BEGIN
laminit = 4.86632
kinit = 1.29116
eueV = 3454.37120
emeV = 3.45437
eTHZ = 0.83526
eGHZ = 835.26317
eiCM = 27.86137
ENDIF ELSE BEGIN
laminit = double(LambdaEntry)
kinit = 2.0d*!dpi/LambdaEntry
emeV = double(81.80320651/(LambdaEntry^2))
eueV = 1.0e3*emeV
eTHZ = double(emeV*0.2417989052)
eGHZ = double(emeV*241.7989052)
eiCM = double(emeV*8.06554097)
ENDELSE
waveLength = cw_field(buttonBase1,/string,title='wavelength (ang)',uvalue = laminit,$
             value=string(laminit),xsize=fieldSize,/column,$
             /return_events)
waveVector = cw_field(buttonBase1,/string,title='wavevector (inv ang)',$
             value=string(kinit),xsize=fieldSize,/column,$
             /return_events,uvalue = kinit )
energyueV = cw_field(buttonBase1,/string,title='E (ueV)',uvalue = eueV,$
             value=string(eueV),xsize=fieldSize,/column,/return_events)
energymeV = cw_field(buttonBase1,/string,title='E (meV)',uvalue = emeV,$
             value=string(emeV),xsize=fieldSize,/column,/return_events)
energyTHz = cw_field(buttonBase1,/string,title='E (THz)',uvalue = eTHZ,$
             value=string(eTHZ),xsize=fieldSize,/column,/return_events)
energyGHz = cw_field(buttonBase1,/string,title='E (GHz)',uvalue = eGHZ,$
             value=string(eGHZ),xsize=fieldSize,/column,/return_events)
energyinvcm = cw_field(buttonBase1,/string,title='E (inv cm)',uvalue = eiCM,$
             value=string(eiCM),xsize=fieldSize,/column,/return_events)


void = widget_button(buttonBase1,value = 'Exit',event_pro = 'NeutCalcDone')


winxsize = 400 & winysize = 300
plotWin = widget_draw(plotBase,xsize = winxsize,ysize = winysize,/motion_events,$
          /button_events,event_pro = 'neut_calcWinDraw')
angleBase = widget_base(plotBase,/row)
anglo = 11.217 & anghi = 129.405

philo = cw_field(angleBase,/string,title='Low angle (degrees)',$
             value=string(anglo),xsize=fieldSize,/column,/return_events,/row)
phihi = cw_field(angleBase,/string,title='High angle (degrees)',$
             value=string(anghi),xsize=fieldSize,/column,/return_events,/row)

values = ['Direct', '(Inverse)']
specType = cw_bgroup(angleBase, values, /row, /exclusive,$
           label_top='Spectrometer Geometry',/no_release,$
           /frame,set_value=0,/return_index,uvalue = 'geom')
centertlb,tlb
widget_control,tlb,/realize

device,decomposed = 0
colors = hfbs_GetColor(/Load, Start=1)
initvals = {emeV:emeV,anglo:anglo,anghi:anghi,colors:colors}
white = colors.white
red = colors.red
yellow = colors.yellow
blue = colors.blue
black = colors.black

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

;wset,winVis
;neut_calcSolveTriangle,0L,initvals = initvals

state = {waveLength:waveLength,$
         waveVector:waveVector,$
         energyueV:energyueV,$
         energymeV:energymeV,$
         energyGHz:energyGHz,$
         energyTHz:energyTHz,$
         energyinvcm:energyinvcm,$
         winxsize:winxsize,$
         winysize:winysize,$
         plotWin:plotWin,$
         winPix:winPix,$
         winVis:winVis,$
         philo:philo,$
         phihi:phihi,$
         mouse:0,$
         xp1:0.0,$
         yp1:0.0,$
         xp2:0.0,$
         yp2:0.0,$
         neutcalc:0,$
         xlo:0.0,$
         ylo:0.0,$
         xhi:1.0,$
         yhi:1.0,$
         autoscale:1,$
         specType:specType,$
         white:white,$
         red:red,$
         yellow:yellow,$
         blue:blue,$
         black:black,$
         title:'',$
         firstTime:1,$
         rorig:rorig,$
         gorig:gorig,$
         borig:borig,$
         inPtr:inPtr,$
         notifyIDs:notifyIDs}

pState = ptr_new(state)


widget_control,tlb,set_uvalue = pState
;neut_calcSolveTriangle,{event,top:tlb,id:void,handler:0l}
neut_calcSolveTriangle,{event,id:void,top:tlb,handler:0l}
ret = dave_set_focus(tlb)
xmanager,'neut_calc',tlb,/no_block,cleanup = 'neut_calcCleanup'
end
