; $Id: func__define.pro,v 1.17.2.1 2008/06/30 23:28:39 kneller Exp $
;###############################################################################
;
; NAME:
;  FUNC__DEFINE
;
; PURPOSE:
;  Class definition for a fit function component in PAN.
;
; CATEGORY:
;  DAVE, Data Analysis, PAN, curve fitting
;
; AUTHOR:
;   Robert M. Dimeo, Ph.D.
;   NIST Center for Neutron Research
;   100 Bureau Driveq
;   Gaithersburg, MD 20899
;   Phone: (301) 975-8135
;   E-mail: robert.dimeo@nist.gov
;   http://www.ncnr.nist.gov/staff/dimeo
;
; LICENSE:
;  The software in this file is written by an employee of
;  National Institute of Standards and Technology
;  as part of the DAVE software project.
;
;  The DAVE software package is not subject to copyright protection
;  and is in the public domain. It should be considered as an
;  experimental neutron scattering data reduction, visualization, and
;  analysis system. As such, the authors assume no responsibility
;  whatsoever for its use, and make no guarantees, expressed or
;  implied, about its quality, reliability, or any other
;  characteristic. The use of certain trade names or commercial
;  products does not imply any endorsement of a particular product,
;  nor does it imply that the named product is necessarily the best
;  product for the stated purpose. We would appreciate acknowledgment
;  if the DAVE software is used of if the code in this file is
;  included in another product.
;
;###############################################################################
;+
; NAME:
;       FUNC__DEFINE
;
; PURPOSE:
;
;       Object class for a set of functions used in OPAN__DEFINE.PRO.
;
;
; AUTHOR:
;
;       Robert M. Dimeo, Ph.D.
;		NIST Center for Neutron Research
;       100 Bureau Drive
;		Gaithersburg, MD 20899
;       Phone: (301) 975-8135
;       E-mail: robert.dimeo@nist.gov
;       http://www.ncnr.nist.gov/staff/dimeo
;
; CATEGORY:
;
;       Objects, data analysis, curve fitting
;
; CALLING SEQUENCE:
;
;       object = obj_new('FUNC')
;
;
; INPUT PARAMETERS:
;
;       NONE
;
; INPUT KEYWORDS:
;
;       name (required).
;
; REQUIRED PROGRAMS:
;
;        NONE
;
; COMMON BLOCKS:
;
;       NONE
;
; RESTRICTIONS
;
;       NONE
;
; OBJECT METHODS:
;	init -- usual lifecycle method
;	cleanup -- usual lifecycle method
;   changefirst -- user changes "amplitude" and "mode" of function
;	changesecond -- user changes "width" of function
;   draw
;   setproperty
;   getproperty
;	getDrawMessage
;
; MODIFICATION HISTORY:
;
;       Written by Rob Dimeo, September 17, 2002.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
pro func::cleanup
ptr_free,self.extra
ptr_free,self.xPtr
;ptr_free,self.qPtr
ptr_free,self.yPtr
ptr_free,self.stepPtr
ptr_free,self.ymaxPtr,self.xmodePtr
ptr_free,self.lowPtr,self.lowvalPtr
ptr_free,self.highPtr,self.highvalPtr
ptr_free,self.fixPtr,self.fixedvalPtr
ptr_free,self.parmErrorPtr
ptr_free,self.tiedPtr
ptr_free,self.parmPtr,self.resPtr
end;func::cleanup
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
function func::getDrawMessage
y = call_function(self.name,*self.xPtr,*self.parmPtr, $
    expr = self.expr, $
    extra = *self.extra,drawMessage = drawMessage, $
    fit_fun_filename = self.fit_fun_filename)
return,drawMessage
end;func::getDrawMessage
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
pro func::changefirst,x,y,xrange
; This calculates new yvalues based on a first mouse click
self->getproperty,parms = parms
case self.name of
'ft_KWW':
'pan_meanfieldorderparameter': begin
                  *self.ymaxPtr = y
                  parms[0] = x
                  parms[3] = y
                  parms[4] = 0.0
                  parms[2] = 0.2*y
                  self->setproperty,parms = parms,/calculate
    end
'pan_decay':   begin
                  lambda = 0.1*(xrange[1] - xrange[0])
                  *self.ymaxPtr = y
                  area = y*lambda
                  parms[0] = area
                  parms[1] = lambda
                  self->setproperty,parms = parms,/calculate
               end
