; $Id: refine_function__define.pro,v 1.7 2006/07/28 23:26:05 azuah Exp $
;###############################################################################
;
; NAME:
;  REFINE_FUNCTION__DEFINE
;
; PURPOSE:
;  Object class definition for individual model functions
;  in RAINS.
;
; CATEGORY:
;  DAVE, Data Analysis, RAINS, surface fitting
;
; AUTHOR:
;   Robert M. Dimeo, Ph.D.
;   NIST Center for Neutron Research
;   100 Bureau Drive
;   Gaithersburg, MD 20899
;   Phone: (301) 975-8135
;   E-mail: robert.dimeo@nist.gov
;   http://www.ncnr.nist.gov/staff/dimeo
;
; LICENSE:
;  The software in this file is written by an employee of
;  National Institute of Standards and Technology
;  as part of the DAVE software project.
;
;  The DAVE software package is not subject to copyright protection
;  and is in the public domain. It should be considered as an
;  experimental neutron scattering data reduction, visualization, and
;  analysis system. As such, the authors assume no responsibility
;  whatsoever for its use, and make no guarantees, expressed or
;  implied, about its quality, reliability, or any other
;  characteristic. The use of certain trade names or commercial
;  products does not imply any endorsement of a particular product,
;  nor does it imply that the named product is necessarily the best
;  product for the stated purpose. We would appreciate acknowledgment
;  if the DAVE software is used of if the code in this file is
;  included in another product.
;
;###############################################################################
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
pro refine_function::cleanup
ptr_free,self.parm_ptr,self.parm_err_ptr,self.x_ptr,self.y_ptr
ptr_free,self.z_ptr,self.step_ptr,self.fix_ptr,self.fixed_val_ptr
ptr_free,self.low_ptr,self.lowval_ptr,self.high_ptr,self.highval_ptr
ptr_free,self.tied_ptr,self.res_ptr,self.parmname_ptr
ptr_free,self.single_pname_ptr,self.multi_pname_ptr
if obj_valid(self.otable) then obj_destroy,self.otable
end
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
function refine_function::evaluate,z_out = z_out,_Extra = extra
z_out = call_function(self.name,[*self.x_ptr,*self.y_ptr], *self.parm_ptr, $
     all_y = self.all_y, expr = self.expr, res_ptr = self.res_ptr,$
     nx = n_elements(*self.x_ptr),ny = n_elements(*self.y_ptr), $
     xunits = self.xunits,otable = self.otable)
(*self.z_ptr) = z_out
return,1
end
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
function refine_function::display_image,_Extra = extra
ret = self->evaluate(z_out = z_out)
pos = [0.15,0.15,0.9,0.9]
tvimage,bytscl(z_out),position = pos
xrange = [min(*self.x_ptr),max(*self.x_ptr)]
yrange = [min(*self.y_ptr),max(*self.y_ptr)]
plot,*self.x_ptr,*self.y_ptr,xrange = xrange,yrange = yrange,/nodata,/noerase, $
   position = pos,/xsty,/ysty
return,1
end
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
function refine_function::get,     name = name,       $
                  params = params,      $
                  parmnames = parmnames,   $
                  single_parmnames = single_parmnames,   $
                  multi_parmnames = multi_parmnames,   $
                  prms_err = prms_err,    $
                  xvalues = xvalues,      $
                  all_y = all_y,       $
                  yvalues = yvalues,      $
                  zvalues = zvalues,      $
                  step = step,         $
                  fixed = fixed,       $
                  fxvalues = fxvalues,    $
                  low = low,         $
                  lovalues = lovalues,    $
                  high = high,         $
                  hivalues = hivalues,    $
                  tied = tied,         $
                  rlimit = rlimit,      $
                  expr = expr,         $
                  wid = wid,         $
                  xunits = xunits,      $
                  errmsg = errmsg

if arg_present(xunits) then xunits = self.xunits
if arg_present(wid) then wid = self.wid
if arg_present(single_parmnames) then single_parmnames = *self.single_pname_ptr
if arg_present(multi_parmnames) then multi_parmnames = *self.multi_pname_ptr
if arg_present(parmnames) then parmnames = *self.parmname_ptr
if arg_present(name) then name = self.name
if arg_present(params) then params = *self.parm_ptr
if arg_present(xvalues) then xvalues = *self.x_ptr
if arg_present(yvalues) then yvalues = *self.y_ptr
if arg_present(all_y) then all_y = self.all_y
if arg_present(step) then step = *self.step_ptr
if arg_present(fixed) then fixed = *self.fix_ptr
if arg_present(prms_err) then prms_err = *self.parm_err_ptr
if arg_present(zvalues) then begin
;   if (n_elements(*self.z_ptr) eq 0) then begin
      ret_val = self->evaluate(z_out = zvalues)
