; $Id: pan.pro,v 1.20 2002/08/23 18:00:53 dimeo Exp $
; PAN.PRO
;
; Version 1.0	(12/07/01)
;
; Procedure widget which allows user to add
; any number of various curve types
; to a data set (possibly as an initial condition for
; a curve fitting routine) using only the
; mouse to determine the position and amplitude.
;
; curveType:
;				0 = gaussian
;				1 = lorentzian
;				2 = sloping background
;				3 = lognormal (symmetric)
;				4 = Voigt function
;				5 = smooth step function
;				6 = damped harmonic oscillator
;				7 = Kohlrausch function
;				8 = methyl tunneling EISF
;			  	9 = 3-site jump EISF
;			   10 = 2-site jump EISF
;			  999 = pseudo-Dirac delta function (only when resolution
;					function is present!)

;
;
; Written by R.M.Dimeo (5/6/2001: Version 0.1)
;
; Modification history:
; --------------------
;
; 5/12/2001 (RMD):	Added widget sensitivity so that user cannot generate any
;					events while dragging or modifying a fit function or while
;					the program is fitting the data.
;
;					Converted widget program to a procedure and rearranged application
;					to accomodate menu bars.  Also had to modify RMDCallPeakAnalysis.pro
;					and launch_ncnr.pro to include an extra keyword, FROMNCNR.
;
; 5/17/2001: (RMD)	Corrected problem with DHO, Lognormal, and Voigt where
;					changing the width dynamically resulted in "jitter".
;
; 5/18/2001 (RMD):	Added fit parameters, errors and a plot of the residuals
;					in the postscript output.
;
; 5/20/2001 (RMD):	User can fit same set of fit functions to multiple groups automatically
;					as specified.
;
; 5/23/2001 (RMD):	User can export the group dependence of a fit parameter out to a separate
;					plotting window or a text file (which can be read in to the program and
;					analyzed).
;
; 5/28/2001 (RMD):	Incorporated a 'pseudo-delta function' which can be used whenever a
;					resolution function is present.  This simply uses a trick with the
;					error function that relies on the fact that a gaussian is exactly a
;					delta function in the limit of vanishing width (sigma).
;
; 6/08/2001 (RMD):	Added 3-site jump model EISF.
;
; 11/12/01 (RMD):	Began modifications to work within DAVE.  Note that I have also begun
;                             fixing all of the memory leaks (it leaks like a sieve!!!)
;
; 12/02/01 (RMD):	Replaced convolution code with HFBS_CONVOL.PRO which also takes into
;					consideration convolution with a pseudo-delta function and irregularly
;					gridded data.
;
; 12/05/01 (RMD):	Put functionality of the Kohlrausch function back in for DAVE implementation.
;
; 12/06/01 (RMD):	Fixed a bug when launching the program for the second time within a single
;					session...it would crash before.  Note that this required a small modification
;					to the procedure FDAVELAUNCHPAN.PRO.
;
; 12/07/01 (RMD):	Replaced WIDGET_DROPLIST for curve type selection with HFBS_PDMENU.PRO.  This
;					is IDL's CW_PDMENU.PRO modified so that it accepts the XSIZE keyword.  This was
; 					necessary because WIDGET_DROPLIST does not behave properly on the MAC platform.
;
;					When cycling through the various fit groups to plot either the EISF or a particular
;					parameter, the data and fit for each group are no longer displayed.  This results in
;					a substantial economy for this process.
;
;					Made a minor cosmetic change so that when a DAVE file is loaded into PAN, the
;					"Select Groups" text field reflects the minimum to maximum group numbers.
;
; 12/10/01 (RMD):	"Save Data and Fits" now prints out all of the data and fits that are selected
;					in the "Select Groups" field, regardless if there are fits or not in those fields.
;
; 12/13/01 (RMD):	Fixed a bug with convoluting data for a single group.  Also fixed a bug with adding
;					a sloping background.
;
; 01/03/02 (RMD):	-Added a new option (under FILE menu selection) for user to load a test data set.
;					-User can save fit parameters as a text file.
;					-If resolution function used in fit, the fit components are convoluted prior to display
;					 and prior to writing them out to a file.
;
;  01/04/02 (RMD):	-Fixed bug with rebinning data when a resolution function is present.
;
;  01/09/02 (RMD):	-Speed of curve fitting increased by passing pointers to the Kohlrausch table
;					values into the fit function rather than the values themselves.
;
;  01/28/02 (RMD):	-Removed the option to sum groups and put them into group 1.
;					-Fixed numerous bugs present when user rebins data, changes groups, fits data, etc.
;					-Fixed a bug found when reading in a resolution function that has a different number
;					 of elements than the signal file.
;
;  02/27/02 (RMD):	-Modified the test data set so that it uses multiple Q-values and simulates the
;					 tunneling spectrum of a methyl group.
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
pro PANCleanup,tlb
widget_control,tlb,get_uvalue = pState
tvlct,(*pState).rorig,(*pState).gorig,(*pState).borig
wdelete,(*pState).winPixId
wdelete,(*pState).winPixId2
thisPtr = !dave_defaults

; Remove all pointers not necessary for apps external to this one
if ptr_valid((*pState).inPtr) then begin
  dave_beast_ops,"get_ptrs",(*pState).inPtr,show_analysis = 0,show_commands = 0,bpointers = bptrs
  bptrs = reverse(bptrs)
  nb = n_elements(bptrs)			  ; number of pointers we want to keep
  zptrs = ptr_valid(count = nz)		  ; total number of all pointers
  if nz gt 0 then begin
    for i = 0,nz-1 do begin
      thisOne = where((bptrs eq zptrs[i]) or (zptrs[i] eq pState),count)
      if count eq 0 then begin
        if zptrs[i] ne thisPtr then ptr_free,zptrs[i]
      endif
    endfor
  endif

dave_beast_ops,"get_ptrs",(*pState).inPtr,show_analysis = 0,show_commands = 0,bpointers = bptrs
endif


s = size((*pState).notifyIDs)
if s[0] eq 1 then count = 0 else count = s[2]-1
for j = 0,count do begin
 ; dave_beast_ops,"duplicate",(*pState).inPtr,outPtr,show_analysis = 0,show_commands = 0
  PANInfo = {PANEvent,$
                        ID:(*pState).notifyIDs[0,j],$
                        Top:(*pState).notifyIDs[1,j],$
                        Handler:0l,$
                        inPtr:(*pState).inPtr}
  if widget_info((*pState).notifyIDs[0,j],/valid_id) then begin $
    widget_control,(*pState).notifyIDs[0,j],send_event = PANInfo
  endif
endfor

return
end
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
pro donePeakAnalysis,event
widget_control,event.top,get_uvalue = pState
widget_control,(*pState).textFit,get_uvalue = bigParmPtr
if n_elements(bigParmPtr) gt 1 then begin
  for i = 0,n_elements(bigParmPtr)-1 do begin
    parmStr = *bigParmPtr[i]
    dave_beast_ops,"remove",parmStr,show_analysis = 0,show_commands = 0
  endfor
  ptr_free,bigParmPtr
endif else begin
ptr_free,bigParmPtr
endelse

widget_control,event.top,/destroy
return
end
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
pro acceptGetPrinterNumber,event
widget_control,event.top, get_uvalue = pState
widget_control,(*pState).bgroup,get_value = printerVal
printerVal = fix(printerVal[0])
case printerVal of
0:  begin
    *(*pState).printerPtr = '0'
    end
1:  begin
    *(*pState).printerPtr = '3'
    end
2:  begin
    *(*pState).printerPtr = '99'
    end
else:
endcase

widget_control,event.top,/destroy
return
end
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
pro cancelGetPrinterNumber,event
widget_control,event.top, get_uvalue = pState
(*pState).printerPtr = ptr_new('-1')
widget_control,event.top,/destroy
return
end
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
pro getPrinterNumber_event,event
return
end
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
function getPrinterNumber,group_leader = group
if n_elements(group) ne 0 then begin
  tlb = widget_base(group_leader = group,/col,/modal)
endif else begin
  tlb = widget_base(group_leader = group,/col)
endelse
printerNames = ['lp0','lp3','Postscript File']
printerValue = 1
bgroup= cw_bgroup(tlb, printerNames, /COLUMN, /EXCLUSIVE, $
                          LABEL_TOP='Select Printer Destination', $
                          /FRAME,set_value=printerValue)
void = widget_button(tlb,value = 'accept',$
                     event_pro = 'acceptGetPrinterNumber',xsize = butsize)
void = widget_button(tlb,value = 'cancel',$
                     event_pro = 'cancelGetPrinterNumber',xsize = butsize)
widget_control,tlb,/realize
printerPtr = ptr_new('-1')
state = {bgroup:bgroup,printerValue:printerValue,printerPtr:printerPtr}
pState = ptr_new(state)
widget_control,tlb,set_uvalue = pState
xmanager,'getPrinterNumber',tlb
return,printerPtr
end
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
PRO AboutPeakAnalysis,event
disp_text = [['PAN version 1.0 (01/04/02)'],['Written by R.M.Dimeo'],['May 6, 2001'],$
             ['NIST Center for Neutron Research']]
void = dialog_message(disp_text,/information,title = 'About Peak Analysis')
RETURN
END
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
function parmStructDefine,z
;indlimPtr = ptr_new()
parmStr = {ngauss:0,$
           nlorentz:0,$
           resLimit:999.0,$
           nBg:0,$
           nlognormal:0,$
           nvoigt:0,$
           nss:0,$
           nDHO:0,$
           nDelta:0,$
           ntunnelEISF:0,$
           nthreeSiteEISF:0,$
           ntwoSiteEISF:0,$
           nkohl:0,$
           kohlParmPtr:ptr_new(/allocate_heap),$
           kohlParmErrPtr:ptr_new(/allocate_heap),$
           kohlParmFixPtr:ptr_new(/allocate_heap),$
           kohlConstraintPtr:ptr_new(/allocate_heap),$
           kohlStepPtr:ptr_new(/allocate_heap),$
           kohlNames:['amplitude','beta','tau'],$
           DHOParmPtr:ptr_new(/allocate_heap),$
           DHOParmErrPtr:ptr_new(/allocate_heap),$
           DHOParmFixPtr:ptr_new(/allocate_heap),$
           DHOConstraintPtr:ptr_new(/allocate_heap),$
           DHONames:['amplitude','cen (damped)','fwhm','temperature'],$
           DHOStepPtr:ptr_new(/allocate_heap),$
           deltaParmPtr:ptr_new(/allocate_heap),$
           deltaParmErrPtr:ptr_new(/allocate_heap),$
           deltaParmFixPtr:ptr_new(/allocate_heap),$
           deltaConstraintPtr:ptr_new(/allocate_heap),$
           deltaNames:['area','center','fwhm'],$
           deltaStepPtr:ptr_new(/allocate_heap),$
           tunnelEISFParmPtr:ptr_new(/allocate_heap),$
           tunnelEISFParmErrPtr:ptr_new(/allocate_heap),$
           tunnelEISFParmFixPtr:ptr_new(/allocate_heap),$
           tunnelEISFConstraintPtr:ptr_new(/allocate_heap),$
           tunnelEISFNames:['radius'],$
           tunnelEISFStepPtr:ptr_new(/allocate_heap),$
           threeSiteEISFParmPtr:ptr_new(/allocate_heap),$
           threeSiteEISFParmErrPtr:ptr_new(/allocate_heap),$
           threeSiteEISFParmFixPtr:ptr_new(/allocate_heap),$
           threeSiteEISFConstraintPtr:ptr_new(/allocate_heap),$
           threeSiteEISFNames:['radius'],$
           threeSiteEISFStepPtr:ptr_new(/allocate_heap),$
           twoSiteEISFParmPtr:ptr_new(/allocate_heap),$
           twoSiteEISFParmErrPtr:ptr_new(/allocate_heap),$
           twoSiteEISFParmFixPtr:ptr_new(/allocate_heap),$
           twoSiteEISFConstraintPtr:ptr_new(/allocate_heap),$
           twoSiteEISFNames:['radius'],$
           twoSiteEISFStepPtr:ptr_new(/allocate_heap),$
           gaussParmPtr:ptr_new(/allocate_heap),$
           gaussParmErrPtr:ptr_new(/allocate_heap),$
           gaussParmFixPtr:ptr_new(/allocate_heap),$
           gaussConstraintPtr:ptr_new(/allocate_heap),$
           gaussNames:['area','cen','fwhm'],$
           gaussStepPtr:ptr_new(/allocate_heap),$
           ssParmPtr:ptr_new(/allocate_heap),$
           ssParmErrPtr:ptr_new(/allocate_heap),$
           ssParmFixPtr:ptr_new(/allocate_heap),$
           ssConstraintPtr:ptr_new(/allocate_heap),$
           ssNames:['area','cen','fwhm'],$
           ssStepPtr:ptr_new(/allocate_heap),$
           lorentzParmPtr:ptr_new(/allocate_heap),$
           lorentzParmErrPtr:ptr_new(/allocate_heap),$'
           lorentzParmFixPtr:ptr_new(/allocate_heap),$
           lorentzConstraintPtr:ptr_new(/allocate_heap),$
           lorentzNames:['area','cen','fwhm'],$
           lorentzStepPtr:ptr_new(/allocate_heap),$
           bgParmPtr:ptr_new(/allocate_heap),$
           bgParmFixPtr:ptr_new(/allocate_heap),$
           bgParmErrPtr:ptr_new(/allocate_heap),$
           bgConstraintPtr:ptr_new(/allocate_heap),$
           bgStepPtr:ptr_new(/allocate_heap),$
           voigtParmPtr:ptr_new(/allocate_heap),$
           voigtParmErrPtr:ptr_new(/allocate_heap),$
           voigtParmFixPtr:ptr_new(/allocate_heap),$
           voigtConstraintPtr:ptr_new(/allocate_heap),$
           voigtNames:['area','cen','width'],$
           voigtStepPtr:ptr_new(/allocate_heap),$
           logNormParmPtr:ptr_new(/allocate_heap),$
           logNormParmFixPtr:ptr_new(/allocate_heap),$
           logNormParmErrPtr:ptr_new(/allocate_heap),$
           logNormConstraintPtr:ptr_new(/allocate_heap),$
           logNormNames:['area','cen','sigma'],$
           logNormStepPtr:ptr_new(/allocate_heap),$
           fitting:0,$
           chisq:0.0,$
           indlimPtr:ptr_new(/allocate_heap),$
           xPtr:ptr_new(/allocate_heap),$
           xdiffPtr:ptr_new(/allocate_heap),$
           resDataPtr:ptr_new(/allocate_heap),$
           curveIdPtr:ptr_new(/allocate_heap)}

return,parmStr
end
;;;;;;;;;;;;;;;;;;;;;;
pro RMDPAEquateStructures,inStr,outStr
; This routine does not copy memory location but the value into
; a NEW memory location.  This only works with structure one-deep!
;
outStr = parmStructDefine()
inStr.indlimPtr = ptr_new()
outStr = inStr

names = tag_names(inStr)
number = n_tags(inStr)
for i = 0,number-1 do begin
  inVarString = strtrim('inStr.',2)+names[i]
  outVarString = strtrim('outStr.',2)+names[i]
  expression = 'help,'+inVarString+',output = output'
  result = execute(expression)
  pointer = strpos(output,'POINTER')
  nullpointer = strpos(output,'NullPointer')
  if pointer[0] ne -1 then begin	; it's a pointer
    if nullpointer[0] eq -1 then begin	; it's a good pointer
      doThis = outVarString+'='+'ptr_new(*'+outVarString+')
    endif else begin				; it's a null pointer
      doThis = outVarString+'=ptr_new()'
    endelse
    result = execute(doThis)
  endif
endfor

return
end
;==========================================
Function RMDPAChooseDets,strdets
;
; Input: 	string containing detector numbers separated either by
;        	commas or - (hyphens).  A hyphen indicates to include the
;        	two detectors and all detectors in between.  A comma simply
;        	means to append that detector to the current list.
;
; Output:	a pointer to an array containing all of the detectors to be
;			summed together.
;
; Catch errors in input string
;nerror = strmid(strdets,0)
nerror = strmid(strdets,0,1)
if (nerror[0] eq '-') or (nerror[0] eq ',') or (nerror[0] eq ' ') then begin
  void = dialog_message(parent = event.top,'Not a valid input field',$
           dialog_parent=event.top)
  return,0
endif
strdets = strcompress(strdets)
test1 = strpos(strdets,'-,')
test2 = strpos(strdets,',-')
if test1[0] ne -1 or test2[0] ne -1 then begin
  void = dialog_message(parent = event.top,'Not a valid input field',$
           dialog_parent=event.top)
  return,0
endif

; count the number of commas occurring in the string
i = 0
inum = 0
cnt = 0
commacnt = intarr(50)
while (inum ne -1) do begin
  i = strpos(strdets,',',i)
  inum = i[0]
  if (inum ne -1) then begin
    commacnt[cnt] = inum
    cnt = cnt+1
    inum = inum + 1
    i = inum
  endif
endwhile
ncommas = cnt
if ncommas gt 0 then begin
  commaPos = intarr(ncommas)
  commaPos = commacnt[0:ncommas-1]
endif
;commaPos = [-1,commaPos[0:ncommas-1]]

; if there are no commas then there are two possibilities
; either there is a single detector present.....
ndash = strpos(strdets,'-')
if (ncommas eq 0) and (ndash[0] eq -1) then begin
  detnum = fix(strdets)
  ndets = 1
  dets = detnum
endif

; or there are a sum of detectors present
if (ncommas eq 0) and (ndash[0] ne -1) then begin
  pos = strpos(strdets,'-')
  len = strlen(strdets)
  numstr1 = strmid(strdets,0,pos[0])
  numstr2 = strmid(strdets,pos[0]+1,len[0]-1)
  num1 = fix(numstr1)
  num2 = fix(numstr2)
  ndets = num2[0] - num1[0] + 1
  dets = intarr(ndets)
  dets = num1[0] + INDGEN(ndets)
endif

; are there one or more commas?
if (ncommas gt 0) then begin
  dets = intarr(100)
  totlen=strlen(strdets)		; total length of the input string
  smallLen = intarr(ncommas+1)	; array defining the length of all substrings in string
								; variable strdets
  smallLen[0] = commaPos[0]
  for i=1,ncommas-1 do begin
      smallLen[i] = commaPos[i]-commaPos[i-1]-1
  endfor
  smallLen[ncommas] = totlen-commaPos[ncommas-1]-1

  substrings = strarr(ncommas+1)	; string array representing string form of detectors to sum
  substrings[0]=strmid(strdets,0,smallLen[0])
  for i = 1,ncommas do begin
    substrings[i]=strmid(strdets,commaPos[i-1]+1,smallLen[i])
  endfor

  ; convert substrings to an array of numbers
  count = 0
  for i = 0,ncommas do begin

    dashpresent = strpos(substrings[i],'-')
    dash = dashpresent[0]

    if dash eq -1 then begin
      detnum = fix(substrings[i])
      ndets = 1
      dets[count] = detnum[0]
      count = count+1
    endif

    if dash ne -1 then begin

      pos = strpos(substrings[i],'-')
      len = strlen(substrings[i])
      numstr1 = strmid(substrings[i],0,pos[0])
      numstr2 = strmid(substrings[i],pos[0]+1,len[0]-1)
      num1 = fix(numstr1)
      num2 = fix(numstr2)
      ndets = num2[0] - num1[0] + 1
      singledets = intarr(ndets)
      singledets = num1[0] + INDGEN(ndets)
      dets[count:count+ndets-1] = singledets[0:ndets-1]
      count = count+ndets
    endif
  endfor

ndets = count
tempdets = intarr(ndets)
tempdets[0:ndets-1] = dets[0:ndets-1]
dets = intarr(ndets)
dets[0:ndets-1] = tempdets[0:ndets-1]
endif
newdetPtr = ptr_new(dets)
RETURN,newdetPtr
END
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
PRO deSensitizeWidgets,event
widget_control,event.top,get_uvalue = pState
if (*pState).platform ne 3 then begin
  widget_control,(*pState).fitButton,sensitive = 0
  widget_control,(*pState).drop,sensitive = 0
  widget_control,(*pState).removeButton,sensitive = 0
  widget_control,(*pState).clearButton,sensitive = 0
  widget_control,(*pState).loadResButton,sensitive = 0
  widget_control,(*pState).modParms,sensitive = 0
;  widget_control,(*pState).tieParms,sensitive = 0
  widget_control,(*pState).displayButton,sensitive = 0

  widget_control,(*pState).filemenu,sensitive = 0
  widget_control,(*pState).plotmenu,sensitive = 0
  widget_control,(*pState).rebinmenu,sensitive = 0
  widget_control,(*pState).printmenu,sensitive = 0
  widget_control,(*pState).miscmenu,sensitive = 0
  widget_control,(*pState).resmenu,sensitive = 0

  widget_control,(*pState).clearResButton,sensitive = 0
  widget_control,(*pState).doneButton,sensitive = 0
  widget_control,(*pState).pickCurve,sensitive = 0

  widget_control,(*pState).drop,sensitive = 0
  widget_control,(*pState).xfitlo,sensitive = 0
  widget_control,(*pState).xfithi,sensitive = 0
  if (*pState).ngroups gt 1 then begin
    widget_control,(*pState).autoFitButton,sensitive = 0
  endif
endif
widget_control,event.top,/clear_events

RETURN
END
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
PRO sensitizeWidgets,event
widget_control,event.top,get_uvalue = pState
if (*pState).platform ne 3 then begin
  widget_control,(*pState).fitButton,sensitive = 1
  widget_control,(*pState).removeButton,sensitive = 1
  widget_control,(*pState).drop,sensitive = 1
  widget_control,(*pState).clearButton,sensitive = 1
  widget_control,(*pState).loadResButton,sensitive = 1
  widget_control,(*pState).modParms,sensitive = 1
;  widget_control,(*pState).tieParms,sensitive = 1
  widget_control,(*pState).displayButton,sensitive = 1

  widget_control,(*pState).filemenu,sensitive = 1
  widget_control,(*pState).plotmenu,sensitive = 1
  widget_control,(*pState).rebinmenu,sensitive = 1
  widget_control,(*pState).printmenu,sensitive = 1
  widget_control,(*pState).miscmenu,sensitive = 1
  widget_control,(*pState).resmenu,sensitive = 1

  widget_control,(*pState).clearResButton,sensitive = 1
  widget_control,(*pState).doneButton,sensitive = 1
  widget_control,(*pState).pickCurve,sensitive = 1

  widget_control,(*pState).drop,sensitive = 1
  widget_control,(*pState).xfitlo,sensitive = 1
  widget_control,(*pState).xfithi,sensitive = 1
  if (*pState).ngroups gt 1 then begin
    widget_control,(*pState).autoFitButton,sensitive = 1
  endif
endif
widget_control,event.top,/clear_events

RETURN
END
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
pro freeThePointer,thisPointer
if ptr_valid(thisPointer) then ptr_free,thisPointer
return
end
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
function calcNumberOfCurves,parmStr
number = parmStr.ngauss+parmStr.nlorentz+$
         parmStr.nbg+parmStr.nlognormal+$
         parmStr.nvoigt+$
         parmStr.nss+$
         parmStr.nDHO+$
         parmStr.nDelta+$
         parmStr.ntunnelEISF+$
         parmStr.nkohl+$
         parmStr.nthreeSiteEISF+$
		 parmStr.ntwoSiteEISF
return,number
end
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
function calcNumberOfParms,parmStr
number = 3*parmStr.ngauss+$
         3*parmStr.nlorentz+$
         2*parmStr.nbg+$
         3*parmStr.nlognormal+$
         3*parmStr.nvoigt+$
         3*parmStr.nss+$
         4*parmStr.nDHO+$
         3*parmStr.nDelta+$
         parmStr.ntunnelEISF+$
         3*parmStr.nkohl+$
         parmStr.nthreeSiteEISF+$
         parmStr.ntwoSiteEISF
return,number
end
;;;;;;;;;;;;;;;;;;;
function convertStructureToParms,parmStr,FIXARRAY = fixarray,$
                                 UPPERARRAY = upperarray,$
                                 LOWERARRAY = lowerarray,$
                                 HILIMITS = hilimits,$
                                 LOLIMITS = lolimits,$
                                 STEPARRAY = steparray,$
                                 C1 = c1,$	; input curve number
                                 C2 = c2,$	; input curve number
                                 P1 = p1,$	; input parameter number
                                 P2 = p2,$	; input parameter number
                                 TIEPARM1 = tieparm1,$	; output parameter number
                                 TIEPARM2 = tieparm2	; output parameter number

; Creates the "fit" vector of parameters based on the
; contents of the structure parmStr
; Also creates the "fix" vector (0 for float, 1 for fixed)
;
nparms = calcNumberOfParms(parmStr)
parms = dblarr(nparms)
fixarray = intarr(nparms)
upperarray = intarr(nparms)
lowerarray = intarr(nparms)
hilimits = fltarr(nparms)
lolimits = fltarr(nparms)
steparray = fltarr(nparms)
curveOrder = *parmStr.curveIdPtr	; this line added (7/26/01)
count = 0
if parmStr.ngauss gt 0 then begin
  for i = 0,parmStr.ngauss-1 do begin
    parms[count:count+2]   = (*parmStr.gaussParmPtr)[3*i:3*i+2]
    fixarray[count:count+2]   = (*parmStr.gaussParmFixPtr)[3*i:3*i+2]
    upperarray[count:count+2]   = (*(*parmStr.gaussConstraintPtr).checkHiLimPtr)[3*i:3*i+2]
    lowerarray[count:count+2]   = (*(*parmStr.gaussConstraintPtr).checkLoLimPtr)[3*i:3*i+2]
    hilimits[count:count+2]   = (*(*parmStr.gaussConstraintPtr).HiLimPtr)[3*i:3*i+2]
    lolimits[count:count+2]   = (*(*parmStr.gaussConstraintPtr).LoLimPtr)[3*i:3*i+2]
    steparray[count:count+2] =  (*parmStr.gaussStepPtr)[3*i:3*i+2]
    count = count+3
  endfor
endif
if parmStr.nlorentz gt 0 then begin
  for i = 0,parmStr.nlorentz-1 do begin
    parms[count:count+2]   = (*parmStr.lorentzParmPtr)[3*i:3*i+2]
    fixarray[count:count+2]   = (*parmStr.lorentzParmFixPtr)[3*i:3*i+2]
    upperarray[count:count+2]   = (*(*parmStr.lorentzConstraintPtr).checkHiLimPtr)[3*i:3*i+2]
    lowerarray[count:count+2]   = (*(*parmStr.lorentzConstraintPtr).checkLoLimPtr)[3*i:3*i+2]
    hilimits[count:count+2]   = (*(*parmStr.lorentzConstraintPtr).HiLimPtr)[3*i:3*i+2]
    lolimits[count:count+2]   = (*(*parmStr.lorentzConstraintPtr).LoLimPtr)[3*i:3*i+2]
    steparray[count:count+2] =  (*parmStr.lorentzStepPtr)[3*i:3*i+2]
    count = count+3
  endfor
endif
if parmStr.nbg eq 1 then begin
  parms[count:count+1] = (*parmStr.bgParmPtr)[0:1]
  fixarray[count:count+1] = (*parmStr.bgParmFixPtr)[0:1]
    upperarray[count:count+1]   = (*(*parmStr.bgConstraintPtr).checkHiLimPtr)[0:1]
    lowerarray[count:count+1]   = (*(*parmStr.bgConstraintPtr).checkLoLimPtr)[0:1]
    hilimits[count:count+1]   = (*(*parmStr.bgConstraintPtr).HiLimPtr)[0:1]
    lolimits[count:count+1]   = (*(*parmStr.bgConstraintPtr).LoLimPtr)[0:1]
    steparray[count:count+1] =  (*parmStr.bgStepPtr)[0:1]
  count = count+2
endif
if parmStr.nvoigt gt 0 then begin
  for i = 0,parmStr.nvoigt-1 do begin
    parms[count:count+2]   = (*parmStr.voigtParmPtr)[3*i:3*i+2]
    fixarray[count:count+2]   = (*parmStr.voigtParmFixPtr)[3*i:3*i+2]
    upperarray[count:count+2]   = (*(*parmStr.voigtConstraintPtr).checkHiLimPtr)[3*i:3*i+2]
    lowerarray[count:count+2]   = (*(*parmStr.voigtConstraintPtr).checkLoLimPtr)[3*i:3*i+2]
    hilimits[count:count+2]   = (*(*parmStr.voigtConstraintPtr).HiLimPtr)[3*i:3*i+2]
    lolimits[count:count+2]   = (*(*parmStr.voigtConstraintPtr).LoLimPtr)[3*i:3*i+2]
    steparray[count:count+2] =  (*parmStr.voigtStepPtr)[3*i:3*i+2]
    count = count+3
  endfor
endif
if parmStr.nlognormal gt 0 then begin
  for i = 0,parmStr.nlognormal-1 do begin
    parms[count:count+2]   = (*parmStr.logNormParmPtr)[3*i:3*i+2]
    fixarray[count:count+2]   = (*parmStr.logNormParmFixPtr)[3*i:3*i+2]
    upperarray[count:count+2]   = (*(*parmStr.logNormConstraintPtr).checkHiLimPtr)[3*i:3*i+2]
    lowerarray[count:count+2]   = (*(*parmStr.logNormConstraintPtr).checkLoLimPtr)[3*i:3*i+2]
    hilimits[count:count+2]   = (*(*parmStr.logNormConstraintPtr).HiLimPtr)[3*i:3*i+2]
    lolimits[count:count+2]   = (*(*parmStr.logNormConstraintPtr).LoLimPtr)[3*i:3*i+2]
    steparray[count:count+2] =  (*parmStr.logNormStepPtr)[3*i:3*i+2]
    count = count+3
  endfor
endif
if parmStr.nss gt 0 then begin
  for i = 0,parmStr.nss-1 do begin
    parms[count:count+2]   = (*parmStr.ssParmPtr)[3*i:3*i+2]
    fixarray[count:count+2]   = (*parmStr.ssParmFixPtr)[3*i:3*i+2]
    upperarray[count:count+2]   = (*(*parmStr.ssConstraintPtr).checkHiLimPtr)[3*i:3*i+2]
    lowerarray[count:count+2]   = (*(*parmStr.ssConstraintPtr).checkLoLimPtr)[3*i:3*i+2]
    hilimits[count:count+2]   = (*(*parmStr.ssConstraintPtr).HiLimPtr)[3*i:3*i+2]
    lolimits[count:count+2]   = (*(*parmStr.ssConstraintPtr).LoLimPtr)[3*i:3*i+2]
    steparray[count:count+2] =  (*parmStr.ssStepPtr)[3*i:3*i+2]
    count = count+3
  endfor
endif
if parmStr.nDHO gt 0 then begin
  for i = 0,parmStr.nDHO-1 do begin
    parms[count:count+3]   = (*parmStr.DHOParmPtr)[4*i:4*i+3]
    fixarray[count:count+3]   = (*parmStr.DHOParmFixPtr)[4*i:4*i+3]
    upperarray[count:count+3]   = (*(*parmStr.DHOConstraintPtr).checkHiLimPtr)[4*i:4*i+3]
    lowerarray[count:count+3]   = (*(*parmStr.DHOConstraintPtr).checkLoLimPtr)[4*i:4*i+3]
    hilimits[count:count+3]   = (*(*parmStr.DHOConstraintPtr).HiLimPtr)[4*i:4*i+3]
    lolimits[count:count+3]   = (*(*parmStr.DHOConstraintPtr).LoLimPtr)[4*i:4*i+3]
    steparray[count:count+3] =  (*parmStr.DHOStepPtr)[4*i:4*i+3]
    count = count+4
  endfor
endif
if parmStr.nkohl gt 0 then begin
  for i = 0,parmStr.nkohl-1 do begin
    parms[count:count+2]   = (*parmStr.kohlParmPtr)[3*i:3*i+2]
    fixarray[count:count+2]   = (*parmStr.kohlParmFixPtr)[3*i:3*i+2]
    upperarray[count:count+2]   = (*(*parmStr.kohlConstraintPtr).checkHiLimPtr)[3*i:3*i+2]
    lowerarray[count:count+2]   = (*(*parmStr.kohlConstraintPtr).checkLoLimPtr)[3*i:3*i+2]
    hilimits[count:count+2]   = (*(*parmStr.kohlConstraintPtr).HiLimPtr)[3*i:3*i+2]
    lolimits[count:count+2]   = (*(*parmStr.kohlConstraintPtr).LoLimPtr)[3*i:3*i+2]
    steparray[count:count+2] =  (*parmStr.kohlStepPtr)[3*i:3*i+2]
    count = count+3
  endfor
endif
if parmStr.ntunnelEISF gt 0 then begin
  for i = 0,parmStr.ntunnelEISF-1 do begin
    parms[count]   = (*parmStr.tunnelEISFParmPtr)[0]
    fixarray[count]   = (*parmStr.tunnelEISFParmFixPtr)[0]
    upperarray[count]   = (*(*parmStr.tunnelEISFConstraintPtr).checkHiLimPtr)[0]
    lowerarray[count]   = (*(*parmStr.tunnelEISFConstraintPtr).checkLoLimPtr)[0]
    hilimits[count]   = (*(*parmStr.tunnelEISFConstraintPtr).HiLimPtr)[0]
    lolimits[count]   = (*(*parmStr.tunnelEISFConstraintPtr).LoLimPtr)[0]
    steparray[count] =  (*parmStr.tunnelEISFStepPtr)[0]
    count = count+1
  endfor
endif
if parmStr.nthreeSiteEISF gt 0 then begin
  for i = 0,parmStr.nthreeSiteEISF-1 do begin
    parms[count]   = (*parmStr.threeSiteEISFParmPtr)[0]
    fixarray[count]   = (*parmStr.threeSiteEISFParmFixPtr)[0]
    upperarray[count]   = (*(*parmStr.threeSiteEISFConstraintPtr).checkHiLimPtr)[0]
    lowerarray[count]   = (*(*parmStr.threeSiteEISFConstraintPtr).checkLoLimPtr)[0]
    hilimits[count]   = (*(*parmStr.threeSiteEISFConstraintPtr).HiLimPtr)[0]
    lolimits[count]   = (*(*parmStr.threeSiteEISFConstraintPtr).LoLimPtr)[0]
    steparray[count] =  (*parmStr.threeSiteEISFStepPtr)[0]
    count = count+1
  endfor
endif
if parmStr.ntwoSiteEISF gt 0 then begin
  for i = 0,parmStr.ntwoSiteEISF-1 do begin
    parms[count]   = (*parmStr.twoSiteEISFParmPtr)[0]
    fixarray[count]   = (*parmStr.twoSiteEISFParmFixPtr)[0]
    upperarray[count]   = (*(*parmStr.twoSiteEISFConstraintPtr).checkHiLimPtr)[0]
    lowerarray[count]   = (*(*parmStr.twoSiteEISFConstraintPtr).checkLoLimPtr)[0]
    hilimits[count]   = (*(*parmStr.twoSiteEISFConstraintPtr).HiLimPtr)[0]
    lolimits[count]   = (*(*parmStr.twoSiteEISFConstraintPtr).LoLimPtr)[0]
    steparray[count] =  (*parmStr.twoSiteEISFStepPtr)[0]
    count = count+1
  endfor
endif
if parmStr.nDelta gt 0 then begin
  for i = 0,parmStr.nDelta-1 do begin
    parms[count:count+2]   = (*parmStr.deltaParmPtr)[3*i:3*i+2]
    fixarray[count:count+2]   = (*parmStr.deltaParmFixPtr)[3*i:3*i+2]
    upperarray[count:count+2]   = (*(*parmStr.deltaConstraintPtr).checkHiLimPtr)[3*i:3*i+2]
    lowerarray[count:count+2]   = (*(*parmStr.deltaConstraintPtr).checkLoLimPtr)[3*i:3*i+2]
    hilimits[count:count+2]   = (*(*parmStr.deltaConstraintPtr).HiLimPtr)[3*i:3*i+2]
    lolimits[count:count+2]   = (*(*parmStr.deltaConstraintPtr).LoLimPtr)[3*i:3*i+2]
    steparray[count:count+2] =  (*parmStr.deltaStepPtr)[3*i:3*i+2]
    count = count+3
  endfor
endif

return,parms
end
;;;;;;;;;;;;;;;;;;;
function convertParmsToStructure,parmStr,parms,FIXARRAY = fixarray,SIGMA = sigma
; Creates the parmStr structure of parameters based on the
; contents of the vector parms
;
; Here the structure parmStr is passed in with any values
; so that the correct assignments of parameters can be made
; into the outgoing structure.
;
nparms =  calcNumberOfParms(parmStr)
count = 0
if parmStr.ngauss gt 0 then begin
  for i = 0,parmStr.ngauss-1 do begin
    (*parmStr.gaussParmPtr)[3*i:3*i+2] = parms[count:count+2]
    if n_elements(fixarray) gt 0 then begin
      (*parmStr.gaussParmFixPtr)[3*i:3*i+2] = fixarray[count:count+2]
    endif
    if n_elements(sigma) ne 0 then begin
      (*parmStr.gaussParmErrPtr)[3*i:3*i+2] = sigma[count:count+2]
    endif
    count = count+3
  endfor
endif
if parmStr.nlorentz gt 0 then begin
  for i = 0,parmStr.nlorentz-1 do begin
    (*parmStr.lorentzParmPtr)[3*i:3*i+2] = parms[count:count+2]
    if n_elements(fixarray) gt 0 then begin
      (*parmStr.lorentzParmFixPtr)[3*i:3*i+2] = fixarray[count:count+2]
    endif
    if n_elements(sigma) ne 0 then begin
      (*parmStr.lorentzParmErrPtr)[3*i:3*i+2] = sigma[count:count+2]
    endif
    count = count+3
  endfor
endif
if parmStr.nbg eq 1 then begin
  (*parmStr.bgParmPtr)[0:1] = parms[count:count+1]
    if n_elements(fixarray) gt 0 then begin
      (*parmStr.bgParmFixPtr)[0:1] = fixarray[count:count+1]
    endif
  if n_elements(sigma) ne 0 then begin
      (*parmStr.bgParmErrPtr)[0:1] = sigma[count:count+1]
  endif
  count = count + 2
endif
if parmStr.nvoigt gt 0 then begin
  for i = 0,parmStr.nvoigt-1 do begin
    (*parmStr.voigtParmPtr)[3*i:3*i+2] = parms[count:count+2]
    if n_elements(fixarray) gt 0 then begin
      (*parmStr.voigtParmFixPtr)[3*i:3*i+2] = fixarray[count:count+2]
    endif
    if n_elements(sigma) ne 0 then begin
      (*parmStr.voigtParmErrPtr)[3*i:3*i+2] = sigma[count:count+2]
    endif
    count = count+3
  endfor
endif
if parmStr.nlognormal gt 0 then begin
  for i = 0,parmStr.nlognormal-1 do begin
    (*parmStr.logNormParmPtr)[3*i:3*i+2] = parms[count:count+2]
    if n_elements(fixarray) gt 0 then begin
      (*parmStr.logNormParmFixPtr)[3*i:3*i+2] = fixarray[count:count+2]
    endif
    if n_elements(sigma) ne 0 then begin
      (*parmStr.logNormParmErrPtr)[3*i:3*i+2] = sigma[count:count+2]
    endif
    count = count+3
  endfor
endif
if parmStr.nss gt 0 then begin
  for i = 0,parmStr.nss-1 do begin
    (*parmStr.ssParmPtr)[3*i:3*i+2] = parms[count:count+2]
    if n_elements(fixarray) gt 0 then begin
      (*parmStr.ssParmFixPtr)[3*i:3*i+2] = fixarray[count:count+2]
    endif
    if n_elements(sigma) ne 0 then begin
      (*parmStr.ssParmErrPtr)[3*i:3*i+2] = sigma[count:count+2]
    endif
    count = count+3
  endfor
endif
if parmStr.nDHO gt 0 then begin
  for i = 0,parmStr.nDHO-1 do begin
    (*parmStr.DHOParmPtr)[4*i:4*i+3] = parms[count:count+3]
    if n_elements(fixarray) gt 0 then begin
      (*parmStr.DHOParmFixPtr)[4*i:4*i+3] = fixarray[count:count+3]
    endif
    if n_elements(sigma) ne 0 then begin
      (*parmStr.DHOParmErrPtr)[4*i:4*i+3] = sigma[count:count+3]
    endif
    count = count+4
  endfor
endif
if parmStr.nkohl gt 0 then begin
  for i = 0,parmStr.nkohl-1 do begin
    (*parmStr.kohlParmPtr)[3*i:3*i+2] = parms[count:count+2]
    if n_elements(fixarray) gt 0 then begin
      (*parmStr.kohlParmFixPtr)[3*i:3*i+2] = fixarray[count:count+2]
    endif
    if n_elements(sigma) ne 0 then begin
      (*parmStr.kohlParmErrPtr)[3*i:3*i+2] = sigma[count:count+2]
    endif
    count = count+3
  endfor
endif
if parmStr.ntunnelEISF eq 1 then begin
  (*parmStr.tunnelEISFParmPtr)[0] = parms[count]
    if n_elements(fixarray) gt 0 then begin
      (*parmStr.tunnelEISFParmFixPtr)[0] = fixarray[count]
    endif
  if n_elements(sigma) ne 0 then begin
      (*parmStr.tunnelEISFParmErrPtr)[0] = sigma[count]
  endif
  count = count + 1
endif
if parmStr.nthreeSiteEISF eq 1 then begin
  (*parmStr.threeSiteEISFParmPtr)[0] = parms[count]
    if n_elements(fixarray) gt 0 then begin
      (*parmStr.threeSiteEISFParmFixPtr)[0] = fixarray[count]
    endif
  if n_elements(sigma) ne 0 then begin
      (*parmStr.threeSiteEISFParmErrPtr)[0] = sigma[count]
  endif
  count = count + 1
endif
if parmStr.ntwoSiteEISF eq 1 then begin
  (*parmStr.twoSiteEISFParmPtr)[0] = parms[count]
    if n_elements(fixarray) gt 0 then begin
      (*parmStr.twoSiteEISFParmFixPtr)[0] = fixarray[count]
    endif
  if n_elements(sigma) ne 0 then begin
      (*parmStr.twoSiteEISFParmErrPtr)[0] = sigma[count]
  endif
  count = count + 1
endif
if parmStr.nDelta gt 0 then begin
  for i = 0,parmStr.nDelta-1 do begin
    (*parmStr.deltaParmPtr)[3*i:3*i+2] = parms[count:count+2]
    if n_elements(fixarray) gt 0 then begin
      (*parmStr.deltaParmFixPtr)[3*i:3*i+2] = fixarray[count:count+2]
    endif
    if n_elements(sigma) ne 0 then begin
      (*parmStr.deltaParmErrPtr)[3*i:3*i+2] = sigma[count:count+2]
    endif
    count = count+3
  endfor
endif
return,parmStr
end
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
function methylTunnelEisfFun,q,r
!except = 0
npts = n_elements(q)
y = dblarr(npts) & arg = dblarr(npts)
arg = abs(r*q*sqrt(3.0))
el = dblarr(npts) & in = dblarr(npts)
el = (5.0+4.0*beselj(arg,0))/9.0
in = (2.0-2.0*beselj(arg,0))/9.0
y = el;/(el+in)
return,y
end
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
function threeSiteEisfFun,q,r
!except = 0
npts = n_elements(q)
y = dblarr(npts) & arg = dblarr(npts)
arg = abs(r*q*sqrt(3.0))
y = (1.0+2.0*beselj(arg,0))/3.0
return,y
end
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
function twoSiteEisfFun,q,r
!except = 0
npts = n_elements(q)
y = dblarr(npts) & arg = dblarr(npts)
arg = abs(r*q)
y = (1.0+beselj(arg,0))/2.0
return,y
end
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
function gaussianGaussFun,x,amp,cen,wid
!except = 0
sig = wid/2.35
sig = abs(sig) > 1d-8
;amp = abs(amp) > 1d-8
npts = n_elements(x)
y = dblarr(npts)
y = (amp/sqrt(2.*!pi*sig^2))*exp(-0.5*((x-cen)/sig)^2)
return,y
end
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
function smoothStepFun,x,amp,cen,wid
!except = 0
sig = wid/2.35
npts = n_elements(x)
y = dblarr(npts)
y = (0.5*amp)*(1.0+errorf((x-cen)/sqrt(2.0*sig^2)))
return,y
end
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
function DHOFun,x,amp,cen,wid,temperature
!except = 0
cen = abs(cen)
gam = 0.5*wid
npts = n_elements(x)
bose = dblarr(npts)
wherevalid = where(x ne 0.0,count)
if count eq npts then begin
  bose = 1./(1.-exp(-11.6*x/temperature))
endif else begin
  wherenotvalid = where(x eq 0.0,newcount)
  bose[wherevalid] = 1./(1.-exp(-11.6*x[wherevalid]/temperature))
  bose[wherenotvalid] = 1./(1.-exp(-11.6*x[wherenotvalid]/temperature))
endelse
y = dblarr(npts)
y = bose*amp*(gam/!pi)*((1.0/((x-cen)^2+gam^2))-(1.0/((x+cen)^2+gam^2)))
return,y
end
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
function voigtian,x,amp,cen,wid
!except = 0
sigma = wid/sqrt(8.*alog(2.))
npts = n_elements(x)
y = dblarr(npts)
yvoigt = dblarr(npts)
yvoigt = voigt(sqrt(alog(2.0)),(x-cen)/sqrt(2.0*sigma^2))
y = (amp/sqrt(2.0*!dpi*sigma^2))*yvoigt/max(yvoigt)
return,y
end
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
function deltaFun,x,amp,cen,wid
!except = 0
sig = wid/2.35
sig = abs(sig) > 1d-8
;amp = abs(amp) > 1d-8
npts = n_elements(x)
y = dblarr(npts)
y = (amp/sqrt(2.*!pi*sig^2))*exp(-0.5*((x-cen)/sig)^2)
return,y
end
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
function logNormalFun,x,amp,cen,sig
!except = 0
npts = n_elements(x)
y = dblarr(npts)
wherezero = where(x eq 0.0,countZero)
whereNotZero = where(x ne 0.0)
y[whereNotZero] = (0.5*amp/(sqrt(2.0*!pi*sig^2)))*(1.0/abs(x[whereNotZero]))*$
                  exp(-0.5*(alog(abs(x[whereNotZero]))-abs(cen))^2/sig^2)
if countZero gt 0 then begin
  y[wherezero] = 0.0
endif
return,y
end
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
function lorentzianLorentzFun,x,amp,cen,wid
!except = 0
gam = 0.5*wid
npts = n_elements(x)
y = dblarr(npts)
y = (amp*gam/!pi)/((x-cen)^2+gam^2)
return,y
end
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
function bgFun,x,c,slope
!except = 0
npts = n_elements(x)
y = dblarr(npts)
y = c + slope*x
return,y
end
;;;;;;;;;;;;;;;;;;;;
pro evalKohlrauschPro,x,parms,y,_Extra = extra
npts = n_elements(x)
amp = parms[0]
beta = abs(parms[1])
; The following line used to be tau = abs(parms[2]) and the next line is new (08/22/02)
tauave = abs(parms[2])
tau = beta*tauave/gamma(1.0/beta)

xtab = *extra.xtabPtr
ytab = *extra.ytabPtr
btab = *extra.btabPtr
ttab = *extra.ttabPtr

xTabLo = min(xtab)
xTabHi = max(xtab)
dxTab = xtab[1]-xtab[0]
xIndex = dblarr(npts)
xIndex = (x-xTabLo)/dxTab

bTabLo = min(btab)
bTabHi = max(btab)
dbTab = btab[1]-btab[0]
bIndex = (beta-bTabLo)/dbTab

tTabLo = min(ttab)
tTabHi = max(ttab)
dtTab = ttab[1]-ttab[0]
tIndex = (tau-tTabLo)/dtTab

y = dblarr(npts)
hbar = 0.6528
if beta eq 1.0 then begin
  gam = 1.0*hbar/tau
  y = (amp*gam/!dpi)/(x^2+gam^2)
endif else begin
  y = amp*interpolate(ytab,xIndex,bIndex,tIndex,/grid)
endelse
end
;;;;;;;;;;;;;;;;;;;
pro RMDPAEvalFitFunction,xlim,parms,yfit,ycomp,_Extra = extra
; Evaluates the fit function (for use in the fitting routine).
; You pass in the parms vector containing the fit parameters.
; Then the parmStr structure (with any old values) is used
; to assign the parameters to the relevant variables.
;
parmStr = extra.inStr.parmStr
curveOrder = extra.inStr.curveOrder
x = *parmStr.xPtr
if n_elements(*parmStr.xdiffPtr) gt 1 then begin
  xdiff = *parmStr.xdiffPtr
endif

thisStr = parmStr
nparms = calcNumberOfParms(thisStr)
ncurves = calcNumberOfCurves(thisStr)
count = 0
npts = n_elements(x)
yfit = dblarr(npts)
ycomp = dblarr(npts,ncurves)
increment = 0

if thisStr.ngauss gt 0 then begin
  wherevalid = where(curveOrder eq 0)
  for i = 0,thisStr.ngauss-1 do begin
    ycomp[*,wherevalid[i]] = gaussianGaussFun(x,parms[count],parms[count+1],parms[count+2])
    yfit[*] = yfit[*] + gaussianGaussFun(x,parms[count],parms[count+1],parms[count+2])
    count = count+3
    increment = increment + 1
  endfor
endif

if thisStr.nlorentz gt 0 then begin
  wherevalid = where(curveOrder eq 1)
  for i = 0,thisStr.nlorentz-1 do begin
    ycomp[*,wherevalid[i]] = lorentzianLorentzFun(x,parms[count],parms[count+1],parms[count+2])
    yfit[*] = yfit[*] + lorentzianLorentzFun(x,parms[count],parms[count+1],parms[count+2])
    count = count+3
    increment = increment + 1
  endfor
endif

if thisStr.nbg eq 1 then begin
  wherevalid = where(curveOrder eq 2)
  ycomp[*,wherevalid[0]] = bgFun(x,parms[count],parms[count+1])
  yfit[*] = yfit[*] + bgFun(x,parms[count],parms[count+1])
  increment = increment + 1
  count = count+2
endif

if thisStr.nvoigt gt 0 then begin
  wherevalid = where(curveOrder eq 4)
  for i = 0,thisStr.nvoigt-1 do begin
    ycomp[*,wherevalid[i]] = voigtian(x,parms[count],parms[count+1],parms[count+2])
    yfit[*] = yfit[*] + voigtian(x,parms[count],parms[count+1],parms[count+2])
    count = count+3
    increment = increment + 1
  endfor
endif

if thisStr.nlognormal gt 0 then begin
  wherevalid = where(curveOrder eq 3)
  for i = 0,thisStr.nlognormal-1 do begin
    ycomp[*,wherevalid[i]] = logNormalFun(x,parms[count],parms[count+1],parms[count+2])
    yfit[*] = yfit[*] + logNormalFun(x,parms[count],parms[count+1],parms[count+2])
    count = count+3
    increment = increment + 1
  endfor
endif

if thisStr.nss gt 0 then begin
  wherevalid = where(curveOrder eq 5)
  for i = 0,thisStr.nss-1 do begin
    ycomp[*,wherevalid[i]] = smoothStepFun(x,parms[count],parms[count+1],parms[count+2])
    yfit[*] = yfit[*] + smoothStepFun(x,parms[count],parms[count+1],parms[count+2])
    count = count+3
    increment = increment + 1
  endfor
endif

if thisStr.nDHO gt 0 then begin
  wherevalid = where(curveOrder eq 6)
  for i = 0,thisStr.nDHO-1 do begin
    ycomp[*,wherevalid[i]] = DHOFun(x,parms[count],parms[count+1],$
                                    parms[count+2],parms[count+3])
    yfit[*] = yfit[*] + DHOFun(x,parms[count],parms[count+1],$
                               parms[count+2],parms[count+3])
    count = count+4
    increment = increment + 1
  endfor
endif

if thisStr.nkohl gt 0 then begin
  xtabPtr = extra.xtabPtr
  ytabPtr = extra.ytabPtr
  btabPtr = extra.btabPtr
  ttabPtr = extra.ttabPtr
  wherevalid = where(curveOrder eq 7)
  for i = 0,thisStr.nkohl-1 do begin
    y = dblarr(npts)
    evalKohlrauschPro,x,[parms[count],parms[count+1],parms[count+2]],$
                      y,xtabPtr = xtabPtr,ytabPtr = ytabPtr,$
                      btabPtr = btabPtr,ttabPtr = ttabPtr
    ycomp[*,wherevalid[i]] = y[*]
    yfit[*] = yfit[*] + y[*]
    count = count+3
    increment = increment + 1
  endfor
endif

if thisStr.ntunnelEISF eq 1 then begin
  wherevalid = where(curveOrder eq 8)
  ycomp[*,wherevalid[0]] = methylTunnelEISFFun(x,parms[count])
  yfit[*] = yfit[*] + methylTunnelEISFFun(x,parms[count])
  increment = increment + 1
  count = count+1
endif

if thisStr.nthreeSiteEISF eq 1 then begin
  wherevalid = where(curveOrder eq 9)
  ycomp[*,wherevalid[0]] = threeSiteEISFFun(x,parms[count])
  yfit[*] = yfit[*] +  threeSiteEISFFun(x,parms[count])
  increment = increment + 1
  count = count+1
endif

if thisStr.ntwoSiteEISF eq 1 then begin
  wherevalid = where(curveOrder eq 10)
  ycomp[*,wherevalid[0]] = twoSiteEISFFun(x,parms[count])
  yfit[*] = yfit[*] +  twoSiteEISFFun(x,parms[count])
  increment = increment + 1
  count = count+1
endif

if n_elements(*thisStr.resDataPtr) eq 0 then begin
;  added the following lines 10/5/01
  if n_elements(*thisStr.indLimPtr) eq 0 then begin
    *thisStr.indLimPtr = indgen(n_elements(x))
  endif
;
  indlim = *thisStr.indlimPtr & newpts = n_elements(indlim)
  yout = dblarr(newpts)
  yout[0:newpts-1] = yfit[indlim]
  yfit = dblarr(newpts) & yfit = yout
endif

multfactor = 1
if n_elements(*parmStr.xdiffPtr) gt 0 then begin
  xdiff = *parmStr.xdiffPtr
endif

if (thisStr.fitting eq 1) and n_elements(*thisStr.resDataPtr) gt 0 then begin
  indlim = *extra.inStr.parmStr.indlimPtr
  resData = *parmStr.resDataPtr
  yout = dblarr(npts)
  resSize = size(resData)
  newpts = resSize[2]
  yres = dblarr(newpts)
  xres = dblarr(newpts)
  xres[*] = resData[0,*]
  yres[*] = resData[1,*]

  yout = dblarr(npts)
  ycon = dblarr(npts)
  ycon = hfbs_convol(x,reform(yres),yfit,reslimit = parmStr.reslimit,xdiff = xdiff)

; if the pseudo delta function is present, do this...
   ynarrowSum = dblarr(npts)

   if thisStr.nDelta gt 0 then begin

      ynarrowSum = dblarr(npts)
      wherevalid = where(curveOrder eq 999,complement = wherenotvalid)
      for i = 0,thisStr.nDelta-1 do begin
		narcen = parms[count+1]
		narsig = parms[count+2]/2.354
		naramp = parms[count]
        narwid = narsig*2.354
		ynewnarrow = hfbs_convol(x,yres,pseudo_delta = [naramp,narcen,narwid],$
		             reslimit = parmStr.reslimit,xdiff = xdiff)
        ycomp[*,wherevalid[i]] = ynewnarrow[*]
        ynarrowSum = ynarrowSum + ynewnarrow[*]
        count = count+3
        increment = increment + 1
      endfor

   endif
   yout = ycon + ynarrowSum
   newpts = n_elements(indlim)
   yfit=dblarr(newpts)
   yfit[0:newpts-1] = yout[indlim]
endif

if (thisStr.fitting eq 0) and n_elements(*thisStr.resDataPtr) gt 0 then begin
  indlim = indgen(npts)
  resData = *parmStr.resDataPtr
  yout = dblarr(npts)
  respts = n_elements(resData[1,*])

  yres = dblarr(respts)
  xres = dblarr(respts)
  yres[*] = reform(resData[1,*])
  xres[*] = reform(resData[0,*])


  yout = dblarr(npts)
  ;ycon = dblarr(npts)

  ycon = hfbs_convol(x,yres,yfit,reslimit = parmStr.reslimit,xdiff = xdiff)

; if the pseudo delta function is present, do this...

  ynarrowSum = dblarr(npts)

   if thisStr.nDelta gt 0 then begin

      ynarrow = dblarr(npts)
      ynarrowSum = dblarr(npts)
; Some new code here
      wherevalid = where(curveOrder eq 999,complement = wherenotvalid)
      if wherenotvalid[0] ne -1 then begin
        nnotvalid = n_elements(wherenotvalid)
        for j = 0,nnotvalid-1 do begin
          yfun = ycomp[*,wherenotvalid[j]]
          yyout = hfbs_convol(x,reform(yres),yfun,reslimit = parmStr.reslimit,xdiff = xdiff)
          ycomp[*,wherenotvalid[j]] = yyout
        endfor
      endif
; End new code here
      for i = 0,thisStr.nDelta-1 do begin
		narcen = parms[count+1]
		narsig = parms[count+2]/2.354
		naramp = parms[count]
		narwid = narsig*2.354
		yres = reform(resData[1,*])
        ynewnarrow = hfbs_convol(x,yres,pseudo_delta=[naramp,narcen,narwid],$
                     reslimit = parmStr.reslimit,xdiff = xdiff)
        ycomp[*,wherevalid[i]] = ynewnarrow[*]
        ynarrowSum = ynarrowSum + ynewnarrow[*]
        count = count+3
        increment = increment + 1
      endfor
   endif
   yout = ycon + ynarrowSum
   yfit = yout
endif

return
end
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
pro RMDCalcDisplay,event
; Calculates the overall fit line based on the current parameters
widget_control,event.top,get_uvalue = pState
data = *(*pState).dataPtr
datsize = size(data)
npts = datsize[2]

x = dblarr(npts)
*(*pState).parmStr.indlimPtr = indgen(npts)
x[0:npts-1] = data[0,0:npts-1]
*(*pState).parmStr.xPtr = x
; test if the structure is populated
ncurves = calcNumberOfCurves((*pState).parmStr)
if ncurves ge 1 then begin
  parms = convertStructureToParms((*pState).parmStr)
  parmStr = (*pState).parmStr
  inStr = {parmStr:parmStr,curveOrder:*(*pState).parmStr.curveIdPtr}
  RMDPAEvalfitfunction,x,parms,yfit,ycomp,inStr = inStr,$
                       xtabPtr = (*pState).xtabPtr,$
                       ytabPtr = (*pState).ytabPtr,$
                       ttabPtr = (*pState).ttabPtr,$
                       btabPtr = (*pState).btabPtr
  (*pState).parmStr = parmStr
 ; The next three lines have been put back in
  if n_elements(*(*pState).currentCurvePtr) gt 0 then begin
    yfit = yfit + *(*pState).currentCurvePtr
  endif
  *(*pState).ytotPtr = yfit
endif else begin
  if n_elements(*(*pState).currentCurvePtr) gt 1 then begin
   yfit = *(*pState).currentCurvePtr
   *(*pState).ytotPtr = yfit
  endif
endelse

return
end
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
pro RMDPlotDisplay,event
widget_control,event.top,get_uvalue = pState
if n_elements(*(*pState).dataPtr) eq 0 then return

data = *(*pState).dataPtr
datsize = size(data)
npts = datsize[2]
xlo = (*pState).xlo & ylo = (*pState).ylo & xhi = (*pState).xhi
yhi = (*pState).yhi
widget_control,(*pState).xfitlo,get_value = lolimit
lolimit = float(lolimit[0])
widget_control,(*pState).xfithi,get_value = hilimit
hilimit = float(hilimit[0])
x = dblarr(npts) & y = dblarr(npts) & yerr = dblarr(npts)
x[0:npts-1] = data[0,0:npts-1] & y[0:npts-1] = data[1,0:npts-1]
yerr[0:npts-1] = data[2,0:npts-1]
thiscolor = (*pState).colors.yellow & errcolors1 = {thiscolor:thiscolor}

if n_elements(*(*pState).currentCurvePtr) gt 1 then begin
  yCurrent = *(*pState).currentCurvePtr
endif


if n_elements(*(*pState).ytotPtr) gt 0 then begin
  wset,(*pState).winPixId2
  ytot = *(*pState).ytotPtr
  residuals = dblarr(npts)
  badPoints = where(yerr eq 0.0,nbadpoints)
  if nbadPoints eq 0 then begin
    residuals = (ytot - y)/yerr
  endif else begin
    goodPoints = where(yerr ne 0,count)
    if count gt 0 then begin
      residuals[goodPoints] = (ytot[goodPoints] - y[goodPoints])/yerr[goodPoints]
      residuals[badPoints] = 0.0
    endif
  endelse
  ; Calculate the min and max y values in the range to be plotted
  xmin = (*pState).xlo
  xmax = (*pState).xhi
  xindex = where(x le xmax and x ge xmin,countx)

  resmin = min(residuals[xindex]) & resmax = max(residuals[xindex])
  dres = 0.1*(resmax-resmin)
  plot,x,residuals,psym = 0,color = (*pState).colors.yellow,$
       xtitle = (*pState).xlabel,yrange = [resmin-dres,resmax+dres],$
       xrange = [(*pState).xlo,(*pState).xhi],ystyle = 1,$
       xstyle = 1,ytitle = (*pState).yerrlabel
  wset,(*pState).gausswinval2
  device,copy = [0,0,!d.x_size,!d.y_size,0,0,(*pState).winPixId2]
endif

ylabel = (*(*(*pState).inPtr).dataStrPtr).commonStr.histLabel
wset,(*pState).winPixId
plot,x,y,psym =  hfbs_selsym(0),xrange = [xlo,xhi],xstyle = 1,$
     yrange = [ylo,yhi],ystyle = 1,color = thiscolor,$
     xtitle = (*pState).xlabel,ytitle = ylabel,$
     title = (*pState).curTitle
hfbs_cerrplot,x,y-yerr,y+yerr,errcolors = errcolors1,width = 0

plots,[lolimit,lolimit],[!y.crange[0],!y.crange[1]],linestyle = 2,$
      color = (*pState).colors.white,thick = 2.0
plots,[hilimit,hilimit],[!y.crange[0],!y.crange[1]],linestyle = 2,$
      color = (*pState).colors.white,thick = 2.0

if n_elements(*(*pState).ytotPtr) gt 0 then ytot = *(*pState).ytotPtr
ncurves = calcNumberOfCurves((*pState).parmStr)
if ncurves ge 1 then begin
  parms = convertStructureToParms((*pState).parmStr)
  parmStr = (*pState).parmStr
  *parmStr.xPtr = x
  *parmStr.indlimPtr = indgen(n_elements(x))
  (*pState).parmStr.xPtr = parmStr.xPtr
  inStr = {parmStr:parmStr,curveOrder:*(*pState).parmStr.curveIdPtr}
  RMDPAEvalfitfunction,x,parms,yfit,ycomp,inStr = inStr,$
                       xtabPtr = (*pState).xtabPtr,$
                       ytabPtr = (*pState).ytabPtr,$
                       ttabPtr = (*pState).ttabPtr,$
                       btabPtr = (*pState).btabPtr

  ;RMDPAEvalfitfunction,x,parms,yfit,ycomp,inStr = inStr
  if n_elements(*(*pState).currentCurvePtr) gt 1 then begin
    oplot,x,yCurrent,linestyle=2,thick = 2.0,color = (*pState).colors.green
  endif
  if n_elements(*(*pState).ytotPtr) gt 0 then begin
    oplot,x[*],ytot,thick = 2,color = (*pState).colors.red
  endif
  for i = 0,ncurves-1 do begin
    oplot,x[*],ycomp[*,i],linestyle=2,thick = 2,color = (*pState).colors.green
    ypos = max(ycomp[*,i],index) & xpos = x[index]
    xyouts,xpos,ypos,strtrim(string(i+1),2),color = (*pState).colors.white,$
           charsize = 2.0,/data
  endfor

endif else begin
  if n_elements(*(*pState).currentCurvePtr) gt 1 then begin
      oplot,x,yCurrent,linestyle=2,thick = 2.0,color = (*pState).colors.green
  endif
endelse


;if (*pState).curveType eq 999 then begin

wset,(*pState).gausswinval1
device,copy = [0,0,!d.x_size,!d.y_size,0,0,(*pState).winPixId]

return
end
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
pro RMDPAAutoScale,event
widget_control,event.top,get_uvalue = pState
(*pState).autoscale = 1
data = *(*pState).dataPtr
datsize = size(data)
npts = datsize[2]
x = dblarr(npts) & y = dblarr(npts)
x[0:npts-1] = data[0,0:npts-1] & y[0:npts-1] = data[1,0:npts-1]
deltax = max(x)-min(x)
(*pState).xlo = min(x)-0.1*deltax & (*pState).xhi = max(x)+0.1*deltax
delta = max(y)-min(y)

(*pState).ylo = min(y)-0.2*delta & (*pState).yhi = 1.2*max(y)
if (*pState).ylo gt 0.0 then (*pState).ylo = 0.0
if (*pState).yhi lt 0.0 then (*pState).yhi = 0.0
RMDCalcDisplay,event
RMDPlotDisplay,event
return
end
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
pro RMDPADisplayFitParms,event
widget_control,event.top,get_uvalue = pState
parmStr = (*pState).parmStr
ncurves = calcNumberOfCurves(parmStr)
if ncurves eq 0 then begin
  strout = ''
  widget_control,(*pState).textFit,set_value = strout
  return
endif
count = 0

curveOrder = *(*pState).parmStr.curveIdPtr
strout = strarr(6+3*calcNumberOfParms(parmStr))

for i = 0,parmStr.ngauss-1 do begin
  wherevalid = where(curveOrder eq 0)
  strout[count] = 'C['+strtrim(string(wherevalid[i]+1),2)+']: Gaussian['+strtrim(string(i+1),2)+']'
  count = count + 1
  area = (*parmStr.gaussParmPtr)[3*i]
  cen = (*parmStr.gaussParmPtr)[3*i+1]
  wid = (*parmStr.gaussParmPtr)[3*i+2]
  peak = area/sqrt(2.0*!pi*(wid/2.35)^2)

  if (*pState).curveNum eq wherevalid[i] then begin
    case (*pState).parmNum of
    0:	begin
    		(*pState).parmLabel = 'Gaussian Area'
    		(*pState).plotParm = area
    		(*pState).plotParmErr = (*parmStr.gaussParmErrPtr)[3*i]
        	end
    1:	begin
    		(*pState).parmLabel = 'Gaussian Center'
    		(*pState).plotParm = cen
    		(*pState).plotParmErr = (*parmStr.gaussParmErrPtr)[3*i+1]
        	end
    2:	begin
    		(*pState).parmLabel = 'Gaussian FWHM'
    		(*pState).plotParm = wid
    		(*pState).plotParmErr = (*parmStr.gaussParmErrPtr)[3*i+2]
        	end
    else:
    endcase
  endif

  strout[count] = 'Peak intensity='+string(peak)
  count = count+1
  for j = 0,2 do begin
    strout[count] = 'P['+strtrim(string(j+1),2)+']: '+parmStr.gaussNames[j]+'='+$
                    string((*parmStr.gaussParmPtr)[3*i+j])+'+/-'+$
                    string((*parmStr.gaussParmErrPtr)[3*i+j])
    count = count+1
  endfor
endfor
for i = 0,parmStr.nlorentz-1 do begin
  wherevalid = where(curveOrder eq 1)
  strout[count] = ''
  count = count+1
  strout[count] = 'C['+strtrim(string(wherevalid[i]+1),2)+']: Lorentzian['+strtrim(string(i+1),2)+']'
  count = count + 1
  area = (*parmStr.lorentzParmPtr)[3*i]
  cen = (*parmStr.lorentzParmPtr)[3*i+1]
  wid = (*parmStr.lorentzParmPtr)[3*i+2]

  if (*pState).curveNum eq wherevalid[i] then begin
    case (*pState).parmNum of
    0:	begin
    		(*pState).parmLabel = 'Lorentzian Area'
    		(*pState).plotParm = area
    		(*pState).plotParmErr = (*parmStr.lorentzParmErrPtr)[3*i]
        	end
    1:	begin
    		(*pState).parmLabel = 'Lorentzian Center'
    		(*pState).plotParm = cen
    		(*pState).plotParmErr = (*parmStr.lorentzParmErrPtr)[3*i+1]
        	end
    2:	begin
    		(*pState).parmLabel = 'Lorentzian FWHM'
    		(*pState).plotParm = wid
    		(*pState).plotParmErr = (*parmStr.lorentzParmErrPtr)[3*i+2]
        	end
    else:
    endcase
  endif

  peak = area/(0.5*wid*!pi)
  strout[count] = 'Peak intensity='+string(peak)
  count = count+1

  for j = 0,2 do begin
    strout[count] = 'P['+strtrim(string(j+1),2)+']: '+parmStr.lorentzNames[j]+'='+$
                    string((*parmStr.lorentzParmPtr)[3*i+j])+'+/-'+$
                    string((*parmStr.lorentzParmErrPtr)[3*i+j])
    count = count+1
  endfor
endfor

for i = 0,parmStr.nlognormal-1 do begin
  wherevalid = where(curveOrder eq 3)
  strout[count] = ''
  count = count+1
  strout[count] = 'C['+strtrim(string(wherevalid[i]+1),2)+']: Lognormal['+strtrim(string(i+1),2)+']'
  count = count + 1

    amp = (*parmStr.logNormParmPtr)[3*i]
    sigmaamp = (*parmStr.logNormParmErrPtr)[3*i]
    cen = (*parmStr.logNormParmPtr)[3*i+1]
    sigmacen = (*parmStr.logNormParmErrPtr)[3*i+1]
    sig = (*parmStr.logNormParmPtr)[3*i+2]
    sigmasig = (*parmStr.logNormParmErrPtr)[3*i+2]
    xMode = exp(abs(cen)-sig*sig)
    var = (exp(2.*abs(cen)+sig^2))*((exp(sig*sig))-1.0)
    width = sqrt(var)

    x = cen & y = sig
    f1 = exp(abs(x))*sqrt(exp(2.0*y^2)-exp(y^2))	; sigma
    df1dx = f1
    df1dy = 1.0*y*exp(x+y^2)*(2.0*exp(y^2)-1.0)/sqrt(exp(y^2)*(exp(y^2)-1.0))
    df1 = sqrt((df1dx*sigmacen)^2+(df1dy*sigmasig)^2)

    f2 = exp(abs(x)-y^2)	; mode
    df2dx = f2
    df2dy = -2.0*y*f2
    df2 = sqrt((df2dx*sigmacen)^2+(df2dy*sigmasig)^2)

  if (*pState).curveNum eq wherevalid[i] then begin
    case (*pState).parmNum of
    0:	begin
    		(*pState).parmLabel = 'Lognormal Area'
    		(*pState).plotParm = amp
    		(*pState).plotParmErr = sigmaamp
        	end
    1:	begin
    		(*pState).parmLabel = 'Lognormal Mode'
    		(*pState).plotParm = xMode
    		(*pState).plotParmErr = df2
        	end
    2:	begin
    		(*pState).parmLabel = 'Lognormal SD'
    		(*pState).plotParm = width
    		(*pState).plotParmErr = df1
        	end
    else:
    endcase
  endif


;    strout[count] = 'P[1]:Area ='+string(amp)+'+/-'+string(sigmaamp)
;    strout[count+1] = 'P[2]:Mode ='+string(xMode)+'+/-'+string(df2)
;    strout[count+2] = 'P[3]:SD ='+string(width)+'+/-'+string(df1)

; The following lines should be uncommented out and the previous three lines
; should be commented out when fitting barrier distribution broadened data.

    strout[count] = 'P[1]:Area ='+string(amp)+'+/-'+string(sigmaamp)
    strout[count+1] = 'P[2]:mu ='+string(cen)+'+/-'+string(sigmacen)
    strout[count+2] = 'P[3]:SD ='+string(sig)+'+/-'+string(sigmasig)

    count = count+3
endfor

for i = 0,parmStr.nbg-1 do begin
    wherevalid = where(curveOrder eq 2)
    strout[count] = ''
    count = count+1
    strout[count] = 'C['+strtrim(string(wherevalid[i]+1),2)+']: Background'
    count = count + 1
    strout[count] = 'P[1]:BG = '+string((*parmStr.bgParmPtr)[0])+'+/-'+$
                    string((*parmStr.bgParmErrPtr)[0])
    strout[count+1] = 'P[2]:Slope = '+string((*parmStr.bgParmPtr)[1])+'+/-'+$
                    string((*parmStr.bgParmErrPtr)[1])

  if (*pState).curveNum eq wherevalid[i] then begin
    case (*pState).parmNum of
    0:	begin
    		(*pState).parmLabel = 'Constant'
    		(*pState).plotParm = (*parmStr.bgParmPtr)[0]
			(*pState).plotParmErr = (*parmStr.bgParmErrPtr)[0]
        	end
    1:	begin
    		(*pState).parmLabel = 'Slope'
    		(*pState).plotParm = (*parmStr.bgParmPtr)[1]
			(*pState).plotParmErr = (*parmStr.bgParmErrPtr)[1]
        	end
    else:
    endcase
  endif


    count = count + 2
endfor

for i = 0,parmStr.nvoigt-1 do begin
  wherevalid = where(curveOrder eq 4)
  strout[count] = ''
  count = count+1
  strout[count] = 'C['+strtrim(string(wherevalid[i]+1),2)+']: Voigt['+strtrim(string(i+1),2)+']'
  count = count + 1

    amp = (*parmStr.voigtParmPtr)[3*i]
    sigmaamp = (*parmStr.voigtParmErrPtr)[3*i]
    cen = (*parmStr.voigtParmPtr)[3*i+1]
    sigmacen = (*parmStr.voigtParmErrPtr)[3*i+1]
    sig = (*parmStr.voigtParmPtr)[3*i+2]
    sigmasig = (*parmStr.voigtParmErrPtr)[3*i+2]
    strout[count] = 'P[1]:Area ='+string(amp)+'+/-'+string(sigmaamp)
    strout[count+1] = 'P[2]:Center ='+string(cen)+'+/-'+string(sigmacen)
    strout[count+2] = 'P[3]:Width ='+string(sig)+'+/-'+string(sigmasig)
    count = count+3

  if (*pState).curveNum eq wherevalid[i] then begin
    case (*pState).parmNum of
    0:	begin
    		(*pState).parmLabel = 'Voigt Area'
    		(*pState).plotParm = amp
    		(*pState).plotParmErr = sigmaamp
        	end
    1:	begin
    		(*pState).parmLabel = 'Voigt Center'
    		(*pState).plotParm = cen
    		(*pState).plotParmErr = sigmacen
        	end
    2:	begin
    		(*pState).parmLabel = 'Voigt Width'
    		(*pState).plotParm = sig
    		(*pState).plotParmErr = sigmasig
        	end
    else:
    endcase
  endif

endfor

for i = 0,parmStr.nss-1 do begin
  wherevalid = where(curveOrder eq 5)
  strout[count] = ''
  count = count+1
  strout[count] = 'C['+strtrim(string(wherevalid[i]+1),2)+']: Smooth Step['+strtrim(string(i+1),2)+']'
  count = count + 1

  if (*pState).curveNum eq wherevalid[i] then begin
    case (*pState).parmNum of
    0:	begin
    		(*pState).parmLabel = 'Smooth Step Amplitude'
    		(*pState).plotParm = (*parmStr.ssParmPtr)[3*i+0]
			(*pState).plotParmErr = (*parmStr.ssParmErrPtr)[3*i+0]
        	end
    1:	begin
    		(*pState).parmLabel = 'Smooth Step Transition Midpoint'
    		(*pState).plotParm = (*parmStr.ssParmPtr)[3*i+1]
			(*pState).plotParmErr = (*parmStr.ssParmErrPtr)[3*i+1]
        	end
    2:	begin
    		(*pState).parmLabel = 'Smooth Step Transition Width'
    		(*pState).plotParm = (*parmStr.ssParmPtr)[3*i+2]
			(*pState).plotParmErr = (*parmStr.ssParmErrPtr)[3*i+2]
        	end
    else:
    endcase
  endif

  for j = 0,2 do begin
    strout[count] = 'P['+strtrim(string(j+1),2)+']: '+parmStr.ssNames[j]+'='+$
                    string((*parmStr.ssParmPtr)[3*i+j])+'+/-'+$
                    string((*parmStr.ssParmErrPtr)[3*i+j])
    count = count+1
  endfor
endfor

for i = 0,parmStr.nDHO-1 do begin
  wherevalid = where(curveOrder eq 6)
  strout[count] = ''
  count = count+1
  strout[count] = 'C['+strtrim(string(wherevalid[i]+1),2)+']: DHO['+strtrim(string(i+1),2)+']'
  count = count + 1

  if (*pState).curveNum eq wherevalid[i] then begin
    case (*pState).parmNum of
    0:	begin
    		(*pState).parmLabel = 'DHO Amplitude'
    		(*pState).plotParm = (*parmStr.DHOParmPtr)[4*i+0]
    		(*pState).plotParmErr = (*parmStr.DHOParmErrPtr)[4*i+0]
        	end
    1:	begin
    		(*pState).parmLabel = 'DHO Center'
    		(*pState).plotParm = (*parmStr.DHOParmPtr)[4*i+1]
    		(*pState).plotParmErr = (*parmStr.DHOParmErrPtr)[4*i+1]
        	end
    2:	begin
    		(*pState).parmLabel = 'DHO FWHM'
    		(*pState).plotParm = (*parmStr.DHOParmPtr)[4*i+2]
    		(*pState).plotParmErr = (*parmStr.DHOParmErrPtr)[4*i+2]
        	end
    3:	begin
    		(*pState).parmLabel = 'DHO Temperature'
    		(*pState).plotParm = (*parmStr.DHOParmPtr)[4*i+3]
    		(*pState).plotParmErr = (*parmStr.DHOParmErrPtr)[4*i+3]
        	end
    else:
    endcase
  endif

  for j = 0,3 do begin
    strout[count] = 'P['+strtrim(string(j+1),2)+']: '+parmStr.DHONames[j]+'='+$
                    string((*parmStr.DHOParmPtr)[4*i+j])+'+/-'+$
                    string((*parmStr.DHOParmErrPtr)[4*i+j])
    count = count+1
  endfor
endfor

for i = 0,parmStr.nDelta-1 do begin
  wherevalid = where(curveOrder eq 999)
  strout[count] = ''
  count = count+1
  strout[count] = 'C['+strtrim(string(wherevalid[i]+1),2)+']: pseudo delta['+strtrim(string(i+1),2)+']'
  count = count + 1
  for j = 0,2 do begin
    strout[count] = 'P['+strtrim(string(j+1),2)+']: '+parmStr.deltaNames[j]+'='+$
                    string((*parmStr.deltaParmPtr)[3*i+j])+'+/-'+$
                    string((*parmStr.deltaParmErrPtr)[3*i+j])
    count = count+1
  endfor

  if (*pState).curveNum eq wherevalid[i] then begin
    case (*pState).parmNum of
    0:	begin
    		(*pState).parmLabel = 'Delta Function Area'
    		(*pState).plotParm = (*parmStr.deltaParmPtr)[3*i]
    		(*pState).plotParmErr = (*parmStr.deltaParmErrPtr)[3*i]
        	end
    1:	begin
    		(*pState).parmLabel = 'Delta Function Center'
    		(*pState).plotParm = (*parmStr.deltaParmPtr)[3*i+1]
    		(*pState).plotParmErr = (*parmStr.deltaParmErrPtr)[3*i+1]
        	end
    2:	begin
    		(*pState).parmLabel = "Delta Function 'FWHM'"
    		(*pState).plotParm = (*parmStr.deltaParmPtr)[3*i+2]
    		(*pState).plotParmErr = (*parmStr.deltaParmErrPtr)[3*i+2]
        	end
    else:
    endcase
  endif
endfor

for i = 0,parmStr.ntunnelEISF-1 do begin
    wherevalid = where(curveOrder eq 8)
    strout[count] = ''
    count = count+1
    strout[count] = 'C['+strtrim(string(wherevalid[i]+1),2)+']: Tunnel EISF'
    count = count + 1
    strout[count] = 'Radius = '+string((*parmStr.tunnelEISFParmPtr)[0])+'+/-'+$
                    string((*parmStr.tunnelEISFParmErrPtr)[0])
    count = count + 1

  if (*pState).curveNum eq wherevalid[i] then begin
    case (*pState).parmNum of
    0:	begin
    		(*pState).parmLabel = 'Radius'
    		(*pState).plotParm = (*parmStr.tunnelEISFParmPtr)[0]
    		(*pState).plotParmErr = (*parmStr.tunnelEISFParmErrPtr)[0]
        end
    else:
    endcase
  endif
endfor

for i = 0,parmStr.nthreeSiteEISF-1 do begin
    wherevalid = where(curveOrder eq 9)
    strout[count] = ''
    count = count+1
    strout[count] = 'C['+strtrim(string(wherevalid[i]+1),2)+']: Three Site Jump EISF'
    count = count + 1
    strout[count] = 'Radius = '+string((*parmStr.threeSiteEISFParmPtr)[0])+'+/-'+$
                    string((*parmStr.threeSiteEISFParmErrPtr)[0])
    count = count + 1

  if (*pState).curveNum eq wherevalid[i] then begin
    case (*pState).parmNum of
    0:	begin
    		(*pState).parmLabel = 'Radius'
    		(*pState).plotParm = (*parmStr.threeSiteEISFParmPtr)[0]
    		(*pState).plotParmErr = (*parmStr.threeSiteEISFParmErrPtr)[0]
        end
    else:
    endcase
  endif
endfor

for i = 0,parmStr.ntwoSiteEISF-1 do begin
    wherevalid = where(curveOrder eq 10)
    strout[count] = ''
    count = count+1
    strout[count] = 'C['+strtrim(string(wherevalid[i]+1),2)+']: Two Site Jump EISF'
    count = count + 1
    strout[count] = 'Radius = '+string((*parmStr.twoSiteEISFParmPtr)[0])+'+/-'+$
                    string((*parmStr.twoSiteEISFParmErrPtr)[0])
    count = count + 1

  if (*pState).curveNum eq wherevalid[i] then begin
    case (*pState).parmNum of
    0:	begin
    		(*pState).parmLabel = 'Radius'
    		(*pState).plotParm = (*parmStr.twoSiteEISFParmPtr)[0]
    		(*pState).plotParmErr = (*parmStr.twoSiteEISFParmErrPtr)[0]
        end
    else:
    endcase
  endif
endfor

for i = 0,parmStr.nkohl-1 do begin
  wherevalid = where(curveOrder eq 7)
  strout[count] = ''
  count = count + 1
  strout[count] = 'C['+strtrim(string(wherevalid[i]+1),2)+']: Kohlrausch['+strtrim(string(i+1),2)+']'
  count = count + 1
  area = (*parmStr.kohlParmPtr)[3*i]
  cen = (*parmStr.kohlParmPtr)[3*i+1]
  avetau = (*parmStr.kohlParmPtr)[3*i+2]

  if (*pState).curveNum eq wherevalid[i] then begin
    case (*pState).parmNum of
    0:	begin
    		(*pState).parmLabel = 'Kohlrausch Amplitude'
    		(*pState).plotParm = area
    		(*pState).plotParmErr = (*parmStr.kohlParmErrPtr)[3*i]
        	end
    1:	begin
    		(*pState).parmLabel = 'Beta'
    		(*pState).plotParm = cen
    		(*pState).plotParmErr = (*parmStr.kohlParmErrPtr)[3*i+1]
        	end
    2:	begin
    		(*pState).parmLabel = '<Tau>'
    		(*pState).plotParm = avetau
    		(*pState).plotParmErr = (*parmStr.kohlParmErrPtr)[3*i+2]
        	end
    else:
    endcase
  endif

  count = count+1
  for j = 0,2 do begin
    strout[count] = 'P['+strtrim(string(j+1),2)+']: '+parmStr.kohlNames[j]+'='+$
                    string((*parmStr.kohlParmPtr)[3*i+j])+'+/-'+$
                    string((*parmStr.kohlParmErrPtr)[3*i+j])
    count = count+1
  endfor
endfor
strout[count] = ''
count = count+1
strout[count] = 'Chi-squared: '+string((*pState).parmStr.chisq)
thisOut = strarr(count+1)
thisOut[0:count] = strout[0:count]
strout = strarr(count+1)
strout = thisOut
if (*pState).printing eq 0 and ((*pState).plotParmTest eq 0) then begin
  widget_control,(*pState).textFit,set_value = strout
  *(*pState).psStringPtr = ''
endif else begin
  *(*pState).psStringPtr = strout
endelse

if (*pState).writeParmsAsText then begin
  thisPath = (*!dave_defaults).workDir;(*(*pState).inPtr).workDir
  filename = DIALOG_PICKFILE(FILTER = '*.txt',/write,$
             title = 'Parameter file name',path = thisPath)
  filename = filename+'.txt'
  openw,lun,filename,/get_lun
  nstrings = n_elements(strout)
  for i = 0,nstrings-1 do begin
    printf,lun,strout[i]
  endfor
  free_lun,lun
  (*pState).writeParmsAsText = 0
endif

return
end
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
pro RMDPAFitData,event
widget_control,event.top,get_uvalue = pState
widget_control,(*pState).selGroup,get_value = thisGroup
thisGroup = fix(thisGroup[0])-1
widget_control,(*pState).textFit,get_uvalue = bigParmPtr
parmStr = *bigParmPtr[thisGroup]
nbigParmCurves = calcNumberOfCurves(*bigParmPtr[thisGroup])
nParmCurves = calcNumberOfCurves((*pState).parmStr)
if ((nbigParmCurves ne nParmCurves) and (nParmCurves gt 0)) then parmStr = (*pState).parmStr
if calcNumberOfCurves(parmStr) eq 0 then begin
  parmStr = (*pState).parmStr
endif

if calcNumberOfCurves(parmStr) eq 0 then return

deSensitizeWidgets,event

parms = convertStructureToParms(parmStr,FIXARRAY = fixarray,$
                                UPPERARRAY = upperarray,$
                                LOWERARRAY = lowerarray,$
                                STEPARRAY = steparray,$
                                HILIMITS = hilimits,$
                                LOLIMITS = lolimits,$
                                C1 = (*pState).tieParmC1,$
                                C2 = (*pState).tieParmC2,$
                                P1 = (*pState).tieParmP1,$
                                P2 = (*pState).tieParmP2,$
                                TIEPARM1 = n1,$
                                TIEPARM2 = n2)


(*pState).fit = 1
parinfo = replicate({fixed:0,limited:[0,0],$
                     limits:[0.D,0.D],$
                     step:0.0D,tied:''},$
                     n_elements(fixarray))

for i = 0,n_elements(fixarray)-1 do begin
    parinfo[i].limited[0] = lowerarray[i]	; activate lower limit
    parinfo[i].limited[1] = upperarray[i]	; activate upper limit
    parinfo[i].limits[0] = lolimits[i]		; set lower limit
    parinfo[i].limits[1] = hilimits[i]		; set upper limit
    parinfo[i].fixed = fixarray[i]			; fix parameters
    parinfo[i].step = steparray[i]			; step size for parameter variation
endfor

nparms = n_elements(parms)
widget_control,(*pState).xfitlo,get_value = xfitlo
xfitlo = float(xfitlo[0])
widget_control,(*pState).xfithi,get_value = xfithi
xfithi = float(xfithi[0])


fitfun = 'RMDPAEvalfitfunction'
data = *(*pState).dataPtr
datsize = size(data)
npts = datsize[2]
x = dblarr(npts) & y = dblarr(npts) & yerr = dblarr(npts)
x[0:npts-1] = data[0,0:npts-1] & y[0:npts-1] = data[1,0:npts-1]

; Test here to see if the spacing between x is uniform
sig = sqrt((moment(deriv(x)))[1])
resPtr = (*pState).parmStr.resDataPtr
if (ptr_valid(res) gt 0) and (sig gt 1.e-4) then begin
  strout = ['Numerical convolution requires equal x-bins.','Please rebin data.']
  void = dialog_message(dialog_parent = event.top,strout)
  return
endif


yerr[0:npts-1] = data[2,0:npts-1]
wherezero = where(yerr eq 0.0,count)

widget_control,(*pState).textFit,set_value = 'Fitting...'

if count gt 0 then yerr[wherezero] = 1.0
weights = 1.d/(yerr^2)
wherevalid = where(x ge xfitlo and x le xfithi,newpts)
xlim = dblarr(newpts) & ylim = dblarr(newpts) & wlim = dblarr(newpts)
yerrlim = dblarr(newpts)
xlim = x[wherevalid]
ylim = y[wherevalid]
wlim = weights[wherevalid]
yerrlim = yerr[wherevalid]

*parmStr.indlimPtr = wherevalid
*parmStr.xPtr = x

*(*pState).parmStr.indlimPtr = wherevalid
*(*pState).parmStr.xPtr = *parmStr.xPtr

parmStr.fitting = 1
inStr = {parmStr:parmStr,curveOrder:*(*pState).parmStr.curveIdPtr}

itmax = 200	; MPCURVEFIT default is 200 for the maximum number of iterations
yfit = mpcurvefit(xlim, ylim, wlim, parms,sigma, $
                  FUNCTION_NAME=fitfun,/quiet,nprint = 0,$
                  status = status,$
                  functargs = {inStr:inStr,$
                               xtabPtr:(*pState).xtabPtr,$
                               ytabPtr:(*pState).ytabPtr,$
                               ttabPtr:(*pState).ttabPtr,$
                               btabPtr:(*pState).btabPtr},$
                  PARINFO=parinfo,chisq = chisq,$
                  /autoderivative,$
                  itmax = itmax,$
                  iter = numIterations)
;print,'Status: ',status
;print,'Number of iterations: ',strcompress(string(numIterations))

parmStr.fitting = 0
(*pState).parmStr.fitting = 0

;if n_elements(*parmStr.indlimPtr) then ptr_free,parmStr.indlimPtr
*parmStr.indlimPtr = (indgen(npts))
*(*pState).parmStr.indlimPtr = *parmStr.indlimPtr
parmStr.fitting = 0
parmStr.chisq = chisq/(float(n_elements(xlim))-float(n_elements(parms)))
(*pState).parmStr.chisq = parmStr.chisq
if ptr_valid((*pState).fixPtr) then ptr_free,(*pState).fixPtr
(*pState).fixPtr = ptr_new(/allocate_heap)
yout = dblarr(npts)
inStr = {parmStr:(*pState).parmStr,curveOrder:*(*pState).parmStr.curveIdPtr}
RMDPAEvalfitfunction,x,parms,yout,ycomp,inStr = inStr,$
                       xtabPtr = (*pState).xtabPtr,$
                       ytabPtr = (*pState).ytabPtr,$
                       ttabPtr = (*pState).ttabPtr,$
                       btabPtr = (*pState).btabPtr

*(*pState).ytotPtr = yout

parmStr = convertParmsToStructure(parmStr,parms,sigma = sigma)
(*pState).parmStr = parmStr
dave_beast_ops,"duplicate",parmStr,outStr
*bigParmPtr[thisGroup] = outStr
*(*pState).currentCurvePtr = 0

RMDCalcDisplay,event
RMDPlotDisplay,event
RMDPADisplayFitParms,event
sensitizeWidgets,event


widget_control,event.top,/clear_events
(*pState).fit = 0
return
end
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
pro RMDPAAddGaussianFun,event
widget_control,event.top,get_uvalue = pState
(*pState).addCurve = 1
(*pState).addGauss = 1
(*pState).curveType = 0
(*pState).zoom = 0
if n_elements(*(*pState).parmStr.gaussParmErrPtr) gt 0 then begin
  oldErr = *(*pState).parmStr.gaussParmErrPtr
  *(*pState).parmStr.gaussParmErrPtr = [oldErr,0.0,0.0,0.0]
endif else begin
  *(*pState).parmStr.gaussParmErrPtr = [0.0,0.0,0.0]
endelse
return
end
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
pro RMDPAAddKohlFun,event
widget_control,event.top,get_uvalue = pState
(*pState).addCurve = 1
(*pState).addGauss = 1
(*pState).curveType = 7
(*pState).zoom = 0
if n_elements(*(*pState).parmStr.kohlParmErrPtr) gt 0 then begin
  oldErr = *(*pState).parmStr.kohlParmErrPtr
  *(*pState).parmStr.kohlParmErrPtr = [oldErr,0.0,0.0,0.0]
endif else begin
  *(*pState).parmStr.kohlParmErrPtr = [0.0,0.0,0.0]
endelse
return
end
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
pro RMDPAAddDHOFun,event
widget_control,event.top,get_uvalue = pState
(*pState).addCurve = 1
(*pState).addGauss = 1
(*pState).curveType = 6
(*pState).zoom = 0
if n_elements(*(*pState).parmStr.DHOParmErrPtr) gt 0 then begin
  oldErr = *(*pState).parmStr.DHOParmErrPtr
  *(*pState).parmStr.DHOParmErrPtr = [oldErr,0.0,0.0,0.0,0.0]
endif else begin
  *(*pState).parmStr.DHOParmErrPtr = [0.0,0.0,0.0,0.0]
endelse

;doneRMDPAAddCurveWidget,event
return
end
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
pro RMDPAAddSmoothStepFun,event
widget_control,event.top,get_uvalue = pState
(*pState).addCurve = 1
(*pState).curveType = 5
(*pState).zoom = 0
if n_elements(*(*pState).parmStr.ssParmErrPtr) gt 0 then begin
  oldErr = *(*pState).parmStr.ssParmErrPtr
  *(*pState).parmStr.ssParmErrPtr = [oldErr,0.0,0.0,0.0]
endif else begin
  *(*pState).parmStr.ssParmErrPtr = [0.0,0.0,0.0]
endelse

;doneRMDPAAddCurveWidget,event
return
end
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
pro RMDPAAddLorentzianFun,event
widget_control,event.top,get_uvalue = pState
(*pState).addCurve = 1
(*pState).addLor = 1
(*pState).curveType = 1
(*pState).zoom = 0
if n_elements(*(*pState).parmStr.lorentzParmErrPtr) gt 0 then begin
  oldErr = *(*pState).parmStr.lorentzParmErrPtr
  *(*pState).parmStr.lorentzParmErrPtr = [oldErr,0.0,0.0,0.0]
endif else begin
  *(*pState).parmStr.lorentzParmErrPtr = [0.0,0.0,0.0]
endelse

;doneRMDPAAddCurveWidget,event
return
end
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
pro RMDPAAddVoigtFun,event
widget_control,event.top,get_uvalue = pState
(*pState).addCurve = 1
(*pState).curveType = 4
(*pState).zoom = 0
if n_elements(*(*pState).parmStr.voigtParmErrPtr) then begin
  oldErr = *(*pState).parmStr.voigtParmErrPtr
  *(*pState).parmStr.voigtParmErrPtr = [oldErr,0.0,0.0,0.0]
endif else begin
  *(*pState).parmStr.voigtParmErrPtr = [0.0,0.0,0.0]
endelse


;doneRMDPAAddCurveWidget,event
return
end
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
pro RMDPAAddLNFun,event
widget_control,event.top,get_uvalue = pState
(*pState).addCurve = 1
(*pState).curveType = 3
(*pState).zoom = 0
if n_elements(*(*pState).parmStr.logNormParmErrPtr) gt 0 then begin
  oldErr = *(*pState).parmStr.logNormParmErrPtr
  *(*pState).parmStr.logNormParmErrPtr = [oldErr,0.0,0.0,0.0]
endif else begin
  *(*pState).parmStr.logNormParmErrPtr = [0.0,0.0,0.0]
endelse


return
end
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
pro RMDPAAddBgFun,event
widget_control,event.top,get_uvalue = pState
(*pState).addCurve = 1
(*pState).addBg = 1
(*pState).curveType = 2
(*pState).zoom = 0
*(*pState).parmStr.bgParmErrPtr = [0.0,0.0]

return
end
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
pro RMDPAAddTunnelEISFFun,event
widget_control,event.top,get_uvalue = pState
(*pState).addCurve = 1
(*pState).curveType = 8
(*pState).zoom = 0
*(*pState).parmStr.tunnelEISFParmErrPtr = [0.0]

return
end
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
pro RMDPAAdd3SiteEISFFun,event
widget_control,event.top,get_uvalue = pState
(*pState).addCurve = 1
(*pState).curveType = 9
(*pState).zoom = 0
*(*pState).parmStr.threeSiteEISFParmErrPtr = [0.0]

return
end
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
pro RMDPAAdd2SiteEISFFun,event
widget_control,event.top,get_uvalue = pState
(*pState).addCurve = 1
(*pState).curveType = 10
(*pState).zoom = 0
*(*pState).parmStr.twoSiteEISFParmErrPtr = [0.0]

return
end
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
pro RMDPAAddDeltaFun,event
widget_control,event.top,get_uvalue = pState
(*pState).addCurve = 1
(*pState).addBg = 1
(*pState).curveType = 999
(*pState).zoom = 0
if n_elements(*(*pState).parmStr.deltaParmErrPtr) gt 0 then begin
  oldErr = *(*pState).parmStr.deltaParmErrPtr
  *(*pState).parmStr.deltaParmErrPtr = [oldErr,0.0,0.0,0.0]
endif else begin
  *(*pState).parmStr.deltaParmErrPtr = [0.0,0.0,0.0]
endelse


return
end
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
pro RMDPAClearCurves,event
widget_control,event.top,get_uvalue = pState
ptr_free,(*pState).fixPtr
(*pState).fixPtr = ptr_new(/allocate_heap)
(*pState).ngauss = 0


if n_elements(*(*pState).bigResDataPtr) gt 1 then begin
  resData = *(*pState).parmStr.resDataPtr
  xdiff = *(*pState).parmStr.xdiffPtr
  resLimit = (*pState).parmStr.resLimit
endif

ptr_free,(*pState).currentParmPtr
(*pState).currentParmPtr = ptr_new(/allocate_heap)
ptr_free,(*pState).currentCurvePtr
(*pState).currentCurvePtr = ptr_new(/allocate_heap)
ptr_free,(*pState).ytotPtr
(*pState).ytotPtr = ptr_new(/allocate_heap)
parmStr = (*pState).parmStr
dave_beast_ops,"remove",parmStr,show_analysis = 0,show_commands = 0
(*pState).modCurve = 0

widget_control,(*pState).pickCurve,set_slider_min = 0
widget_control,(*pState).pickCurve,set_slider_max = 1
wset,(*pState).winPixId2
erase
wset,(*pState).gausswinval2
device,copy = [0,0,!d.x_size,!d.y_size,0,0,(*pState).winPixId2]
wset,(*pState).winPixId
erase
device,copy = [0,0,!d.x_size,!d.y_size,0,0,(*pState).winPixId]

widget_control,(*pState).textFit,get_uvalue = bigParmPtr,/no_copy
for i = 0,n_elements(bigParmPtr)-1 do begin
  dave_beast_ops,"remove",bigParmPtr[i],show_analysis = 0,show_commands = 0
endfor
bigParmPtr = ptrarr((*pState).ngroups,/allocate_heap)
parmStr = parmStructDefine()

; If resolution function present, put it into the correct parmStr field
if n_elements(resData) gt 1 then begin
  *parmStr.resDataPtr = resData
  *parmStr.xdiffPtr = xdiff
  parmStr.resLimit = resLimit
endif

(*pState).parmStr = parmStr
for i = 0,(*pState).ngroups-1 do begin
  *bigParmPtr[i] = (*pState).parmStr
endfor

widget_control,(*pState).textFit,set_uvalue = bigParmPtr,/no_copy



RMDPlotDisplay,event
widget_control,event.top,get_uvalue = pState


return
end
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
pro RMDPAAddCurve,event
widget_control,event.top,get_uvalue = pState
case event.index[0] of
0: begin

   deSensitizeWidgets,event
   widget_control,event.top,get_uvalue = pState

   RMDPAAddDeltaFun,event
   widget_control,event.top,get_uvalue = pState
   widget_control,(*pState).textfit,set_value = $
                ['Hold down mouse button and drag',$
                 'function centroid to desired location.','',$
                 'Release button when finished.']
   end
1: begin

   deSensitizeWidgets,event
   widget_control,event.top,get_uvalue = pState

   RMDPAAddGaussianFun,event
   widget_control,event.top,get_uvalue = pState
   widget_control,(*pState).textfit,set_value = $
                ['Hold down mouse button and drag',$
                 'function centroid to desired location.','',$
                 'Release button when finished.']
   end
2: begin

   deSensitizeWidgets,event
   widget_control,event.top,get_uvalue = pState

   RMDPAAddLorentzianFun,event
   widget_control,event.top,get_uvalue = pState
   widget_control,(*pState).textfit,set_value = $
                ['Hold down mouse button and drag',$
                 'function centroid to desired location.','',$
                 'Release button when finished.']
   end
3: begin

   deSensitizeWidgets,event
   widget_control,event.top,get_uvalue = pState

   RMDPAAddLNFun,event
   widget_control,event.top,get_uvalue = pState
   widget_control,(*pState).textfit,set_value = $
                ['Hold down mouse button and drag',$
                 'function centroid to desired location.','',$
                 'Release button when finished.']
   end
4: begin

   deSensitizeWidgets,event
   widget_control,event.top,get_uvalue = pState

   RMDPAAddVoigtFun,event
   widget_control,event.top,get_uvalue = pState
   widget_control,(*pState).textfit,set_value = $
                ['Hold down mouse button and drag',$
                 'function centroid to desired location.','',$
                 'Release button when finished.']
   end
5: begin

   deSensitizeWidgets,event
   widget_control,event.top,get_uvalue = pState

   RMDPAAddDHOFun,event
   widget_control,event.top,get_uvalue = pState
   widget_control,(*pState).textfit,set_value = $
                ['Hold down mouse button and drag',$
                 'function centroid to desired location.','',$
                 'Release button when finished.']
   end
6: begin

   deSensitizeWidgets,event
   widget_control,event.top,get_uvalue = pState

   RMDPAAddSmoothStepFun,event
   widget_control,event.top,get_uvalue = pState
   widget_control,(*pState).textfit,set_value = $
                ['Hold down mouse button and drag',$
                 'function centroid to desired location.','',$
                 'Release button when finished.']
   end
7: begin

   deSensitizeWidgets,event
   widget_control,event.top,get_uvalue = pState

   RMDPAAddBgFun,event
   widget_control,event.top,get_uvalue = pState
   widget_control,(*pState).textfit,set_value = $
                ['Hold down mouse button and drag',$
                 'function centroid to desired location.','',$
                 'Release button when finished.']
   end
8: begin

   deSensitizeWidgets,event
   widget_control,event.top,get_uvalue = pState

   RMDPAAddTunnelEISFFun,event
   widget_control,event.top,get_uvalue = pState
   widget_control,(*pState).textfit,set_value = $
                ['Hold down mouse button and drag',$
                 'function centroid to desired location.','',$
                 'Release button when finished.']
   end
9: begin

   deSensitizeWidgets,event
   widget_control,event.top,get_uvalue = pState

   RMDPAAdd3SiteEISFFun,event
   widget_control,event.top,get_uvalue = pState
   widget_control,(*pState).textfit,set_value = $
                ['Hold down mouse button and drag',$
                 'function centroid to desired location.','',$
                 'Release button when finished.']
   end
10: begin

   deSensitizeWidgets,event
   widget_control,event.top,get_uvalue = pState

   RMDPAAdd2SiteEISFFun,event
   widget_control,event.top,get_uvalue = pState
   widget_control,(*pState).textfit,set_value = $
                ['Hold down mouse button and drag',$
                 'function centroid to desired location.','',$
                 'Release button when finished.']
   end
11: begin

   deSensitizeWidgets,event
   widget_control,event.top,get_uvalue = pState

   RMDPAAddKohlFun,event
   widget_control,event.top,get_uvalue = pState
   widget_control,(*pState).textfit,set_value = $
                ['Hold down mouse button and set',$
                 'the peak height.','',$
                 'Release button when finished.']
   end
else:
endcase


return
end
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
pro tieparmswidget_event,event

widget_Control,event.top,get_uvalue=state
widget_control,state.curve1,get_value=c1 & c1 = fix(c1[0])
widget_control,state.curve2,get_value=c2 & c2 = fix(c2[0])
widget_control,state.parm1,get_value=p1 & p1 = fix(p1[0])
widget_control,state.parm2,get_value=p2 & p2 = fix(p2[0])
widget_control,state.const,get_value=const & const = double(const[0])
widget_control,state.multiplier,get_value=multiplier & multiplier = double(multiplier[0])
*state.outPtr = [c1,p1,multiplier,c2,p2,const]
(*state.outStrPtr).c1 = c1
(*state.outStrPtr).c2 = c2
(*state.outStrPtr).p1 = p1
(*state.outStrPtr).p2 = p2
(*state.outStrPtr).constant = const
(*state.outStrPtr).mult = multiplier
widget_control,event.top,/destroy
return
end
;;;;;;;;;;;;;;;;;;;;;;;;;
function tieparmswidget,group_leader=group_leader

if keyword_set(group_leader) then base = widget_base(/column ,group_leader=group_leader,/modal) $
   else base = widget_base(/column,title = 'Tie Fitting Parameters Dialog')
;void = widget_label(base,value='Tie Fitting Parameters Dialog')
;build a field for every entry in the input structure
void = widget_label(base,value = 'Type in the appropriate curves, parameters, multiplier, and constant')

newBase = widget_base(base,/row)
curve1 = cw_field(newBase,title = 'C',value = '1',/row,/string,xsize = 3)
parm1 = cw_field(newBase,title = 'P',value = '1',/row,/string,xsize = 3)
lab1 = widget_label(newbase,value = '=')
multiplier = cw_field(newBase,title = '',value = '1.0',/row,/string,xsize = 3)
lab2 = widget_label(newbase,value = '*')
curve2 = cw_field(newBase,title = 'C',value = '2',/row,/string,xsize = 3)
parm2 = cw_field(newBase,title = 'P',value = '1',/row,/string,xsize = 3)
lab3 = widget_label(newbase,value = '+')
const = cw_field(newBase,title = '',value = '0.0',/string,xsize = 3)
output = [1,1,1.0,2,1,0.0]
outStr = {c1:1,p1:1,c2:2,p2:1,constant:0.0,mult:1.0}

void = widget_button(base,value='done')
widget_control,base,/realize
state = { curve1:curve1,parm1:parm1,$
          curve2:curve2,parm2:parm2,$
          multiplier:multiplier,$
          outStrPtr:ptr_new(outStr),$
          const:const,outPtr:ptr_new(output)}

widget_control,base,set_uvalue=state
xmanager,'tieparmswidget',base
output = (*state.outPtr)
outStr = (*state.outStrPtr)
ptr_free,state.outPtr ;free the pointer
ptr_free,state.outStrPtr ;free the pointer
return,outStr
end
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
pro RMDPATieParms,event
widget_control,event.top,get_uvalue = pState
ncurves = calcNumberOfCurves((*pState).parmStr)

if ncurves eq 0 then begin

  return
endif

widget_control,(*pState).pickCurve,get_value = curveSel

curveSel = fix(curveSel[0])-1	; decrement by one since using as an index into a vector
if curveSel eq -1 then begin

  return
endif
curveOrder = *(*pState).parmStr.curveIdPtr
curveType = curveOrder[curveSel]
wherevalid = where(curveOrder eq curveType,count)

result = tieparmswidget(group_leader = event.top)

(*pState).tieParmP1 = result.p1
(*pState).tieParmP2 = result.p2
(*pState).tieParmC1 = result.c1
(*pState).tieParmC2 = result.c1
(*pState).tieParmConst = result.constant
(*pState).tieParmMult = result.mult

;freeThePointer,(*pState).currentCurvePtr
;freeThePointer,(*pState).currentParmPtr


return
end
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
pro RMDPAFixParms,event
widget_control,event.top,get_uvalue = pState
ncurves = calcNumberOfCurves((*pState).parmStr)

if ncurves eq 0 then begin

  return
endif

widget_control,(*pState).pickCurve,get_value = curveSel

curveSel = fix(curveSel[0])-1	; decrement by one since using as an index into a vector
if curveSel eq -1 then begin

  return
endif
curveOrder = *(*pState).parmStr.curveIdPtr
curveType = curveOrder[curveSel]
wherevalid = where(curveOrder eq curveType,count)

  case curveType of
  0:	begin	; gaussian
        ngauss = (*pState).parmStr.ngauss
	    	index = where(wherevalid eq curveSel)
 			oldParms = *(*pState).parmStr.gaussParmPtr
 			curParms = fltarr(3)
 			curParms[*] = oldParms[3*index[0]:3*index[0]+2]
 			fixArray = *(*pState).parmStr.gaussParmFixPtr
 			fixPtr = ptr_new(fixArray[3*index[0]:3*index[0]+2])
			gaussConstraintPtr = (*pState).parmStr.gaussConstraintPtr
			constraint = {checkLoLimPtr:ptr_new((*(*gaussConstraintPtr).checkLoLimPtr)[3*index[0]:3*index[0]+2]),$
						  checkHiLimPtr:ptr_new((*(*gaussConstraintPtr).checkHiLimPtr)[3*index[0]:3*index[0]+2]),$
						  HiLimPtr:ptr_new((*(*gaussConstraintPtr).HiLimPtr)[3*index[0]:3*index[0]+2]),$
						  LoLimPtr:ptr_new((*(*gaussConstraintPtr).LoLimPtr)[3*index[0]:3*index[0]+2])}

 			outPtr = ptrarr(3,/allocate_heap)
            outPtr = RMDPAFixParmsWidget(group_leader = event.top,$
                     ptr_new(curParms),fixPtr,$
                     ptr_new(['Area','Center','FWHM']),$
                     ptr_new(constraint))
 			constraint = *outPtr[2]

			(*(*gaussConstraintPtr).checkLoLimPtr)[3*index[0]:3*index[0]+2] = *constraint.checkLoLimPtr
			(*(*gaussConstraintPtr).checkHiLimPtr)[3*index[0]:3*index[0]+2] = *constraint.checkHiLimPtr
			(*(*gaussConstraintPtr).LoLimPtr)[3*index[0]:3*index[0]+2] = *constraint.LoLimPtr
			(*(*gaussConstraintPtr).HiLimPtr)[3*index[0]:3*index[0]+2] = *constraint.HiLimPtr
 			newParms = *outPtr[1]
 			updatedFixArray = intarr(3)
 			updatedFixArray = *outPtr[0]
 			fixArray[3*index[0]:3*index[0]+2] = updatedFixArray[0:2]
 			if ptr_valid((*pState).parmStr.gaussParmFixPtr) then ptr_free,(*pState).parmStr.gaussParmFixPtr
 			(*pState).parmStr.gaussParmFixPtr = ptr_new(fixArray)
 			updatedParms = fltarr(3)
 			updatedParms[0:2] = (*outPtr[1])[0:2]
 			oldParms[3*index[0]:3*index[0]+2] = updatedParms[0:2]
 			if ptr_valid((*pState).parmStr.gaussParmPtr) then ptr_free,(*pState).parmStr.gaussParmPtr
	    	(*pState).parmStr.gaussParmPtr = ptr_new(oldParms)
	    end
  1:	begin	; lorentzian
        nlorentz = (*pState).parmStr.nlorentz
	    	index = where(wherevalid eq curveSel)
 			oldParms = *(*pState).parmStr.lorentzParmPtr
 			curParms = fltarr(3)
 			curParms[*] = oldParms[3*index[0]:3*index[0]+2]
 			fixArray = *(*pState).parmStr.lorentzParmFixPtr
 			fixPtr = ptr_new(fixArray[3*index[0]:3*index[0]+2])
			lorentzConstraintPtr = (*pState).parmStr.lorentzConstraintPtr
			constraint = {checkLoLimPtr:ptr_new((*(*lorentzConstraintPtr).checkLoLimPtr)[3*index[0]:3*index[0]+2]),$
						  checkHiLimPtr:ptr_new((*(*lorentzConstraintPtr).checkHiLimPtr)[3*index[0]:3*index[0]+2]),$
						  HiLimPtr:ptr_new((*(*lorentzConstraintPtr).HiLimPtr)[3*index[0]:3*index[0]+2]),$
						  LoLimPtr:ptr_new((*(*lorentzConstraintPtr).LoLimPtr)[3*index[0]:3*index[0]+2])}

  			outPtr = ptrarr(3,/allocate_heap)
            outPtr = RMDPAFixParmsWidget(group_leader = event.top,$
                     ptr_new(curParms),fixPtr,$
                     ptr_new(['Area','Center','FWHM']),$
                     ptr_new(constraint))
 			constraint = *outPtr[2]

			(*(*lorentzConstraintPtr).checkLoLimPtr)[3*index[0]:3*index[0]+2] = *constraint.checkLoLimPtr
			(*(*lorentzConstraintPtr).checkHiLimPtr)[3*index[0]:3*index[0]+2] = *constraint.checkHiLimPtr
			(*(*lorentzConstraintPtr).LoLimPtr)[3*index[0]:3*index[0]+2] = *constraint.LoLimPtr
			(*(*lorentzConstraintPtr).HiLimPtr)[3*index[0]:3*index[0]+2] = *constraint.HiLimPtr

 			newParms = *outPtr[1]
 			updatedFixArray = intarr(3)
 			updatedFixArray = *outPtr[0]
 			fixArray[3*index[0]:3*index[0]+2] = updatedFixArray[0:2]
 			freeThePointer,(*pState).parmStr.lorentzParmFixPtr
 			(*pState).parmStr.lorentzParmFixPtr = ptr_new(fixArray)
 			updatedParms = fltarr(3)
 			updatedParms[0:2] = (*outPtr[1])[0:2]
 			oldParms[3*index[0]:3*index[0]+2] = updatedParms[0:2]
 			freeThePointer,(*pState).parmStr.lorentzParmPtr
	    	(*pState).parmStr.lorentzParmPtr = ptr_new(oldParms)
	    end
  2:	begin	; sloping background
            nbg = (*pState).parmStr.nbg
            oldParms = *(*pState).parmStr.bgParmPtr
 			fixArray = *(*pState).parmStr.bgParmFixPtr
 			freeThePointer,fixPtr
 			fixPtr = ptr_new(fixArray)
			bgConstraintPtr = (*pState).parmStr.bgConstraintPtr
			constraint = {checkLoLimPtr:ptr_new((*(*bgConstraintPtr).checkLoLimPtr)[0:1]),$
						  checkHiLimPtr:ptr_new((*(*bgConstraintPtr).checkHiLimPtr)[0:1]),$
						  HiLimPtr:ptr_new((*(*bgConstraintPtr).HiLimPtr)[0:1]),$
						  LoLimPtr:ptr_new((*(*bgConstraintPtr).LoLimPtr)[0:1])}

 			outPtr = ptrarr(3,/allocate_heap)
            outPtr = RMDPAFixParmsWidget(group_leader = event.top,$
                     ptr_new(oldParms),fixPtr,$
                     ptr_new(['Mean','Slope']),$
                     ptr_new(constraint))
 			constraint = *outPtr[2]

			(*(*bgConstraintPtr).checkLoLimPtr)[0:1] = *constraint.checkLoLimPtr
			(*(*bgConstraintPtr).checkHiLimPtr)[0:1] = *constraint.checkHiLimPtr
			(*(*bgConstraintPtr).LoLimPtr)[0:1] = *constraint.LoLimPtr
			(*(*bgConstraintPtr).HiLimPtr)[0:1] = *constraint.HiLimPtr

            updatedFixArray = intarr(2)
 			newParms = *outPtr[1]
 			oldParms[0:1] = newParms[0:1]
 			updatedFixArray = *outPtr[0]
 			fixArray[0:1] = updatedFixArray[0:1]
 			freeThePointer,(*pState).parmStr.bgParmFixPtr
 			freeThePointer,(*pState).parmStr.bgParmPtr
 			(*pState).parmStr.bgParmFixPtr = ptr_new(fixArray)
	        (*pState).parmStr.bgParmPtr = ptr_new(oldParms)
	    end
  3:	begin	; lognormal
        nlognormal = (*pState).parmStr.nlognormal
	    	index = where(wherevalid eq curveSel)
 			oldParms = *(*pState).parmStr.logNormParmPtr
 			fixArray = *(*pState).parmStr.logNormParmFixPtr
 			freeThePointer,fixPtr
 			fixPtr = ptr_new(fixArray[3*index[0]:3*index[0]+2])
 			curParms = fltarr(3)
 			curParms[*] = oldParms[3*index[0]:3*index[0]+2]
			logNormConstraintPtr = (*pState).parmStr.logNormConstraintPtr
			constraint = {checkLoLimPtr:ptr_new((*(*logNormConstraintPtr).checkLoLimPtr)[3*index[0]:3*index[0]+2]),$
						  checkHiLimPtr:ptr_new((*(*logNormConstraintPtr).checkHiLimPtr)[3*index[0]:3*index[0]+2]),$
						  HiLimPtr:ptr_new((*(*logNormConstraintPtr).HiLimPtr)[3*index[0]:3*index[0]+2]),$
						  LoLimPtr:ptr_new((*(*logNormConstraintPtr).LoLimPtr)[3*index[0]:3*index[0]+2])}

 			outPtr = ptrarr(3,/allocate_heap)
            outPtr = RMDPAFixParmsWidget(group_leader = event.top,$
                     ptr_new(curParms),fixPtr,$
                     ptr_new(['Area','mu','sigma']),$
                     ptr_new(constraint))
 			constraint = *outPtr[2]

			(*(*logNormConstraintPtr).checkLoLimPtr)[3*index[0]:3*index[0]+2] = *constraint.checkLoLimPtr
			(*(*logNormConstraintPtr).checkHiLimPtr)[3*index[0]:3*index[0]+2] = *constraint.checkHiLimPtr
			(*(*logNormConstraintPtr).LoLimPtr)[3*index[0]:3*index[0]+2] = *constraint.LoLimPtr
			(*(*logNormConstraintPtr).HiLimPtr)[3*index[0]:3*index[0]+2] = *constraint.HiLimPtr

 			newParms = *outPtr[1]
 			updatedFixArray = intarr(3)
 			updatedFixArray = *outPtr[0]
 			fixArray[3*index[0]:3*index[0]+2] = updatedFixArray[0:2]
 			freeThePointer,(*pState).parmStr.logNormParmFixPtr
 			(*pState).parmStr.logNormParmFixPtr = ptr_new(fixArray)
 			updatedParms = fltarr(3)
 			updatedParms[0:2] = (*outPtr[1])[0:2]
 			oldParms[3*index[0]:3*index[0]+2] = updatedParms[0:2]
 			freeThePointer,(*pState).parmStr.logNormParmPtr
	    	(*pState).parmStr.logNormParmPtr = ptr_new(oldParms)
	    end
  4:	begin	; voigt
        nlognormal = (*pState).parmStr.nvoigt
	    	index = where(wherevalid eq curveSel)
 			oldParms = *(*pState).parmStr.voigtParmPtr
 			fixArray = *(*pState).parmStr.voigtParmFixPtr
 			freeThePointer,fixPtr
 			fixPtr = ptr_new(fixArray[3*index[0]:3*index[0]+2])
 			curParms = fltarr(3);4)
 			curParms[*] = oldParms[3*index[0]:3*index[0]+2]
			voigtConstraintPtr = (*pState).parmStr.voigtConstraintPtr
			constraint = {checkLoLimPtr:ptr_new((*(*voigtConstraintPtr).checkLoLimPtr)[3*index[0]:3*index[0]+2]),$
						  checkHiLimPtr:ptr_new((*(*voigtConstraintPtr).checkHiLimPtr)[3*index[0]:3*index[0]+2]),$
						  HiLimPtr:ptr_new((*(*voigtConstraintPtr).HiLimPtr)[3*index[0]:3*index[0]+2]),$
						  LoLimPtr:ptr_new((*(*voigtConstraintPtr).LoLimPtr)[3*index[0]:3*index[0]+2])}

 			outPtr = ptrarr(3,/allocate_heap)
            outPtr = RMDPAFixParmsWidget(group_leader = event.top,$
                     ptr_new(curParms),fixPtr,$
                     ptr_new(['Area','Center','Width']),$
                     ptr_new(constraint))
 			constraint = *outPtr[2]

			(*(*voigtConstraintPtr).checkLoLimPtr)[3*index[0]:3*index[0]+2] = *constraint.checkLoLimPtr
			(*(*voigtConstraintPtr).checkHiLimPtr)[3*index[0]:3*index[0]+2] = *constraint.checkHiLimPtr
			(*(*voigtConstraintPtr).LoLimPtr)[3*index[0]:3*index[0]+2] = *constraint.LoLimPtr
			(*(*voigtConstraintPtr).HiLimPtr)[3*index[0]:3*index[0]+2] = *constraint.HiLimPtr

 			newParms = *outPtr[1]
 			updatedFixArray = intarr(3);4)
 			updatedFixArray = *outPtr[0]
 			fixArray[3*index[0]:3*index[0]+2] = updatedFixArray[0:2]
 			freeThePointer,(*pState).parmStr.voigtParmFixPtr
 			(*pState).parmStr.voigtParmFixPtr = ptr_new(fixArray)
 			updatedParms = fltarr(3);)
 			updatedParms[0:2] = (*outPtr[1])[0:2]
 			oldParms[3*index[0]:3*index[0]+2] = updatedParms[0:2]
 			freeThePointer,(*pState).parmStr.voigtParmPtr
	    	(*pState).parmStr.voigtParmPtr = ptr_new(oldParms)
	    end
  5:	begin	; smooth step
        ngauss = (*pState).parmStr.nss
	    	index = where(wherevalid eq curveSel)
 			oldParms = *(*pState).parmStr.ssParmPtr
 			curParms = fltarr(3)
 			curParms[*] = oldParms[3*index[0]:3*index[0]+2]
 			fixArray = *(*pState).parmStr.ssParmFixPtr
 			freeThePointer,fixPtr
 			fixPtr = ptr_new(fixArray[3*index[0]:3*index[0]+2])
			ssConstraintPtr = (*pState).parmStr.ssConstraintPtr
			constraint = {checkLoLimPtr:ptr_new((*(*ssConstraintPtr).checkLoLimPtr)[3*index[0]:3*index[0]+2]),$
						  checkHiLimPtr:ptr_new((*(*ssConstraintPtr).checkHiLimPtr)[3*index[0]:3*index[0]+2]),$
						  HiLimPtr:ptr_new((*(*ssConstraintPtr).HiLimPtr)[3*index[0]:3*index[0]+2]),$
						  LoLimPtr:ptr_new((*(*ssConstraintPtr).LoLimPtr)[3*index[0]:3*index[0]+2])}

 			outPtr = ptrarr(3,/allocate_heap)
            outPtr = RMDPAFixParmsWidget(group_leader = event.top,$
                     ptr_new(curParms),fixPtr,$
                     ptr_new(['Area','Center','FWHM']),$
                     ptr_new(constraint))
 			constraint = *outPtr[2]

			(*(*ssConstraintPtr).checkLoLimPtr)[3*index[0]:3*index[0]+2] = *constraint.checkLoLimPtr
			(*(*ssConstraintPtr).checkHiLimPtr)[3*index[0]:3*index[0]+2] = *constraint.checkHiLimPtr
			(*(*ssConstraintPtr).LoLimPtr)[3*index[0]:3*index[0]+2] = *constraint.LoLimPtr
			(*(*ssConstraintPtr).HiLimPtr)[3*index[0]:3*index[0]+2] = *constraint.HiLimPtr
 			newParms = *outPtr[1]
 			updatedFixArray = intarr(3)
 			updatedFixArray = *outPtr[0]
 			fixArray[3*index[0]:3*index[0]+2] = updatedFixArray[0:2]
 			freeThePointer,(*pState).parmStr.ssParmFixPtr
 			(*pState).parmStr.ssParmFixPtr = ptr_new(fixArray)
 			updatedParms = fltarr(3)
 			updatedParms[0:2] = (*outPtr[1])[0:2]
 			oldParms[3*index[0]:3*index[0]+2] = updatedParms[0:2]
	    	freeThePointer,(*pState).parmStr.ssParmPtr
	    	(*pState).parmStr.ssParmPtr = ptr_new(oldParms)
	    end
  6:	begin	; DHO
        ngauss = (*pState).parmStr.nDHO
	    	index = where(wherevalid eq curveSel)
 			oldParms = *(*pState).parmStr.DHOParmPtr
 			curParms = fltarr(4)
 			curParms[*] = oldParms[4*index[0]:4*index[0]+3]
 			fixArray = *(*pState).parmStr.DHOParmFixPtr
 			freeThePointer,fixPtr
 			fixPtr = ptr_new(fixArray[4*index[0]:4*index[0]+3])
			DHOConstraintPtr = (*pState).parmStr.DHOConstraintPtr
			constraint = {checkLoLimPtr:ptr_new((*(*DHOConstraintPtr).checkLoLimPtr)[4*index[0]:4*index[0]+3]),$
						  checkHiLimPtr:ptr_new((*(*DHOConstraintPtr).checkHiLimPtr)[4*index[0]:4*index[0]+3]),$
						  HiLimPtr:ptr_new((*(*DHOConstraintPtr).HiLimPtr)[4*index[0]:4*index[0]+3]),$
						  LoLimPtr:ptr_new((*(*DHOConstraintPtr).LoLimPtr)[4*index[0]:4*index[0]+3])}

 			outPtr = ptrarr(3,/allocate_heap)
            outPtr = RMDPAFixParmsWidget(group_leader = event.top,$
                     ptr_new(curParms),fixPtr,$
                     ptr_new(['Amplitude','Center','FWHM','Temperature']),$
                     ptr_new(constraint))
 			constraint = *outPtr[2]

			(*(*DHOConstraintPtr).checkLoLimPtr)[4*index[0]:4*index[0]+3] = *constraint.checkLoLimPtr
			(*(*DHOConstraintPtr).checkHiLimPtr)[4*index[0]:4*index[0]+3] = *constraint.checkHiLimPtr
			(*(*DHOConstraintPtr).LoLimPtr)[4*index[0]:4*index[0]+3] = *constraint.LoLimPtr
			(*(*DHOConstraintPtr).HiLimPtr)[4*index[0]:4*index[0]+3] = *constraint.HiLimPtr
 			newParms = *outPtr[1]
 			updatedFixArray = intarr(4)
 			updatedFixArray = *outPtr[0]
 			fixArray[4*index[0]:4*index[0]+3] = updatedFixArray[0:3]
 			freeThePointer,(*pState).parmStr.DHOParmFixPtr
 			(*pState).parmStr.DHOParmFixPtr = ptr_new(fixArray)
 			updatedParms = fltarr(4)
 			updatedParms[0:3] = (*outPtr[1])[0:3]
 			oldParms[4*index[0]:4*index[0]+3] = updatedParms[0:3]
 			freeThePointer,(*pState).parmStr.DHOParmPtr
	    	(*pState).parmStr.DHOParmPtr = ptr_new(oldParms)
	    end
  999:	begin	; Dirac delta function
        ngauss = (*pState).parmStr.nDelta
	    	index = where(wherevalid eq curveSel)
 			oldParms = *(*pState).parmStr.deltaParmPtr
 			curParms = dblarr(3)
 			curParms[*] = oldParms[3*index[0]:3*index[0]+2]
 			fixArray = *(*pState).parmStr.deltaParmFixPtr
 			freeThePointer,fixPtr
 			fixPtr = ptr_new(fixArray[3*index[0]:3*index[0]+2])
			deltaConstraintPtr = (*pState).parmStr.deltaConstraintPtr
			constraint = {checkLoLimPtr:ptr_new((*(*deltaConstraintPtr).checkLoLimPtr)[3*index[0]:3*index[0]+2]),$
						  checkHiLimPtr:ptr_new((*(*deltaConstraintPtr).checkHiLimPtr)[3*index[0]:3*index[0]+2]),$
						  HiLimPtr:ptr_new((*(*deltaConstraintPtr).HiLimPtr)[3*index[0]:3*index[0]+2]),$
						  LoLimPtr:ptr_new((*(*deltaConstraintPtr).LoLimPtr)[3*index[0]:3*index[0]+2])}

 			outPtr = ptrarr(3,/allocate_heap)
            outPtr = RMDPAFixParmsWidget(group_leader = event.top,$
                     ptr_new(curParms),fixPtr,$
                     ptr_new(['Area','Center','Width']),$
                     ptr_new(constraint))
 			constraint = *outPtr[2]

			(*(*deltaConstraintPtr).checkLoLimPtr)[3*index[0]:3*index[0]+2] = *constraint.checkLoLimPtr
			(*(*deltaConstraintPtr).checkHiLimPtr)[3*index[0]:3*index[0]+2] = *constraint.checkHiLimPtr
			(*(*deltaConstraintPtr).LoLimPtr)[3*index[0]:3*index[0]+2] = *constraint.LoLimPtr
			(*(*deltaConstraintPtr).HiLimPtr)[3*index[0]:3*index[0]+2] = *constraint.HiLimPtr
 			newParms = *outPtr[1]
 			updatedFixArray = intarr(3)
 			updatedFixArray = *outPtr[0]
 			fixArray[3*index[0]:3*index[0]+2] = updatedFixArray[0:2]
 			freeThePointer,(*pState).parmStr.deltaParmFixPtr
 			(*pState).parmStr.deltaParmFixPtr = ptr_new(fixArray)
 			updatedParms = dblarr(3)
 			updatedParms[0:2] = (*outPtr[1])[0:2]
 			oldParms[3*index[0]:3*index[0]+2] = updatedParms[0:2]
 			freeThePointer,(*pState).parmStr.deltaParmPtr
	    	(*pState).parmStr.deltaParmPtr = ptr_new(oldParms)
	    end

  8:	begin	; Methyl tunnel EISF
            nbg = (*pState).parmStr.ntunnelEISF
            oldParms = *(*pState).parmStr.tunnelEISFParmPtr
 			fixArray = *(*pState).parmStr.tunnelEISFParmFixPtr
 			freeThePointer,fixPtr
 			fixPtr = ptr_new(fixArray)
			tunnelEISFConstraintPtr = (*pState).parmStr.tunnelEISFConstraintPtr
			constraint = {checkLoLimPtr:ptr_new((*(*tunnelEISFConstraintPtr).checkLoLimPtr)[0]),$
						  checkHiLimPtr:ptr_new((*(*tunnelEISFConstraintPtr).checkHiLimPtr)[0]),$
						  HiLimPtr:ptr_new((*(*tunnelEISFConstraintPtr).HiLimPtr)[0]),$
						  LoLimPtr:ptr_new((*(*tunnelEISFConstraintPtr).LoLimPtr)[0])}

 			outPtr = ptrarr(3,/allocate_heap)
            outPtr = RMDPAFixParmsWidget(group_leader = event.top,$
                     ptr_new(oldParms),fixPtr,$
                     ptr_new(['radius']),$
                     ptr_new(constraint))
 			constraint = *outPtr[2]

			(*(*tunnelEISFConstraintPtr).checkLoLimPtr)[0] = *constraint.checkLoLimPtr
			(*(*tunnelEISFConstraintPtr).checkHiLimPtr)[0] = *constraint.checkHiLimPtr
			(*(*tunnelEISFConstraintPtr).LoLimPtr)[0] = *constraint.LoLimPtr
			(*(*tunnelEISFConstraintPtr).HiLimPtr)[0] = *constraint.HiLimPtr

            updatedFixArray = intarr(1)
 			newParms = *outPtr[1]
 			oldParms[0] = newParms[0]
 			updatedFixArray = *outPtr[0]
 			fixArray[0] = updatedFixArray[0]
 			freeThePointer,(*pState).parmStr.tunnelEISFParmFixPtr
 			freeThePointer,(*pState).parmStr.tunnelEISFParmPtr
 			(*pState).parmStr.tunnelEISFParmFixPtr = ptr_new(fixArray)
	        (*pState).parmStr.tunnelEISFParmPtr = ptr_new(oldParms)
	    end
  9:	begin	; three site jump EISF
            nbg = (*pState).parmStr.nthreeSiteEISF
            oldParms = *(*pState).parmStr.threeSiteEISFParmPtr
 			fixArray = *(*pState).parmStr.threeSiteEISFParmFixPtr
 			freeThePointer,fixPtr
 			fixPtr = ptr_new(fixArray)
			threeSiteEISFConstraintPtr = (*pState).parmStr.threeSiteEISFConstraintPtr
			constraint = {checkLoLimPtr:ptr_new((*(*threeSiteEISFConstraintPtr).checkLoLimPtr)[0]),$
						  checkHiLimPtr:ptr_new((*(*threeSiteEISFConstraintPtr).checkHiLimPtr)[0]),$
						  HiLimPtr:ptr_new((*(*threeSiteEISFConstraintPtr).HiLimPtr)[0]),$
						  LoLimPtr:ptr_new((*(*threeSiteEISFConstraintPtr).LoLimPtr)[0])}

 			outPtr = ptrarr(3,/allocate_heap)
            outPtr = RMDPAFixParmsWidget(group_leader = event.top,$
                     ptr_new(oldParms),fixPtr,$
                     ptr_new(['radius']),$
                     ptr_new(constraint))
 			constraint = *outPtr[2]

			(*(*threeSiteEISFConstraintPtr).checkLoLimPtr)[0] = *constraint.checkLoLimPtr
			(*(*threeSiteEISFConstraintPtr).checkHiLimPtr)[0] = *constraint.checkHiLimPtr
			(*(*threeSiteEISFConstraintPtr).LoLimPtr)[0] = *constraint.LoLimPtr
			(*(*threeSiteEISFConstraintPtr).HiLimPtr)[0] = *constraint.HiLimPtr

            updatedFixArray = intarr(1)
 			newParms = *outPtr[1]
 			oldParms[0] = newParms[0]
 			updatedFixArray = *outPtr[0]
 			fixArray[0] = updatedFixArray[0]
 			freeThePointer,(*pState).parmStr.threeSiteEISFParmFixPtr
 			freeThePointer,(*pState).parmStr.threeSiteEISFParmPtr
 			(*pState).parmStr.threeSiteEISFParmFixPtr = ptr_new(fixArray)
	        (*pState).parmStr.threeSiteEISFParmPtr = ptr_new(oldParms)
	    end
  10:	begin	; two site jump EISF
            nbg = (*pState).parmStr.ntwoSiteEISF
            oldParms = *(*pState).parmStr.twoSiteEISFParmPtr
 			fixArray = *(*pState).parmStr.twoSiteEISFParmFixPtr
 			freeThePointer,fixPtr
 			fixPtr = ptr_new(fixArray)
			twoSiteEISFConstraintPtr = (*pState).parmStr.twoSiteEISFConstraintPtr
			constraint = {checkLoLimPtr:ptr_new((*(*twoSiteEISFConstraintPtr).checkLoLimPtr)[0]),$
						  checkHiLimPtr:ptr_new((*(*twoSiteEISFConstraintPtr).checkHiLimPtr)[0]),$
						  HiLimPtr:ptr_new((*(*twoSiteEISFConstraintPtr).HiLimPtr)[0]),$
						  LoLimPtr:ptr_new((*(*twoSiteEISFConstraintPtr).LoLimPtr)[0])}

 			outPtr = ptrarr(3,/allocate_heap)
            outPtr = RMDPAFixParmsWidget(group_leader = event.top,$
                     ptr_new(oldParms),fixPtr,$
                     ptr_new(['radius']),$
                     ptr_new(constraint))
 			constraint = *outPtr[2]

			(*(*twoSiteEISFConstraintPtr).checkLoLimPtr)[0] = *constraint.checkLoLimPtr
			(*(*twoSiteEISFConstraintPtr).checkHiLimPtr)[0] = *constraint.checkHiLimPtr
			(*(*twoSiteEISFConstraintPtr).LoLimPtr)[0] = *constraint.LoLimPtr
			(*(*twoSiteEISFConstraintPtr).HiLimPtr)[0] = *constraint.HiLimPtr

            updatedFixArray = intarr(1)
 			newParms = *outPtr[1]
 			oldParms[0] = newParms[0]
 			updatedFixArray = *outPtr[0]
 			fixArray[0] = updatedFixArray[0]
 			freeThePointer,(*pState).parmStr.twoSiteEISFParmFixPtr
 			freeThePointer,(*pState).parmStr.twoSiteEISFParmPtr
 			(*pState).parmStr.twoSiteEISFParmFixPtr = ptr_new(fixArray)
	        (*pState).parmStr.twoSiteEISFParmPtr = ptr_new(oldParms)
	    end
  7:	begin	; Kohlrausch
        nkohl = (*pState).parmStr.nkohl
	    	index = where(wherevalid eq curveSel)
 			oldParms = *(*pState).parmStr.kohlParmPtr
 			curParms = fltarr(3)
 			curParms[*] = oldParms[3*index[0]:3*index[0]+2]
 			fixArray = *(*pState).parmStr.kohlParmFixPtr
 			fixPtr = ptr_new(fixArray[3*index[0]:3*index[0]+2])
			kohlConstraintPtr = (*pState).parmStr.kohlConstraintPtr
			constraint = {checkLoLimPtr:ptr_new((*(*kohlConstraintPtr).checkLoLimPtr)[3*index[0]:3*index[0]+2]),$
						  checkHiLimPtr:ptr_new((*(*kohlConstraintPtr).checkHiLimPtr)[3*index[0]:3*index[0]+2]),$
						  HiLimPtr:ptr_new((*(*kohlConstraintPtr).HiLimPtr)[3*index[0]:3*index[0]+2]),$
						  LoLimPtr:ptr_new((*(*kohlConstraintPtr).LoLimPtr)[3*index[0]:3*index[0]+2])}


 			outPtr = ptrarr(3,/allocate_heap)
            outPtr = RMDPAFixParmsWidget(group_leader = event.top,$
                     ptr_new(curParms),fixPtr,$
                     ptr_new(['Amplitude','Beta','Tau']),$
                     ptr_new(constraint))
 			constraint = *outPtr[2]

			(*(*kohlConstraintPtr).checkLoLimPtr)[3*index[0]:3*index[0]+2] = *constraint.checkLoLimPtr
			(*(*kohlConstraintPtr).checkHiLimPtr)[3*index[0]:3*index[0]+2] = *constraint.checkHiLimPtr
			(*(*kohlConstraintPtr).LoLimPtr)[3*index[0]:3*index[0]+2] = *constraint.LoLimPtr
			(*(*kohlConstraintPtr).HiLimPtr)[3*index[0]:3*index[0]+2] = *constraint.HiLimPtr
 			newParms = *outPtr[1]
 			updatedFixArray = intarr(3)
 			updatedFixArray = *outPtr[0]
 			fixArray[3*index[0]:3*index[0]+2] = updatedFixArray[0:2]
 			if ptr_valid((*pState).parmStr.kohlParmFixPtr) then ptr_free,(*pState).parmStr.kohlParmFixPtr
 			(*pState).parmStr.kohlParmFixPtr = ptr_new(fixArray)
 			updatedParms = fltarr(3)
 			updatedParms[0:2] = (*outPtr[1])[0:2]
 			oldParms[3*index[0]:3*index[0]+2] = updatedParms[0:2]
 			if ptr_valid((*pState).parmStr.kohlParmPtr) then ptr_free,(*pState).parmStr.kohlParmPtr
	    	(*pState).parmStr.kohlParmPtr = ptr_new(oldParms)
	    end
  else:
  endcase
;freeThePointer,(*pState).currentCurvePtr
;freeThePointer,(*pState).currentParmPtr

; Added the next 4 lines (11/16/01) in order to update
; the parameter constraints in bigParmPtr
widget_control,(*pState).selGroup,get_value = thisGroup
thisGroup = fix(thisGroup[0]) - 1
widget_control,(*pState).textFit,get_uvalue = bigParmPtr,/no_copy
*bigParmPtr[thisGroup] = (*pState).parmStr
widget_control,(*pState).textFit,set_uvalue = bigParmPtr,/no_copy


RMDCalcDisplay,event
widget_control,event.top,get_uvalue = pState


RMDPlotDisplay,event
widget_control,event.top,get_uvalue = pState



return
end
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
pro PeakAnalysisAddCurveToStructure,event
widget_control,event.top,get_uvalue = pState
parmStr = (*pState).parmStr
curParms = *(*pState).currentParmPtr
data = (*pState).dataPtr
datSize = size(data)
nchan = datSize[2]
dx = (*(*pState).dataPtr)[0,1]-(*(*pState).dataPtr)[0,0]
loWidLimit = 0.5*dx

case (*pState).curveType of
0:	begin	; gaussian
      ;freeThePointer,(*pState).currentCurvePtr
      *(*pState).currentCurvePtr = 0
	  (*pState).parmStr.ngauss = (*pState).parmStr.ngauss + 1
	  if n_elements(*(*pState).parmStr.gaussParmPtr) gt 0 then begin
	    oldParms = *(*pState).parmStr.gaussParmPtr
	    newParms = dblarr(n_elements(oldParms)+3)
	    newParms = [oldParms,curParms]
	    *(*pState).parmStr.gaussParmPtr = newParms
	  endif else begin
	    *(*pState).parmStr.gaussParmPtr = curParms
	  endelse
	  if n_elements(*(*pState).parmStr.gaussParmFixPtr) gt 0 then begin
	    oldFixArray = *(*pState).parmStr.gaussParmFixPtr
	    newFixArray = intarr(n_elements(oldFixArray)+3)
	    newFixArray = [oldFixArray,0,0,0]
	    *(*pState).parmStr.gaussParmFixPtr = newFixArray
	  endif else begin
	    (*pState).parmStr.gaussParmFixPtr = ptr_new([0,0,0])
	  endelse
	  if n_elements(*(*pState).parmStr.gaussStepPtr) gt 0 then begin
	    oldStep = *(*pState).parmStr.gaussStepPtr
	    newStep = dblarr(n_elements(oldStep)+3)
	    newStep = [oldStep,0.0,0.0,0.0]
	    *(*pState).parmStr.gaussStepPtr = newStep
	  endif else begin
	    *(*pState).parmStr.gaussStepPtr = [0.0,0.0,0.0]
	  endelse
      if n_elements(*(*pState).parmStr.gaussConstraintPtr) gt 0 then begin
	    oldLoLimCheckArray = *(*(*pState).parmStr.gaussConstraintPtr).checkLoLimPtr
	    newLoLimCheckArray = intarr(n_elements(oldLoLimCheckArray)+3)
	    newLoLimCheckArray = [oldLoLimCheckArray,0,0,1]
	    *(*(*pState).parmStr.gaussConstraintPtr).checkLoLimPtr = newLoLimCheckArray
	    oldHiLimCheckArray = *(*(*pState).parmStr.gaussConstraintPtr).checkHiLimPtr
	    newHiLimCheckArray = intarr(n_elements(oldHiLimCheckArray)+3)
	    newHiLimCheckArray = [oldHiLimCheckArray,0,0,0]
	    *(*(*pState).parmStr.gaussConstraintPtr).checkHiLimPtr = newHiLimCheckArray
 	    oldLoLimArray = *(*(*pState).parmStr.gaussConstraintPtr).LoLimPtr
	    newLoLimArray = fltarr(n_elements(oldLoLimArray)+3)
	    newLoLimArray = [oldLoLimArray,0.0,0.0,loWidLimit]
	    *(*(*pState).parmStr.gaussConstraintPtr).LoLimPtr = newLoLimArray
 	    oldHiLimArray = *(*(*pState).parmStr.gaussConstraintPtr).HiLimPtr
	    newHiLimArray = fltarr(n_elements(oldHiLimArray)+3)
	    newHiLimArray = [oldHiLimArray,1.0,1.0,1.0]
	    *(*(*pState).parmStr.gaussConstraintPtr).HiLimPtr = newHiLimArray
      endif else begin
 	    *(*pState).parmStr.gaussConstraintPtr = {checkLoLimPtr:ptr_new([0,0,1]),$
 	                                           checkHiLimPtr:ptr_new([0,0,0]),$
 			                                   LoLimPtr:ptr_new([0.,0.,loWidLimit]),$
 			                                   HiLimPtr:ptr_new([1.,1.,1.])}
      endelse

      ;(*pState).currentParmPtr = ptr_new()
      if n_elements(*(*pState).parmStr.curveIdPtr) eq 0 then begin
        *(*pState).parmStr.curveIdPtr = 0
      endif else begin
        oldId = *(*pState).parmStr.curveIdPtr
        *(*pState).parmStr.curveIdPtr = [oldId,0]
      endelse
	end
1:	begin	; lorentzian
	  (*pState).parmStr.nlorentz = (*pState).parmStr.nlorentz + 1
	  ;freeThePointer,(*pState).currentCurvePtr
	  *(*pState).currentCurvePtr = 0
	  if n_elements(*(*pState).parmStr.lorentzParmPtr) gt 0 then begin
	    oldParms = *(*pState).parmStr.lorentzParmPtr
	    newParms = dblarr(n_elements(oldParms)+3)
	    newParms = [oldParms,curParms]
	    *(*pState).parmStr.lorentzParmPtr = newParms
	  endif else begin
	    (*pState).parmStr.lorentzParmPtr = ptr_new(curParms)
	  endelse
	  if n_elements(*(*pState).parmStr.lorentzStepPtr) gt 0 then begin
	    oldStep = *(*pState).parmStr.lorentzStepPtr
	    newStep = dblarr(n_elements(oldStep)+3)
	    newStep = [oldStep,0.0,0.0,0.0]
	    *(*pState).parmStr.lorentzStepPtr = newStep
	  endif else begin
	    *(*pState).parmStr.lorentzStepPtr = [0.0,0.0,0.0]
	  endelse
	  if n_elements(*(*pState).parmStr.lorentzParmFixPtr) gt 0 then begin
	    oldFixArray = *(*pState).parmStr.lorentzParmFixPtr
	    newFixArray = intarr(n_elements(oldFixArray)+3)
	    newFixArray = [oldFixArray,0,0,0]
	    *(*pState).parmStr.lorentzParmFixPtr = newFixArray
	  endif else begin
	    *(*pState).parmStr.lorentzParmFixPtr = [0,0,0]
	  endelse
      if n_elements(*(*pState).parmStr.lorentzConstraintPtr) gt 0 then begin
	    oldLoLimCheckArray = *(*(*pState).parmStr.lorentzConstraintPtr).checkLoLimPtr
	    newLoLimCheckArray = intarr(n_elements(oldLoLimCheckArray)+3)
	    newLoLimCheckArray = [oldLoLimCheckArray,0,0,1]
	    *(*(*pState).parmStr.lorentzConstraintPtr).checkLoLimPtr = (newLoLimCheckArray)
	    oldHiLimCheckArray = *(*(*pState).parmStr.lorentzConstraintPtr).checkHiLimPtr
	    newHiLimCheckArray = intarr(n_elements(oldHiLimCheckArray)+3)
	    newHiLimCheckArray = [oldHiLimCheckArray,0,0,0]
	    *(*(*pState).parmStr.lorentzConstraintPtr).checkHiLimPtr = (newHiLimCheckArray)
 	    oldLoLimArray = *(*(*pState).parmStr.lorentzConstraintPtr).LoLimPtr
	    newLoLimArray = fltarr(n_elements(oldLoLimArray)+3)
	    newLoLimArray = [oldLoLimArray,0.0,0.0,loWidLimit]
	    *(*(*pState).parmStr.lorentzConstraintPtr).LoLimPtr = (newLoLimArray)
 	    oldHiLimArray = *(*(*pState).parmStr.lorentzConstraintPtr).HiLimPtr
	    newHiLimArray = fltarr(n_elements(oldHiLimArray)+3)
	    newHiLimArray = [oldHiLimArray,1.0,1.0,1.0]
	    *(*(*pState).parmStr.lorentzConstraintPtr).HiLimPtr = (newHiLimArray)
      endif else begin
 	    *(*pState).parmStr.lorentzConstraintPtr = {checkLoLimPtr:ptr_new([0,0,1]),$
 	                                           checkHiLimPtr:ptr_new([0,0,0]),$
 			                                   LoLimPtr:ptr_new([0.,0.,loWidLimit]),$
 			                                   HiLimPtr:ptr_new([1.,1.,1.])}
      endelse

      ;(*pState).currentParmPtr = ptr_new()
      if n_elements(*(*pState).parmStr.curveIdPtr) eq 0 then begin
        *(*pState).parmStr.curveIdPtr = 1
      endif else begin
        oldId = *(*pState).parmStr.curveIdPtr
        *(*pState).parmStr.curveIdPtr = [oldId,1]
      endelse
	end
2:	begin	; background
      *(*pState).currentCurvePtr = 0
	  (*pState).parmStr.nbg = 1
	  *(*pState).parmStr.bgParmPtr = curParms
	  *(*pState).parmStr.bgParmFixPtr = [0,0]
 	  *(*pState).parmStr.bgConstraintPtr = {checkLoLimPtr:ptr_new([0,0]),$
 	                                           checkHiLimPtr:ptr_new([0,0]),$
 			                                   LoLimPtr:ptr_new([0.,0.]),$
 			                                   HiLimPtr:ptr_new([1.,1.])}

	  if n_elements(*(*pState).parmStr.bgStepPtr) gt 0 then begin
	    oldStep = *(*pState).parmStr.bgStepPtr
	    newStep = dblarr(2)
	    newStep = [0.0,0.0]
	    *(*pState).parmStr.bgStepPtr = newStep
	  endif else begin
	    *(*pState).parmStr.bgStepPtr = [0.0,0.0]
	  endelse

      if n_elements(*(*pState).parmStr.curveIdPtr) eq 0 then begin
        *(*pState).parmStr.curveIdPtr = 2
      endif else begin
        oldId = *(*pState).parmStr.curveIdPtr
        *(*pState).parmStr.curveIdPtr = [oldId,2]
      endelse
	end
3:	begin	; lognormal
      ;freeThePointer,(*pState).currentCurvePtr
      *(*pState).currentCurvePtr = 0
	  (*pState).parmStr.nlognormal = (*pState).parmStr.nlognormal + 1
	  if n_elements(*(*pState).parmStr.logNormParmPtr) gt 0 then begin
	    oldParms = *(*pState).parmStr.logNormParmPtr
	    newParms = dblarr(n_elements(oldParms)+3)
	    newParms = [oldParms,curParms]
	    *(*pState).parmStr.logNormParmPtr = newParms
	  endif else begin
	    *(*pState).parmStr.logNormParmPtr = curParms
	  endelse
	  if n_elements(*(*pState).parmStr.logNormParmFixPtr) gt 0 then begin
	    oldFixArray = *(*pState).parmStr.logNormParmFixPtr
	    newFixArray = intarr(n_elements(oldFixArray)+3)
	    newFixArray = [oldFixArray,0,0,0]
	    *(*pState).parmStr.logNormParmFixPtr = (newFixArray)
	  endif else begin
	    *(*pState).parmStr.logNormParmFixPtr = [0,0,0]
	  endelse

	  if n_elements(*(*pState).parmStr.logNormStepPtr) gt 0 then begin
	    oldStep = *(*pState).parmStr.logNormStepPtr
	    newStep = dblarr(n_elements(oldStep)+3)
	    newStep = [oldStep,0.0,0.0,0.0]
	    *(*pState).parmStr.logNormStepPtr = (newStep)
	  endif else begin
	    *(*pState).parmStr.logNormStepPtr = [0.0,0.0,0.0]
	  endelse

      if n_elements(*(*pState).parmStr.logNormConstraintPtr) gt 0 then begin
	    oldLoLimCheckArray = *(*(*pState).parmStr.logNormConstraintPtr).checkLoLimPtr
	    newLoLimCheckArray = intarr(n_elements(oldLoLimCheckArray)+3)
	    newLoLimCheckArray = [oldLoLimCheckArray,0,0,1]
	    *(*(*pState).parmStr.logNormConstraintPtr).checkLoLimPtr = (newLoLimCheckArray)
	    oldHiLimCheckArray = *(*(*pState).parmStr.logNormConstraintPtr).checkHiLimPtr
	    newHiLimCheckArray = intarr(n_elements(oldHiLimCheckArray)+3)
	    newHiLimCheckArray = [oldHiLimCheckArray,0,0,0]
	    *(*(*pState).parmStr.logNormConstraintPtr).checkHiLimPtr = (newHiLimCheckArray)
 	    oldLoLimArray = *(*(*pState).parmStr.logNormConstraintPtr).LoLimPtr
	    newLoLimArray = fltarr(n_elements(oldLoLimArray)+3)
	    newLoLimArray = [oldLoLimArray,0.0,0.0,loWidLimit]
	    *(*(*pState).parmStr.logNormConstraintPtr).LoLimPtr = (newLoLimArray)
 	    oldHiLimArray = *(*(*pState).parmStr.logNormConstraintPtr).HiLimPtr
	    newHiLimArray = fltarr(n_elements(oldHiLimArray)+3)
	    newHiLimArray = [oldHiLimArray,1.0,1.0,1.0]
	    *(*(*pState).parmStr.logNormConstraintPtr).HiLimPtr = (newHiLimArray)
      endif else begin
 	    *(*pState).parmStr.logNormConstraintPtr = {checkLoLimPtr:ptr_new([0,0,0]),$
 	                                           checkHiLimPtr:ptr_new([0,0,0]),$
 			                                   LoLimPtr:ptr_new([0.,0.,0.]),$
 			                                   HiLimPtr:ptr_new([1.,1.,1.])}
      endelse


      if n_elements(*(*pState).parmStr.curveIdPtr) eq 0 then begin
        *(*pState).parmStr.curveIdPtr = 3
      endif else begin
        oldId = *(*pState).parmStr.curveIdPtr
        *(*pState).parmStr.curveIdPtr = [oldId,3]
      endelse
	end
4:	begin	; voigt
      ;freeThePointer,(*pState).currentCurvePtr
      *(*pState).currentCurvePtr = 0
	  (*pState).parmStr.nvoigt = (*pState).parmStr.nvoigt + 1
	  if n_elements(*(*pState).parmStr.voigtParmPtr) gt 0 then begin
	    oldParms = *(*pState).parmStr.voigtParmPtr
	    newParms = dblarr(n_elements(oldParms)+3)
	    newParms = [oldParms,curParms]
	    *(*pState).parmStr.voigtParmPtr = (newParms)
	  endif else begin
	    *(*pState).parmStr.voigtParmPtr = (curParms)
	  endelse
	  if n_elements(*(*pState).parmStr.voigtParmFixPtr) gt 0 then begin
	    oldFixArray = *(*pState).parmStr.voigtParmFixPtr
	    newFixArray = intarr(n_elements(oldFixArray)+3)
	    newFixArray = [oldFixArray,0,0,0];,0]
	    *(*pState).parmStr.voigtParmFixPtr = (newFixArray)
	  endif else begin
	    *(*pState).parmStr.voigtParmFixPtr = [0,0,0]
	  endelse

	  if n_elements(*(*pState).parmStr.voigtStepPtr) gt 0 then begin
	    oldStep = *(*pState).parmStr.voigtStepPtr
	    newStep = dblarr(n_elements(oldStep)+3)
	    newStep = [oldStep,0.0,0.0,0.0]
	    *(*pState).parmStr.voigtStepPtr = newStep
	  endif else begin
	    *(*pState).parmStr.voigtStepPtr = [0.0,0.0,0.0]
	  endelse

      if n_elements(*(*pState).parmStr.voigtConstraintPtr) gt 0 then begin
	    oldLoLimCheckArray = *(*(*pState).parmStr.voigtConstraintPtr).checkLoLimPtr
	    newLoLimCheckArray = intarr(n_elements(oldLoLimCheckArray)+3)
	    newLoLimCheckArray = [oldLoLimCheckArray,0,0,1]
	    *(*(*pState).parmStr.voigtConstraintPtr).checkLoLimPtr = (newLoLimCheckArray)
	    oldHiLimCheckArray = *(*(*pState).parmStr.voigtConstraintPtr).checkHiLimPtr
	    newHiLimCheckArray = intarr(n_elements(oldHiLimCheckArray)+3)
	    newHiLimCheckArray = [oldHiLimCheckArray,0,0,0]
	    *(*(*pState).parmStr.voigtConstraintPtr).checkHiLimPtr = (newHiLimCheckArray)
 	    oldLoLimArray = *(*(*pState).parmStr.voigtConstraintPtr).LoLimPtr
	    newLoLimArray = fltarr(n_elements(oldLoLimArray)+3)
	    newLoLimArray = [oldLoLimArray,0.0,0.0,loWidLimit]
	    *(*(*pState).parmStr.voigtConstraintPtr).LoLimPtr = (newLoLimArray)
 	    oldHiLimArray = *(*(*pState).parmStr.voigtConstraintPtr).HiLimPtr
	    newHiLimArray = fltarr(n_elements(oldHiLimArray)+3)
	    newHiLimArray = [oldHiLimArray,1.0,1.0,1.0]
	    *(*(*pState).parmStr.voigtConstraintPtr).HiLimPtr = (newHiLimArray)
      endif else begin
 	    *(*pState).parmStr.voigtConstraintPtr = {checkLoLimPtr:ptr_new([0,0,1]),$
 	                                           checkHiLimPtr:ptr_new([0,0,0]),$
 			                                   LoLimPtr:ptr_new([0.,0.,loWidLimit]),$
 			                                   HiLimPtr:ptr_new([1.,1.,1.])}
      endelse

      ;(*pState).currentParmPtr = ptr_new()
      if n_elements(*(*pState).parmStr.curveIdPtr) eq 0 then begin
        *(*pState).parmStr.curveIdPtr = 4
      endif else begin
        oldId = *(*pState).parmStr.curveIdPtr
        *(*pState).parmStr.curveIdPtr = [oldId,4]
      endelse
	end
5:	begin	; smooth step
	  (*pState).parmStr.nss = (*pState).parmStr.nss + 1
	  ;freeThePointer,(*pState).currentCurvePtr
	  *(*pState).currentCurvePtr = 0
	  if n_elements(*(*pState).parmStr.ssParmPtr) gt 0 then begin
	    oldParms = *(*pState).parmStr.ssParmPtr
	    newParms = dblarr(n_elements(oldParms)+3)
	    newParms = [oldParms,curParms]
	    *(*pState).parmStr.ssParmPtr = (newParms)
	  endif else begin
	    *(*pState).parmStr.ssParmPtr = (curParms)
	  endelse
	  if n_elements(*(*pState).parmStr.ssParmFixPtr) gt 0 then begin
	    oldFixArray = *(*pState).parmStr.ssParmFixPtr
	    newFixArray = intarr(n_elements(oldFixArray)+3)
	    newFixArray = [oldFixArray,0,0,0]
	    *(*pState).parmStr.ssParmFixPtr = (newFixArray)
	  endif else begin
	    *(*pState).parmStr.ssParmFixPtr = [0,0,0]
	  endelse

	  if n_elements(*(*pState).parmStr.ssStepPtr) gt 0 then begin
	    oldStep = *(*pState).parmStr.ssStepPtr
	    newStep = dblarr(n_elements(oldStep)+3)
	    newStep = [oldStep,0.0,0.0,0.0]
	    *(*pState).parmStr.ssStepPtr = (newStep)
	  endif else begin
	    *(*pState).parmStr.ssStepPtr = [0.0,0.0,0.0]
	  endelse

      if n_elements(*(*pState).parmStr.ssConstraintPtr) gt 0 then begin
	    oldLoLimCheckArray = *(*(*pState).parmStr.ssConstraintPtr).checkLoLimPtr
	    newLoLimCheckArray = intarr(n_elements(oldLoLimCheckArray)+3)
	    newLoLimCheckArray = [oldLoLimCheckArray,0,0,0]
	   *(*(*pState).parmStr.ssConstraintPtr).checkLoLimPtr = (newLoLimCheckArray)
	    oldHiLimCheckArray = *(*(*pState).parmStr.ssConstraintPtr).checkHiLimPtr
	    newHiLimCheckArray = intarr(n_elements(oldHiLimCheckArray)+3)
	    newHiLimCheckArray = [oldHiLimCheckArray,0,0,0]
	    *(*(*pState).parmStr.ssConstraintPtr).checkHiLimPtr = (newHiLimCheckArray)
 	    oldLoLimArray = *(*(*pState).parmStr.ssConstraintPtr).LoLimPtr
	    newLoLimArray = fltarr(n_elements(oldLoLimArray)+3)
	    newLoLimArray = [oldLoLimArray,0.0,0.0,0.0]
	    *(*(*pState).parmStr.ssConstraintPtr).LoLimPtr = (newLoLimArray)
 	    oldHiLimArray = *(*(*pState).parmStr.ssConstraintPtr).HiLimPtr
	    newHiLimArray = fltarr(n_elements(oldHiLimArray)+3)
	    newHiLimArray = [oldHiLimArray,1.0,1.0,1.0]
	    *(*(*pState).parmStr.ssConstraintPtr).HiLimPtr = (newHiLimArray)
      endif else begin
 	    *(*pState).parmStr.ssConstraintPtr = {checkLoLimPtr:ptr_new([0,0,0]),$
 	                                           checkHiLimPtr:ptr_new([0,0,0]),$
 			                                   LoLimPtr:ptr_new([0.,0.,0.]),$
 			                                   HiLimPtr:ptr_new([1.,1.,1.])}
      endelse
      ;(*pState).currentParmPtr = ptr_new()
      if n_elements(*(*pState).parmStr.curveIdPtr) eq 0 then begin
        *(*pState).parmStr.curveIdPtr = 5
      endif else begin
        oldId = *(*pState).parmStr.curveIdPtr
        *(*pState).parmStr.curveIdPtr = [oldId,5]
      endelse
	end
6:	begin	; DHO
	  (*pState).parmStr.nDHO = (*pState).parmStr.nDHO + 1
	  ;freeThePointer,(*pState).currentCurvePtr
	  *(*pState).currentCurvePtr = 0
	  if n_elements(*(*pState).parmStr.DHOParmPtr) gt 0 then begin
	    oldParms = *(*pState).parmStr.DHOParmPtr
	    newParms = dblarr(n_elements(oldParms)+4)
	    newParms = [oldParms,curParms]
	    *(*pState).parmStr.DHOParmPtr = (newParms)
	  endif else begin
	    *(*pState).parmStr.DHOParmPtr = (curParms)
	  endelse
	  if n_elements(*(*pState).parmStr.DHOParmFixPtr) gt 0 then begin
	    oldFixArray = *(*pState).parmStr.DHOParmFixPtr
	    newFixArray = intarr(n_elements(oldFixArray)+4)
	    newFixArray = [oldFixArray,0,0,0,1]
	    *(*pState).parmStr.DHOParmFixPtr = (newFixArray)
	  endif else begin
	    *(*pState).parmStr.DHOParmFixPtr = [0,0,0,1]
	  endelse

	  if n_elements(*(*pState).parmStr.DHOStepPtr) gt 0 then begin
	    oldStep = *(*pState).parmStr.DHOStepPtr
	    newStep = dblarr(n_elements(oldStep)+4)
	    newStep = [oldStep,0.0,0.0,0.0,0.0]
	    *(*pState).parmStr.DHOStepPtr = (newStep)
	  endif else begin
	    *(*pState).parmStr.DHOStepPtr = [0.0,0.0,0.0,0.0]
	  endelse

      if n_elements(*(*pState).parmStr.DHOConstraintPtr) gt 0 then begin
	    oldLoLimCheckArray = *(*(*pState).parmStr.DHOConstraintPtr).checkLoLimPtr
	    newLoLimCheckArray = intarr(n_elements(oldLoLimCheckArray)+4)
	    newLoLimCheckArray = [oldLoLimCheckArray,0,0,1,0]
	    *(*(*pState).parmStr.DHOConstraintPtr).checkLoLimPtr = (newLoLimCheckArray)
	    oldHiLimCheckArray = *(*(*pState).parmStr.DHOConstraintPtr).checkHiLimPtr
	    newHiLimCheckArray = intarr(n_elements(oldHiLimCheckArray)+4)
	    newHiLimCheckArray = [oldHiLimCheckArray,0,0,0,0]
	    *(*(*pState).parmStr.DHOConstraintPtr).checkHiLimPtr = (newHiLimCheckArray)
 	    oldLoLimArray = *(*(*pState).parmStr.DHOConstraintPtr).LoLimPtr
	    newLoLimArray = fltarr(n_elements(oldLoLimArray)+4)
	    newLoLimArray = [oldLoLimArray,0.0,0.0,loWidLimit,0.0]
	    *(*(*pState).parmStr.DHOConstraintPtr).LoLimPtr = (newLoLimArray)
 	    oldHiLimArray = *(*(*pState).parmStr.DHOConstraintPtr).HiLimPtr
	    newHiLimArray = fltarr(n_elements(oldHiLimArray)+4)
	    newHiLimArray = [oldHiLimArray,1.0,1.0,1.0,1.0]
	    *(*(*pState).parmStr.DHOConstraintPtr).HiLimPtr = (newHiLimArray)
      endif else begin
 	    *(*pState).parmStr.DHOConstraintPtr = {checkLoLimPtr:ptr_new([0,0,1,0]),$
 	                                           checkHiLimPtr:ptr_new([0,0,0,0]),$
 			                                   LoLimPtr:ptr_new([0.,0.,loWidLimit,0.]),$
 			                                   HiLimPtr:ptr_new([1.,1.,1.,1.])}
      endelse
      ;(*pState).currentParmPtr = ptr_new()
      if n_elements(*(*pState).parmStr.curveIdPtr) eq 0 then begin
        *(*pState).parmStr.curveIdPtr = 6
      endif else begin
        oldId = *(*pState).parmStr.curveIdPtr
        *(*pState).parmStr.curveIdPtr = [oldId,6]
      endelse
	end
999:begin	; Dirac delta function
	  (*pState).parmStr.nDelta = (*pState).parmStr.nDelta + 1
	  ;freeThePointer,(*pState).currentCurvePtr
	  *(*pState).currentCurvePtr = 0
	  if n_elements(*(*pState).parmStr.deltaParmPtr) gt 0 then begin
	    oldParms = *(*pState).parmStr.deltaParmPtr
	    newParms = dblarr(n_elements(oldParms)+3)
	    newParms = [oldParms,curParms]
	    *(*pState).parmStr.deltaParmPtr = newParms
	  endif else begin
	    *(*pState).parmStr.deltaParmPtr = curParms
	  endelse
	  if n_elements(*(*pState).parmStr.deltaParmFixPtr) gt 0 then begin
	    oldFixArray = *(*pState).parmStr.deltaParmFixPtr
	    newFixArray = intarr(n_elements(oldFixArray)+3)
	    newFixArray = [oldFixArray,0,0,0]
	    *(*pState).parmStr.deltaParmFixPtr = newFixArray
	  endif else begin
	    *(*pState).parmStr.deltaParmFixPtr = [0,0,0]
	  endelse

	  if n_elements(*(*pState).parmStr.deltaStepPtr) gt 0 then begin
	    oldStep = *(*pState).parmStr.deltaStepPtr
	    newStep = dblarr(n_elements(oldStep)+3)
	    newStep = [oldStep,0.0,0.0,0.0]
	    *(*pState).parmStr.deltaStepPtr = newStep
	  endif else begin
	    *(*pState).parmStr.deltaStepPtr = [0.0,0.0,0.0]
	  endelse


      if n_elements(*(*pState).parmStr.deltaConstraintPtr) gt 0 then begin
	    oldLoLimCheckArray = *(*(*pState).parmStr.deltaConstraintPtr).checkLoLimPtr
	    newLoLimCheckArray = intarr(n_elements(oldLoLimCheckArray)+3)
	    newLoLimCheckArray = [oldLoLimCheckArray,0,0,1]
	    *(*(*pState).parmStr.deltaConstraintPtr).checkLoLimPtr = newLoLimCheckArray
	    oldHiLimCheckArray = *(*(*pState).parmStr.deltaConstraintPtr).checkHiLimPtr
	    newHiLimCheckArray = intarr(n_elements(oldHiLimCheckArray)+3)
	    newHiLimCheckArray = [oldHiLimCheckArray,0,0,0]
	    *(*(*pState).parmStr.deltaConstraintPtr).checkHiLimPtr = newHiLimCheckArray
 	    oldLoLimArray = *(*(*pState).parmStr.deltaConstraintPtr).LoLimPtr
	    newLoLimArray = fltarr(n_elements(oldLoLimArray)+3)
	    newLoLimArray = [oldLoLimArray,0.0,0.0,loWidLimit]
	    *(*(*pState).parmStr.deltaConstraintPtr).LoLimPtr = (newLoLimArray)
 	    oldHiLimArray = *(*(*pState).parmStr.deltaConstraintPtr).HiLimPtr
	    newHiLimArray = fltarr(n_elements(oldHiLimArray)+3)
	    newHiLimArray = [oldHiLimArray,1.0,1.0,1.0]
	    *(*(*pState).parmStr.deltaConstraintPtr).HiLimPtr = (newHiLimArray)
      endif else begin
 	    *(*pState).parmStr.deltaConstraintPtr = {checkLoLimPtr:ptr_new([0,0,1]),$
 	                                           checkHiLimPtr:ptr_new([0,0,0]),$
 			                                   LoLimPtr:ptr_new([0.,0.,loWidLimit]),$
 			                                   HiLimPtr:ptr_new([1.,1.,1.])}
      endelse
     ; (*pState).currentParmPtr = ptr_new()
      if n_elements(*(*pState).parmStr.curveIdPtr) eq 0 then begin
        *(*pState).parmStr.curveIdPtr = (999)
      endif else begin
        oldId = *(*pState).parmStr.curveIdPtr
        *(*pState).parmStr.curveIdPtr = [oldId,999]
      endelse
	end
8:	begin	; methyl tunneling EISF
	  (*pState).parmStr.ntunnelEISF = 1
	  *(*pState).parmStr.tunnelEISFParmPtr = curParms
	  *(*pState).parmStr.tunnelEISFParmFixPtr = [0]
	  ;freeThePointer,(*pState).currentParmPtr
	 ; freeThePointer,(*pState).currentCurvePtr
	 *(*pState).currentCurvePtr = 0
 	  (*pState).parmStr.tunnelEISFConstraintPtr = ptr_new({	checkLoLimPtr:ptr_new([0]),$
 	                                           				checkHiLimPtr:ptr_new([0]),$
 			                                   				LoLimPtr:ptr_new([0.]),$
 			                                   				HiLimPtr:ptr_new([1.])})

	  if n_elements(*(*pState).parmStr.tunnelEISFStepPtr) eq 0 then begin
	    oldStep = *(*pState).parmStr.tunnelEISFStepPtr
	    newStep = dblarr(1)
	    newStep = [0.0]
	    *(*pState).parmStr.tunnelEISFStepPtr = newStep
	  endif else begin
	    *(*pState).parmStr.tunnelEISFStepPtr = [0.0]
	  endelse
      if n_elements(*(*pState).parmStr.curveIdPtr) eq 0 then begin
        *(*pState).parmStr.curveIdPtr = 8
      endif else begin
        oldId = *(*pState).parmStr.curveIdPtr
        *(*pState).parmStr.curveIdPtr = [oldId,8]
      endelse
	end
9:	begin	; three site jump EISF
	  (*pState).parmStr.nthreeSiteEISF = 1
	  *(*pState).parmStr.threeSiteEISFParmPtr = curParms
	  *(*pState).parmStr.threeSiteEISFParmFixPtr = [0]
	  *(*pState).currentCurvePtr = 0
 	  (*pState).parmStr.threeSiteEISFConstraintPtr = ptr_new({	checkLoLimPtr:ptr_new([0]),$
 	                                           				checkHiLimPtr:ptr_new([0]),$
 			                                   				LoLimPtr:ptr_new([0.]),$
 			                                   				HiLimPtr:ptr_new([1.])})

	  if n_elements(*(*pState).parmStr.threeSiteEISFStepPtr) eq 0 then begin
	    oldStep = *(*pState).parmStr.threeSiteEISFStepPtr
	    newStep = dblarr(1)
	    newStep = [0.0]
	    *(*pState).parmStr.threeSiteEISFStepPtr = newStep
	  endif else begin
	    *(*pState).parmStr.threeSiteEISFStepPtr = [0.0]
	  endelse
      if n_elements(*(*pState).parmStr.curveIdPtr) eq 0 then begin
        *(*pState).parmStr.curveIdPtr = 9
      endif else begin
        oldId = *(*pState).parmStr.curveIdPtr
        *(*pState).parmStr.curveIdPtr = [oldId,9]
      endelse
	end
10:	begin	; two site jump EISF
	  (*pState).parmStr.ntwoSiteEISF = 1
	  *(*pState).parmStr.twoSiteEISFParmPtr = curParms
	  *(*pState).parmStr.twoSiteEISFParmFixPtr = [0]
	  *(*pState).currentCurvePtr = 0
 	  (*pState).parmStr.twoSiteEISFConstraintPtr = ptr_new({	checkLoLimPtr:ptr_new([0]),$
 	                                           				checkHiLimPtr:ptr_new([0]),$
 			                                   				LoLimPtr:ptr_new([0.]),$
 			                                   				HiLimPtr:ptr_new([1.])})

	  if n_elements(*(*pState).parmStr.twoSiteEISFStepPtr) gt 0 then begin
	    oldStep = *(*pState).parmStr.twoSiteEISFStepPtr
	    newStep = dblarr(1)
	    newStep = [0.0]
	    *(*pState).parmStr.twoSiteEISFStepPtr = (newStep)
	  endif else begin
	    *(*pState).parmStr.twoSiteEISFStepPtr = [0.0]
	  endelse
      if n_elements(*(*pState).parmStr.curveIdPtr) eq 0 then begin
        *(*pState).parmStr.curveIdPtr = 10
      endif else begin
        oldId = *(*pState).parmStr.curveIdPtr
        *(*pState).parmStr.curveIdPtr = [oldId,10]
      endelse
	end
7:	begin	; Kohlrausch
      ;freeThePointer,(*pState).currentCurvePtr
      *(*pState).currentCurvePtr = 0
	  (*pState).parmStr.nkohl = (*pState).parmStr.nkohl + 1
	  if n_elements(*(*pState).parmStr.kohlParmPtr) gt 0 then begin
	    oldParms = *(*pState).parmStr.kohlParmPtr
	    newParms = dblarr(n_elements(oldParms)+3)
	    newParms = [oldParms,curParms]
	    *(*pState).parmStr.kohlParmPtr = (newParms)
	  endif else begin
	    *(*pState).parmStr.kohlParmPtr = (curParms)
	  endelse
	  if n_elements(*(*pState).parmStr.kohlParmFixPtr) gt 0 then begin
	    oldFixArray = *(*pState).parmStr.kohlParmFixPtr
	    newFixArray = intarr(n_elements(oldFixArray)+3)
	    newFixArray = [oldFixArray,0,0,0]
	    *(*pState).parmStr.kohlParmFixPtr = (newFixArray)
	  endif else begin
	    *(*pState).parmStr.kohlParmFixPtr = [0,0,0]
	  endelse

      betastep = 0.01*((*(*pState).btabPtr)[1]-(*(*pState).btabPtr)[0])
      taustep = 0.05*((*(*pState).ttabPtr)[1]-(*(*pState).ttabPtr)[0])

	  if n_elements(*(*pState).parmStr.kohlStepPtr) gt 0 then begin
	    oldStep = *(*pState).parmStr.kohlStepPtr
	    newStep = dblarr(n_elements(oldStep)+3)
	    newStep = [oldStep,0.0,betastep,taustep]
	    *(*pState).parmStr.kohlStepPtr = (newStep)
	  endif else begin
	    *(*pState).parmStr.kohlStepPtr = [0.0,betastep,taustep]
	  endelse

      if n_elements(*(*pState).parmStr.kohlConstraintPtr) gt 0 then begin
	    oldLoLimCheckArray = *(*(*pState).parmStr.kohlConstraintPtr).checkLoLimPtr
	    newLoLimCheckArray = intarr(n_elements(oldLoLimCheckArray)+3)
	    newLoLimCheckArray = [oldLoLimCheckArray,0,1,1]
	    *(*(*pState).parmStr.kohlConstraintPtr).checkLoLimPtr = (newLoLimCheckArray)
	    oldHiLimCheckArray = *(*(*pState).parmStr.kohlConstraintPtr).checkHiLimPtr
	    newHiLimCheckArray = intarr(n_elements(oldHiLimCheckArray)+3)
	    newHiLimCheckArray = [oldHiLimCheckArray,0,1,1]
	    *(*(*pState).parmStr.kohlConstraintPtr).checkHiLimPtr = (newHiLimCheckArray)
 	    oldLoLimArray = *(*(*pState).parmStr.kohlConstraintPtr).LoLimPtr
	    newLoLimArray = fltarr(n_elements(oldLoLimArray)+3)
	    newLoLimArray = [oldLoLimArray,0.0,min(*(*pState).btabPtr),min(*(*pState).ttabPtr)]
	    *(*(*pState).parmStr.kohlConstraintPtr).LoLimPtr = (newLoLimArray)
 	    oldHiLimArray = *(*(*pState).parmStr.kohlConstraintPtr).HiLimPtr
	    newHiLimArray = fltarr(n_elements(oldHiLimArray)+3)
	    newHiLimArray = [oldHiLimArray,1.0,max(*(*pState).btabPtr),max(*(*pState).ttabPtr)]
	    *(*(*pState).parmStr.kohlConstraintPtr).HiLimPtr = (newHiLimArray)
      endif else begin
 	    (*pState).parmStr.kohlConstraintPtr = ptr_new({checkLoLimPtr:ptr_new([0,1,1]),$
 	                                           checkHiLimPtr:ptr_new([0,1,1]),$
 			                                   LoLimPtr:ptr_new([0.,min(*(*pState).btabPtr),min(*(*pState).ttabPtr)]),$
 			                                   HiLimPtr:ptr_new([1.,max(*(*pState).btabPtr),max(*(*pState).ttabPtr)])})
      endelse
      ;print,*(*(*pState).parmStr.gaussConstraintPtr).checkLoLimPtr
      ;(*pState).currentParmPtr = ptr_new()
      if n_elements(*(*pState).parmStr.curveIdPtr) eq 0 then begin
        *(*pState).parmStr.curveIdPtr = 7
      endif else begin
        oldId = *(*pState).parmStr.curveIdPtr
        *(*pState).parmStr.curveIdPtr = [oldId,7]
      endelse
	end
else:
endcase

; commented out the next 10 lines out 11/15/01
if (*pState).ngroups gt 1 then begin
  widget_control,(*pState).selGroup,get_value = groupNum
  groupNum = fix(groupNum[0])-1
  widget_control,(*pState).textFit,get_uvalue = bigParmPtr,/no_copy
  parmStr = (*pState).parmStr
  ;dave_beast_ops,"duplicate",parmStr,outStr
  ;dave_beast_ops,"remove",parmStr
  *bigParmPtr[groupNum] = (*pState).parmStr;outStr;(*pState).parmStr
  widget_control,(*pState).textFit,set_uvalue = bigParmPtr,/no_copy
endif

if n_elements(*(*pState).parmStr.curveIdPtr) gt 0 then begin
  widget_control,(*pState).pickCurve,set_slider_min = 1
  if n_elements(*(*pState).parmStr.curveIdPtr) eq 1 then $
               widget_control,(*pState).pickCurve,set_slider_min = 0
  widget_control,(*pState).pickCurve,set_slider_max = n_elements(*(*pState).parmStr.curveIdPtr)
endif

return
end
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
function RMDPARemoveElementFromVector,inVector,index
; This routine only works if there are at least two elements
; in the input vector, inVector.
nparms = n_elements(inVector)
newnparms = nparms-1
varType = size(inVector,/type)
case varType of
2:	begin	; integer
	  outVector = intarr(newnparms)
	end
3:	begin	; longword integer
	  outVector = lonarr(newnparms)
	end
4:	begin	; floating point
	  outVector = fltarr(newnparms)
	end
5:	begin	; double precision
	  outVector = dblarr(newnparms)
	end
7:	begin	; string array
	  outVector = strarr(newnparms)
	end
else:
endcase

case index of
0:	begin
    outVector[0:newnparms-1] = inVector[1:nparms-1]
	end
nparms-1:	begin
			outVector[0:newnparms-1] = inVector[0:nparms-2]
			end
else:	begin
		outVector[0:index-1] = inVector[0:index-1]
		outVector[index:newnparms-1] = inVector[index+1:nparms-1]
		end
endcase
return,outVector
end
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
pro RMDPARemoveCurve,event
widget_control,event.top,get_uvalue = pState

ncurves = calcNumberOfCurves((*pState).parmStr)
if ncurves ge 1 then begin

  widget_control,(*pState).pickCurve,get_value = curveSel

  curveSel = fix(curveSel[0])-1	; decrement by one since using as an index into a vector
  curveOrder = *(*pState).parmStr.curveIdPtr
  if curveSel ge 0 then begin
    curveType = curveOrder[curveSel]
  endif else begin
    curveType = -1
  endelse
  wherevalid = where(curveOrder eq curveType,count)

  parmStr = (*pState).parmStr

  if ncurves gt 1 then begin
  	 curveOrderOut = RMDPARemoveElementFromVector(curveOrder,curveSel)

    *(*pState).parmStr.curveIdPtr = curveOrderOut

  case curveType of
  0:	begin	; gaussian
        ngauss = (*pState).parmStr.ngauss
	    if ngauss eq 1 then begin
	      ptr_free,(*pState).parmStr.gaussParmPtr
	      ptr_free,(*pState).parmStr.gaussParmErrPtr
	      (*pState).parmStr.gaussParmPtr = ptr_new(/allocate_heap)
	      (*pState).parmStr.gaussParmErrPtr = ptr_new(/allocate_heap)
	      (*pState).parmStr.ngauss = 0
	    endif else begin
	    	index = where(wherevalid eq curveSel)
 			oldParms = *(*pState).parmStr.gaussParmPtr
 			for j = 0,2 do begin
 			  oldParms = RMDPARemoveElementFromVector(oldParms,3*index[0])
 			endfor
	    	*(*pState).parmStr.gaussParmPtr = oldParms
        	(*pState).parmStr.ngauss = (*pState).parmStr.ngauss - 1
	  	endelse
	    end
  1:	begin	; lorentzian
        nlorentz = (*pState).parmStr.nlorentz
	    if nlorentz eq 1 then begin
	      ptr_free,(*pState).parmStr.lorentzParmPtr
	      ptr_free,(*pState).parmStr.lorentzParmErrPtr
	      (*pState).parmStr.lorentzParmPtr = ptr_new(/allocate_heap)
	      (*pState).parmStr.lorentzParmErrPtr = ptr_new(/allocate_heap)
	      (*pState).parmStr.nlorentz = 0
	    endif else begin
	    	index = where(wherevalid eq curveSel)
 			oldParms = *(*pState).parmStr.lorentzParmPtr
 			for j = 0,2 do begin
 			  oldParms = RMDPARemoveElementFromVector(oldParms,3*index[0])
 			endfor
	    	*(*pState).parmStr.lorentzParmPtr = (oldParms)
        	(*pState).parmStr.nlorentz = (*pState).parmStr.nlorentz - 1
	  	endelse
	    end
  2:	begin	; sloping background
          nbg = (*pState).parmStr.nbg
	      ptr_free,(*pState).parmStr.bgParmPtr
	      ptr_free,(*pState).parmStr.bgParmErrPtr
	      (*pState).parmStr.bgParmPtr = ptr_new(/allocate_heap)
	      (*pState).parmStr.bgParmErrPtr = ptr_new(/allocate_heap)
	      (*pState).parmStr.nbg = 0
	    end
  3:	begin	; lognormal
        nlognormal = (*pState).parmStr.nlognormal
	    if nlognormal eq 1 then begin
	      ptr_free,(*pState).parmStr.logNormParmPtr
	      ptr_free,(*pState).parmStr.logNormParmErrPtr
	      (*pState).parmStr.logNormParmPtr = ptr_new(/allocate_heap)
	      (*pState).parmStr.logNormParmErrPtr =  ptr_new(/allocate_heap)
	      (*pState).parmStr.nlognormal = 0
	    endif else begin
	    	index = where(wherevalid eq curveSel)
 			oldParms = *(*pState).parmStr.logNormParmPtr
 			for j = 0,2 do begin
 			  oldParms = RMDPARemoveElementFromVector(oldParms,3*index[0])
 			endfor
	    	*(*pState).parmStr.logNormParmPtr = (oldParms)
        	(*pState).parmStr.nlognormal = (*pState).parmStr.nlognormal - 1
	  	endelse
	    end
  4:	begin	; voigt
        nvoigt = (*pState).parmStr.nvoigt
	    if nvoigt eq 1 then begin
	      ptr_free,(*pState).parmStr.voigtParmPtr
	      ptr_free,(*pState).parmStr.voigtParmErrPtr
	      (*pState).parmStr.voigtParmPtr = ptr_new(/allocate_heap)
	      (*pState).parmStr.voigtParmErrPtr = ptr_new(/allocate_heap)
	      (*pState).parmStr.nvoigt = 0
	    endif else begin
	    	index = where(wherevalid eq curveSel)
 			oldParms = *(*pState).parmStr.voigtParmPtr
 			for j = 0,2 do begin
 			  oldParms = RMDPARemoveElementFromVector(oldParms,3*index[0])
 			endfor
	    	*(*pState).parmStr.voigtParmPtr = (oldParms)
        	(*pState).parmStr.nvoigt = (*pState).parmStr.nvoigt - 1
	  	endelse
	    end
  5:	begin	; smooth step
        ngauss = (*pState).parmStr.nss
	    if ngauss eq 1 then begin
	      ptr_free,(*pState).parmStr.ssParmPtr
	      ptr_free,(*pState).parmStr.ssParmErrPtr
	      (*pState).parmStr.ssParmPtr = ptr_new(/allocate_heap)
	      (*pState).parmStr.ssParmErrPtr = ptr_new(/allocate_heap)
	      (*pState).parmStr.nss = 0
	    endif else begin
	    	index = where(wherevalid eq curveSel)
 			oldParms = *(*pState).parmStr.ssParmPtr
 			for j = 0,2 do begin
 			  oldParms = RMDPARemoveElementFromVector(oldParms,3*index[0])
 			endfor
	    	*(*pState).parmStr.ssParmPtr = (oldParms)
        	(*pState).parmStr.nss = (*pState).parmStr.nss - 1
	  	endelse
	    end
  6:	begin	; DHO
        ngauss = (*pState).parmStr.nDHO
	    if ngauss eq 1 then begin
	      ptr_free,(*pState).parmStr.DHOParmPtr
	      ptr_free,(*pState).parmStr.DHOParmErrPtr
	      (*pState).parmStr.DHOParmPtr = ptr_new(/allocate_heap)
	      (*pState).parmStr.DHOParmErrPtr = ptr_new(/allocate_heap)
	      (*pState).parmStr.nDHO = 0
	    endif else begin
	    	index = where(wherevalid eq curveSel)
 			oldParms = *(*pState).parmStr.DHOParmPtr
 			for j = 0,3 do begin
 			  oldParms = RMDPARemoveElementFromVector(oldParms,4*index[0])
 			endfor
	    	*(*pState).parmStr.DHOParmPtr = (oldParms)
        	(*pState).parmStr.nDHO = (*pState).parmStr.nDHO - 1
	  	endelse
	    end
  999:	begin	; Dirac delta
        ngauss = (*pState).parmStr.nDelta
	    if ngauss eq 1 then begin
	      ptr_free,(*pState).parmStr.deltaParmPtr
	      ptr_free,(*pState).parmStr.deltaParmErrPtr
	      (*pState).parmStr.deltaParmPtr = ptr_new(/allocate_heap)
	      (*pState).parmStr.deltaParmErrPtr = ptr_new(/allocate_heap)
	      (*pState).parmStr.nDelta = 0
	    endif else begin
	    	index = where(wherevalid eq curveSel)
 			oldParms = *(*pState).parmStr.deltaParmPtr
 			for j = 0,2 do begin
 			  oldParms = RMDPARemoveElementFromVector(oldParms,3*index[0])
 			endfor
	    	*(*pState).parmStr.deltaParmPtr = (oldParms)
        	(*pState).parmStr.nDelta = (*pState).parmStr.nDelta - 1
	  	endelse
	    end
  8:	begin	; methyl tunnel EISF
          nbg = (*pState).parmStr.ntunnelEISF
	      ptr_free,(*pState).parmStr.tunnelEISFParmPtr
	      ptr_free,(*pState).parmStr.tunnelEISFParmErrPtr
	      (*pState).parmStr.tunnelEISFParmPtr = ptr_new(/allocate_heap)
	      (*pState).parmStr.tunnelEISFParmErrPtr = ptr_new(/allocate_heap)
	      (*pState).parmStr.ntunnelEISF = 0
	    end
  9:	begin	; three site jump EISF
          nbg = (*pState).parmStr.nthreeSiteEISF
	      ptr_free,(*pState).parmStr.threeSiteEISFParmPtr
	      ptr_free,(*pState).parmStr.threeSiteEISFParmErrPtr
	      (*pState).parmStr.threeSiteEISFParmPtr = ptr_new(/allocate_heap)
	      (*pState).parmStr.threeSiteEISFParmErrPtr = ptr_new(/allocate_heap)
	      (*pState).parmStr.nthreeSiteEISF = 0
	    end
  10:	begin	; two site jump EISF
          nbg = (*pState).parmStr.ntwoSiteEISF
	      ptr_free,(*pState).parmStr.twoSiteEISFParmPtr
	      ptr_free,(*pState).parmStr.twoSiteEISFParmErrPtr
	      (*pState).parmStr.twoSiteEISFParmPtr = ptr_new(/allocate_heap)
	      (*pState).parmStr.twoSiteEISFParmErrPtr = ptr_new(/allocate_heap)
	      (*pState).parmStr.ntwoSiteEISF = 0
	    end
  7:	begin	; Kohlrausch
        nkohl = (*pState).parmStr.nkohl
	    if nkohl eq 1 then begin
	      ptr_free,(*pState).parmStr.kohlParmPtr
	      ptr_free,(*pState).parmStr.kohlParmErrPtr
	      (*pState).parmStr.kohlParmPtr = ptr_new(/allocate_heap)
	      (*pState).parmStr.kohlParmErrPtr = ptr_new(/allocate_heap)
	      (*pState).parmStr.nkohl = 0
	    endif else begin
	    	index = where(wherevalid eq curveSel)
 			oldParms = *(*pState).parmStr.kohlParmPtr
 			for j = 0,2 do begin
 			  oldParms = RMDPARemoveElementFromVector(oldParms,3*index[0])
 			endfor
	    	*(*pState).parmStr.kohlParmPtr = oldParms
        	(*pState).parmStr.nkohl = (*pState).parmStr.nkohl - 1
	  	endelse
	    end
  else:
  endcase

  freeThePointer,(*pState).currentParmPtr
  freeThePointer,(*pState).currentCurvePtr
  (*pState).currentParmPtr = ptr_new(/allocate_heap)
  (*pState).currentCurvePtr = ptr_new(/allocate_heap)


  RMDCalcDisplay,event
  widget_control,event.top,get_uvalue = pState


  RMDPlotDisplay,event
  widget_control,event.top,get_uvalue = pState

; These 4 lines added 11/16/01
; They update the bigParmPtr to contain the updated curves
widget_control,(*pState).selGroup,get_value = groupNum
groupNum = fix(groupNum[0]) - 1
widget_control,(*pState).textFit,get_uvalue = bigParmPtr,/no_copy
*bigParmPtr[groupNum] = (*pState).parmStr
widget_control,(*pState).textFit,set_uvalue = bigParmPtr,/no_copy

  if n_elements(*(*pState).parmStr.curveIdPtr) gt 0 then begin
    widget_control,(*pState).pickCurve,set_slider_min = 1
    if n_elements(*(*pState).parmStr.curveIdPtr) eq 1 then $
                 widget_control,(*pState).pickCurve,set_slider_min = 0
    widget_control,(*pState).pickCurve,set_slider_max = n_elements(*(*pState).parmStr.curveIdPtr)
  endif
  endif else begin

    RMDPAClearCurves,event
    widget_control,event.top,get_uvalue = pState
  endelse
endif


return
end
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
pro PeakAnalysisAddCurve,event
widget_control,event.top,get_uvalue = pState
xyact = (*pState).xyact
data = *(*pState).dataPtr & datsize = size(data)
npts = datsize[2]
x = dblarr(npts)
x = data[0,*]

case (*pState).curveType of
0:	begin
     xlo = min(x) & xhi = max(x)
     deltaX = xhi-xlo
     wid = 0.02*deltaX
     sig = wid/2.35
	 amp = sqrt(2.0*!pi*sig^2)*xyact[1]
	 ygauss = dblarr(npts)
	 *(*pState).currentParmPtr = [amp,xyact[0],wid]
	 ygauss = gaussianGaussFun(x,amp,xyact[0],wid)
	 *(*pState).currentCurvePtr = ygauss
	end
1:	begin
     xlo = min(x) & xhi = max(x)
     deltaX = xhi-xlo
     wid = 0.02*deltaX
     gam = 0.5*wid
	 amp = xyact[1]*gam*!pi
     *(*pState).currentParmPtr = [amp,xyact[0],wid]
	 ylorentz = dblarr(npts)
	 ylorentz = lorentzianLorentzFun(x,amp,xyact[0],wid)
	 *(*pState).currentCurvePtr = ylorentz
	end
2:	begin
     yBg = dblarr(npts)
     slope = 0.0
     yBg = bgFun(x,xyact[1],slope)
     *(*pState).currentParmPtr = [xyact[1],slope]
     *(*pState).currentCurvePtr = yBg
	end
3:	begin
     xlo = min(x) & xhi = max(x)
     deltaX = xhi-xlo
     wid = 0.02*deltaX;0.5
     sig = wid/2.35
     xm = xyact[0]
     mean = alog(abs(xm))+sig^2
     ymax = max(logNormalFun(x,1.0,xm-mean,sig))
	 amp = xyact[1]/ymax
	 ylognormal = dblarr(npts);
	 *(*pState).currentParmPtr = [amp,xm-mean,sig]
	 ylognormal = logNormalFun(x,amp,xm-mean,sig)
	 *(*pState).currentCurvePtr = ylognormal
	end
4:	begin
     xlo = min(x) & xhi = max(x)
     deltaX = xhi-xlo
     wid = 0.02*deltaX
	 yvoigt = dblarr(npts)
	 sig = wid/sqrt(8.*alog(2.))
	 amp = sqrt(2.0*!pi*sig^2)*xyact[1]
	 yvoigt = voigtian(x,amp,xyact[0],wid)
	 *(*pState).currentCurvePtr = yvoigt
	 *(*pState).currentParmPtr = [xyact[1],xyact[0],wid]
	end
5:	begin
     wid = 0.5 & sig = wid/2.35
	 amp = xyact[1]
	 cen = xyact[0]
	 yss = dblarr(npts)
	 *(*pState).currentParmPtr = [amp,cen,wid]
	 yss = smoothStepFun(x,amp,cen,wid)
	 *(*pState).currentCurvePtr = yss
	end
6:	begin
     xlo = min(x) & xhi = max(x)
     deltaX = xhi-xlo
     wid = 0.02*deltaX
	 amp = xyact[1]
	 cen = xyact[0]
	 temperature = 300.0
	 yDHO = dblarr(npts)
	 yDHO = DHOFun(x,amp,cen,wid,temperature)
	 newamp = xyact[1]*amp/max(yDHO)
	 *(*pState).currentParmPtr = [newamp,cen,wid,temperature]
	 yDHO = DHOFun(x,newamp,cen,wid,temperature)
	 *(*pState).currentCurvePtr = yDHO
	end
999:begin
	 if not ptr_valid((*pState).parmStr.resDataPtr) then begin
	   void = dialog_message(parent = event.top,['Resolution function' ,'must be present'],/information)
	   (*pState).addCurve = 0
	   (*pState).modCurve = 0
	   (*pState).mouse = 0
	   widget_control,(*pState).textFit,set_value = ''

	   sensitizeWidgets,event
	   widget_control,event.top,get_uvalue = pState

	   return
	 endif
     xlo = min(x) & xhi = max(x)
     nx = n_elements(x)
     ddx = (xhi-xlo)/(npts-1.0)
     deltaX = xhi-xlo
     xres = (*(*pState).parmStr.resDataPtr)[0,*]
     yres = (*(*pState).parmStr.resDataPtr)[1,*]
     scale = int_tabulated(xres,yres)
     yres = yres/scale	; normalize res function to unity if not already normalized!
     amp = xyact[1]/max(yres)
     wid = 0.5*ddx
     sig = wid/2.35
;	 amp = sqrt(2.0*!pi*sig^2)*xyact[1]
;     amp = 2.0*amp
	 ygauss = dblarr(npts)
	 *(*pState).currentParmPtr = [amp,xyact[0],wid]
	 ygauss = deltaFun(x,amp,xyact[0],wid)
	 *(*pState).currentCurvePtr = ygauss
	end
8:	begin
     ytunnelEISF = dblarr(npts)
     radius = 1.0
     ytunnelEISF = methylTunnelEISFFun(x,radius)
     *(*pState).currentParmPtr = [radius]
     *(*pState).currentCurvePtr = ytunnelEISF
	end
9:	begin
     ythreeSiteEISF = dblarr(npts)
     radius = 1.0
     ythreeSiteEISF = threeSiteEISFFun(x,radius)
     *(*pState).currentParmPtr = [radius]
     *(*pState).currentCurvePtr = ythreeSiteEISF
	end
10:	begin
     ytwoSiteEISF = dblarr(npts)
     radius = 1.0
     ytwoSiteEISF = twoSiteEISFFun(x,radius)
     *(*pState).currentParmPtr = [radius]
     *(*pState).currentCurvePtr = ytwoSiteEISF
	end
7:	begin
     xlo = min(x) & xhi = max(x)
     deltaX = xhi-xlo

     cen = 0.0
     wid = 0.02*deltaX
     gam = 0.5*wid
	 amp = xyact[1]*gam*!dpi

;     (*pState).currentParmPtr = ptr_new([amp,cen,wid])
;	 ylorentz = dblarr(npts)
;	 ylorentz = lorentzianLorentzFun(x,amp,cen,wid)
;	 (*pState).currentCurvePtr = ptr_new(ylorentz)
     tau = 2.0*(*pState).hbar/wid; = 2.0/wid
     ykohl = dblarr(npts)
     evalKohlrauschPro,x,[amp,1.0,tau],$
                       ykohl,xtabPtr = (*pState).xtabPtr,ytabPtr = (*pState).ytabPtr,$
                       btabPtr = (*pState).btabPtr,ttabPtr = (*pState).ttabPtr
     tau = 2.0*(*pState).hbar/wid; = 2.0/wid
     *(*pState).currentParmPtr = [amp,1.0,tau]
	 ;ylorentz = dblarr(npts)
	 ;ylorentz = lorentzianLorentzFun(x,amp,cen,wid)
	 *(*pState).currentCurvePtr = ykohl

	end
else:
endcase

return
end
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
pro PeakAnalysisModCurve,event
; Here we change only the widths of the functions that have a peak.
widget_control,event.top,get_uvalue = pState
xyact = (*pState).xyact
data = *(*pState).dataPtr & datsize = size(data)
npts = datsize[2]
x = dblarr(npts)
x = data[0,*]

case (*pState).curveType of
0:	begin
     xlo = min(x) & xhi = max(x)
     deltaX = xhi-xlo
     wid = 0.02*deltaX;0.5

     curParms = *(*pState).currentParmPtr
	 newwid = abs(-(xyact[0]-curParms[1]-wid))
     ymax = curParms[0]/sqrt(2.0*!pi*(curParms[2]/2.35)^2)
	 newamp = ymax*sqrt(2.0*!pi*(newwid/2.35)^2)
	 *(*pState).currentCurvePtr = gaussianGaussFun(x,newamp,curParms[1],newwid)
	 *(*pState).currentParmPtr = [newamp,curParms[1],newwid]
	end
1:	begin
     curParms = *(*pState).currentParmPtr
     gam = 0.5*curparms[2]
     xlo = min(x) & xhi = max(x)
     deltaX = xhi-xlo
     wid = 0.02*deltaX;0.5

	 newwid = abs(-(xyact[0]-curParms[1]-wid))
     ymax = curParms[0]/(!pi*gam)
	 newamp = ymax*newwid*0.5*!pi
	 *(*pState).currentCurvePtr = lorentzianLorentzFun(x,newamp,curParms[1],newwid)
	 *(*pState).currentParmPtr = [newamp,curParms[1],newwid]
	end
2:	begin
     curParms = *(*pState).currentParmPtr
     slope = curparms[1]
     midpoint = (max(x)+min(x))/2.0
     ymid = bgFun(midpoint,curParms[0],curParms[1])
	 newslope = ((xyact[1]-ymid)/(xyact[0]-midpoint))
	 newB = (ymid*xyact[0]-xyact[1]*midpoint)/(xyact[0]-midpoint)
	 *(*pState).currentCurvePtr = bgFun(x,newB,newslope)
	 *(*pState).currentParmPtr = [newB,newslope]
	end
3:	begin
     xlo = min(x) & xhi = max(x)
     deltaX = xhi-xlo
     wid = 0.02*deltaX;0.5

     curParms = *(*pState).currentParmPtr
	 newwid = abs(-(xyact[0]-curParms[1]-wid)) >1d-8
	 newsig = newwid/2.35
     ymax = curParms[0]/sqrt(2.0*!pi*(curParms[2])^2)
	 newamp = ymax*sqrt(2.0*!pi*(newwid/2.35)^2)
	 *(*pState).currentCurvePtr = logNormalFun(x,newamp,curParms[1],newsig)
	 *(*pState).currentParmPtr = [newamp,curParms[1],newsig]
	end
4:	begin
     xlo = min(x) & xhi = max(x)
     deltaX = xhi-xlo
     wid = 0.02*deltaX
     curParms = *(*pState).currentParmPtr
     ymax = max(*(*pState).currentCurvePtr)
     curAmp = curParms[0]
     curCen = curParms[1]
     curWid = curParms[2]
     curSigma = curWid/sqrt(8.*alog(2.))
	 newwid = abs(-(xyact[0]-curParms[1]-wid)) > 1.d-8

     newAmp = curAmp*ymax/max(voigtian(x,curAmp,curCen,newWid))

	 ;newamp = ymax*sqrt(2.0*!pi*(newwid/sqrt(8.*alog(2.)))^2)
	 yvoigt = voigtian(x,newAmp,curCen,newWid)
	 *(*pState).currentCurvePtr = yvoigt
	 *(*pState).currentParmPtr = [newAmp,curCen,newWid]
	end
5:	begin
     curParms = *(*pState).currentParmPtr
	 newwid = abs(-(xyact[0]-curParms[1]-0.5))
	 *(*pState).currentCurvePtr = smoothStepFun(x,curParms[0],curParms[1],newwid)
	 *(*pState).currentParmPtr = [curParms[0],curParms[1],newwid]
	end
6:	begin
     curParms = *(*pState).currentParmPtr
     ymax = max(*(*pState).currentCurvePtr)
     curAmp = curParms[0]
     curCen = curParms[1]
     curWid = curParms[2]
     curTemp = curParms[3]
     newwid = abs(abs(xyact[0])-abs(curCen)) > 1d-8
	 newAmp = curAmp*ymax/max(DHOFun(x,curAmp,curCen,newwid,curTemp))
	 *(*pState).currentCurvePtr = DHOFun(x,newamp,curCen,newwid,curTemp)
	 *(*pState).currentParmPtr = [newamp,curCen,newwid,curTemp]
	end
999:begin
     xlo = min(x) & xhi = max(x)
     deltaX = xhi-xlo
     npts = n_elements(x)
     ddx = (xhi-xlo)/(npts-1.)

     wid = 1.01*0.5*ddx
     curParms = *(*pState).currentParmPtr
	 newwid = wid
     ymax = curParms[0]/sqrt(2.0*!pi*(wid/2.354)^2)
	 newamp = ymax*sqrt(2.0*!pi*(wid/2.354)^2)
	 *(*pState).currentCurvePtr = gaussianGaussFun(x,newamp,curParms[1],newwid)
	 *(*pState).currentParmPtr = [newamp,curParms[1],newwid]
	 widget_control,(*pState).textFit,set_value = ''
	end
8:	begin
     curParms = *(*pState).currentParmPtr
     radius = curparms[0]
     newradius = xyact[0]
	 *(*pState).currentCurvePtr = methylTunnelEISFFun(x,newradius)
	 *(*pState).currentParmPtr = [newRadius]
	end
9:	begin
     curParms = *(*pState).currentParmPtr
     radius = curparms[0]
     newradius = xyact[0]
	 *(*pState).currentCurvePtr = threeSiteEISFFun(x,newradius)
	 *(*pState).currentParmPtr = [newRadius]
	end
10:	begin
     curParms = *(*pState).currentParmPtr
     radius = curparms[0]
     newradius = xyact[0]
	 *(*pState).currentCurvePtr = twoSiteEISFFun(x,newradius)
	 *(*pState).currentParmPtr = [newRadius]
	end
7:	begin
     curParms = *(*pState).currentParmPtr
     wid = 2.0/curParms[2]
     gam = 0.5*wid
     xlo = min(x) & xhi = max(x)
     deltaX = xhi-xlo
     wid = 0.02*deltaX

	 newwid = abs(-(xyact[0]-wid))
	 newtau = 2.0/newwid
     ymax = curParms[0]/(!pi*gam)
	 newamp = ymax*newwid*0.5*!pi
	 ykohl = dblarr(npts)
     evalKohlrauschPro,x,[newamp,1.0,newtau],$
                       ykohl,xtabPtr = (*pState).xtabPtr,ytabPtr = (*pState).ytabPtr,$
                       btabPtr = (*pState).btabPtr,ttabPtr = (*pState).ttabPtr
	 *(*pState).currentCurvePtr = ykohl
	 *(*pState).currentParmPtr = [newamp,1.0,newtau]


	end
else:
endcase


return
end
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
pro RMDPAWinDraw,event
; Event handler for the draw widget
widget_control,event.top,get_uvalue = pState
if n_elements(*(*pState).dataPtr) eq 0 then begin

  return
endif
xlo = (*pState).xlo & xhi = (*pState).xhi
ylo = (*pState).ylo & yhi = (*pState).yhi

thiscolor1 = (*pState).colors.white
errcolors1 = {thiscolor:thiscolor1}
data = *(*pState).dataPtr & datsize = size(data)
npts = datsize[2]
yerr = dblarr(npts) & x = dblarr(npts) & y = dblarr(npts)
x = data[0,*] & y = data[1,*] & yerr = data[2,*]
datsize = size(data) & npts = datsize[2]
origWid = 0.5	; original width for gaussian or lorentzian

case event.type of
0:	begin	;	button press
     (*pState).mouse = event.press
     ; test if we are just adding a curve
     if (*pState).mouse eq 1 and (*pState).modCurve ne 1 and $
       (*pState).addCurve eq 1 then begin
	   wset,(*pState).winPixId
	   (*pState).xinit = event.x
	   (*pState).yinit = event.y
       (*pState).xyact = convert_coord((*pState).xinit,(*pState).yinit,/device,/to_data)
       widget_control,(*pState).textfit,set_value = $
                ['Hold down mouse button and drag',$
                 'function centroid to desired location.','',$
                 'Release button when finished']

	   PeakAnalysisAddCurve,event
	   widget_control,event.top,get_uvalue = pState


	   RMDCalcDisplay,event
	   widget_control,event.top,get_uvalue = pState


	   RMDPlotDisplay,event
	   widget_control,event.top,get_uvalue = pState
	   *(*pState).fixPtr = 0;ptr_new()
	endif

	if (*pState).mouse eq 1 and (*pState).modCurve eq 1 and $
	   (*pState).addCurve eq 0 then begin			; modify the width
	   wset,(*pState).winPixId
	   (*pState).xinit = event.x
	   (*pState).yinit = event.y
       (*pState).xyact = convert_coord((*pState).xinit,(*pState).yinit,/device,/to_data)

	   PeakAnalysisModCurve,event
	   widget_control,event.top,get_uvalue = pState


	   RMDCalcDisplay,event
	   widget_control,event.top,get_uvalue = pState


	   RMDPlotDisplay,event
	   widget_control,event.top,get_uvalue = pState
	endif

	if (*pState).mouse eq 4 and (*pState).modCurve eq 1 and $
	   (*pState).addCurve eq 0 then begin			; cancel add curve
  	    (*pState).mouse = 0
       (*pState).zoom = 0
	   (*pState).modCurve = 0

	   sensitizeWidgets,event
	   widget_control,event.top,get_uvalue = pState

	   RMDCalcDisplay,event
	   widget_control,event.top,get_uvalue = pState


	   RMDPlotDisplay,event
	   widget_control,event.top,get_uvalue = pState
       widget_control,(*pState).textfit,set_value = ''

	  return
	endif

; test for zooming
	if (*pState).mouse eq 4 and (*pState).addCurve ne 1 and $
	  (*pState).modCurve ne 1 then begin

	    RMDPAAutoScale,event
	  widget_control,event.top,get_uvalue = pState
  	    (*pState).mouse = 0

	  return
	endif

     if (*pState).mouse eq 1 and (*pState).modCurve ne 1 and $
        (*pState).addCurve ne 1 then begin

  	    (*pState).xp1 = event.x
	    (*pState).yp1 = event.y
	    wset, (*pState).gausswinval1
	    device, copy = [0,0,!d.x_size,!d.y_size,0,0,(*pState).winPixId] & empty
	 endif
	end
1:	begin	;	button release

	if ((*pState).mouse eq 1) and ((*pState).addCurve ne 1 and $
	    (*pState).modCurve ne 1) then begin	; finish zooming
		wset,(*pState).winPixId
		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).gausswinval1
		(*pState).xlo = lc[0] & (*pState).xhi = uc[0]
		(*pState).ylo = lc[1] & (*pState).yhi = uc[1]


		RMDPlotDisplay,event
		widget_control,event.top,get_uvalue = pState
		(*pState).mouse = 0
        widget_control,(*pState).textFit,set_value = ''
	endif


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;


	  if (*pState).mouse eq 1  and (*pState).modCurve ne 1 and $
	    (*pState).addCurve eq 1 then begin		; get set to adjust the width
		(*pState).xfinal = event.x
		(*pState).yfinal = event.y
        (*pState).xyact = convert_coord((*pState).xfinal,(*pState).yfinal,/device,/to_data)

	    PeakAnalysisModCurve,event
	    widget_control,event.top,get_uvalue = pState

	 	(*pState).addGauss = 0
	 	(*pState).addCurve = 0
        (*pState).mouse = 0
        (*pState).modGauss = 1
        (*pState).modCurve = 1
        if (*pState).curveType eq 999 then begin
          (*pState).mouse = 1
          (*pState).modCurve = 1
          (*pState).addCurve = 0
          widget_control,(*pState).textFit,set_value = ''
        endif else begin

          if (*pState).curveType eq 2 then begin
            widget_control,(*pState).textfit,set_value = $
                 ['Hold down mouse button and','move mouse on screen to',$
                  'change slope.','','Release button when finished.']
          ;widget_control,(*pState).textFit,set_value = 'change slope'
          endif else begin
            widget_control,(*pState).textfit,set_value = $
            ['Hold down mouse button and','drag mouse to change width.','',$
                      'Release button when finished']

          endelse
	    endelse
	  endif

	if (*pState).mouse eq 1 and (*pState).modCurve eq 1 and $
	   (*pState).addCurve eq 0 then begin	; set the width at its final value here

       ;print,'setting final values'
       wset,(*pState).winPixId
       (*pState).zoom = 0
	   (*pState).modGauss = 0
	   (*pState).modCurve = 0
	   (*pState).xinit = event.x
	   (*pState).yinit = event.y
       (*pState).xyact = convert_coord((*pState).xinit,(*pState).yinit,/device,/to_data)

       PeakAnalysisModCurve,event
	   widget_control,event.top,get_uvalue = pState

	   RMDCalcDisplay,event
	   widget_control,event.top,get_uvalue = pState


	    PeakAnalysisAddCurveToStructure,event
	    widget_control,event.top,get_uvalue = pState

	    (*pState).modCurve = 0
	    (*pState).mouse = 0

	   RMDCalcDisplay,event
	   widget_control,event.top,get_uvalue = pState


	   RMDPlotDisplay,event
	   widget_control,event.top,get_uvalue = pState
       widget_control,(*pState).textFit,set_value = ''

	    sensitizeWidgets,event
	    widget_control,event.top,get_uvalue = pState

	endif

	end
2:	begin	;	mouse motion

    if ((*pState).mouse eq 1) and ((*pState).addCurve ne 1 and $
        (*pState).modCurve ne 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).gausswinval1
    	device, copy = [0,0,!d.x_size,!d.y_size,0,0, (*pState).winPixId] & empty
    	plots, xc, yc, /device,color = (*pState).colors.white
    endif


; change the position by dragging
	  if (*pState).mouse eq 1 and (*pState).modCurve ne 1 and $
	    (*pState).addCurve eq 1 then begin
	    wset,(*pState).winPixId
	    (*pState).xinit = event.x
	    (*pState).yinit = event.y
        (*pState).zoom = 0
       (*pState).xyact = convert_coord((*pState).xinit,(*pState).yinit,/device,/to_data)

	   PeakAnalysisAddCurve,event
	   widget_control,event.top,get_uvalue = pState


	   RMDCalcDisplay,event
	   widget_control,event.top,get_uvalue = pState

	   RMDPlotDisplay,event
	   widget_control,event.top,get_uvalue = pState

	  endif
;  change the width by dragging
	if (*pState).mouse eq 1 and (*pState).modCurve eq 1 then begin
  	   wset,(*pState).winPixId
	   (*pState).zoom = 0
	   (*pState).xinit = event.x
	   (*pState).yinit = event.y
       (*pState).xyact = convert_coord((*pState).xinit,(*pState).yinit,/device,/to_data)

	   PeakAnalysisModCurve,event
	   widget_control,event.top,get_uvalue = pState


	   RMDCalcDisplay,event
	   widget_control,event.top,get_uvalue = pState

	   RMDPlotDisplay,event
	   widget_control,event.top,get_uvalue = pState

	endif
	end
else:
endcase


return
end
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
pro RMDPARebinData,event
widget_control,event.top,get_uvalue = pState

;catch,errno
;if (errno ne 0) then begin
;  catch,/cancel
;  void = dialog_message(dialog_parent = event.top,/error,["Unknown error detected",!err_string])
;
;  return
;endif

if (*pState).ngroups eq 1 then begin
  x = (*(*pState).origDataPtr)[0,*]
  y = (*(*pState).origDataPtr)[1,*]
  yerr = (*(*pState).origDataPtr)[2,*]
  dx = deriv(x)

  ind_de_max = max(dx,imax)
  dx_max = dx[imax] & dx_max = 1.2*dx_max[0]

  xlo = min(x) & xhi = max(x)
  Result = informationPanel(group_leader = event.top,title='Binning information',$
           binwidth = dx_max,xlo = xlo,xhi = xhi)

; display the hourglass symbol to denote we're doing some work here
;  widget_control,/hourglass

  xhi = float(Result.xhi) & xlo = float(Result.xlo)
  dx = float(Result.binwidth)
  nbins = 1+fix((xhi-xlo)/dx)

  xrange = where(x ge xlo and x le xhi,count)

  nchan = n_elements(x)
  if nchan le nbins then begin
    void = dialog_message(parent = event.top,'Must use a larger binwidth!')
    widget_control,event.top, set_uvalue = pState,/no_copy
    return
  endif

  xlim = dblarr(count)
  ylim = dblarr(count)
  yerrlim = dblarr(count)
  xlim = x[xrange]
  ylim = y[xrange]
  yerrlim = yerr[xrange]

  yout = dblarr(nbins,3)
  yout = HFBS_RebinOneDimData(xlim,nbins,ylim,yerrlim)
  newdata = dblarr(3,nbins)
  x = dblarr(nbins) & y = dblarr(nbins) & yerr = dblarr(nbins)
  x[0:nbins-1] = yout[0:nbins-1,0]
  y[0:nbins-1] = yout[0:nbins-1,1]
  yerr[0:nbins-1] = yout[0:nbins-1,2]
  newdata[0,0:nbins-1] = x[0:nbins-1]
  newdata[1,0:nbins-1] = y[0:nbins-1]
  newdata[2,0:nbins-1] = yerr[0:nbins-1]
  if n_elements((*(*pState).origBigDataStr.resArrayPtr)) gt 0 then begin
    ;print,'Number of elements',n_elements((*(*pState).origBigDataStr.resArrayPtr))
    yres = (*(*pState).origBigDataStr.resArrayPtr)[*,0]	; *
    reserr= (*(*pState).origBigDataStr.resErrorArrayPtr)[*,0]	; *
    reserrlim = dblarr(count)	; *
    reserrlim = reserr[xrange]	; *
    reslim = yres[xrange]	; *
    resout = HFBS_RebinOneDimData(xlim,nbins,reslim,reserrlim)	; *
    resArray = dblarr(nbins)
    resErrArray = dblarr(nbins)
    resArray[0:nbins-1] = reform(resout[0:nbins-1,1])	; *
    resErrArray[0:nbins-1] = reform(resout[0:nbins-1,2])	; *
    *(*pState).bigDataStr.resArrayPtr = resArray ; *
    *(*pState).bigDataStr.resErrorArrayPtr = resErrArray ; *

  ; now put the resArray into the pointer used by PAN!
    nx = n_elements(x) ; *
    resData = fltarr(3,nx) ; *
    resData[0,0:nx-1] = x[0:nx-1] ; *
    resData[1,0:nx-1] = resArray[0:nx-1,0] ; *
    resData[2,0:nx-1] = resErrArray[0:nx-1,0] ; *
    wherevalid = where((x le (*pState).parmStr.resLimit) and (x ge (-1.0*(*pState).parmStr.resLimit)),mpts) ; *
    xres = dblarr(mpts) ; *
    xres = x[wherevalid] ; *
    ;;
    xdiff = fltarr(mpts,nx) ; *
    xres = reform(xres) ; *
	; vectorized method of calculating xdiff
	nx1 = nx
	nx2 = mpts
	xdiff = fltarr(nx1,nx2)
	u1 = 1+bytarr(nx1)
	u2 = 1+bytarr(nx2)
	xdiff = transpose(u1#x[wherevalid]-x#u2)
;    for i = 0,mpts-1 do begin ; *
;      xdiff[i,0:nx-1] = (shift(xres,mpts))[i]-x[*] ; *
;    endfor ; *
    ;;

    *(*pState).parmStr.xdiffPtr = xdiff ; *
    *(*pState).parmStr.resDataPtr = resData  ; *

	outData = dblarr(3,nx,1)
  	outData[0,0:nx-1,0] = x[0:nx-1]
  	outData[1,0:nx-1,0] = resData[1,0:nx-1]
  	outData[2,0:nx-1,0] = resData[2,0:nx-1]
	*(*pState).bigResDataPtr = outData
  endif
  *(*pState).dataPtr = newdata
  *(*pState).parmStr.xPtr = x[0:nbins-1]
  *(*pState).parmStr.indlimPtr = indgen(nbins)


  RMDCalcDisplay,event
  widget_control,event.top,get_uvalue = pState

  RMDPlotDisplay,event
  widget_control,event.top,get_uvalue = pState

  widget_control,(*pState).textFit,get_uvalue = bigParmPtr,/no_copy	; *
  parmStr = (*pState).parmStr
  dave_beast_ops,"duplicate",parmStr,outStr; *
  *bigParmPtr[0] = outStr; *
  widget_control,(*pState).textFit,set_uvalue = bigParmPtr,/no_copy; *
endif else begin		; multiple groups
  x = (*(*pState).origDataPtr)[0,*]
  y = (*(*pState).origDataPtr)[1,*]
  yerr = (*(*pState).origDataPtr)[2,*]
  dx = deriv(x)

  ind_de_max = max(dx,imax)
  dx_max = dx[imax] & dx_max = 1.2*dx_max[0]

  xlo = min(x) & xhi = max(x)
  Result = informationpanel(group_leader = event.top,title='Binning information',$
           binwidth = dx_max,xlo = xlo,xhi = xhi)

  xhi = float(Result.xhi) & xlo = float(Result.xlo)
  dx = float(Result.binwidth)
  nbins = 1+fix((xhi-xlo)/dx)
  x = *(*pState).origBigDataStr.xPtr
  xrange = where(x ge xlo and x le xhi,count)

  nchan = n_elements(x)
  if nchan le nbins then begin
    void = dialog_message(parent = event.top,'Must use a larger binwidth!')
    widget_control,event.top, set_uvalue = pState,/no_copy
    return
  endif
  dataArray = dblarr(nbins,(*pState).ngroups)
  errorArray = dblarr(nbins,(*pState).ngroups)
  if n_elements((*(*pState).origBigDataStr.resArrayPtr)) gt 0 then begin	; *
    resArray = dblarr(nbins,(*pState).ngroups)								; *
    resErrArray = dblarr(nbins,(*pState).ngroups)							; *
  endif																		; *

  if n_elements(*(*pState).bigResDataPtr) gt 1 then begin  	; *
    newResData = dblarr(3,nbins,(*pState).ngroups)			; *
  endif														; *

  for j = 0,(*pState).ngroups-1 do begin
    x = *(*pState).origBigDataStr.xPtr
    xrange = where(x ge xlo and x le xhi,count)
    y = (*(*pState).origBigDataStr.dataArrayPtr)[*,j]
    yerr = (*(*pState).origBigDataStr.errorArrayPtr)[*,j]

    xlim = dblarr(count)
    ylim = dblarr(count)
    yerrlim = dblarr(count)

    xlim = x[xrange]
    ylim = y[xrange]
    yerrlim = yerr[xrange]
    if n_elements((*(*pState).origBigDataStr.resArrayPtr)) gt 0 then begin
      ;print,'Number of elements: ',n_elements((*(*pState).origBigDataStr.resArrayPtr))
      yres = (*(*pState).origBigDataStr.resArrayPtr)[*,j]	; *
      reserr= (*(*pState).origBigDataStr.resErrorArrayPtr)[*,j]	; *
      reserrlim = dblarr(count)	; *
      reserrlim = reserr[xrange]	; *
      reslim = yres[xrange]	; *
      resout = HFBS_RebinOneDimData(xlim,nbins,reslim,reserrlim)	; *
      resArray[0:nbins-1,j] = reform(resout[0:nbins-1,1])	; *
      resErrArray[0:nbins-1,j] = reform(resout[0:nbins-1,2])	; *

      newResData[0,0:nbins-1,j] = resout[0:nbins-1,0]
      newResData[1,0:nbins-1,j] = resout[0:nbins-1,1]
      newResData[2,0:nbins-1,j] = resout[0:nbins-1,2]

    endif

    yout = dblarr(nbins,3)
    yout = HFBS_RebinOneDimData(xlim,nbins,ylim,yerrlim)
    newdata = dblarr(3,nbins)
    x = dblarr(nbins) & y = dblarr(nbins) & yerr = dblarr(nbins)
    x[0:nbins-1] = yout[0:nbins-1,0]
    y[0:nbins-1] = yout[0:nbins-1,1]
    yerr[0:nbins-1] = yout[0:nbins-1,2]
    dataArray[0:nbins-1,j] = y[0:nbins-1]
    errorArray[0:nbins-1,j] = yerr[0:nbins-1]
  endfor
  if n_elements(*(*pState).bigResDataPtr) gt 1 then begin
    *(*pState).bigResDataPtr = newResData
  endif

  *(*pState).bigDataStr.xPtr = x
  *(*pState).bigDataStr.dataArrayPtr = dataArray
  *(*pState).bigDataStr.errorArrayPtr = errorArray
  widget_control,(*pState).selGroup,get_value = groupNum
  groupNum = fix(groupNum[0])-1
  nx = n_elements(x) ; *

  if n_elements(resArray) gt 0 then begin
    *(*pState).bigDataStr.resArrayPtr = resArray ; *
    *(*pState).bigDataStr.resErrorArrayPtr = resErrArray ; *
    resData = fltarr(3,nx) ; *
    resData[0,0:nx-1] = x[0:nx-1] ; *
    resData[1,0:nx-1] = resArray[0:nx-1,groupNum] ; *
    resData[2,0:nx-1] = resErrArray[0:nx-1,groupNum] ; *
    *(*pState).parmStr.resDataPtr = resData
  ;endif

    wherevalid = where((x le (*pState).parmStr.resLimit) and (x ge (-1.0*(*pState).parmStr.resLimit)),mpts) ; *
    xres = dblarr(mpts) ; *
    xres = reform(resData[0,wherevalid]) ; *
  ;;
    xdiff = fltarr(mpts,nx) ; *
    xres = reform(xres) ; *
	; vectorized method of calculating xdiff
	nx1 = nx
	nx2 = mpts
	xdiff = fltarr(nx1,nx2)
	u1 = 1+bytarr(nx1)
	u2 = 1+bytarr(nx2)
	xdiff = transpose(u1#x[wherevalid]-x#u2)

    ;for i = 0,mpts-1 do begin ; *
    ;  xdiff[i,0:nx-1] = (shift(xres,mpts))[i]-x[*] ; *
    ;endfor ; *
  ;;
    *(*pState).parmStr.xdiffPtr = xdiff ; *
    *(*pState).parmStr.resDataPtr = resData  ; *

  endif
  newdata = dblarr(3,nbins)
  newdata[0,*] = x[*]
  newdata[1,*] = dataArray[*,groupNum]
  newdata[2,*] = errorArray[*,groupNum]
  *(*pState).dataPtr = newdata
  *(*pState).parmStr.xPtr = x[0:nbins-1]
  *(*pState).parmStr.indlimPtr = indgen(nbins)

  RMDCalcDisplay,event
  widget_control,event.top,get_uvalue = pState

  RMDPlotDisplay,event
  widget_control,event.top,get_uvalue = pState
  parmStr = (*pState).parmStr
  widget_control,(*pState).textFit,get_uvalue = bigParmPtr,/no_copy	; *
  dave_beast_ops,"duplicate",parmStr,outStr; *
  *bigParmPtr[groupNum] = outStr; *
  widget_control,(*pState).textFit,set_uvalue = bigParmPtr,/no_copy; *
endelse
;catch,/cancel


return
end
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
pro RMDPAOrigBin,event
widget_control,event.top,get_uvalue = pState


if (*pState).ngroups gt 1 then begin	; multiple groups in data array

  *(*pState).bigDataStr.xPtr = *(*pState).origBigDataStr.xPtr
  *(*pState).bigDataStr.dataArrayPtr = *(*pState).origBigDataStr.dataArrayPtr
  *(*pState).bigDataStr.errorArrayPtr = *(*pState).origBigDataStr.errorArrayPtr

  widget_control,(*pState).selGroup,get_value = group
  group = fix(group[0])-1
  datsize = size(*(*pState).bigDataStr.dataArrayPtr)
  nchan = datsize[1]
  data = dblarr(3,nchan)
  data[0,0:nchan-1] = (*(*pState).bigDataStr.xPtr)[0:nchan-1]
  data[1,0:nchan-1] = (*(*pState).bigDataStr.dataArrayPtr)[0:nchan-1,group]
  data[2,0:nchan-1] = (*(*pState).bigDataStr.errorArrayPtr)[0:nchan-1,group]
  *(*pState).dataPtr = data
  *(*pState).parmStr.xPtr = data[0,0:nchan-1]

  x = *(*pState).parmStr.xPtr ; *
  nx = n_elements(x)
  widget_control,(*pState).selGroup,get_value = groupNum
  groupNum = fix(groupNum[0])-1

  if n_elements(*(*pState).bigDataStr.resArrayPtr) gt 0 then begin
    *(*pState).bigDataStr.resArrayPtr = *(*pState).origBigDataStr.resArrayPtr ; *
    *(*pState).bigDataStr.resErrorArrayPtr = *(*pState).origBigDataStr.resErrorArrayPtr ; *

    resArray = *(*pState).bigDataStr.resArrayPtr
    resErrArray = *(*pState).bigDataStr.errorArrayPtr
  ; now put the resArray into the pointer used by PAN!
    nx = n_elements(x) ; *
    resData = fltarr(3,nx) ; *
    resData[0,0:nx-1] = x[0:nx-1] ; *
    resData[1,0:nx-1] = resArray[0:nx-1,groupNum] ; *
    resData[2,0:nx-1] = resErrArray[0:nx-1,groupNum] ; *
    *(*pState).parmStr.resDataPtr = resData ; *
    wherevalid = where((x le (*pState).parmStr.resLimit) and (x ge (-1.0*(*pState).parmStr.resLimit)),mpts) ; *
    xres = dblarr(mpts) ; *
    xres = reform(resData[0,wherevalid]) ; *
  ;;
    xdiff = fltarr(mpts,nx) ; *
    xres = reform(xres) ; *
	; vectorized method for calculating xdiff
	nx1 = nx
	nx2 = mpts
	xdiff = fltarr(nx1,nx2)
	u1 = 1+bytarr(nx1)
	u2 = 1+bytarr(nx2)
	xdiff = transpose(u1#x[wherevalid]-x#u2)
    ;for i = 0,mpts-1 do begin ; *
    ;  xdiff[i,0:nx-1] = (shift(xres,mpts))[i]-x[*] ; *
    ;endfor ; *
  ;;
    *(*pState).parmStr.xdiffPtr = xdiff ; *
    *(*pState).parmStr.resDataPtr = resData  ; *
  	widget_control,(*pState).textFit,get_uvalue = bigParmPtr,/no_copy	; *
  	parmStr = (*pState).parmStr
  	dave_beast_ops,"duplicate",parmStr,outStr; *
  	*bigParmPtr[groupNum] = outStr; *
  	widget_control,(*pState).textFit,set_uvalue = bigParmPtr,/no_copy; *
  endif

endif else begin	; we only have a single "group" in the data array
  *(*pState).dataPtr = *(*pState).origDataPtr
  *(*pState).parmStr.xPtr = (*(*pState).origDataPtr)[0,*]
  *(*pState).parmStr.indlimPtr = indgen(n_elements((*(*pState).origDataPtr)[0,*]))
  x = *(*pState).parmStr.xPtr
  if n_elements(*(*pState).bigDataStr.resArrayPtr) gt 0 then begin
    *(*pState).bigDataStr.resArrayPtr = *(*pState).origBigDataStr.resArrayPtr ; *
    *(*pState).bigDataStr.resErrorArrayPtr = *(*pState).origBigDataStr.resErrorArrayPtr ; *

    resArray = *(*pState).bigDataStr.resArrayPtr
    resErrArray = *(*pState).bigDataStr.errorArrayPtr
  ; now put the resArray into the pointer used by PAN!
    nx = n_elements(x) ; *

    resData = fltarr(3,nx) ; *
    resData[0,0:nx-1] = x[0:nx-1] ; *
    resData[1,0:nx-1] = resArray[0:nx-1,0] ; *
    resData[2,0:nx-1] = resErrArray[0:nx-1,0] ; *
    *(*pState).parmStr.resDataPtr = resData ; *
    wherevalid = where((x le (*pState).parmStr.resLimit) and (x ge (-1.0*(*pState).parmStr.resLimit)),mpts) ; *
    xres = dblarr(mpts) ; *
    xres = x[wherevalid] ; *
  ;;
    xdiff = fltarr(mpts,nx) ; *
    ;xres = reform(xres) ; *
	; vectorized method of calculating xdiff
	nx1 = nx
	nx2 = mpts
	xdiff = fltarr(nx1,nx2)
	u1 = 1+bytarr(nx1)
	u2 = 1+bytarr(nx2)
	xdiff = transpose(u1#x[wherevalid]-x#u2)
	; loop method for calculating xdiff
;    for i = 0,mpts-1 do begin ; *
;      xdiff[i,0:nx-1] = (shift(xres,mpts))[i]-x[*] ; *
;    endfor ; *
  ;;
    *(*pState).parmStr.xdiffPtr = xdiff ; *
    *(*pState).parmStr.resDataPtr = resData  ; *
    widget_control,(*pState).textFit,get_uvalue = bigParmPtr,/no_copy	; *
    parmStr = (*pState).parmStr
    dave_beast_ops,"duplicate",parmStr,outStr; *
    *bigParmPtr[0] = outStr; *
    widget_control,(*pState).textFit,set_uvalue = bigParmPtr,/no_copy; *
  endif


endelse


RMDCalcDisplay,event
widget_control,event.top,get_uvalue = pState

RMDPlotDisplay,event
widget_control,event.top,get_uvalue = pState


return
end
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
pro RMDPAPrintDisplay,event
widget_control,event.top,get_uvalue = pState

(*pState).printing = 1

RMDPADisplayFitParms,event
widget_control,event.top,get_uvalue = pState

data = *(*pState).dataPtr
datsize = size(data)
npts = datsize[2]
xlo = (*pState).xlo & ylo = (*pState).ylo & xhi = (*pState).xhi
yhi = (*pState).yhi

x = dblarr(npts) & y = dblarr(npts) & yerr = dblarr(npts)
x[0:npts-1] = data[0,0:npts-1] & y[0:npts-1] = data[1,0:npts-1]
yerr[0:npts-1] = data[2,0:npts-1]
thiscolor = (*pState).colors.black & errcolors1 = {thiscolor:thiscolor}

if n_elements(*(*pState).currentCurvePtr) gt 1 then begin
  yCurrent = *(*pState).currentCurvePtr
endif

thisPath = (*!dave_defaults).workDir;(*(*pState).inPtr).workDir
thisDevice = !d.name
plotxsize = 6.5 & plotysize = 9.5
    filename = DIALOG_PICKFILE(FILTER = '*.ps',dialog_parent = event.top,title = 'Enter PS filename',path = thisPath)
    filename = filename+'.ps'
    SET_PLOT, 'PS'
    DEVICE, FILENAME=filename,/inches,yoffset = 0.1,xsize=plotxsize,ysize=plotysize,bits_per_pixel=8,color=1

	!p.multi = [0,1,3]
	xmin = 0.1 & xmax = 0.6

	plot,x,y,psym =  hfbs_selsym(0),xrange = [xlo,xhi],xstyle = 1,$
    	 yrange = [ylo,yhi],ystyle = 1,color = thiscolor,$
     	 xtitle = (*pState).xlabel,ytitle = (*pState).ylabel,$
     	 position = [xmin,0.3,xmax,0.7],title = (*pState).curTitle,$
     	 charsize = 1.5
	hfbs_cerrplot,x,y-yerr,y+yerr,width = 0.0,errcolors = errcolors1

	if n_elements(*(*pState).ytotPtr) gt 1 then ytot = *(*pState).ytotPtr
	ncurves = calcNumberOfCurves((*pState).parmStr)
	if ncurves ge 1 then begin
  		*(*pState).parmStr.indlimPtr = indgen(n_elements(x))
  		parms = convertStructureToParms((*pState).parmStr)
  		parmStr = (*pState).parmStr
  		inStr = {parmStr:parmStr,curveOrder:*(*pState).parmStr.curveIdPtr}
  		RMDPAEvalfitfunction,x,parms,yfit,ycomp,inStr = inStr,$
                       xtabPtr = (*pState).xtabPtr,$
                       ytabPtr = (*pState).ytabPtr,$
                       ttabPtr = (*pState).ttabPtr,$
                       btabPtr = (*pState).btabPtr
  		if n_elements(*(*pState).currentCurvePtr) gt 1 then begin
    		oplot,x,yCurrent,linestyle=2,thick = 2.0,color = (*pState).colors.black
  		endif
  		if n_elements(*(*pState).ytotPtr) gt 0 then begin
   			oplot,x[*],ytot,thick = 2,color = (*pState).colors.black
  		endif
  		for i = 0,ncurves-1 do begin
    		oplot,x[*],ycomp[*,i],linestyle=2,thick = 2,color = (*pState).colors.black
  		endfor
	endif else begin
  		if n_elements(*(*pState).currentCurvePtr) gt 1 then begin
    		oplot,x,yCurrent,linestyle=2,thick = 2.0,color = (*pState).colors.black
  		endif
	endelse

;;;;
if n_elements(*(*pState).ytotPtr) gt 0 then begin
  ytot = *(*pState).ytotPtr
  residuals = dblarr(npts)
  badPoints = where(yerr eq 0,nbadpoints)
  if nbadPoints eq 0 then begin
    residuals = (ytot - y)/yerr
  endif else begin
    goodPoints = where(yerr ne 0)
    residuals[goodPoints] = (ytot[goodPoints] - y[goodPoints])/yerr[goodPoints]
    residuals[badPoints] = 0.0
  endelse
  plot,x,residuals,psym = 0,color = (*pState).colors.black,$
       xtitle = (*pState).xlabel,$
       xrange = [(*pState).xlo,(*pState).xhi],$
       xstyle = 1,ytitle = (*pState).yerrlabel,$
       position = [xmin,0.15,xmax,0.25],$
       charsize = 1.5
	endif else begin
  		plot,x,y,position = [xmin,0.15,xmax,0.25],/nodata,xstyle = 4,ystyle = 4
	endelse
	plot,x,y,position = [xmin,0.1,xmax,0.15],/nodata,xstyle = 4,ystyle = 4


; if fit parameters exists, get them and put them in the right-hand column
; of the plot.

	(*pState).printing = 0
	if n_elements(*(*pState).psStringPtr) gt 1 then begin
  		strout = *(*pState).psStringPtr
  		nlines = n_elements(strout)
  		newyhi = 0.75 & newylo = 0.05
  		delta = (newyhi-newylo)/(nlines-1.)
 		if delta ge 0.01 then delta = 0.01
  			for i = 0,nlines-1 do begin
   				xyouts,0.65,newyhi-i*delta,strout[i],charsize = 0.60,/normal,color = (*pState).colors.black
  			endfor
	endif
;;;;
  	DEVICE, /CLOSE_FILE
  	set_plot,thisDevice

!p.multi = 0

return
end
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
pro RMDPASaveFits,event
widget_control,event.top,get_uvalue = pState
if n_elements(*(*pState).bigDataStr.dataArrayPtr) eq 0 then begin

  void = dialog_message(dialog_parent = event.top,'There is no data present')
  return
endif
widget_control,(*pState).addGroups,get_value = groupString
indexPtr = RMDPAChooseDets(groupString)
index = *indexPtr
nchoices = n_elements(index)
qValues = dblarr(nchoices)
elastic = dblarr(nchoices)
elasticErr = dblarr(nchoices)

dataArray = *(*pState).bigDataStr.dataArrayPtr
datSize = size(dataArray)
ndets = datSize[2]

if (max(index) gt ndets) or (min(index) lt 1) then begin
  void = dialog_message('Group selection contains invalid choice')

  return
endif

for i = 0,nchoices-1 do begin
  whereNotValid = where(indgen(ndets) eq index[i]-1,count)
  if count eq 0 then begin
    void = dialog_message('Group selection contains invalid choice')

    return
  endif
endfor

thisPath = (*!dave_defaults).workDir;(*(*pState).inPtr).workDir
filename = DIALOG_PICKFILE(FILTER = '*.txt',/write,title = 'Data and Fits Text File Name',path = thisPath)
filename = filename+'.txt'
openw,lun,filename,/get_lun

(*pState).plotParmTest = 1
ylabel = (*(*(*pState).inPtr).dataStrPtr).commonStr.ylabel
for i = 0,nchoices-1 do begin
  widget_control,(*pState).selGroup,set_value = index[i]	; advance the index to next group

  RMDPAChangeGroups,event
  widget_control,event.top,get_uvalue = pState
  qValues[i] = (*(*pState).groupValsPtr)[index[i]-1]
  strout = strtrim(ylabel,2)+' = '+strtrim(string(qvalues[i]),2)
  printf,lun,strout
  data = *(*pState).dataPtr
  datsize = size(data)
  npts = datsize[2]
  xlo = (*pState).xlo & ylo = (*pState).ylo & xhi = (*pState).xhi
  yhi = (*pState).yhi

  x = dblarr(npts) & y = dblarr(npts) & yerr = dblarr(npts)
  x[0:npts-1] = data[0,0:npts-1] & y[0:npts-1] = data[1,0:npts-1]
  yerr[0:npts-1] = data[2,0:npts-1]

  ; x,y,yerr are the data

  ncurves = calcNumberOfCurves((*pState).parmStr)
  if ncurves gt 0 then begin
    parms = convertStructureToParms((*pState).parmStr)
    parmStr = (*pState).parmStr
    inStr = {parmStr:parmStr,curveOrder:*(*pState).parmStr.curveIdPtr}
    RMDPAEvalfitfunction,x,parms,yfit,ycomp,inStr = inStr,$
                         xtabPtr = (*pState).xtabPtr,$
                         ytabPtr = (*pState).ytabPtr,$
                         ttabPtr = (*pState).ttabPtr,$
                         btabPtr = (*pState).btabPtr

    thisFormat = '('+strtrim(string(4+ncurves),2)+'f15.5)'
    dataOut = fltarr(4+ncurves)
    for j = 0,npts-1 do begin
      dataOut[0:4+ncurves-1] = [x[j],y[j],yerr[j],yfit[j],transpose(ycomp[j,0:ncurves-1])]
      printf,lun,dataOut[0:4+ncurves-1],format = thisFormat
    endfor
  endif else begin
    ncurves = 0
    thisFormat = '('+strtrim(string(4+ncurves),2)+'f15.5)'
    dataOut = fltarr(3)
    for j = 0,npts-1 do begin
      dataOut[0:2] = [x[j],y[j],yerr[j]]
      printf,lun,dataOut[0:2],format = thisFormat
    endfor
  endelse
printf,lun,''
endfor
free_lun,lun
(*pState).plotParmTest = 0


return
end
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
pro RMDPAWriteResFun,event
widget_control,event.top,get_uvalue = pState

void = dialog_message(dialog_parent = event.top,["Limit the range of the resolution function",$
"so that it's symmetric about 0"],/information)

RMDPARebinData,event
widget_control,event.top,get_uvalue = pState

data = *(*pState).dataPtr
datsize = size(data)
npts = datsize[2]
xlo = (*pState).xlo & ylo = (*pState).ylo & xhi = (*pState).xhi
yhi = (*pState).yhi

x = dblarr(npts) & y = dblarr(npts) & yerr = dblarr(npts)
x[0:npts-1] = data[0,0:npts-1] & y[0:npts-1] = data[1,0:npts-1]
yerr[0:npts-1] = data[2,0:npts-1]

thisPath = (*!dave_defaults).workDir;(*(*pState).inPtr).workDir
filename = DIALOG_PICKFILE(FILTER = '*.txt',/write,title = 'Resolution file name',path = thisPath)
filename = filename+'.txt'
openw,lun,filename,/get_lun
thisFormat = '(3f15.5)'

for i = 0,npts-1 do begin
  printf,lun,x[i],y[i],yerr[i],format = thisFormat
endfor
free_lun,lun


return
end
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
pro RMDPASaveFitParms,event
widget_control,event.top,get_uvalue = pState

if (*pState).ngroups eq 1 then begin
  parmStr = (*pState).parmStr
  ncurves = calcNumberOfCurves(parmStr)
  if ncurves eq 0 then begin

    return
  endif
  thisPath = (*!dave_defaults).workDir;(*(*pState).inPtr).workDir
  filename = DIALOG_PICKFILE(FILTER = '*.fitsav',/write,title = 'Name of fit parameter file',path = thisPath)
  filename = filename+'.fitsav'
  SAVE, parmStr, FILENAME = filename
endif else begin
  widget_control,(*pState).textFit,get_uvalue = bigParmPtr
  thisPath = (*!dave_defaults).workDir;(*(*pState).inPtr).workDir
  filename = DIALOG_PICKFILE(FILTER = '*.fitsav',/write,title = 'Name of fit parameter file',path = thisPath)
  filename = filename+'.fitsav'
  SAVE, bigParmPtr, FILENAME = filename
  widget_control,(*pState).textFit,set_uvalue = bigParmPtr
endelse


return
end
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
pro RMDPAReadFitParms,event
widget_control,event.top,get_uvalue = pState


RMDPAClearCurves,event
widget_control,event.top,get_uvalue = pState
thisPath = (*!dave_defaults).workDir;(*(*pState).inPtr).workDir
filename = DIALOG_PICKFILE(FILTER = '*.fitsav',/write,title = 'Name of fit parameter file',$
           path = thisPath)
if filename eq '' then begin

  return
endif
restore, FILENAME = filename

if (*pState).ngroups eq 1 then begin
  names = strarr(n_tags(parmStr))
  names = tag_names(parmStr)
  for i = 0,n_tags((*pState).parmStr)-1 do begin
    expr1 = '(*pState).parmStr.'+strtrim(names[i],2)+'=parmStr.'+strtrim(names[i],2)
    result = execute(expr1)
  endfor
endif

if (*pState).ngroups gt 1 then begin
  valid = where(ptr_valid(bigParmPtr),thisMany)
  ncurves = intarr(thisMany)
  thisStr = *bigParmPtr[valid[0]]
  if n_elements(*(*pState).bigResDataPtr) gt 1 then res = *(*pState).bigResDataPtr

  if (thisStr.ndelta gt 0) and (n_elements(res) eq 0) then begin
    strout = ['Load the resolution function file first!','Then load the parameters.']
    void = dialog_message(dialog_parent = event.top,strout)

    return
  endif


  for i = 0,thisMany-1 do begin
    ntags = n_tags(*bigParmPtr[valid[i]])
    names = strarr(ntags)
    names = tag_names(*bigParmPtr[valid[i]])
    parmStr = *bigParmPtr[valid[i]]
    for j = 0,ntags-1 do begin
      expr1 = '(*pState).parmStr.'+strtrim(names[j],2)+'=parmStr.'+strtrim(names[j],2)
      result = execute(expr1)
    endfor
    newParmStr = (*pState).parmStr
    dave_beast_ops,"duplicate",newParmStr,outStr
    ;RMDPAEquateStructures,newParmStr,outStr
    *bigParmPtr[valid[i]] = outStr
    ncurves[valid[i]] = calcNumberOfCurves(*bigParmPtr[valid[i]])
    if ncurves[valid[i]] gt 0 then begin
      thisOutPtr = outStr.curveIdPtr
    endif
  endfor
  (*pState).parmStr.curveIdPtr = ptr_new(*thisOutPtr)
  widget_control,(*pState).textFit,set_uvalue = bigParmPtr
endif


RMDCalcDisplay,event
widget_control,event.top,get_uvalue = pState


RMDPlotDisplay,event
widget_control,event.top,get_uvalue = pState

if ptr_valid((*pState).parmStr.curveIdPtr) then begin
  widget_control,(*pState).pickCurve,set_slider_min = 1
  if n_elements(*(*pState).parmStr.curveIdPtr) eq 1 then $
               widget_control,(*pState).pickCurve,set_slider_min = 0
  widget_control,(*pState).pickCurve,set_slider_max = n_elements(*(*pState).parmStr.curveIdPtr)
endif


return
end
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
pro RMDPALoadResFun,event
widget_control,event.top,get_uvalue = pState

catch,errno
if (errno ne 0) then begin
  catch,/cancel
  void = dialog_message(parent = event.top,/error,["Unknown error detected",!err_string])
  flag = 1

  sensitizeWidgets,event
  widget_control,event.top,get_uvalue = pState

  return
endif

if (*pState).ngroups eq 1 then begin
  thisPath = (*!dave_defaults).workDir;(*(*pState).inPtr).workDir
  file = DIALOG_PICKFILE(/read,filter = '*.txt',title='resolution function file',path = thisPath)
  Result2 = STRPOS(file, 'txt')
  if strpos(file,'txt') eq -1 then begin
    void = dialog_message(parent = event.top,'Not a valid filetype',/error)

    return
  endif
  ; display the hourglass symbol to denote we're doing some work here
;  widget_control,/hourglass

   OPENR, lun, file, /GET_LUN
   nbig  = 50000
   x     = dblarr(nbig)
   y     = dblarr(nbig)
   yerr  = dblarr(nbig)
   x1    = 0.0
   y1    = 0.0
   y1err = 0.0
   count = 0
   WHILE (NOT EOF(lun)) DO BEGIN
      READF, lun, x1,y1,y1err
      x[count] = x1
      y[count] = y1
      yerr[count] = y1err
      count = count + 1
   ENDWHILE
   FREE_LUN, lun

  nchan = count

  xres = dblarr(nchan)
  yres = dblarr(nchan)
  yerrres = dblarr(nchan)
  xres[0:nchan-1] = x[0:nchan-1]
  yres[0:nchan-1] = y[0:nchan-1]
  yerrres[0:nchan-1] = yerr[0:nchan-1]


  void = dialog_message(parent = event.top,["Select absolute energy limit (|E|) for resolution",$
									   "so that it's symmetric about 0"],/information)

  limResult = informationpanel(group_leader = event.top,title='Resolution function limits',$
            	High = 0.5*max(xres))

wherevalid = where((xres le limResult.High) and (xres ge (-1.0*limResult.High)),newchan)

  resData = dblarr(3,newchan)
  resData[0,0:newchan-1] = xres[wherevalid]
  resData[1,0:newchan-1] = yres[wherevalid]
  resData[2,0:newchan-1] = yerrres[wherevalid]

; need to interpolate these resolution data to the same energy
; spacing as the signal data:



	xdiff = dblarr(newchan,newchan)
	for j = 0,newchan-1 do begin
		for i = 0,newchan-1 do begin
			xdiff[i,j] = xres[i] - xres[j]
		endfor
	endfor
	(*pState).parmStr.xdiffPtr = ptr_new(xdiff)
    (*pState).parmStr.resDataPtr = ptr_new(resData,/no_copy)



  data = *(*pState).dataPtr & datsize = size(data) & npts = datsize[2]

  xd = dblarr(npts) & yd = dblarr(npts) & yerrd = dblarr(npts)
  xd[0:npts-1] = data[0,0:npts-1] & yd[0:npts-1] = data[1,0:npts-1]
  yerrd[0:npts-1] = data[2,0:npts-1] & dxd = (max(xd)-min(xd))/(npts-1.0)
  widget_control,(*pState).resLabel,set_value = 'Res function'



  RMDCalcDisplay,event
  widget_control,event.top,get_uvalue = pState

  RMDPlotDisplay,event
  widget_control,event.top,get_uvalue = pState

endif else begin

  case (*pState).fileId of
    'hfbs1':	begin
                thisPath = (*!dave_defaults).workDir;(*(*pState).inPtr).workDir
                file = DIALOG_PICKFILE(/read,filter = '*.hfbs',title='resolution function data file',path = thisPath)
  				Result2 = STRPOS(file, 'hfbs')
  				if strpos(file,'hfbs') eq -1 then begin
   				   void = dialog_message(parent = event.top,'Not a valid filetype',/error)

				   return
				endif


                deSensitizeWidgets,event
				widget_control,event.top,get_uvalue = pState

				; display the hourglass symbol to indicate that we're doing some work here
				;widget_control,/hourglass
				ReadHFBSFileQ,file,0,energy,data,error,ndet,nchan,comments,$
        	      			  integ_int,Norm2Mon = 1

				dataSize = size(data)
				nchan = dataSize[2]
				ndet = dataSize[1]

				data = data[1:ndet-1,0:nchan-1]
				error = error[1:ndet-1,0:nchan-1]
				ndet = ndet - 1
				; Limit the data to a smaller range than the dynamic range of the file
				void = dialog_message(parent = event.top,["Select absolute energy limit (|E|) for resolution",$
									   "so that it's symmetric about 0"],/information)

  				limResult = informationpanel(group_leader = event.top,title='Resolution function limits',$
           			High = 0.5*max(energy))

				wherevalid = where((energy le limResult.High) and (energy ge (-1.0*limResult.High)),newchan)
				outData = dblarr(3,newchan,ndet)

				for i = 0,ndet-1 do begin
				  outData[0,0:newchan-1,i] = energy[wherevalid]
				  outData[1,0:newchan-1,i] = data[i,wherevalid]
				  outData[2,0:newchan-1,i] = error[i,wherevalid]
				endfor


				if newchan le 60 then begin
  				  (*pState).bigResDataPtr = ptr_new(outData)
				endif else begin
					newpts = 60
					newOutData = dblarr(3,newpts,ndet)
					xlo = -1.0*limResult.High
					xhi = limResult.High
					dx = (xhi-xlo)/(newpts-1.)
					x = dblarr(newpts)
					x = xlo+dx*dindgen(newpts)
					for j = 0,ndet-1 do begin
						newOutData[0,0:newpts-1,j] = x[0:newpts-1]
						yinterp = dblarr(newpts)
						yinterp = interpol(outData[1,0:newchan-1,j],outData[0,0:newchan-1,j],x[0:newpts-1])
						erinterp = dblarr(newpts)
						erinterp = interpol(outData[2,0:newchan-1,j],outData[0,0:newchan-1,j],x[0:newpts-1])
						newOutData[1,0:newpts-1,j] = yinterp[0:newpts-1]
						newOutData[2,0:newpts-1,j] = erinterp[0:newpts-1]
					endfor
  				  	(*pState).bigResDataPtr = ptr_new(newOutData)
  				  	newchan = newpts
  				  	outData = dblarr(3,newchan,ndet)
  				    outData = newOutData
				endelse


                sensitizeWidgets,event
				widget_control,event.top,get_uvalue = pState

				widget_control,(*pState).resLabel,set_value = 'Res function'
				widget_control,(*pState).selGroup,get_value = group
				group = fix(group[0])-1
				resData = dblarr(3,newchan)
				resData[0,0:newchan-1] = outData[0,0:newchan-1,group]
				resData[1,0:newchan-1] = outData[1,0:newchan-1,group]
				resData[2,0:newchan-1] = outData[2,0:newchan-1,group]

				xdiff = dblarr(newchan,newchan)
				for j = 0,newchan-1 do begin
				  for i = 0,newchan-1 do begin
				    xdiff[i,j] = resData[0,i] - resData[0,j]
				  endfor
				endfor
				(*pState).parmStr.xdiffPtr = ptr_new(xdiff)

				(*pState).parmStr.resDataPtr = ptr_new(resData,/no_copy)

  				RMDCalcDisplay,event
  				widget_control,event.top,get_uvalue = pState

  				RMDPlotDisplay,event
  				widget_control,event.top,get_uvalue = pState
    			end
    'hfbs2':	begin
    			void = dialog_message(parent = event.top,['Temperature scan files do not','accept resolution functions'])

    			end
    'dcs1':		begin
			    thisPath = (*!dave_defaults).workDir;(*(*pState).inPtr).workDir
                file = DIALOG_PICKFILE(/read,filter = '*.sqw_i',title='resolution function data file',path = thisPath)
  				Result2 = STRPOS(file, 'sqw_i')
  				if strpos(file,'sqw_i') eq -1 then begin
   				   void = dialog_message(parent = event.top,'Not a valid filetype',/error)

				   return
				endif


                deSensitizeWidgets,event
				widget_control,event.top,get_uvalue = pState

				; display the hourglass symbol to indicate that we're doing some work here
				;widget_control,/hourglass
				ReadDCSFile,file,energy,data,error,ndet,nchan,comments,xlabel,ylabel,title
				;ReadHFBSFileQ,file,0,energy,data,error,ndet,nchan,comments,$
        	    ;  			  integ_int,Norm2Mon = 1

				dataSize = size(data)
				nchan = dataSize[2]
				ndet = dataSize[1]

				data = data[0:ndet-1,0:nchan-1]
				error = error[0:ndet-1,0:nchan-1]

				; Limit the data to a smaller range than the dynamic range of the file
				void = dialog_message(parent = event.top,["Select absolute energy limit (|E|) for resolution",$
									   "so that it's symmetric about 0"],/information)

  				limResult = informationpanel(group_leader = event.top,title='Resolution function limits',$
           			High = 0.5*max(energy))

				wherevalid = where((energy le limResult.High) and (energy ge (-1.0*limResult.High)),newchan)
				outData = dblarr(3,newchan,ndet)

				for i = 0,ndet-1 do begin
				  outData[0,0:newchan-1,i] = energy[wherevalid]
				  outData[1,0:newchan-1,i] = data[i,wherevalid]
				  outData[2,0:newchan-1,i] = error[i,wherevalid]
				endfor


				if newchan le 60 then begin
  				  (*pState).bigResDataPtr = ptr_new(outData)
				endif else begin
					newpts = 60
					newOutData = dblarr(3,newpts,ndet)
					xlo = -1.0*limResult.High
					xhi = limResult.High
					dx = (xhi-xlo)/(newpts-1.)
					x = dblarr(newpts)
					x = xlo+dx*dindgen(newpts)
					for j = 0,ndet-1 do begin
						newOutData[0,0:newpts-1,j] = x[0:newpts-1]
						yinterp = dblarr(newpts)
						yinterp = interpol(outData[1,0:newchan-1,j],outData[0,0:newchan-1,j],x[0:newpts-1])
						erinterp = dblarr(newpts)
						erinterp = interpol(outData[2,0:newchan-1,j],outData[0,0:newchan-1,j],x[0:newpts-1])
						newOutData[1,0:newpts-1,j] = yinterp[0:newpts-1]
						newOutData[2,0:newpts-1,j] = erinterp[0:newpts-1]
					endfor
  				  	(*pState).bigResDataPtr = ptr_new(newOutData)
  				  	newchan = newpts
  				  	outData = dblarr(3,newchan,ndet)
  				    outData = newOutData
				endelse


                sensitizeWidgets,event
				widget_control,event.top,get_uvalue = pState

				widget_control,(*pState).resLabel,set_value = 'Res function'
				widget_control,(*pState).selGroup,get_value = group
				group = fix(group[0])-1
				resData = dblarr(3,newchan)
				resData[0,0:newchan-1] = outData[0,0:newchan-1,group];energy[wherevalid]
				resData[1,0:newchan-1] = outData[1,0:newchan-1,group];data[group,wherevalid]
				resData[2,0:newchan-1] = outData[2,0:newchan-1,group];error[group,wherevalid]

				xdiff = dblarr(newchan,newchan)
				for j = 0,newchan-1 do begin
				  for i = 0,newchan-1 do begin
				    xdiff[i,j] = resData[0,i] - resData[0,j]
				  endfor
				endfor
				(*pState).parmStr.xdiffPtr = ptr_new(xdiff)

				(*pState).parmStr.resDataPtr = ptr_new(resData,/no_copy)

  				RMDCalcDisplay,event
  				widget_control,event.top,get_uvalue = pState

  				RMDPlotDisplay,event
  				widget_control,event.top,get_uvalue = pState
    			end
    'dcs1_old':		begin
  			    thisPath = (*!dave_defaults).workDir;(*(*pState).inPtr).workDir
				file = DIALOG_PICKFILE(/read,filter = '*.sqw_i',path = thisPath)
				Result2 = STRPOS(file, 'sqw_i')
				if strpos(file,'sqw_i') eq -1 then begin
				  ;void = dialog_message(parent = event.top,'Not a valid filetype',/error)

				  return
				endif

                deSensitizeWidgets,event
				widget_control,event.top,get_uvalue = pState

				; display the hourglass symbol to indicate that we're doing some work here
				;widget_control,/hourglass
				ReadDCSFile,file,energy,data,error,ndet,nchan,comments,xlabel,ylabel,title
				dataSize = size(data)
				nchan = dataSize[2]
				ndet = dataSize[1]
				; Limit the data to a smaller range than the dynamic range of the file
				void = dialog_message(parent = event.top,["Select absolute energy limit (|E|) for resolution",$
									   "so that it's symmetric about 0"],/information)

  				limResult = informationpanel(group_leader = event.top,title='Resolution function limits',$
           			High = 0.5*max(energy))

				wherevalid = where((energy le limResult.High) and (energy ge (-1.0*limResult.High)),newchan)
				outData = dblarr(3,newchan,ndet)

				for i = 0,ndet-1 do begin
				  outData[0,0:newchan-1,i] = energy[wherevalid]
				  outData[1,0:newchan-1,i] = data[i,wherevalid]
				  outData[2,0:newchan-1,i] = error[i,wherevalid]
				endfor

				(*pState).bigResDataPtr = ptr_new(outData)


                sensitizeWidgets,event
				widget_control,event.top,get_uvalue = pState

				widget_control,(*pState).resLabel,set_value = 'Res function'
				widget_control,(*pState).selGroup,get_value = group
				group = fix(group[0])-1

				resData = dblarr(3,newchan)
				resData[0,0:newchan-1] = energy[wherevalid]
				resData[1,0:newchan-1] = data[group,wherevalid]
				resData[2,0:newchan-1] = error[group,wherevalid]

				(*pState).parmStr.resDataPtr = ptr_new(resData,/no_copy)

  				RMDCalcDisplay,event
  				widget_control,event.top,get_uvalue = pState

  				RMDPlotDisplay,event
  				widget_control,event.top,get_uvalue = pState
    			end
    'dcs2':		begin
				thisPath = (*!dave_defaults).workDir;(*(*pState).inPtr).workDir
				file = DIALOG_PICKFILE(/read,filter = '*.spe',path = thisPath)
				Result2 = STRPOS(file, 'spe')
				if strpos(file,'spe') eq -1 then begin
				  ;void = dialog_message(parent = event.top,'Not a valid filetype',/error)

				  return
				endif

                deSensitizeWidgets,event
				widget_control,event.top,get_uvalue = pState

				; display the hourglass symbol to indicate that we're doing some work here
				;widget_control,/hourglass
				ReadDCSFile,file,energy,data,error,ndet,nchan,comments,xlabel,ylabel,title
				dataSize = size(data)
				nchan = dataSize[2]
				ndet = dataSize[1]
				; Limit the data to a smaller range than the dynamic range of the file
				void = dialog_message(parent = event.top,["Select absolute energy limit (|E|) for resolution",$
									   "so that it's symmetric about 0"],/information)

  				limResult = informationpanel(group_leader = event.top,title='Resolution function limits',$
           			High = 0.5*max(energy))

				wherevalid = where((energy le limResult.High) and (energy ge (-1.0*limResult.High)),newchan)
				outData = dblarr(3,newchan,ndet)

				for i = 0,ndet-1 do begin
				  outData[0,0:newchan-1,i] = energy[wherevalid]
				  outData[1,0:newchan-1,i] = data[i,wherevalid]
				  outData[2,0:newchan-1,i] = error[i,wherevalid]
				endfor

				(*pState).bigResDataPtr = ptr_new(outData)


                sensitizeWidgets,event
				widget_control,event.top,get_uvalue = pState

				widget_control,(*pState).resLabel,set_value = 'Res function'
				widget_control,(*pState).selGroup,get_value = group
				group = fix(group[0])-1

				resData = dblarr(3,newchan)
				resData[0,0:newchan-1] = energy[wherevalid]
				resData[1,0:newchan-1] = data[group,wherevalid]
				resData[2,0:newchan-1] = error[group,wherevalid]

				(*pState).parmStr.resDataPtr = ptr_new(resData,/no_copy)

  				RMDCalcDisplay,event
  				widget_control,event.top,get_uvalue = pState

  				RMDPlotDisplay,event
  				widget_control,event.top,get_uvalue = pState
    			end
    'fcs':		begin
				thisPath = (*!dave_defaults).workDir;(*(*pState).inPtr).workDir
                file = DIALOG_PICKFILE(/read,filter = '*.xy',title='resolution function data file',path = thisPath)
  				Result2 = STRPOS(file, 'xy')
  				if strpos(file,'xy') eq -1 then begin
   				   void = dialog_message(parent = event.top,'Not a valid filetype',/error)

				   return
				endif


                deSensitizeWidgets,event
				widget_control,event.top,get_uvalue = pState

				; display the hourglass symbol to indicate that we're doing some work here
				;widget_control,/hourglass
				ReadFCSFile,file,energy,data,error,ndet,nchan,comments,xlabel,ylabel,title
				;ReadHFBSFileQ,file,0,energy,data,error,ndet,nchan,comments,$
        	    ;  			  integ_int,Norm2Mon = 1

				dataSize = size(data)
				nchan = dataSize[2]
				ndet = dataSize[1]

				data = data[0:ndet-1,0:nchan-1]
				error = error[0:ndet-1,0:nchan-1]

				; Limit the data to a smaller range than the dynamic range of the file
				void = dialog_message(parent = event.top,["Select absolute energy limit (|E|) for resolution",$
									   "so that it's symmetric about 0"],/information)

  				limResult = informationpanel(group_leader = event.top,title='Resolution function limits',$
           			High = 0.5*max(energy))

				wherevalid = where((energy le limResult.High) and (energy ge (-1.0*limResult.High)),newchan)
				outData = dblarr(3,newchan,ndet)

				for i = 0,ndet-1 do begin
				  outData[0,0:newchan-1,i] = energy[wherevalid]
				  outData[1,0:newchan-1,i] = data[i,wherevalid]
				  outData[2,0:newchan-1,i] = error[i,wherevalid]
				endfor


				if newchan le 60 then begin
  				  (*pState).bigResDataPtr = ptr_new(outData)
				endif else begin
					newpts = 60
					newOutData = dblarr(3,newpts,ndet)
					xlo = -1.0*limResult.High
					xhi = limResult.High
					dx = (xhi-xlo)/(newpts-1.)
					x = dblarr(newpts)
					x = xlo+dx*dindgen(newpts)
					for j = 0,ndet-1 do begin
						newOutData[0,0:newpts-1,j] = x[0:newpts-1]
						yinterp = dblarr(newpts)
						yinterp = interpol(outData[1,0:newchan-1,j],outData[0,0:newchan-1,j],x[0:newpts-1])
						erinterp = dblarr(newpts)
						erinterp = interpol(outData[2,0:newchan-1,j],outData[0,0:newchan-1,j],x[0:newpts-1])
						newOutData[1,0:newpts-1,j] = yinterp[0:newpts-1]
						newOutData[2,0:newpts-1,j] = erinterp[0:newpts-1]
					endfor
  				  	(*pState).bigResDataPtr = ptr_new(newOutData)
  				  	newchan = newpts
  				  	outData = dblarr(3,newchan,ndet)
  				    outData = newOutData
				endelse


                sensitizeWidgets,event
				widget_control,event.top,get_uvalue = pState

				widget_control,(*pState).resLabel,set_value = 'Res function'
				widget_control,(*pState).selGroup,get_value = group
				group = fix(group[0])-1
				resData = dblarr(3,newchan)
				resData[0,0:newchan-1] = outData[0,0:newchan-1,group];energy[wherevalid]
				resData[1,0:newchan-1] = outData[1,0:newchan-1,group];data[group,wherevalid]
				resData[2,0:newchan-1] = outData[2,0:newchan-1,group];error[group,wherevalid]

				xdiff = dblarr(newchan,newchan)
				for j = 0,newchan-1 do begin
				  for i = 0,newchan-1 do begin
				    xdiff[i,j] = resData[0,i] - resData[0,j]
				  endfor
				endfor
				(*pState).parmStr.xdiffPtr = ptr_new(xdiff)

				(*pState).parmStr.resDataPtr = ptr_new(resData,/no_copy)

  				RMDCalcDisplay,event
  				widget_control,event.top,get_uvalue = pState

  				RMDPlotDisplay,event
  				widget_control,event.top,get_uvalue = pState
    			end
  endcase
endelse

return
end
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
pro RMDPAClearResFun,event
widget_control,event.top,get_uvalue = pState
widget_control,(*pState).resLabel,set_value = 'No res function     '

if n_elements(*(*pState).parmStr.resDataPtr) gt 0 and $
   calcNumberOfCurves((*pState).parmStr) eq 0 then begin
  ptr_free,(*pState).parmStr.resDataPtr
  (*pState).parmStr.resDataPtr = ptr_new(/allocate_heap)

  return
endif
if n_elements(*(*pState).parmStr.resDataPtr) gt 0 then begin
  ptr_free,(*pState).parmStr.resDataPtr
  (*pState).parmStr.resDataPtr = ptr_new(/allocate_heap)
endif
if n_elements(*(*pState).bigResDataPtr) gt 0 then begin
  ptr_free,(*pState).bigResDataPtr
  (*pState).bigResDataPtr = ptr_new(/allocate_heap)
endif

if calcNumberOfCurves((*pState).parmStr) eq 0 then begin

  RMDPAClearCurves,event
  widget_control,event.top,get_uvalue = pState

  return
endif


RMDCalcDisplay,event
widget_control,event.top,get_uvalue = pState

RMDPlotDisplay,event
widget_control,event.top,get_uvalue = pState

return
end
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
pro RMDPAChangeGroups,event
widget_control,event.top,get_uvalue = pState
widget_control,(*pState).selGroup,get_value = groupNum
groupNum = fix(groupNum[0])-1

if (*pState).ngroups eq 1 then begin

  return
endif
;;;;11/14/01;;;
resLimit = (*pState).parmStr.resLimit
if (*pState).autofit eq 0 then begin
  widget_control,(*pState).textFit,get_uvalue = bigParmPtr
  (*pState).parmStr = *bigParmPtr[groupNum]
  (*pState).parmStr.resLimit = resLimit
endif
;;;;;;;;;;;;;;;;;;;;;
dataArray = *(*pState).bigDataStr.dataArrayPtr
errorArray = *(*pState).bigDataStr.errorArrayPtr
x = *(*pState).bigDataStr.xPtr
npts = n_elements(x)
(*pState).curTitle = (*(*pState).titlePtr)[groupNum]
if (*pState).parmStr.resLimit ne 999.0 and n_elements(*(*pState).bigResDataPtr) gt 1 then begin
  wherevalid = where((x le (*pState).parmStr.resLimit) and (x ge (-1.0*(*pState).parmStr.resLimit)),mpts)
  xres = x[wherevalid]
  xdiff = dblarr(mpts,npts)
  for j = 0,mpts-1 do begin
    xdiff[j,*] = (shift(xres,mpts))[j] - x[*]
  endfor
  *(*pState).parmStr.xdiffPtr = xdiff
endif else begin
  xdiff = dblarr(npts,npts)
  for i = 0,npts-1 do begin
    for j = 0,npts-1 do begin
      xdiff[j,i] = x[j] - x[i]
    endfor
  endfor

endelse
if n_elements(xdiff) gt 0 then *(*pState).parmStr.xdiffPtr = xdiff

data = dblarr(3,npts)
data[0,0:npts-1] = x[0:npts-1]
data[1,0:npts-1] = dataArray[0:npts-1,groupNum]
data[2,0:npts-1] = errorArray[0:npts-1,groupNum]


yvalue = ((*(*(*(*pState).inPtr).dataStrPtr).commonStr.histPtr).y)[groupNum]
ylabel = (*pState).ylabel+'='+string(yvalue,format = '(f7.3)')
(*pState).curTitle = ylabel

if n_elements(*(*pState).bigResDataPtr) gt 1 then begin
  bigResData = *(*pState).bigResDataPtr
  datSize = size(bigResData)
  ndet = datSize[3]
  nchan = datSize[2]

  resData = dblarr(3,nchan)
  resData[0,0:nchan-1] = bigResData[0,0:nchan-1,groupNum]
  resData[1,0:nchan-1] = bigResData[1,0:nchan-1,groupNum]
  resData[2,0:nchan-1] = bigResData[2,0:nchan-1,groupNum]

  *(*pState).parmStr.resDataPtr = resData
endif

*(*pState).dataPtr = data
*(*pState).origDataPtr = data
if ((*pState).autoFit eq 0) and ((*pState).plotParmTest eq 0) then begin
  RMDCalcDisplay,event
  RMDPlotDisplay,event
endif
if ((*pState).plotParmTest eq 0) then begin

  RMDPADisplayFitParms,event
  widget_control,event.top,get_uvalue = pState
endif


return
end
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
pro RMDPAAddGroups,event
widget_control,event.top,get_uvalue = pState

catch,errno
if (errno ne 0) then begin
  catch,/cancel
  void = dialog_message(dialog_parent = event.top,/error,["Unknown error detected",!err_string])

  return
endif

widget_control,(*pState).addGroups,get_value = groupString
indexPtr = RMDPAChooseDets(groupString)
index = *indexPtr
nchoices = n_elements(index)
;freeThePointer,(*pState).dataPtr
*(*pState).dataPtr = 0

dataArray = *(*pState).bigDataStr.dataArrayPtr
datSize = size(dataArray)
ndets = datSize[2]
errorArray = *(*pState).bigDataStr.errorArrayPtr
x = *(*pState).bigDataStr.xPtr
npts = n_elements(x)

for i = 0,nchoices-1 do begin
  whereNotValid = where(indgen(ndets) eq index[i]-1,count)
  if count eq 0 then begin
    void = dialog_message(dialog_parent = event.top,'Group selection contains invalid choice')

    return
  endif
endfor

data = dblarr(3,npts)
data[0,0:npts-1] = x[0:npts-1]
;data[1,0:npts-1] = dataArray[groupNum,0:npts-1]
;data[2,0:npts-1] = errorArray[groupNum,0:npts-1]
if n_elements(*(*pState).bigResDataPtr) gt 1 then begin
  bigResData = *(*pState).bigResDataPtr
  datSize = size(bigResData)
  ndet = datSize[3]
  nchan = datSize[2]
  resData = dblarr(3,nchan)
endif

if n_elements(*(*pState).bigResDataPtr) gt 1 then begin
  bigResData = *(*pState).bigResDataPtr
endif

error = dblarr(npts)
for i = 0,nchoices-1 do begin
  data[1,0:npts-1] = data[1,0:npts-1] + dataArray[0:npts-1,index[i]-1]
  error[0:npts-1] = error[0:npts-1]+(errorArray[0:npts-1,index[i]-1])^2
  if n_elements(*(*pState).bigResDataPtr) gt 1 then begin
    resData[0,0:nchan-1] = bigResData[0,0:nchan-1,index[i]-1]
    resData[1,0:nchan-1] = resData[1,0:nchan-1] + bigResData[1,0:nchan-1,index[i]-1]
    resData[2,0:nchan-1] = resData[2,0:nchan-1] + (bigResData[2,0:nchan-1,index[i]-1])^2
  endif
endfor
data[0,0:npts-1] = x[0:npts-1]
data[2,0:npts-1] = sqrt(error[0:npts-1])

if n_elements(*(*pState).bigResDataPtr) gt 1 then begin
  resData[2,0:nchan-1] = sqrt(resData[2,0:nchan-1])
  *(*pState).parmStr.resDataPtr = resData
endif

*(*pState).dataPtr = data
*(*pState).origDataPtr = data

RMDPAAutoScale,event
widget_control,event.top,get_uvalue = pState


return
end
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
pro RMDPAAutoFitAllData,event
widget_control,event.top,get_uvalue = pState
; Cycles through all of the groups as listed in the AddGroups cw_field

; Test here to see if the spacing between x is uniform
data = *(*pState).dataPtr
xx = reform(data[0,*])

sig = sqrt((moment(deriv(xx)))[1])
if n_elements(*(*pState).parmStr.resDataPtr) gt 1 then begin
  res = *(*pState).parmStr.resDataPtr
  if (n_elements(res) gt 0) and (sig gt 1.e-4) then begin
    strout = ['Numerical convolution requires equal x-bins.','Please rebin data.']
    void = dialog_message(dialog_parent = event.top,strout)

    return
  endif
endif

if (*pState).ngroups eq 1 then begin

  RMDPAFitData,event
  widget_control,event.top,get_uvalue = pState

  return
endif

(*pState).fit = 1
(*pState).autoFit = 1
ncurves = calcNumberOfCurves((*pState).parmStr)

parmStr = (*pState).parmStr
ngroups = (*pState).ngroups

widget_control,(*pState).addGroups,get_value = groupString
indexPtr = RMDPAChooseDets(groupString)
index = *indexPtr
nchoices = n_elements(index)
*(*pState).dataPtr = 0

dataArray = *(*pState).bigDataStr.dataArrayPtr
datSize = size(dataArray)
ndets = datSize[1]
errorArray = *(*pState).bigDataStr.errorArrayPtr
x = *(*pState).bigDataStr.xPtr
npts = n_elements(x)

for i = 0,nchoices-1 do begin
  whereNotValid = where(indgen(ndets) eq index[i]-1,count)
  if count eq 0 then begin
    void = dialog_message('Group selection contains invalid choice')

    return
  endif
endfor

data = dblarr(3,npts)
data[0,0:npts-1] = x[0:npts-1]

ncurves = calcNumberOfCurves((*pState).parmStr)

widget_control,(*pState).selGroup,set_value = index[0]	; advance the index to first group

RMDPAChangeGroups,event
widget_control,event.top,get_uvalue = pState


RMDPAFitData,event
widget_control,event.top,get_uvalue = pState

if nchoices gt 1 then begin
  for i = 1,nchoices-1 do begin
    widget_control,(*pState).selGroup,set_value = index[i]


    RMDPAChangeGroups,event
    widget_control,event.top,get_uvalue = pState


    RMDPAFitData,event
    widget_control,event.top,get_uvalue = pState
  endfor
endif

(*pState).fit = 0
(*pState).autoFit = 0

return
end
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
pro RMDPAAutoFitAllDataOld,event
widget_control,event.top,get_uvalue = pState
; Cycles through all of the groups as listed in the AddGroups cw_field

widget_control,(*pState).addGroups,get_value = groupString
indexPtr = RMDPAChooseDets(groupString)
index = *indexPtr
nchoices = n_elements(index)
;freeThePointer,(*pState).dataPtr
*(*pState).dataPtr = 0
dataArray = *(*pState).bigDataStr.dataArrayPtr
datSize = size(dataArray)
ndets = datSize[1]
errorArray = *(*pState).bigDataStr.errorArrayPtr
x = *(*pState).bigDataStr.xPtr
npts = n_elements(x)

for i = 0,nchoices-1 do begin
  whereNotValid = where(indgen(ndets) eq index[i]-1,count)
  if count eq 0 then begin
    void = dialog_message('Group selection contains invalid choice')

    return
  endif
endfor

data = dblarr(3,npts)
data[0,0:npts-1] = x[0:npts-1]
titles = *(*pState).titlePtr

for i = 0,nchoices-1 do begin
  widget_control,(*pState).selGroup,set_value = fix(index[i])
  data = dblarr(3,npts)
  data[0,0:npts-1] = x[0:npts-1]
  data[1,0:npts-1] = dataArray[index[i]-1,0:npts-1]
  data[2,0:npts-1] = errorArray[index[i]-1,0:npts-1]
  (*pState).xlo = min(data[0,*]) & (*pState).xhi = max(data[0,*])
  delta = max(data[1,0:npts-1])-min(data[1,0:npts-1])
  (*pState).ylo = min(data[1,0:npts-1])-0.2*delta & (*pState).yhi = 1.2*max(data[1,0:npts-1])
  if (*pState).ylo gt 0.0 then (*pState).ylo = 0.0
  (*pState).curTitle = titles[index[i]-1]
  *(*pState).dataPtr = data
  *(*pState).origDataPtr = data

  if i gt 0 then (*pState).parmStr = (*pState).bigParmStr[index[i-1]-1]
  ;(*pState).bigParmStr[index[i]-1] = (*pState).parmStr

  wait,0.2


  RMDPAFitData,event
  widget_control,event.top,get_uvalue = pState
  wait,0.1
endfor


return
end
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
pro RMDPAWriteCP,event
widget_control,event.top,get_uvalue = pState
if not ptr_valid((*pState).plotParmDataPtr) then begin

  return
endif
data = *(*pState).plotParmDataPtr
datsize = size(data)
npts = datsize[2]

x = dblarr(npts) & y = dblarr(npts) & yerr = dblarr(npts)
x[0:npts-1] = data[0,0:npts-1] & y[0:npts-1] = data[1,0:npts-1]
yerr[0:npts-1] = data[2,0:npts-1]
thisPath = (*!dave_defaults).workDir;(*(*pState).inPtr).workDir
filename = DIALOG_PICKFILE(FILTER = '*.txt',/write,title = 'Enter file name',path = thisPath)
filename = filename+'.txt'
openw,lun,filename,/get_lun
thisFormat = '(3f15.5)'

for i = 0,npts-1 do begin
  printf,lun,x[i],y[i],yerr[i],format = thisFormat
endfor
free_lun,lun


return
end
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
pro RMDPAEnterAxisTitles,event
widget_control,event.top,get_uvalue = pState
result = informationpanel(group_leader = event.top,title='Enter axis titles',$
         xlabel = 'E (meV)',ylabel = 'I (arb units)')
(*pState).xlabel = result.xlabel
(*pState).ylabel = result.ylabel

RMDPlotDisplay,event
widget_control,event.top,get_uvalue = pState

return
end
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
pro RMDPAEnterCP,event
widget_control,event.top,get_uvalue = pState
if calcNumberOfCurves((*pState).parmStr) eq 0 then begin
  void = dialog_message(dialog_parent = event.top,'No fits present')

  return
endif

catch,errno
if (errno ne 0) then begin
  catch,/cancel
  void = dialog_message(/error,["Unknown error detected",!err_string])

  return
endif

(*pState).plotParmTest = 1

result = informationpanel(group_leader = event.top,title='Enter curve and parameter (e.g. C[1].P[2])',$
         Parameter = 'C[ 1 ].P[ 2 ]')
parmString = strcompress(result.Parameter,/REMOVE_ALL)

pos1 = 1
pos2 = strpos(parmString,']')
firstNumberString = strmid(parmString,pos1+1,pos2-2)
pos3 = strpos(parmString,'P[')
pos4 = strpos(parmString,']',pos3)
secondNumberString = strmid(parmString,pos3+2,pos4-pos3-2)
(*pState).curveNum = fix(firstNumberString)-1
(*pState).parmNum = fix(secondNumberString)-1


; cycle through all of the relevant groups and extract the
; relevant curve parameter
widget_control,(*pState).addGroups,get_value = groupString
indexPtr = RMDPAChooseDets(groupString)
index = *indexPtr
nchoices = n_elements(index)
dataArray = *(*pState).bigDataStr.dataArrayPtr
datSize = size(dataArray)
ndets = datSize[2]

for i = 0,nchoices-1 do begin
  whereNotValid = where(indgen(ndets) eq index[i]-1,count)
  if count eq 0 then begin
    void = dialog_message('Group selection contains invalid choice')

    return
  endif
endfor

plotData = dblarr(3,nchoices)

for i = 0,nchoices-1 do begin
  widget_control,(*pState).selGroup,set_value = index[i]	; advance the index to next group

  RMDPAChangeGroups,event
  widget_control,event.top,get_uvalue = pState

  RMDPADisplayFitParms,event
  widget_control,event.top,get_uvalue = pState
  plotData[1,i] = (*pState).plotParm
  plotData[2,i] = (*pState).plotParmErr
  plotData[0,i] = (*(*pState).groupValsPtr)[index[i]-1]
endfor
*(*pState).plotParmDataPtr = plotData

void = RMDPAPlotParmWidget(group_leader = event.top,(*pState).plotParmDataPtr,$
                           xlabel = *(*pState).groupLabelsPtr,$
                           ylabel = (*pState).parmLabel,$
                           platform = (*pState).platform)
(*pState).plotParmTest = 0

RMDPAChangeGroups,event
widget_control,event.top,get_uvalue = pState


return
end
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
pro RMDPADisplayFileName,event
widget_control,event.top,get_uvalue = pState
strout = *(*pState).headerPtr
;if (*pState).fileName eq '' then begin
;  strout = 'No file information present'
;endif else begin
;  strout = (*pState).fileName
;endelse

void = dialog_message(strout,/information,title = 'Data File Information')

return
end
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
pro RMDPAPlotEISF,event
; This procedure gets the parameters that represent the elastic integrated
; intensity and the inelastic integrated intensity, calculates the EISF and
; plots them to the screen.
;
widget_control,event.top,get_uvalue = pState
if calcNumberOfCurves((*pState).parmStr) eq 0 then begin

  return
endif

catch,errno
if (errno ne 0) then begin
  catch,/cancel
  void = dialog_message(/error,["Unknown error detected",!err_string])

  return
endif

(*pState).plotParmTest = 1

result = informationpanel(group_leader = event.top,$
         title='Enter curve and parameter for elastic integrated intensity',$
         Parameter = 'C[ 1 ].P[ 1 ]')
parmString = strcompress(result.Parameter,/REMOVE_ALL)

pos1 = 1
pos2 = strpos(parmString,']')
firstNumberString = strmid(parmString,pos1+1,pos2-2)
pos3 = strpos(parmString,'P[')
pos4 = strpos(parmString,']',pos3)
secondNumberString = strmid(parmString,pos3+2,pos4-pos3-2)
(*pState).curveNum = fix(firstNumberString)-1
(*pState).parmNum = fix(secondNumberString)-1


; cycle through all of the relevant groups and extract the
; relevant curve parameter
widget_control,(*pState).addGroups,get_value = groupString
indexPtr = RMDPAChooseDets(groupString)
index = *indexPtr
nchoices = n_elements(index)
qValues = dblarr(nchoices)
elastic = dblarr(nchoices)
elasticErr = dblarr(nchoices)

dataArray = *(*pState).bigDataStr.dataArrayPtr
datSize = size(dataArray)
ndets = datSize[1]
for i = 0,nchoices-1 do begin
  whereNotValid = where(indgen(ndets) eq index[i]-1,count)
  if count eq 0 then begin
    void = dialog_message('Group selection contains invalid choice')

    return
  endif
endfor

for i = 0,nchoices-1 do begin
  widget_control,(*pState).selGroup,set_value = index[i]	; advance the index to next group

  RMDPAChangeGroups,event
  widget_control,event.top,get_uvalue = pState

  RMDPADisplayFitParms,event
  widget_control,event.top,get_uvalue = pState
  elastic[i] = (*pState).plotParm
  elasticErr[i] = (*pState).plotParmErr
  qValues[i] = (*(*pState).groupValsPtr)[index[i]-1]
endfor

result = informationpanel(group_leader = event.top,$
         title='Enter curve and parameter for inelastic integrated intensity',$
         Parameter = 'C[ 2 ].P[ 1 ]')
parmString = strcompress(result.Parameter,/REMOVE_ALL)

pos1 = 1
pos2 = strpos(parmString,']')
firstNumberString = strmid(parmString,pos1+1,pos2-2)
pos3 = strpos(parmString,'P[')
pos4 = strpos(parmString,']',pos3)
secondNumberString = strmid(parmString,pos3+2,pos4-pos3-2)
(*pState).curveNum = fix(firstNumberString)-1
(*pState).parmNum = fix(secondNumberString)-1


; cycle through all of the relevant groups and extract the
; relevant curve parameter
widget_control,(*pState).addGroups,get_value = groupString
indexPtr = RMDPAChooseDets(groupString)
index = *indexPtr
nchoices = n_elements(index)
qValues = dblarr(nchoices)
inElastic = dblarr(nchoices)
inElasticErr = dblarr(nchoices)

dataArray = *(*pState).bigDataStr.dataArrayPtr
datSize = size(dataArray)
ndets = datSize[1]
for i = 0,nchoices-1 do begin
  whereNotValid = where(indgen(ndets) eq index[i]-1,count)
  if count eq 0 then begin
    void = dialog_message('Group selection contains invalid choice')

    return
  endif
endfor

for i = 0,nchoices-1 do begin
  widget_control,(*pState).selGroup,set_value = index[i]	; advance the index to next group

  RMDPAChangeGroups,event
  widget_control,event.top,get_uvalue = pState

  RMDPADisplayFitParms,event
  widget_control,event.top,get_uvalue = pState
  inElastic[i] = (*pState).plotParm
  inElasticErr[i] = (*pState).plotParmErr
  qValues[i] = (*(*pState).groupValsPtr)[index[i]-1]
endfor

; now cycle through as many inelastic features as user wants
void = 'Yes'
void = dialog_message('Add another inelastic feature?',/question)
while void eq 'Yes' do begin

  result = informationpanel(group_leader = event.top,$
           title='Enter curve and parameter for inelastic integrated intensity',$
           Parameter = 'C[ 2 ].P[ 1 ]')
  parmString = strcompress(result.Parameter,/REMOVE_ALL)

  pos1 = 1
  pos2 = strpos(parmString,']')
  firstNumberString = strmid(parmString,pos1+1,pos2-2)
  pos3 = strpos(parmString,'P[')
  pos4 = strpos(parmString,']',pos3)
  secondNumberString = strmid(parmString,pos3+2,pos4-pos3-2)
  (*pState).curveNum = fix(firstNumberString)-1
  (*pState).parmNum = fix(secondNumberString)-1

; cycle through all of the relevant groups and extract the
; relevant curve parameter
  widget_control,(*pState).addGroups,get_value = groupString
  indexPtr = RMDPAChooseDets(groupString)
  index = *indexPtr
  nchoices = n_elements(index)

  dataArray = *(*pState).bigDataStr.dataArrayPtr
  datSize = size(dataArray)
  ndets = datSize[1]
  for i = 0,nchoices-1 do begin
    whereNotValid = where(indgen(ndets) eq index[i]-1,count)
    if count eq 0 then begin
      void = dialog_message('Group selection contains invalid choice')

      return
    endif
  endfor

  for i = 0,nchoices-1 do begin
    widget_control,(*pState).selGroup,set_value = index[i]	; advance the index to next group

    RMDPAChangeGroups,event
    widget_control,event.top,get_uvalue = pState

    RMDPADisplayFitParms,event
    widget_control,event.top,get_uvalue = pState
    inElastic[i] = inelastic[i]+(*pState).plotParm
    inElasticErr[i] = sqrt((inElasticErr[i])^2 + ((*pState).plotParmErr)^2)
  endfor

  void = dialog_message('Add another inelastic feature?',/question)
endwhile

; subtract off some inelastic intensity from the denominator?
void = 'Yes'
void = dialog_message('Subtract an inelastic feature from denominator?',/question)
if void eq 'Yes' then begin
  sub = dblarr(nchoices) & subErr = dblarr(nchoices)
  thisPath = (*!dave_defaults).workDir;(*(*pState).inPtr).workDir
  filename = DIALOG_PICKFILE(FILTER = '*.txt',/write,title = 'Enter file name',path = thisPath)
  openr,lun,filename,/get_lun
  bigNumber = 500
  xx = dblarr(bigNumber)
  yy = dblarr(bigNumber)
  yyerr = dblarr(bigNumber)
  xxx = 0.0 & yyy = 0.0 & zzz = 0.0
  count = 0
  WHILE (NOT EOF(lun)) DO BEGIN
      READF, lun, xxx,yyy,zzz
      xx[count] = xxx
      yy[count] = yyy
      yyerr[count] = zzz
      count = count + 1
  ENDWHILE
  FREE_LUN, lun
  inElastic = inElastic - yy[0:count-1]
  inElasticErr = sqrt(inElasticErr^2+yyerr[0:count-1]^2)
endif

sigNum = dblarr(nchoices) & sigNum = elasticErr
sigDen = dblarr(nchoices) & sigDen = sqrt(elasticErr^2+inElasticErr^2)
eisfErr = dblarr(nchoices)
eisf = dblarr(nchoices)
eisf = elastic/(elastic+inElastic)
eisfErr = eisf*sqrt((sigNum/elastic)^2+(sigDen/(elastic+inElastic))^2)


(*pState).parmLabel = 'EISF'
eisfData = dblarr(3,nchoices)
eisfData[1,0:nchoices-1] = eisf[0:nchoices-1]
eisfData[2,0:nchoices-1] = eisfErr[0:nchoices-1]
eisfData[0,0:nchoices-1] = qValues[0:nchoices-1]

*(*pState).plotParmDataPtr = eisfData


void = RMDPAPlotParmWidget(group_leader = event.top,(*pState).plotParmDataPtr,$
                           xlabel = *(*pState).groupLabelsPtr,$
                           ylabel = (*pState).parmLabel,$
                           platform = (*pState).platform)

(*pState).plotParmTest = 0

RMDPAChangeGroups,event
widget_control,event.top,get_uvalue = pState




return
end
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
pro RMDPASaveFitParmsAsText,event
widget_control,event.top,get_uvalue = pState
(*pState).writeParmsAsText = 1

RMDPADisplayFitParms,event
widget_control,event.top,get_uvalue = pState

return
end
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
pro RMDPALoadTest,event
; This routine creates a fake data set for user to
; play with to learn how to use PAN.
widget_control,event.top,get_uvalue = pState
RMDPAClearCurves,event
RMDPAClearResFun,event
workDir = (*!dave_defaults).workDir;(*(*pState).inPtr).workDir
datDir = (*!dave_defaults).datDir;(*(*pState).inPtr).datDir

qlo = 0.25 & qhi = 2.4
nq = 20
r = 1.78	; (methyl radius in angstroms)
q = hfbs_makepoints(xlo = qlo,xhi = qhi,npts = nq)
eisf = (5.0+4.0*beselj(q*r))/9.0
eisf = eisf+0.05*randomn(s,nq,/normal)

npts = 100
xlo = -10.0 & xhi = 10.0
x = hfbs_makepoints(xlo = xlo,xhi = xhi,npts = npts)
area = 1400.0
elWid = 0.90
elCen = 0.0
;ielArea = 0.5*elArea
ielWid = 1.1
ielCen = 4.0
bg = 50.0
y1 = fltarr(npts,nq)
data = fltarr(npts,nq)
for i = 0,nq-1 do begin
; Create an elastic peak with a couple of inelastic lines
	y1[*,i] = eisf[i]*hfbs_gaussian(x,area = area,cen = elCen,wid = elWid) + $
     		0.5*(1.0-eisf[i])*hfbs_lorentzian(x,area = area,cen = ielCen,wid = ielWid) + $
     		0.5*(1.0-eisf[i])*hfbs_lorentzian(x,area = area,cen = -ielCen,wid = ielWid) + $
     		bg
endfor
y = fltarr(npts,nq)
;s = 101L	; initialize the seed so that the
;			; fake data is noisy but it will always
;			; have the same noise so the fits should
;			; always be the same.
for j = 0,nq-1 do begin
  for i = 0,npts-1 do begin
    data[i,j] = randomn(s,1,poisson = y1[i,j])
  endfor
endfor
yerr = sqrt(data)
; Now stuff all of this into a DAVE structure
  hbar_omega = '!6!sh!r!e/!n !7x!6'
  xlabel = 'E '
  ylabel = 'Q'
  xunits = 'energy:ueV'
  yunits = 'wavevector:A-1'
  histlabel = 'I (arbitrary units)'
  histunits = ''

  *(*(*(*pState).inPtr).dataStrPtr).commonStr.histPtr = {qty:data,$
                                                err:yerr,$
                                                x:x,$
                                                y:q}

  (*(*(*pState).inPtr).dataStrPtr).commonStr.instrument = 'HAL 9000'
  (*(*(*pState).inPtr).dataStrPtr).commonStr.xtype = 'POINTS'
  (*(*(*pState).inPtr).dataStrPtr).commonStr.ytype = 'POINTS'
  (*(*(*pState).inPtr).dataStrPtr).commonStr.xlabel = xlabel
  (*(*(*pState).inPtr).dataStrPtr).commonStr.ylabel = ylabel
  (*(*(*pState).inPtr).dataStrPtr).commonStr.histlabel = histlabel
  (*(*(*pState).inPtr).dataStrPtr).commonStr.xunits = xunits
  (*(*(*pState).inPtr).dataStrPtr).commonStr.yunits = yunits
  (*(*(*pState).inPtr).dataStrPtr).commonStr.histunits = histunits
  treatment = ['Test data set','Simulates methyl group tunneling']
  *(*(*(*pState).inPtr).dataStrPtr).commonStr.treatmentPtr = treatment

; now save the workspace and read
filename = 'balasub01.dave'
state = *(*pState).inPtr
davePtr = ptr_new(state,/no_copy)
save, davePtr, FILENAME = filename
ptr_free,davePtr
filename = file_which('balasub01.dave',/include_current_dir)
RMDPALoadDave,event,filename = filename
return
end
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
pro RMDPACreateTestRes,event
; This routine creates a fake resolution function data set for user to
; play with to learn how to use PAN.
widget_control,event.top,get_uvalue = pState
RMDPAClearCurves,event
RMDPAClearResFun,event
workDir = (*!dave_defaults).workDir
datDir = (*!dave_defaults).datDir

qlo = 0.25 & qhi = 2.4
nq = 20
r = 1.78	; (methyl radius in angstroms)
q = hfbs_makepoints(xlo = qlo,xhi = qhi,npts = nq)

npts = 100
xlo = -10.0 & xhi = 10.0
x = hfbs_makepoints(xlo = xlo,xhi = xhi,npts = npts)
area = 1400.0
elWid = 0.90
elCen = 0.0
bg = 10.0

y1 = fltarr(npts,nq)
data = fltarr(npts,nq)
for i = 0,nq-1 do begin
; Create an elastic peak with a couple of inelastic lines
	y1[*,i] = hfbs_gaussian(x,area = area,cen = elCen,wid = elWid)+bg
endfor
y = fltarr(npts,nq)

for j = 0,nq-1 do begin
  for i = 0,npts-1 do begin
    data[i,j] = randomn(s,1,poisson = y1[i,j])
  endfor
endfor
yerr = sqrt(data)
; Now stuff all of this into a DAVE structure
  hbar_omega = '!6!sh!r!e/!n !7x!6'
  xlabel = 'E '
  ylabel = 'Q'
  xunits = 'energy:ueV'
  yunits = 'wavevector:A-1'
  histlabel = 'I (arbitrary units)'
  histunits = ''

  *(*(*(*pState).inPtr).dataStrPtr).commonStr.histPtr = {qty:data,$
                                                err:yerr,$
                                                x:x,$
                                                y:q}

  (*(*(*pState).inPtr).dataStrPtr).commonStr.instrument = 'HAL 9000'
  (*(*(*pState).inPtr).dataStrPtr).commonStr.xtype = 'POINTS'
  (*(*(*pState).inPtr).dataStrPtr).commonStr.ytype = 'POINTS'
  (*(*(*pState).inPtr).dataStrPtr).commonStr.xlabel = xlabel
  (*(*(*pState).inPtr).dataStrPtr).commonStr.ylabel = ylabel
  (*(*(*pState).inPtr).dataStrPtr).commonStr.histlabel = histlabel
  (*(*(*pState).inPtr).dataStrPtr).commonStr.xunits = xunits
  (*(*(*pState).inPtr).dataStrPtr).commonStr.yunits = yunits
  (*(*(*pState).inPtr).dataStrPtr).commonStr.histunits = histunits
  treatment = ['Test data set','Simulates Resolution function']
  *(*(*(*pState).inPtr).dataStrPtr).commonStr.treatmentPtr = treatment

; now save the workspace and read
filename = 'chandraRes01.dave'
state = *(*pState).inPtr
davePtr = ptr_new(state,/no_copy)
save, davePtr, FILENAME = filename
ptr_free,davePtr
;filename = file_which('chandraRes01.dave',/include_current_dir)
;RMDPALoadDave,event,filename = filename
return
end
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
pro RMDPAStuffIt,event
widget_control,event.top,get_uvalue = pState
davePtr = (*pState).davePtr

state = *davePtr
;ptr_free,davePtr
workDir = (*!dave_defaults).workDir
datDir = (*!dave_defaults).datDir
*(*pState).inPtr = state

;;;;
; Pull out the relevant portions of the DAVE workspace here and
; make them fit in with the PAN program
instrument = (*state.dataStrPtr).commonStr.instrument
energy = (*(*(*(*pState).inPtr).dataStrPtr).commonStr.histPtr).x
xtype = (*(*(*pState).inPtr).dataStrPtr).commonStr.xtype
if strupcase(xtype[0]) eq 'HISTOGRAM' then begin
  nx = n_elements(energy)
  xaverage = fltarr(nx-1)
  xaverage = 0.5*(energy[1:nx-1]+energy[0:nx-2])
  energy = xaverage
endif


q = (*(*(*(*pState).inPtr).dataStrPtr).commonStr.histPtr).y
ytype = (*(*(*pState).inPtr).dataStrPtr).commonStr.ytype
if strupcase(ytype[0]) eq 'HISTOGRAM' then begin
  ny = n_elements(q)
  qaverage = fltarr(ny-1)
  qaverage = 0.5*(q[1:ny-1]+q[0:ny-2])
  q = qaverage
endif

data = (*(*(*(*pState).inPtr).dataStrPtr).commonStr.histPtr).qty
histLabel = (*(*(*pState).inPtr).dataStrPtr).commonStr.histLabel

dataSize = size(data)
if dataSize[0] ne 1 then begin
  if dataSize[1] lt n_elements(energy) then begin		; get bin centers
    nnchan = n_elements(energy)
    elo = dblarr(nnchan-1) & ehi = dblarr(nnchan-1)
    elo = energy[0:nnchan-2] & ehi = energy[1:nnchan-1]
    e = dblarr(nnchan-1) & e = 0.5*(ehi+elo)
    energy = dblarr(nnchan-1)
    energy = e
  endif
endif
error = (*(*(*(*pState).inPtr).dataStrPtr).commonStr.histPtr).err
treatment = *(*(*(*pState).inPtr).dataStrPtr).commonStr.treatmentPtr
*(*pState).headerPtr = treatment
xlabel = (*(*(*pState).inPtr).dataStrPtr).commonStr.xlabel
xunits = (*(*(*pState).inPtr).dataStrPtr).commonStr.xunits
yunits = (*(*(*pState).inPtr).dataStrPtr).commonStr.yunits
ylabel = (*(*(*pState).inPtr).dataStrPtr).commonStr.ylabel

xxunits = strtrim(strmid(xunits,strpos(xunits,':')+1))
yyunits = strtrim(strmid(yunits,strpos(yunits,':')+1))
xunits = hfbs_replaceSymbol(xxunits)
yunits = hfbs_replaceSymbol(yyunits)

xlabelDisp = xlabel+'('+xunits+')'
ylabelDisp = ylabel+'('+yunits+')'

(*pState).xlabel = xlabelDisp
(*pState).ylabel = ylabelDisp
(*pState).curTitle = ylabel
yvalues = (*(*(*(*pState).inPtr).dataStrPtr).commonStr.histPtr).y

*(*pState).groupValsPtr = yvalues
*(*pState).groupLabelsPtr = ylabelDisp
groupVals = *(*pState).groupValsPtr
groupLabels = *(*pState).groupLabelsPtr


; set slider maximum value to the number of groups (minimum is 1)
widget_control,(*pState).selGroup,$
   set_slider_max = n_elements(q),$
   set_slider_min = 1
addString = '1-'+strtrim(string(n_elements(q)),2)
widget_control,(*pState).addGroups,set_value = addString
qdet = q
(*pState).ngroups = n_elements(q)

; from original PAN HFBS read filter
instrument = (*(*(*pState).inPtr).dataStrPtr).commonStr.instrument
if dataSize[0] gt 1 then begin
  nchan = dataSize[1]
  ndet = dataSize[2]
  nlo = 0
;  if strupCase(instrument) eq 'HFBS' then nlo = 1 else nlo = 0
endif else begin
  nchan = dataSize[1]
  ndet = 1
  nlo = 0
  outData = dblarr(nchan,1)
  outData[*,0] = data[*]
  data = outData
  outError = dblarr(nchan,1)
  outError[*,0] = error[*]
  error = outError
endelse
*(*pState).bigDataStr.dataArrayPtr = data[0:nchan-1,nlo:ndet-1]
*(*pState).bigDataStr.errorArrayPtr = error[0:nchan-1,nlo:ndet-1]
*(*pState).bigDataStr.xPtr = energy[0:nchan-1]

*(*pState).origBigDataStr.xPtr = *(*pState).bigDataStr.xPtr
*(*pState).origBigDataStr.dataArrayPtr = *(*pState).bigDataStr.dataArrayPtr
*(*pState).origBigDataStr.errorArrayPtr = *(*pState).bigDataStr.errorArrayPtr

(*pState).xlo = min(energy)
(*pState).xhi = max(energy)
widget_control,(*pState).xfitlo,set_value = (*pState).xlo
widget_control,(*pState).xfithi,set_value = (*pState).xhi
if ndet gt 1 then strout = strarr(ndet-1) else strout = strarr(1)
hbar_omega = '!6!sh!r!e/!n !7x!6'

if ndet gt 1 then begin
  for i = 0,ndet-2 do begin
    strout[i] = '!6Q!DELASTIC!N='+strtrim(string(q[i],format = '(f4.2)'),2)+$
                ' !6!sA!r!u!9 %!6!n!E-1!N'
  endfor
endif
;if ndet gt 1 then groupVals = fltarr(ndet-1) else groupVals = fltarr(1)
;groupVals = qdet
;*(*pState).groupValsPtr = groupVals
;groupLabels = 'Q (!6!sA!r!u!9 %!6!n!E-1!N)'
;*(*pState).groupLabelsPtr = groupLabels
*(*pState).titlePtr = strout

;(*pState).xlabel = hbar_omega+' (!4l!6eV)'
;(*pState).ylabel = 'I(Q,'+hbar_omega+')'

; get the size of the data array in bigDataStr
dataArray = *(*pState).bigDataStr.dataArrayPtr
arraySize = size(dataArray)

if n_elements(fileId) eq 0 then fileId = 'txt'
fileId = strlowcase(fileId)

if arraySize[0] ne 1 then begin
  ngroups = arraySize[1]
  if not ptr_valid(groupValsPtr) then begin
    groupVals = intarr(ngroups)
    groupVals = 1+indgen(ngroups)
  endif else begin
    groupVals = *groupValsPtr
  endelse
  if not ptr_valid(groupLabelsPtr) then begin
    groupLabels = 'Group'
  endif else begin
    groupLabels = *groupLabelsPtr
  endelse

  npts = arraySize[1]
  data = dblarr(3,npts)
  widget_control,(*pState).selGroup,get_value = groupNum
  groupNum = fix(groupNum[0]) - 1
  data[0,*] = *(*pState).bigDataStr.xPtr
  data[1,*] = (*(*pState).bigDataStr.dataArrayPtr)[*,groupNum]
  data[2,*] = (*(*pState).bigDataStr.errorArrayPtr)[*,groupNum]
  *(*pState).origDataPtr = data
  *(*pState).titlePtr = replicate('',ngroups)
endif else begin
  ngroups = 1
  if n_elements(groupVals) eq 0 then begin
    groupVals = 1
    groupLabel = 'Group'
  endif
  ;data = *dataPtr
  datsize = size(data) & npts = datsize[1]
  newdata = dblarr(3,npts)
  newdata[0,*] = energy[*]
  newdata[1,*] = data[*,0]
  newdata[2,*] = error[*,0]
  data = newdata
  *(*pState).origDataPtr = data
  *(*pState).titlePtr = ''
endelse

x = dblarr(npts) & y = dblarr(npts) & yerr = dblarr(npts)
x[0:npts-1] = data[0,0:npts-1] & y[0:npts-1] = data[1,0:npts-1]

xdiff = dblarr(npts,npts)
for j = 0,npts-1 do begin
  for i = 0,npts-1 do begin
    xdiff[i,j] = x[i]-x[j]
  endfor
endfor

yerr[0:npts-1] = data[2,0:npts-1]
xlo = min(x) & xhi = max(x)
delta = max(y)-min(y)
ylo = min(y)-0.2*delta & yhi = 1.2*max(y)
if ylo gt 0.0 then ylo = 0.0
*(*pState).dataPtr = data

;parmStr = parmStructDefine()
*(*pState).parmStr.indlimPtr = indgen(n_elements(x))
parmStr = (*pState).parmStr
ngroups = n_elements(q)
;;    11/14/01
; Since we have loaded in a new DAVE data structure then
; we should free up pre-existing parameter information.
; Then begin by allocating memory for a new pointer array
; of the same name.  We use Copley's dave_beast_ops routine
; with the duplicate keyword to ensure that the parameter info
; is different for each group.  No more pointer duplication should
; be required.
widget_control,(*pState).textFit,get_uvalue = bigParmPtr,/no_copy
ptr_free,bigParmPtr
z = ptr_valid(count = n) & print,'Number of pointers before: ',n
bigParmPtr = ptrarr(ngroups,/allocate_heap)
for i = 0,ngroups-1 do begin
  dave_beast_ops,"duplicate",parmStr,outStr,show_commands = 0,show_analysis = 0
  *bigParmPtr[i] = outStr
endfor

(*pState).parmStr = parmStr

widget_control,(*pState).textFit,set_uvalue = bigParmPtr,/no_copy
(*pState).autoscale = 1


RMDPAAutoScale,event
widget_control,event.top,get_uvalue = pState

; When we read in a DAVE file we are also reading in the working
; directory and data directory of the system on which it was created.
; If different from the machine user is currently using then we must
; catch this error and have user select an appropriate directory.
;
;yout = hfbs_dirValid((*(*pState).inPtr).datDir)
;if yout eq 0 then begin
;  strout = ['Data directory is invalid on this system','Please select another']
;  void = dialog_message(dialog_parent = event.top,strout,/error)
;  directory = DIALOG_PICKFILE(title = 'Select data directory',/directory)
;  (*(*pState).inPtr).datDir = directory
;endif

;yout = hfbs_dirValid((*(*pState).inPtr).workDir)
;if yout eq 0 then begin
;  strout = ['Working directory is invalid on this system','Please select another']
;  void = dialog_message(dialog_parent = event.top,strout,/error)
;  directory = DIALOG_PICKFILE(title = 'Select data directory',/directory)
;  (*(*pState).inPtr).workDir = directory
;endif

; Scale the Kohlrausch table appropriately
  xmax = max(x)
  xmin = min(x)
  bigx = max([abs(xmax),abs(xmin)]) ; the maximum value in the dynamic range

  ktable = *(*pState).ktablePtr
  ksize = size(ktable)
  npts = ksize[1]-1
  nb = ksize[2]-1
  nt = ksize[3]-1
  ytab = dblarr(npts,nb,nt)
  xtab = dblarr(npts)
  btab = dblarr(nb)
  ttab = dblarr(nt)
  ytab[0:npts-1,0:nb-1,0:nt-1] = ktable[0:npts-1,0:nb-1,0:nt-1]
  xtab[0:npts-1] = ktable[0:npts-1,nb,nt]
  btab[0:nb-1] = ktable[npts,0:nb-1,nt]
  ttab[0:nt-1] = ktable[npts,nb,0:nt-1]

  xtabmax = max([abs(min(xtab)),abs(max(xtab))])
  ; calculate the scaling factor
  lambda = xtabmax/bigx  ; scaling factor
  ; scale the tabulated values
  xtab[0:npts-1] = (xtab[0:npts-1]/lambda)
  ytab[0:npts-1,0:nb-1,0:nt-1] = lambda*ktable[0:npts-1,0:nb-1,0:nt-1]
  ttab[0:nt-1] = lambda*ktable[npts,nb,0:nt-1]
  *(*pState).xtabPtr = xtab
  *(*pState).btabPtr = btab
  *(*pState).ttabPtr = ttab
  *(*pState).ytabPtr = ytab

return
end
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
pro RMDPALoadDave,event,filename = filename
; Restore a DAVE file here
widget_control,event.top,get_uvalue = pState
thisPath = (*!dave_defaults).workDir
if n_elements(filename) eq 0 then begin
  filename = DIALOG_PICKFILE(dialog_parent = event.top,$
                                              title = 'Select data file to restore',$
                                              /read,filter = '*.dave',$
                                              path = thisPath)
  if filename eq '' then begin

    return
  endif
endif

restore,filename
(*pState).davePtr = davePtr

RMDPAStuffIt,event

return
end
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
pro RMDPALoadDaveResFun,event
; Restore a DAVE file here
widget_control,event.top,get_uvalue = pState
if n_elements(*(*pState).dataPtr) eq 0 then begin

  void = dialog_message(dialog_parent = event.top,'Load data file first!')
  return
endif
thisPath = (*!dave_defaults).workDir;(*(*pState).inPtr).workDir
filename = DIALOG_PICKFILE(dialog_parent = event.top,$
                                              title = 'Select resolution data file to restore',$
                                              /read,filter = '*.dave',$
                                              path = thisPath)
if filename eq '' then begin

  return
endif
restore,filename
state = *davePtr
ptr_free,davePtr

;;;;
; Pull out the relevant portions of the DAVE workspace here and
; make them fit in with the PAN program
energy = (*(*state.dataStrPtr).commonStr.histPtr).x
q = (*(*state.dataStrPtr).commonStr.histPtr).y
data = (*(*state.dataStrPtr).commonStr.histPtr).qty
error = (*(*state.dataStrPtr).commonStr.histPtr).err

xtype = (*(*(*pState).inPtr).dataStrPtr).commonStr.xtype
if strupcase(xtype[0]) eq 'HISTOGRAM' then begin
  nx = n_elements(energy)
  xaverage = fltarr(nx-1)
  xaverage = 0.5*(energy[1:nx-1]+energy[0:nx-2])
  energy = xaverage
endif

q = (*(*(*(*pState).inPtr).dataStrPtr).commonStr.histPtr).y
ytype = (*(*(*pState).inPtr).dataStrPtr).commonStr.ytype
if strupcase(ytype[0]) eq 'HISTOGRAM' then begin
  ny = n_elements(q)
  qaverage = fltarr(ny-1)
  qaverage = 0.5*(q[1:ny-1]+q[0:ny-2])
  q = qaverage
endif


strout = ["Select absolute energy limit (|E|) for resolution function",$
              "so that it's symmetric about 0"]
void = dialog_message(dialog_parent = event.top,strout,/information)
limresult = informationpanel(group_leader = event.top,title = 'Resolution function limit',$
                high = 0.5*max(energy))

(*pState).parmStr.resLimit = limresult.high
wherevalid = where((energy le limresult.high) and (energy ge (-1.0*limresult.high)),newchan)

; from original PAN HFBS read filter
dataSize = size(data)
if dataSize[0] gt 1 then begin
  nchan = dataSize[1]
  ndet = dataSize[2]
endif else begin
  nchan = dataSize[1]
  ndet = 1
endelse

nlo = 0
data = data[0:nchan-1,nlo:ndet-1]
error = error[0:nchan-1,nlo:ndet-1]

x = *(*pState).parmStr.xPtr
nx = n_elements(x)

; nchan	: number of channels in resolution function
; nx	: number of channels in data
; Here we must have nx >= nchan

intData = dblarr(nx,ndet)	; *
intErr = dblarr(nx,ndet)	; *

outData = dblarr(3,nx,ndet)
for i = 0,ndet-1 do begin
  outData[0,0:nx-1,i] = x[0:nx-1]
  outData[1,0:nx-1,i] = interpol(data[0:nchan-1,i],energy[*],x,/spline)
  outData[2,0:nx-1,i] = interpol(error[0:nchan-1,i],energy[*],x,/spline)
  intData[0:nx-1,i] = reform(outData[1,0:nx-1,i]);interpol(data[0:nchan-1,i],energy[*],x)	; *
  intErr[0:nx-1,i] = reform(outData[2,0:nx-1,i]);interpol(error[0:nchan-1,i],energy[*],x)	; *
endfor

*(*pState).origBigDataStr.resArrayPtr = intData	; *
*(*pState).origBigDataStr.resErrorArrayPtr = intErr	; *
*(*pState).bigDataStr.resArrayPtr = intData	; *
*(*pState).bigDataStr.resErrorArrayPtr = intErr	; *

*(*pState).bigResDataPtr = outData


sensitizeWidgets,event
widget_control,event.top,get_uvalue = pState

widget_control,(*pState).resLabel,set_value = 'Res function'
widget_control,(*pState).selGroup,get_value = group
group = fix(group[0])-1

resData = dblarr(3,nx)
resData[0,0:nx-1] = outData[0,0:nx-1,group]
resData[1,0:nx-1] = outData[1,0:nx-1,group]
resData[2,0:nx-1] = outData[2,0:nx-1,group]


wherevalid = where((x le limresult.high) and (x ge (-1.0*limresult.high)),mpts)
xres = dblarr(mpts)
xres = reform(resData[0,wherevalid])

;; loop method for computing xdiff
;xdiff = fltarr(mpts,nx)
;xres = reform(xres)
;for i = 0,mpts-1 do begin
;  xdiff[i,0:nx-1] = (shift(xres,mpts))[i]-x[*]
;endfor
;;
;; vectorized method for computing xdiff (04/10/02-RMD)
nx1 = nx
nx2 = mpts
xdiff = fltarr(nx1,nx2)
u1 = 1+bytarr(nx1)
u2 = 1+bytarr(nx2)
xdiff = transpose(u1#x[wherevalid]-x#u2)
;;


*(*pState).parmStr.xdiffPtr = xdiff
*(*pState).parmStr.resDataPtr = resData

RMDCalcDisplay,event
widget_control,event.top,get_uvalue = pState

RMDPlotDisplay,event
widget_control,event.top,get_uvalue = pState


return
end
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
pro RMDPASaveResFun,event
; This routine saves the current fits (all detectors) as the resolution
; function.  The function (with any offset subtracted here) is evaluated and saved
; using the current energy spacing.
;
widget_control,event.top,get_uvalue = pState
;void = dialog_message(dialog_parent = event.top,'This feature not working yet',/information)
;return

; First get the size of the data
if n_elements(*(*pState).bigDataStr.dataArrayPtr) lt 2 then return
if n_elements(*(*pState).ytotPtr) lt 2 then return

data = *(*pState).bigDataStr.dataArrayPtr
datSize = size(data)
if datSize[0] eq 2 then begin
  nchan = datSize[1]
  ndet = datSize[2]
endif else begin
  nchan = datSize[1]
  return
endelse


widget_control,(*pState).addGroups,get_value = groupString
indexPtr = RMDPAChooseDets(groupString)
index = *indexPtr
nchoices = n_elements(index)
RMDPAChangeGroups,event
yout = *(*pState).ytotPtr	; the overall fit
x = reform((*(*pState).dataPtr)[0,*])
qty = fltarr(nchan,ndet)
err = fltarr(nchan,ndet)


if nchoices gt 1 then begin
  for i = 0,nchoices-1 do begin
    widget_control,(*pState).selGroup,set_value = index[i]
    RMDPAChangeGroups,event
    qty[*,index[i]-1] = *(*pState).ytotPtr
    x = reform((*(*pState).dataPtr)[0,*])
  endfor
endif

; Now put this information into a DAVE structure and ask the user
; to determine a name for the file
thisPath = (*!dave_defaults).workDir
filename = DIALOG_PICKFILE(dialog_parent = event.top,$
                                              title = 'Select name of the resolution function file',$
                                              /write,filter = '*.dave',$
                                              path = thisPath)
if (filename eq '') or (filename eq ' ') then return
filename = filename+'.dave'
; Ok, now stuff this into the DAVE structure
(*(*(*(*pState).inPtr).dataStrPtr).commonStr.histPtr).qty = qty
(*(*(*(*pState).inPtr).dataStrPtr).commonStr.histPtr).err = err
(*(*(*(*pState).inPtr).dataStrPtr).commonStr.histPtr).x = x
state = *(*pState).inPtr
davePtr = ptr_new(state,/no_copy)
save,davePtr,filename = filename
ptr_free,davePtr
;(*pState).plotParmTest = 1
return
end
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
pro RMDPAHelp,event
widget_control,event.top,get_uvalue = pState
pdf_file = file_which('pandoc.pdf',/include_current_dir)
void = launch_help(pdf_file,tlb = event.top)
return
end
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
pro PAN_event,event
widget_control,event.top,get_uvalue = pState
if n_elements(*(*pState).dataPtr) eq 0 then begin

  return
endif
if event.id eq (*pState).addgroups then begin
  (*pState).curTitle = '!6Group Sum'

  RMDPAAddGroups,event
  widget_control,event.top,get_uvalue = pState
endif
if event.id eq (*pState).xfitlo or event.id eq (*pState).xfithi then begin

  RMDCalcDisplay,event
  RMDPlotDisplay,event
  widget_control,event.top,get_uvalue = pState
endif

if event.id eq (*pState).drop then begin
 index = event.value-1
 case index of
 0: begin

   deSensitizeWidgets,event
   widget_control,event.top,get_uvalue = pState

   RMDPAAddDeltaFun,event
   widget_control,event.top,get_uvalue = pState
   widget_control,(*pState).textfit,set_value = $
                ['Hold down mouse button and drag',$
                 'function centroid to desired location.','',$
                 'Release button when finished.']
   end
 1: begin

   deSensitizeWidgets,event
   widget_control,event.top,get_uvalue = pState

   RMDPAAddGaussianFun,event
   widget_control,event.top,get_uvalue = pState
   widget_control,(*pState).textfit,set_value = $
                ['Hold down mouse button and drag',$
                 'function centroid to desired location.','',$
                 'Release button when finished.']
   end
 2: begin

   deSensitizeWidgets,event
   widget_control,event.top,get_uvalue = pState

   RMDPAAddLorentzianFun,event
   widget_control,event.top,get_uvalue = pState
   widget_control,(*pState).textfit,set_value = $
                ['Hold down mouse button and drag',$
                 'function centroid to desired location.','',$
                 'Release button when finished.']
   end
 3: begin

   deSensitizeWidgets,event
   widget_control,event.top,get_uvalue = pState

   RMDPAAddLNFun,event
   widget_control,event.top,get_uvalue = pState
   widget_control,(*pState).textfit,set_value = $
                ['Hold down mouse button and drag',$
                 'function centroid to desired location.','',$
                 'Release button when finished.']
   end
 4: begin

   deSensitizeWidgets,event
   widget_control,event.top,get_uvalue = pState

   RMDPAAddVoigtFun,event
   widget_control,event.top,get_uvalue = pState
   widget_control,(*pState).textfit,set_value = $
                ['Hold down mouse button and drag',$
                 'function centroid to desired location.','',$
                 'Release button when finished.']
   end
 5: begin

   deSensitizeWidgets,event
   widget_control,event.top,get_uvalue = pState

   RMDPAAddDHOFun,event
   widget_control,event.top,get_uvalue = pState
   widget_control,(*pState).textfit,set_value = $
                ['Hold down mouse button and drag',$
                 'function centroid to desired location.','',$
                 'Release button when finished.']
   end
 6: begin

   deSensitizeWidgets,event
   widget_control,event.top,get_uvalue = pState

   RMDPAAddSmoothStepFun,event
   widget_control,event.top,get_uvalue = pState
   widget_control,(*pState).textfit,set_value = $
                ['Hold down mouse button and drag',$
                 'function centroid to desired location.','',$
                 'Release button when finished.']
   end
 7: begin

   deSensitizeWidgets,event
   widget_control,event.top,get_uvalue = pState

   RMDPAAddBgFun,event
   widget_control,event.top,get_uvalue = pState
   widget_control,(*pState).textfit,set_value = $
                ['Hold down mouse button and drag',$
                 'function centroid to desired location.','',$
                 'Release button when finished.']
   end
 8: begin

   deSensitizeWidgets,event
   widget_control,event.top,get_uvalue = pState

   RMDPAAddTunnelEISFFun,event
   widget_control,event.top,get_uvalue = pState
   widget_control,(*pState).textfit,set_value = $
                ['Hold down mouse button and drag',$
                 'function centroid to desired location.','',$
                 'Release button when finished.']
   end
 9: begin

   deSensitizeWidgets,event
   widget_control,event.top,get_uvalue = pState

   RMDPAAdd3SiteEISFFun,event
   widget_control,event.top,get_uvalue = pState
   widget_control,(*pState).textfit,set_value = $
                ['Hold down mouse button and drag',$
                 'function centroid to desired location.','',$
                 'Release button when finished.']
   end
 10: begin

   deSensitizeWidgets,event
   widget_control,event.top,get_uvalue = pState

   RMDPAAdd2SiteEISFFun,event
   widget_control,event.top,get_uvalue = pState
   widget_control,(*pState).textfit,set_value = $
                ['Hold down mouse button and drag',$
                 'function centroid to desired location.','',$
                 'Release button when finished.']
   end
 11: begin

   deSensitizeWidgets,event
   widget_control,event.top,get_uvalue = pState

   RMDPAAddKohlFun,event
   widget_control,event.top,get_uvalue = pState
   widget_control,(*pState).textfit,set_value = $
                ['Hold down mouse button and set',$
                 'the peak height.','',$
                 'Release button when finished.']
   end
 else:
 endcase
endif




return
end
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
pro PAN,notifyIDs,inPtr,group_leader = group_leader
; First get the original color tables upon entering PAN
tvlct,rorig,gorig,borig,/get
z = ptr_valid(count = n)
!except = 0
;;;;;;;;;;;
daveptr = inPtr
;;;;;;;;;;
state = *davePtr
dataStr = *state.dataStrPtr
commonStr = dataStr.commonStr
histPtr = commonStr.histPtr

file_path = (*!dave_defaults).workDir

tlb = widget_base(/row,title = 'Peak Fitting',mbar = bar,$
                            group_leader = group_leader,$
                            tlb_frame_attr = 1)
filemenu = widget_button(bar, VALUE='File', /MENU)
plotmenu = widget_button(bar,value = 'Plot',/menu)
resmenu = widget_button(bar, VALUE='Resolution', /MENU)
rebinmenu = widget_button(bar, VALUE='Rebin', /MENU)
printmenu = widget_button(bar,value = 'Print',/menu)
miscmenu = widget_button(bar, VALUE='Misc', /MENU)
void = widget_button(printmenu,value = 'Print display',$
                     event_pro = 'RMDPAPrintDisplay')

void = widget_button(plotmenu,value = 'Enter axis titles',$
                                event_pro = 'RMDPAEnterAxisTitles')
void = widget_button(filemenu,value = 'Load Dave',$
                                event_pro = 'RMDPALoadDave')
void = widget_button(filemenu,value = 'Save Data and Fits',$
                               event_pro = 'RMDPASaveFits')
void = widget_button(filemenu,value = 'Save Fit Parameters',$
                                event_pro = 'RMDPASaveFitParms')
void = widget_button(filemenu,value = 'Read Fit Parameters',$
                                event_pro = 'RMDPAReadFitParms')
void = widget_button(filemenu,value = 'Save Fit Parameters As Text',$
                                event_pro = 'RMDPASaveFitParmsAsText')
void = widget_button(filemenu,value = 'Display Data Information',$
								event_pro = 'hfbs_DisplayTreatment')
void = widget_button(filemenu,value = 'Load Test Data',$
                                event_pro = 'RMDPALoadTest')
void = widget_button(filemenu,value = 'Load Test Resolution Data',$
                                event_pro = 'RMDPACreateTestRes')
thisSensitivity = 1
void = widget_button(miscmenu,value = 'Enter curve and parameter to plot',$
                       event_pro = 'RMDPAEnterCP',sensitive = thisSensitivity)
void = widget_button(miscmenu,value = 'Plot EISF',$
                       event_pro = 'RMDPAPlotEISF',sensitive = thisSensitivity)
void = widget_button(miscmenu,value = 'Help',$
                       event_pro = 'RMDPAHelp',sensitive = 1)
void = widget_button(miscmenu,value = 'About Peak Analysis',$
                                event_pro = 'AboutPeakAnalysis')

butsize = 150
butbase = widget_base(tlb,/col,/base_align_center)
plotbase = widget_base(tlb,/col,/base_align_center)
textBase = widget_base(tlb,/col,/base_align_center)

void = widget_button(rebinmenu,value = 'Rebin data',$
       event_pro = 'RMDPARebinData',xsize = butsize)
void = widget_button(rebinmenu,value = 'Original binning',$
       event_pro = 'RMDPAOrigBin',xsize = butsize)

ngroups = 1
if ngroups gt 1 then begin
  selGroup = widget_slider(butbase,title='Select Group',$
                           value = 1,maximum = 100,$
                           event_pro = 'RMDPAChangeGroups',$
                           minimum = 1)
  addGroups = cw_field(butbase,title='Select Groups',value='5-14',$
                       xsize=8,/string,/return_events)
endif else begin
  selGroup = widget_slider(butbase,title='Select Group',$
                           value = 1,maximum = 100,event_pro = 'RMDPAChangeGroups')
  addGroups = cw_field(butbase,title='Select Groups',value='5-14',$
                       xsize=8,/string,/return_events)
endelse


void = widget_label(butbase,value = '')
curvebase1 = widget_base(butbase,/col,/base_align_center,/frame)

curveNames = ['Select fit function','pseudo delta function',$
  			  'Gaussian', 'Lorentzian',$
              'Lognormal', 'Voigt',$
              'Damped Harmonic Oscillator',$
              'Smooth Step Function',$
              'Sloping Background',$
              'Methyl tunnel EISF',$
              '3-site jump EISF',$
              '2-site jump EISF',$
              'Kohlrausch function',$
              'Cancel']

desc = replicate({ flags:0, name:'' }, 14)
desc.flags = [1,0*indgen(13)]
desc.name = curveNames
drop = hfbs_pdmenu(curvebase1,desc,/return_index,xsize = butsize)
;void = widget_label(curvebase1,value = 'Select Fit Function')
;drop = widget_droplist(curvebase1, VALUE=curveNames,xsize = butsize,$
;       event_pro = 'RMDPAAddCurve')

removeButton = widget_button(curvebase1,value = 'Remove Fit Function',$
                       event_pro = 'RMDPARemoveCurve',xsize = butsize)
clearButton = widget_button(curvebase1,value = 'Clear Fit',$
                     event_pro = 'RMDPAClearCurves',xsize = butsize)
loadResButton = widget_button(resmenu,value = 'Load Res Function',$
						event_pro = 'RMDPALoadDaveResFun',xsize = butsize)
clearResButton = widget_button(resmenu,value = 'Clear Res Function',$
                          event_pro = 'RMDPAClearResFun',xsize = butsize)

; This next button is a "work-in-progress"
void = widget_button(resmenu,value = 'Save Fits as Res Function',$
                          event_pro = 'RMDPASaveResFun',xsize = butsize);,sensitive = 0)

void = widget_label(butbase,value = '')
xfitlo  = cw_field(butbase,title='Lower fit bound',value=xlo,$
             xsize=8,/string,/return_events)
xfithi  = cw_field(butbase,title='Upper fit bound',value=xhi,$
             xsize=8,/string,/return_events)
fitButton = widget_button(butbase,value = 'Fit Current Group',$
             event_pro = 'RMDPAFitData',xsize = butsize)
if ngroups gt 1 then sensitivity = 1 else sensitivity = 0

  autoFitButton = widget_button(butbase,value = 'Fit All Selected Groups',$
                    event_pro = 'RMDPAAutoFitAllData',xsize = butsize,$
                    sensitive = sensitivity)

modParms = widget_button(butbase,value = 'Modify Fit Parameters',$
                 xsize = butsize,event_pro = 'RMDPAFixParms')
pickCurve = widget_slider(butbase,title='Select curve',value = 0,maximum = 1)

displayButton = widget_button(butBase,value = 'Display Fits',$
                       event_pro = 'RMDPADisplayFitParms',xsize = butsize)
doneButton = widget_button(filemenu,value = 'Exit',$
                    event_pro = 'donePeakAnalysis',xsize = butsize)


winxsize = 450 & winysize = 350 & winysize2 = 200
win1 = widget_draw(plotBase,xsize = winxsize,ysize = winysize,$
       /button_events,event_pro = 'RMDPAWinDraw',/motion_events)

win2 = widget_draw(plotBase,xsize = winxsize,ysize = winysize2)

textFit = widget_text(textBase,value = '',/scroll,ysize = 20,xsize = 30)
resLabel = widget_label(textbase,value = 'No res function')
; Center the base on the screen
centertlb,tlb
widget_control,tlb,/realize
device,decomposed = 0
colors = hfbs_GetColor(/Load, Start=1)
; Load the tabulated values of the Kohlrausch-Williams-Watts function
; here and put it in the pointer called ktablePtr.
widget_control,textFit,set_value = 'Loading in lookup tables...'
widget_control,tlb,sensitive = 0

pan_readKTable,ktablePtr
widget_control,tlb,sensitive = 1
widget_control,textFit,set_value = 'Lookup tables successfully loaded'

if ptr_valid(ktablePtr) then begin
  noTable = 0
endif else begin
  ktablePtr = ptr_new()
  noTable = 1
endelse

window,/free,/pixmap,xsize = winxsize,ysize = winysize
winPixId = !d.window
widget_control,win1,get_value = gausswinval1

window,/free,/pixmap,xsize = winxsize,ysize = winysize2
winPixId2 = !d.window
widget_control,win2,get_value = gausswinval2
outPtr = ptr_new(/allocate_heap)
widget_control,textFit,set_uvalue = outPtr

yerrlabel = '!6(y-y!dfit!6!n)/!4r!6'

if ptr_valid(titlePtr) then begin
  curTitle = (*titlePtr)[0]
endif else begin
  curTitle = ''
endelse

parmStr = parmStructDefine()
dave_beast_ops,"get_ptrs",parmStr,show_commands=0,show_analysis=0,bpointers=bptrs


bigDataStr = {xPtr:ptr_new(/allocate_heap),$
                     dataArrayPtr:ptr_new(/allocate_heap),$
                     errorArrayPtr:ptr_new(/allocate_heap),$
                     xresPtr:ptr_new(/allocate_heap),$
                     resArrayPtr:ptr_new(/allocate_heap),$
                     resErrorArrayPtr:ptr_new(/allocate_heap)}

origBigDataStr = {xPtr:ptr_new(/allocate_heap),$
                           dataArrayPtr:ptr_new(/allocate_heap),$
                           errorArrayPtr:ptr_new(/allocate_heap),$
                           xresPtr:ptr_new(/allocate_heap),$
                           resArrayPtr:ptr_new(/allocate_heap),$
                           resErrorArrayPtr:ptr_new(/allocate_heap)}

state = {drop:drop,$
		 davePtr:davePtr,$
         gausswinval1:gausswinval1,$
         plotParmTest:0,$
         headerPtr:ptr_new(/allocate_heap),$
         fileName:'',$
         hbar:0.6528,$		; hbar in ueV*ns or meV*pS
         noTable:noTable,$
         xtabPtr:ptr_new(/allocate_heap),$
         ytabPtr:ptr_new(/allocate_heap),$
         btabPtr:ptr_new(/allocate_heap),$
         ttabPtr:ptr_new(/allocate_heap),$
         fileId:0,$;fileId,$
		 fit:0,$
         resLabel:resLabel,$
         plotParmDataPtr:ptr_new(/allocate_heap),$
         parmLabel:'',$
         plotParm:0.0,$
         plotParmErr:0.0,$
         curveNum:0,$
         parmNum:0,$
         groupValsPtr:ptr_new(/allocate_heap),$;groupVals),$
         groupLabelsPtr:ptr_new(/allocate_heap),$;groupLabels),$
         psStringPtr:ptr_new(/allocate_heap),$
         autoFit:0,$
         printing:0,$
         bigDataStr:bigDataStr,$
         bigResDataPtr:ptr_new(/allocate_heap),$
         origBigDataStr:origBigDataStr,$
         autoFitButton:autoFitButton,$
         titlePtr:ptr_new(/allocate_heap),$
         curTitle:curTitle,$
         ngroups:ngroups,$
         selGroup:selGroup,$
         addGroups:addGroups,$
         fitButton:fitButton,$
         removeButton:removeButton,$
         clearButton:clearButton,$
         loadResButton:loadResButton,$
         clearResButton:clearResButton,$
         displayButton:displayButton,$
         modParms:modParms,$
         miscmenu:miscmenu,$
         filemenu:filemenu,$
         plotmenu:plotmenu,$
         resmenu:resmenu,$
         printmenu:printmenu,$
         rebinmenu:rebinmenu,$
         doneButton:doneButton,$
         file_path:file_path,$
         pickCurve:pickCurve,$
         platform:0,$
         winPixId:winPixId,$
         dataPtr:ptr_new(/allocate_heap),$
         winxsize:winxsize,$
         winysize:winysize,$
         parmStr:parmStr,$
         modCurve:0,$
         addCurve:0,$
         addGauss:0,$
         addLor:0,$
         addBg:0,$
         curveType:0,$
         currentParmPtr:ptr_new(/allocate_heap),$
         currentCurvePtr:ptr_new(/allocate_heap),$
         xyact:[0.0,0.0,0.0],$
         xinit:0,$
         xfinal:0,$
         yinit:0,$
         yfinal:0,$
         mouse:0,$
         colors:colors,$
         ngauss:0,$
         gaussParmPtr:ptr_new(/allocate_heap),$
         oldParms:dblarr(3),$
         modGauss:0,$
         yfitPtr:ptr_new(/allocate_heap),$
         gaussChange:0,$
         xlo:0.0,$
         xhi:1.0,$
         ylo:0.0,$
         yhi:1.0,$
         autoscale:1,$
         zoom:1,$
         xp1:0,$
         yp1:0,$
         xp2:0,$
         yp2:0,$
         gausswinval2:gausswinval2,$
         winysize2:winysize2,$
         yerrlabel:yerrlabel,$
         xlabel:'',$
         ylabel:'',$
         ytotPtr:ptr_new(/allocate_heap),$
         ygaussPtr:ptr_new(/allocate_heap),$
         winPixId2:winPixId2,$
         gaussfunPtr:ptr_new(/allocate_heap),$
         outPtr:ptr_new(/allocate_heap),$
         parmPtr:ptr_new(/allocate_heap),$
         writeOutPtr:ptr_new(/allocate_heap),$
         xfitlo:xfitlo,$
         xfithi:xfithi,$
         fixPtr:ptr_new(/allocate_heap),$
         parmerrPtr:ptr_new(/allocate_heap),$
         origDataPtr:ptr_new(/allocate_heap),$
         textFit:textFit,$
         ktablePtr:ktablePtr,$
         ElasticPtr:ptr_new(1.0),$
         Inelastic_1Ptr:ptr_new(0.5),$
         tieParmP1:0,$
         tieParmP2:0,$
         tieParmC1:0,$
         tieParmC2:0,$
         tieParmConst:0.0,$
         tieParmMult:1.0,$
         Inelastic_2Ptr:ptr_new(0.2),$
         rorig:rorig,$
         borig:borig,$
         gorig:gorig,$
         writeParmsAsText:0,$
         inPtr:inPtr,$
         notifyIDs:notifyIDs}
pState = ptr_new(state,/no_copy)
widget_control,tlb,set_uvalue = pState
if n_elements(*histPtr) gt 0 then begin
	RMDPAStuffIt,{event,id:void,top:tlb,handler:0l}
endif
xmanager,'PAN',tlb,cleanup = 'PANCleanup'
return
end
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