'pan_kww':   begin
                  lambda = 0.1*(xrange[1] - xrange[0])
                  *self.ymaxPtr = y
                  parms[2] = 0.8
                  parms[0] = y
                  parms[1] = lambda
                  self->setproperty,parms = parms,/calculate
               end
'pan_delta':		begin
					  oldwidth = 0.01*(xrange[1]-xrange[0])
					  area = parms[0] & center = parms[1]
					  width = oldwidth
					  sig = width/sqrt(8.0*alog(2.0))
					  area = y*sqrt(2.0*!dpi*sig^2)

;                                          xvals = (*self.xPtr)
;                                          yvals = (*self.yPtr)
;                                          index = where(xvals ge xrange[0] and xvals le xrange[1],count)
;                                          area = int_tabulated(xvals[index],yvals[index])

;                                          print,area,xvals,yvals
;					  parms[0] = area
					  parms[0] = y
					  parms[1] = x
					  *self.ymaxPtr = y
					  self->setproperty,parms = parms,/calculate
					end
'pan_gaussian':		begin
					  oldwidth = 0.05*(xrange[1]-xrange[0])
					  area = parms[0] & center = parms[1]
					  width = oldwidth
					  sig = width/sqrt(8.0*alog(2.0))
					  area = y*sqrt(2.0*!dpi*sig^2)
					  parms[0] = area
					  parms[1] = x
					  parms[2] = width
					  *self.ymaxPtr = y
					  self->setproperty,parms = parms,/calculate
					end

'pan_lorentzian':	begin
					  oldwidth = 0.05*(xrange[1]-xrange[0])
					  area = parms[0] & center = parms[1]
					  width = oldwidth
					  gam = 0.5*width
					  area = y*gam*!dpi
					  parms[0] = area
					  parms[1] = x
					  parms[2] = width
					  *self.ymaxPtr = y
					  self->setproperty,parms = parms,/calculate
					end

'pan_kohlrausch':	begin
					  oldwidth = 0.05*(xrange[1]-xrange[0])
					  area = parms[0] & center = 0.0
					  width = oldwidth
					  gam = 0.5*width
					  area = 2.0*y*gam*!dpi
					  parms[0] = area
					  parms[1] = 1.0
					  parms[2] = 0.6528/width
					  *self.ymaxPtr = y
					  self->setproperty,parms = parms,/calculate
					end

'pan_lognormal':	begin
					  oldwidth = 0.02*(xrange[1]-xrange[0])
					  area = parms[0] & center = parms[1]
					  amp = y
					  *self.ymaxPtr = y
					  sig = oldWidth/2.354
					  xmode = exp(center-sig^2)
					  *self.xmodePtr = xmode
					  area = 2.0*sqrt(2.0*!dpi*sig^2)*abs(xmode)*y*exp(-0.5*sig^2)
					  parms[0] = area
					  parms[1] = sig^2+alog(abs(x))
					  parms[2] = sig
					  self->setproperty,parms = parms,/calculate
					end

'pan_dho':			begin
					  oldwidth = 0.1*(xrange[1]-xrange[0])
					  amp = parms[0]
					  center = parms[1]
					  width = oldwidth
					  gamma = 0.5*width
					  t = 293.0
					  area = y/pan_dho(x,[1.0,center,width,t])
					  parms[0] = area
					  parms[1] = x
					  parms[2] = width
					  parms[3] = 293.0
					  *self.ymaxPtr = y
					  self->setproperty,parms = parms,/calculate
					end

'pan_background':	begin
					  parms[0] = y
					  parms[1] = 0.0
					  *self.ymaxPtr = y
					  self->setproperty,parms = parms,/calculate
					end

'pan_step':			begin
					  width = 0.05*(xrange[1]-xrange[0])
					  parms[0] = y
					  parms[1] = x
					  parms[2] = width
					  self->setproperty,parms = parms,/calculate
					end

else:
endcase
return
end;func::changefirst
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
pro func::changesecond,x,y,xrange
; This calculates new yvalues based on a second mouse click
self->getproperty,parms = parms
case self.name of
'ft_KWW':
'pan_meanfieldorderparameter': begin
                  *self.ymaxPtr = y
                  parms[2] = y - parms[3]
                  self->setproperty,parms = parms,/calculate    
    end