;   endif else $
;      zvalues = (*self.z_ptr)   ; use last evaluated value
endif
if arg_present(fxvalues) then fxvalues = *self.fixed_val_ptr
if arg_present(low) then low = *self.low_ptr
if arg_present(lovalues) then lovalues = *self.lowval_ptr
if arg_present(high) then high = *self.high_ptr
if arg_present(hivalues) then hivalues = *self.highval_ptr
if arg_present(tied) then tied = *self.tied_ptr
if arg_present(rlimit) then rlimit = self.rlimit
if arg_present(expr) then expr = self.expr

return,1
end
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
function refine_function::set,     name = name,       $
                  params = params,      $
                  prms_err = prms_err,    $
                  xvalues = xvalues,      $
                  all_y = all_y,       $
                  yvalues = yvalues,      $
                  step = step,         $
                  fixed = fixed,       $
                  fxvalues = fxvalues,    $
                  low = low,         $
                  lovalues = lovalues,    $
                  high = high,         $
                  hivalues = hivalues,    $
                  tied = tied,         $
                  rlimit = rlimit,      $
                  expr = expr,         $
                  calculate = calculate,   $
                  res_ptr = res_ptr,      $
                  wid = wid,         $
                  errmsg = errmsg

if n_elements(wid) ne 0 then self.wid = wid
if n_elements(res_ptr) ne 0 then *self.res_ptr = *res_ptr
if n_elements(params) ne 0 then *self.parm_ptr = params
if n_elements(xvalues) ne 0 then *self.x_ptr = xvalues
if n_elements(yvalues) ne 0 then  *self.y_ptr = yvalues
if n_elements(all_y) ne 0 then self.all_y = all_y
if n_elements(step) ne 0 then *self.step_ptr = step
if n_elements(fixed) ne 0 then *self.fix_ptr = fixed
if n_elements(prms_err) ne 0 then *self.parm_err_ptr = prms_err

if n_elements(fxvalues) ne 0 then *self.fixed_val_ptr = fxvalues
if n_elements(low) ne 0 then *self.low_ptr = low
if n_elements(lovalues) ne 0 then *self.lowval_ptr = lovalues
if n_elements(high) ne 0 then *self.high_ptr = high
if n_elements(hivalues) ne 0 then *self.highval_ptr = hivalues
if n_elements(tied) ne 0 then *self.tied_ptr = tied
if n_elements(rlimit) ne 0 then self.rlimit = rlimit
if n_elements(expr) ne 0 then self.expr = expr

if n_elements(calculate) ne 0 then ret = self->evaluate()

return,1
end
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
function refine_function::init,   name = name,         $
                  params = params,      $
                  xvalues = xvalues,      $
                  all_y = all_y,       $
                  yvalues = yvalues,      $
                  step = step,         $
                  fixed = fixed,       $
                  fxvalues = fxvalues,    $
                  low = low,         $
                  lovalues = lovalues,    $
                  high = high,         $
                  hivalues = hivalues,    $
                  tied = tied,         $
                  res_ptr = res_ptr,      $
                  rlimit = rlimit,      $
                  expr = expr,         $
                  wid = wid,         $
                  xunits = xunits,      $
                  errmsg = errmsg
errmsg = 'No errors generated in REFINE_FUNCTION object class initiation'

if n_elements(name) eq 0 then begin
   errmsg = 'Function name is a required keyword'
   return,0
endif

if n_elements(xvalues) eq 0 then begin
   errmsg = 'xvalues is a required keyword'
   return,0
endif
if n_elements(yvalues) eq 0 then begin
   errmsg = 'yvalues is a required keyword'
   return,0
endif
; Check to see if we are using any of the models requiring a
; lookup table...if so then instantiate the table_lookup object
if name eq 'ref_diffusion_in_a_sphere' then begin
   self.otable = obj_new('table_lookup')