'pan_decay':   begin
					  lambda = 0.5*parms[0]+abs(x)
					  amp = *self.ymaxPtr
					  parms[0] = lambda*amp
					  parms[1] = lambda
					  self->setproperty,parms = parms,/calculate
					end
'pan_kww':     begin
					  parms[1] = x * (2.0)^(1.0/parms[2])
					  self->setproperty,parms = parms,/calculate
					end
'pan_gaussian':		begin
					  area = parms[0] & center = parms[1]
					  width = 2.0*abs(x-center)
					  sig = width/sqrt(8.0*alog(2.0))
					  amp = parms[0]/sqrt(2.0*!dpi*sig^2)
					  area = *self.ymaxPtr*sqrt(2.0*!dpi*sig^2)
					  parms[0] = area
					  parms[2] = width
					  self->setproperty,parms = parms,/calculate
					end

'pan_delta':		begin
					; Don't change anything here
					end

'pan_lorentzian':	begin
					  area = parms[0] & center = parms[1]
					  width = 2.0*abs(x-center)
					  gamma = 0.5*width
					  amp = parms[0]/(gamma*!dpi)
					  area = *self.ymaxPtr*gamma*!dpi
					  parms[0] = area
					  parms[2] = width
					  self->setproperty,parms = parms,/calculate
					end

'pan_kohlrausch':	begin
					  wid = 0.05*(xrange[1]-xrange[0])
					  area = parms[0]
					  width = 2.0*abs(x-wid)
					  gam = 0.5*width
					  amp = 2.0*parms[0]/(gam*!dpi)
					  area = *self.ymaxPtr*gam*!dpi
					  parms[0] = area
					  parms[2] = 0.6528/width
					  self->setproperty,parms = parms,/calculate
					end

'pan_lognormal':	begin

					  area = parms[0] & mu = parms[1]
					  wid = 0.02*(xrange[1]-xrange[0])
					  oldSig = wid/2.354
					  xmode = *self.xmodePtr

					  newWidth = abs(-(abs(x)-xmode-wid)) > 1d-8
					  newSig = newWidth/2.354
					  xmode = exp(mu-newSig^2)

					  newArea = 2.0*sqrt(2.0*!dpi*newSig^2)*abs(xmode)*(*self.ymaxPtr)* $
					            exp(-0.5*newSig^2)

					  parms[0] = area
					  parms[1] = newSig^2+alog(abs(xmode))
					  parms[2] = newSig
					  self->setproperty,parms = parms,/calculate
					end

'pan_dho':			begin
					  oldwidth = 0.1*(xrange[1]-xrange[0])
					  amp = parms[0] & center = parms[1]
					  width = oldwidth
					  newWidth = abs(-(abs(x)-center-width)) > 1d-8
					  gamma = 0.5*newWidth
					  area = (*self.ymaxPtr)/pan_dho(x,[1.0,center,newWidth,293.0])
					  parms[0] = area
					  parms[2] = newWidth
					  *self.ymaxPtr = y
					  self->setproperty,parms = parms,/calculate
					end

'pan_background':	begin
					  offset = *self.ymaxPtr
					  mp = 0.5*(xrange[0]+xrange[1])
					  slope = (y-offset)/(x-mp)
					  parms[1] = slope
					  parms[0] = offset-slope*mp
					  self->setproperty,parms = parms,/calculate
					end

'pan_step':			begin
					  width = 0.01*(xrange[1]-xrange[0])
					  center = parms[1]
					  parms[2] = abs(x-width-center)
					  self->setproperty,parms = parms,/calculate
					end

else:
endcase

return
end;func::changesecond
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
pro func::draw,overplot = overplot
if n_elements(overplot) eq 0 then overplot = 0
if overplot eq 0 then begin
  plot,*self.xPtr,*self.yPtr,psym = 0
endif else begin
  oplot,*self.xPtr,*self.yPtr,psym = 0
endelse
end;func::draw
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
pro func::setproperty, $
              name = name,$
              xvalues = xvalues, $
              qgroup=qgroup,$
              step = step, $
              parms = parms, $
              fixed = fixed, $
              fixvalues = fixvalues, $
              low = low, $
              lovalues = lovalues, $
              high = high, $
              hivalues = hivalues, $
              parmError = parmError, $
              canDraw = canDraw, $
              tied = tied, $
              expr = expr, $
              rlimit = rlimit,	$
              resptr = resptr,	$
              calculate = calculate	; set this keyword to populate self.yPtr with
              						; the updated values

!except = 0
if n_elements(rlimit) ne 0 then self.rlimit = rlimit
if n_elements(resptr) ne 0 then begin 
  if ptr_valid(resptr) ne 0 then *self.resptr = *resptr 
endif
  
if n_elements(expr) ne 0 then self.expr = expr
if n_elements(canDraw) ne 0 then self.canDraw = canDraw
if n_elements(tied) ne 0 then *self.tiedPtr = tied
if n_elements(step) ne 0 then *self.stepPtr = step
if n_elements(name) ne 0 then self.name = name
if n_elements(xvalues) ne 0 then *self.xPtr = xvalues
if n_elements(qgroup) ne 0 then self.qgroup=qgroup;*self.qPtr = qgroup
if n_elements(parms) ne 0 then *self.parmPtr = parms
if n_elements(parmError) ne 0 then *self.parmErrorPtr = parmError
if n_elements(fixed) ne 0 then *self.fixPtr = fixed
if n_elements(fixvalues) ne 0 then *self.fixedvalPtr = fixvalues
if n_elements(low) ne 0 then *self.lowPtr = low
if n_elements(lovalues) ne 0 then *self.lowvalPtr = lovalues
if n_elements(high) ne 0 then *self.highPtr = high
if n_elements(hivalues) ne 0 then *self.highvalPtr = hivalues
; Now that we have all of the information, calculate the function if
; the user so desires.
if keyword_set(calculate) then begin
  if n_elements(*self.xPtr) ne 0 then begin
    if n_elements(*self.resPtr) eq 0 then begin
    	*self.yPtr = call_function(self.name,*self.xPtr,*self.parmPtr, $
       	          expr = self.expr, extra = *self.extra, $
       	          fit_fun_filename = self.fit_fun_filename,qgroup=self.qgroup)
	endif else begin
    	*self.yPtr = call_function(self.name,*self.xPtr,*self.parmPtr, $
       	          expr = self.expr, resPtr = self.resPtr,extra = *self.extra, $
       	          fit_fun_filename = self.fit_fun_filename,qgroup=self.qgroup)
	endelse
  endif else begin
    print,'Error...no valid x-values'
  endelse
endif
end;func::setProperty
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
pro func::getproperty, $
              name = name,  $
              xvalues = xvalues, $
              qgroup=qgroup,$
              yvalues = yvalues,  $
              step = step, $
              parms = parms, $
              fixed = fixed, $
              fixvalues = fixvalues, $
              low = low, $
              lovalues = lovalues, $
              high = high, $
              hivalues = hivalues,$
              parmnames = parmnames,$
              parmError = parmError, $
              tied = tied, $
              canDraw = canDraw, $
              fit_fun_filename = fit_fun_filename,	$
              expr = expr
if arg_present(parmnames) then begin
  qgroup = self.qgroup;*self.qPtr
;SO DO I ENTER THE QVALUES IN THE FOLLOWING MANNER OR DO I HAVE TO ENTER THEM VIA *self.extra?????????

;THIS IS WHERE ALL THE ACTUAL EVALUATION HAPPENS, AND THUS WHERE THE Qgroup VALUE NEEDS TO BE ENTERED.
  if self.expr eq '' then begin
;    z = call_function(self.name,parmnames = parmnames, $
;    	extra = *self.extra,fit_fun_filename = self.fit_fun_filename)


    z = call_function(self.name,parmnames = parmnames, $
    	extra = *self.extra,fit_fun_filename = self.fit_fun_filename,qgroup=qgroup)
  endif else begin
;    z = call_function(self.name,*self.xPtr,*self.parmPtr, $
;                      parmnames = parmnames, $
;                      expr = self.expr, extra = *self.extra, $
;                      fit_fun_filename = self.fit_fun_filename)

    z = call_function(self.name,*self.xPtr,*self.parmPtr, $
                      parmnames = parmnames, $
                      expr = self.expr, extra = *self.extra, $
                      fit_fun_filename = self.fit_fun_filename,qgroup=qgroup)
  endelse