endif
; Default is they're all different
if n_elements(all_y) eq 0 then all_y = 0
self.all_y = all_y
self.name = name
if n_elements(wid) eq 0 then wid = 0L
self.wid = wid
; Allocate heap memory to the pointer references
self.parmname_ptr = ptr_new(/allocate_heap)
self.parm_ptr = ptr_new(/allocate_heap)
self.parm_err_ptr = ptr_new(/allocate_heap)
self.x_ptr = ptr_new(xvalues)
self.y_ptr = ptr_new(yvalues)
self.z_ptr = ptr_new(/allocate_heap)
self.step_ptr = ptr_new(/allocate_heap)
self.fix_ptr = ptr_new(/allocate_heap)
self.fixed_val_ptr = ptr_new(/allocate_heap)
self.low_ptr = ptr_new(/allocate_heap)
self.lowval_ptr = ptr_new(/allocate_heap)
self.high_ptr = ptr_new(/allocate_heap)
self.highval_ptr = ptr_new(/allocate_heap)
self.tied_ptr = ptr_new(/allocate_heap)
self.res_ptr = ptr_new(/allocate_heap)
self.single_pname_ptr = ptr_new(/allocate_heap)
self.multi_pname_ptr = ptr_new(/allocate_heap)

if n_elements(xunits) ne 0 then self.xunits = strmid(xunits,7)
if n_elements(res_ptr) ne 0 then *self.res_ptr = *res_ptr
; How many parameters are in the function?
if n_elements(expr) ne 0 then begin ; user-defined expression
   self.expr = expr
   dummy = call_function(self.name,[xvalues,yvalues],params, $
         parmnames = parmnames, all_y = self.all_y,$
         expr = self.expr,nx = n_elements(xvalues), $
         ny = n_elements(yvalues),single_parmnames = single_parmnames, $
         multi_parmnames = multi_parmnames, $
         step = def_step,xunits = self.xunits, $
         otable = self.otable)
endif else begin         ; library function
   dummy = call_function(self.name,[xvalues,yvalues], $
      parmnames = parmnames,  all_y = self.all_y,$
      single_parmnames = single_parmnames, $
      multi_parmnames = multi_parmnames, $
      nx = n_elements(xvalues),ny = n_elements(yvalues), $
      step = def_step,xunits = self.xunits, $
      otable = self.otable)
   self.expr = ''
endelse
*self.parmname_ptr = parmnames
;print,'******'
;for i = 0,n_elements(parmnames)-1 do print,parmnames[i]
;print,'******'
;;print,n_elements(parmnames)

*self.single_pname_ptr = single_parmnames
*self.multi_pname_ptr = multi_parmnames
self.nparms = n_elements(parmnames)
; Check for values that have been passed in now
unity = 1.+dblarr(self.nparms)
zerod = 0.0*unity
zeroi = 0*indgen(self.nparms)
*self.parm_ptr = n_elements(params) eq 0 ? unity:params
*self.tied_ptr = n_elements(tied) eq 0 ? zeroi:tied
; Use default step sizes from the function itself if
*self.step_ptr = n_elements(step) eq 0 ? def_step:step

*self.parm_err_ptr = zerod
*self.fix_ptr = n_elements(fixed) eq 0 ? zeroi:fixed

*self.fixed_val_ptr = n_elements(fxvalues) eq 0 ? *self.parm_ptr:fxvalues
*self.low_ptr = n_elements(low) eq 0 ? zeroi:low
*self.high_ptr = n_elements(high) eq 0 ? zeroi:high
*self.highval_ptr = n_elements(hivalues) eq 0 ? zerod:hivalues
*self.lowval_ptr = n_elements(lovalues) eq 0 ? zerod:lovalues
return,1
end
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
pro refine_function__define

define = {  refine_function,            $
         name:'',                 $
         all_y:0,                 $
         expr:'',                 $
         xunits:'',                $
         otable:obj_new(),            $
         parmname_ptr:ptr_new(),           $
         single_pname_ptr:ptr_new(),        $
         multi_pname_ptr:ptr_new(),         $
         nparms:0,               $
         parm_ptr:ptr_new(),            $
         parm_err_ptr:ptr_new(),           $
         x_ptr:ptr_new(),            $
         y_ptr:ptr_new(),            $
         z_ptr:ptr_new(),            $
         step_ptr:ptr_new(),            $
         fix_ptr:ptr_new(),            $
         fixed_val_ptr:ptr_new(),        $
         low_ptr:ptr_new(),            $
         lowval_ptr:ptr_new(),         $
         high_ptr:ptr_new(),            $
         highval_ptr:ptr_new(),          $
         tied_ptr:ptr_new(),            $
         res_ptr:ptr_new(),            $
         wid:0L,                  $
         rlimit:fltarr(2)            $
     }

end