endif
if arg_present(fit_fun_filename) then fit_fun_filename = self.fit_fun_filename
if arg_present(expr) then expr = self.expr
if arg_present(canDraw) then canDraw = self.canDraw
if arg_present(tied) then tied = *self.tiedPtr
if arg_present(step) then step = *self.stepPtr
if arg_present(name) then name = self.name
if arg_present(xvalues) then xvalues = *self.xPtr
if arg_present(qgroup) then qgroup = self.qgroup;*self.qPtr
if arg_present(yvalues) then yvalues = *self.yPtr
if arg_present(parms) then parms = *self.parmPtr
if arg_present(parmError) then parmError = *self.parmErrorPtr
if arg_present(fixed) then fixed = *self.fixPtr
if arg_present(fixvalues) then fixvalues = *self.fixedvalPtr
if arg_present(low) then low = *self.lowPtr
if arg_present(lovalues) then lovalues = *self.lowvalPtr
if arg_present(high) then high = *self.highPtr
if arg_present(hivalues) then hivalues = *self.highvalPtr
end;func::getProperty
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
function func::init, $
                   name = name, $
                   xvalues = xvalues,$
;NEW:
                   qgroup = qgroup,$
                   fit_fun_filename = fit_fun_filename,	$
                   step = step, $
                   parms = parms, $
                   fixed = fixed, $
                   fixvalues = fixvalues, $
                   low = low, $
                   lovalues = lovalues, $
                   high = high, $
                   hivalues = hivalues, $
                   tied = tied, $
                   resPtr = resPtr, $
                   rlimit = rlimit, $
                   expr = expr, $
                   _Extra = extra




        ; Name must be present!
        self.extra = ptr_new(extra)
        if n_elements(name) eq 0 then return,-1
        self.parmErrorPtr = ptr_new(/allocate_heap)
        self.name = name
        self.stepPtr = ptr_new(/allocate_heap)
        self.xPtr = ptr_new(/allocate_heap)
        self.yPtr = ptr_new(/allocate_heap)
        if n_elements(xvalues) eq 0 then begin
          xlo = -10.0 & xhi = 10.0 & nx = 100
          dx = (xhi-xlo)/(nx-1.0) & x = xlo+dx*findgen(nx)
          *self.xPtr = x
        endif else begin
          *self.xPtr = xvalues
        endelse

        ;NEW
        ;self.qPtr = ptr_new(/allocate_heap)
        if n_elements(qgroup) eq 0 then begin
          ;q = 0.0
          self.qgroup = 0.0;*self.qPtr = q
        endif else begin
;          print,'###########################'
;          print,'func::init qgroup=',qgroup
;          print,'###########################'
          self.qgroup = qgroup;*self.qPtr = qgroup
        endelse



        ; Let's fill up the function with some dummy data if none is given
        ; when instantiating the class....
        self.resPtr = ptr_new(/allocate_heap)
        self.parmPtr = ptr_new(/allocate_heap)
        self.lowPtr = ptr_new(/allocate_heap)
        self.lowvalPtr = ptr_new(/allocate_heap)
        self.highPtr = ptr_new(/allocate_heap)
        self.highvalPtr = ptr_new(/allocate_heap)
        self.fixPtr = ptr_new(/allocate_heap)
        self.tiedPtr = ptr_new(/allocate_heap)
        self.fixedvalPtr = ptr_new(/allocate_heap)
        self.ymaxPtr = ptr_new(/allocate_heap)
        self.xmodePtr = ptr_new(/allocate_heap)
        if n_elements(fit_fun_filename) ne 0 then self.fit_fun_filename = fit_fun_filename $
        	else self.fit_fun_filename = ""
        fit_fun_filename = self.fit_fun_filename
        if n_elements(expr) ne 0 then self.expr = expr $
        	else self.expr = ""
        expr = self.expr
        ; Test if we're defining a user function.  We are explicitly
        ; assuming here that the xvalues, expression, parms, and
        ; parmnames are being passed in here!!!!


        if expr ne "" and fit_fun_filename eq "" then begin
          *self.parmPtr = parms
          dummy = call_function(self.name,xvalues,parms, $
                                Qgroup=Qgroup,$
                                parmnames = parmnames, $
                                expr = self.expr, $
                                fit_fun_filename = self.fit_fun_filename, $
                                canDraw = canDraw, $
                                extra = *self.extra)
          self.canDraw = canDraw
          nparms = n_elements(parms)
        endif
        if fit_fun_filename ne "" and expr eq "" then begin
        	*self.parmPtr = parms
        	dummy = call_function(self.name,xvalues,parms, $, $
                                Qgroup=Qgroup,$
                                parmnames = parmnames, $
                                fit_fun_filename = self.fit_fun_filename, $
                                canDraw = canDraw, $
                                extra = *self.extra)
        	self.canDraw = canDraw
        	nparms = n_elements(parms)
        endif
        ; Now take care of all of the library of fit functions

        if fit_fun_filename eq "" and $
        	expr eq "" then begin
        	  ; Call the function to get out the parameter names
          	dummy = call_function(self.name,parmnames = parmnames,$
           	       extra = *self.extra)
          	nparms = n_elements(parmnames)

        endif
        if fit_fun_filename eq "" and $
        	expr eq "" then begin
        	  ; Call the function to get out the parameter names
          	dummy = call_function(self.name,parmnames = parmnames,$
           	       extra = *self.extra)
          	nparms = n_elements(parmnames)
        endif

        if n_elements(resPtr) ne 0 then *self.resPtr = *resPtr
        if n_elements(rlimit) ne 0 then self.rlimit = rlimit
        unity = 1.0+0.0*findgen(nparms)
        zerof = 0.0*unity
        zeroi = 0*indgen(nparms)
        *self.tiedPtr = n_elements(tied) eq 0 ? replicate(0,nparms) : tied
        *self.stepPtr = n_elements(step) eq 0 ? replicate(0D,nparms) : step
        *self.parmErrorPtr = replicate(0D,nparms)

        *self.parmPtr = n_elements(parms) eq 0 ? unity : parms
        if n_elements(expr) eq 0 then expr = ''
        self.expr = expr
        canDraw = 0

;        help,/traceback
;        print,'func::init self.name=',self.name
        if (n_elements(*self.resPtr) ne 0) then begin
          *self.yPtr = call_function(self.name,*self.xPtr,*self.parmPtr, $
                                     Qgroup=Qgroup,$
                                     expr = self.expr, canDraw = canDraw, $
                                     fit_fun_filename = self.fit_fun_filename,	$
                                     resPtr = self.resPtr, $
                                     rlimit = self.rlimit, $
                                     extra = *self.extra)
        endif else begin
          if (n_elements(*self.resPtr) eq 0) and (strupcase(self.name) ne 'PAN_QENS') then begin
          *self.yPtr = call_function(self.name,*self.xPtr,*self.parmPtr, $, $
                                     Qgroup=Qgroup,$
                                     fit_fun_filename = self.fit_fun_filename,	$
                                     expr = self.expr, canDraw = canDraw, $
                                     extra = *self.extra)
          endif
        endelse

        self.canDraw = canDraw

        *self.fixPtr = n_elements(fixed) eq 0 ? zeroi : fixed
        *self.fixedvalPtr = n_elements(fixvalues) eq 0 ? *self.parmPtr : fixvalues
        *self.lowPtr = n_elements(low) eq 0 ? zeroi : low
        *self.lowvalPtr = n_elements(lovalues) eq 0 ? zerof : lovalues
        *self.highPtr = n_elements(high) eq 0 ? zeroi : high
        *self.highvalPtr = n_elements(hivalues) eq 0 ? zerof : hivalues
        return,1
end;func::init
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
pro func__define
;
define = {func, $
          name:"", $
          expr:"", $
          fit_fun_filename:"",	$
          canDraw:0, $
          extra:ptr_new(/allocate_heap), $
          ymaxPtr:ptr_new(/allocate_heap), $
          xmodePtr:ptr_new(/allocate_heap), $
          parmPtr:ptr_new(/allocate_heap), $
          parmErrorPtr:ptr_new(/allocate_heap), $
;NEW FOR QGroup VALUE
          qgroup:0.0,$;ptr_new(/allocate_heap),$
          xPtr:ptr_new(/allocate_heap),  $
          yPtr:ptr_new(/allocate_heap),  $
          stepPtr:ptr_new(/allocate_heap), $
          fixPtr:ptr_new(/allocate_heap),  $
          fixedvalPtr:ptr_new(/allocate_heap),  $
          lowPtr:ptr_new(/allocate_heap),  $
          lowvalPtr:ptr_new(/allocate_heap),  $
          highPtr:ptr_new(/allocate_heap),  $
          tiedPtr:ptr_new(/allocate_heap), $
          resPtr:ptr_new(/allocate_heap), $
          rlimit:[0.0,0.0], $
          highvalPtr:ptr_new(/allocate_heap) $
          }
end;func__define
