; $Id: ooiqt__define.pro,v 1.1 2005/11/10 23:20:58 kneller Exp $
;###############################################################################
;
;
;CLASS NAME:
;        ooIQT
;
;PURPOSE:
;        Data class for autoplotIQT.
;CATEGORY:
;
;
;SUPERCLASSES:
;
;
;METHODS:
;    ooIQT::read
;    ooIQT::draw
;    ooIQT::fitDSE
;    doubleStretchExponential
;    ooIQT::getproperty
;    ooIQT::setproperty
;    ooIQT_cleanup
;    ooIQT::cleanup
;    ooIQT::init
;    ooIQT__define
;
;
; AUTHOR:
; Larry Kneller
; NIST Center for Neutron Research
; 100 Bureau Drive, Gaithersburg, MD 20899
; United States
; kneller@nist.gov  301-975-8839
; Fri Oct 21 18:19:23 2005
;
; LICENSE:
; The software in this file is written by an employee of
; National Institute of Standards and Technology
; as part of the DAVE software project.
;
; The DAVE software package is not subject to copyright protection
; and is in the public domain. It should be considered as an
; experimental neutron scattering data reduction, visualization, and
; analysis system. As such, the authors assume no responsibility
; whatsoever for its use, and make no guarantees, expressed or
; implied, about its quality, reliability, or any other
; characteristic. The use of certain trade names or commercial
; products does not imply any endorsement of a particular product,
; nor does it imply that the named product is necessarily the best
; product for the stated purpose. We would appreciate acknowledgment
; if the DAVE software is used or if the code in this file is
; included in another product.
;
;###############################################################################

;DATA CLASS FOR THE I(Q,t) DATA STRUCTURE.
;
;THIS DATA STRUCTURE IS SURPRISINGLY COMPLICATED AND
;WARRANTS THE CREATION OF A SEPARATE DATA CLASS.
;


;###############################################################################
;
;NAME:
;        ooIQT::read
;
;PURPOSE:
;
;PARAMETERS:
;
;KEYWORDS:
;
;_EXTRA - is used to pass keywords meant for the superclass.
;
;###############################################################################
pro ooIQT::read,fn


    if n_elements(fn) eq 0 then begin
        fn = dialog_pickfile(filter='*.dat')
    endif



    ln = file_lines(fn)



;NOTE HOW COMPLICATED THESE DATA STRUCTURES ARE!!!

    parms = dblarr(7)
    sparms = dblarr(7)
    self.p = ptr_new(parms)
    self.sp = ptr_new(sparms)
    self.chisq = 0.0d

    line = ''
        t=[0.0d];dblarr(ln[i]-1)
        iqt=[0.0d];dblarr(ln[i]-1)
        siqt=[0.0d];dblarr(ln[i]-1)

;        print,'______________'
        openr,lun,fn,/get_lun
        readf,lun,line  ;READ HEADER LINE
;        print,line
        for j=1,ln-1 do begin

            readf,lun,line
;            print,line
            segs = strsplit(line,/extract)

            if n_elements(segs) eq 4 then begin
                ;ONLY ADD LINES WITH 4 COLUMNS OF DATA.  ELIMINATES BLANK LINES.
                self.q = double(segs[0])
                t = [t,double(segs[1])]
                iqt = [iqt,double(segs[2])]
                siqt = [siqt,double(segs[3])]
            endif
        endfor;j
        free_lun,lun
        self.i = ptr_new(iqt[1:*])
        self.si = ptr_new(siqt[1:*])
        self.t = ptr_new(t[1:*])
        self.mask = ptr_new(dblarr(n_elements(*self.t)))

end;ooIQT::read
;###############################################################################
;
;NAME:
;        ooIQT::draw
;
;PURPOSE:
;
;PARAMETERS:
;
;KEYWORDS:
;
;_EXTRA - is used to pass keywords meant for the superclass.
;
;###############################################################################
pro ooIQT::draw,wid = wid, $
                oplot=oplot,$
                color = color,$
                psym=psym,$
                fit=fit,$
                nowid=nowid,$
                xvar=xvar,$
                xrange=xrange,$
                yrange=yrange,$
                _Extra=extra




    if n_elements(nowid) eq 0 then nowid = 0
    if n_elements(fit) eq 0 then fit = 0
    if n_elements(xvar) eq 0 then xvar = 0


    q = self.q
    if xvar eq 0 then begin
        x = *self.t
        xtitle = 't (ns)'
    endif else begin
        x = (self.q^2)*(*self.t)
        xtitle = 'Q^2*2 (ns/A^2)'
    endelse

    y = *self.i
    sy = *self.si
    p = *self.p



    if n_elements(wid) eq 0 then begin
        window,0
        wset,0
    endif else begin
        if nowid eq 0 then begin
            wset,wid
        endif
    endelse

    if n_elements(oplot) eq 0 then oplot = 0

    device,get_decomposed = dc
    device,decomposed = 1


    black = 0L
    red = 255L
    green = 256L*red
    blue = 256L*green
    white = red + green + blue

    if n_elements(color) eq 0 then color = black
    if n_elements(psym) eq 0 then psym = 4

    if oplot eq 0 then begin
        if n_elements(xrange) eq 2 and n_elements(yrange) eq 2 then begin
            if firstplot eq 0 then begin
                plot,x,y,psym=4,background = white, color = black,$
                        xtitle = xtitle,ytitle='I(Q,t)',title='I(Q,t) Data',$
                        xrange=xrange,yrange=yrange,$
                        xstyle=1,ystyle=1,$
                        _Extra=extra
            endif else begin
                plot,x,y,psym=4,background = white, color = black,$
                        xtitle = xtitle,ytitle='I(Q,t)',title='I(Q,t) Data',$
                        _Extra=extra
            endelse
        endif else begin
            plot,x,y,psym=4,background = white, color = black,$
                    xtitle = xtitle,ytitle='I(Q,t)',title='I(Q,t) Data',$
                    _Extra=extra
        endelse

    endif else begin
        oplot,x,y,psym=psym,color = color
    endelse
    errplot,x,y-sy,y+sy,color=color

    if fit eq 1 then begin
        oplot,x,doubleStretchExponential(x,p),color=color
    endif

    device,decomposed = dc
end;ooIQT::draw
;###############################################################################
;
;NAME:
;        ooIQT::fitDSE
;
;PURPOSE:
;
;PARAMETERS:
;
;KEYWORDS:
;
;_EXTRA - is used to pass keywords meant for the superclass.
;
;###############################################################################
pro ooIQT::fitDSE,start=start,fixed=fixed,limits=limits,draw=draw,xvar=xvar

    if n_elements(start) eq 0 then start = [1.0,0.5,1.0,1.0,0.0,1.0,1.0]
    if n_elements(draw) eq 0 then draw = 0

    if n_elements(xvar) eq 0 then xvar = 0 ;xvar=0 -> x=t; 1 -> x=Q^2*t

    q = self.q
    if xvar eq 0 then begin
        x = *self.t
    endif else x = (self.q^2)*(*self.t)

    y = *self.i
    sy = *self.si

    mask = where(*self.mask ne 1)
    if mask[0] ne -1 then begin
        x = x[mask]
        y = y[mask]
        sz = sy[mask]
    endif


    ;print,'x=',x
    ;print,'y=',y
    ;print,'sy=',sy

    wzero = where(sy eq 0)
    if wzero[0] ne -1 then begin
        sy[wzero] = 1.0
    endif

    parinfo = replicate({value:0.D, fixed:0, limited:[0,0], $
                       limits:[0.D,0]}, 7)

    if n_elements(fixed) eq 0 then begin
        parinfo[0].fixed = 1
        parinfo[3:6].fixed = 1
    endif else begin
        parinfo[*].fixed = fixed
    endelse
    parinfo[*].value = start

    p0 = start
    p = mpfitfun('doubleStretchExponential', x, y, sy, p0,perror = perror,$
                                    parinfo=parinfo,/quiet)    ; Fit a function

    if n_elements(perror) eq 7 then begin
        sp = perror
    endif else sp = dblarr(7)
    ;print, p
    ;print,sp

    *self.p = p
    *self.sp = sp

    if draw eq 1 then self->draw

end;ooIQT::fitDSE

;###############################################################################
;
;NAME:
;        doubleStretchExponential
;
;PURPOSE:
;
;PARAMETERS:
;
;KEYWORDS:
;
;_EXTRA - is used to pass keywords meant for the superclass.
;
;RETURN VALUE:
;
;###############################################################################
function doubleStretchExponential,X,P
;###############################################################################
;
;FUNCTION NAME:
;    doubleStetchExponential
;
;PURPOSE:
;               General function for fitting all possible I(Q,t) curves..
;PARAMETERS:
;       X   The x values
;       P   The parameters
;
;NOTE:  The x values will be determined by the the calling function.
;       They could be
;
;
    A0 = p[0]
    A1 = p[1]
    D1 = p[2]
    B1 = p[3]
    A2 = p[4]
    D2 = p[5]
    B2 = p[6]


    p = [A0,A1,D1,B1,A2,D2,B2]

    ;return, A0 + A1*exp(-1.0*D1*X^B1) + A2*exp(-1.0*D2*X^B2)

;THE FOLLOWING FORM OF THE EXPRESSION GUARANTEES THAT THE VALUE IS
;A0 AT X=0, WHERE X IS t OR  (Q^2)*t
    return,A0*(A1*exp(-1.0*(D1*X)^B1) + (1.0-A1)*A2*exp(-1.0*(D2*X)^B2) + (1.0-A1)*(1.0-A2))

end;doubleStretchExponential


;############################################
;###############################################################################
;
;NAME:
;        ooIQT::getproperty
;
;PURPOSE:
;
;PARAMETERS:
;
;KEYWORDS:
;
;_EXTRA - is used to pass keywords meant for the superclass.
;
;###############################################################################
pro ooIQT::getproperty, $
                i=i,$
                si=si,$
                q=q,$
                mask=mask,$
                t=t,$
                P=p,$
                sp=sp,$
                chisq=chisq,$
                _Extra=extra


    ooIQT__define,ooIQT
    tags = tag_names(ooIQT)



catch, theError

if theError ne 0 then begin
    catch,/cancel
    ok = error_message(!error_state.msg  $
                       +'Returning . . . ',$
                       traceback=1,/error)
    return
endif

    if arg_present(i) then i=self.i
    if arg_present(si) then si=self.si
    if arg_present(q) then q=self.q
    if arg_present(mask) then mask=self.mask
    if arg_present(t) then t=self.t
    if arg_present(p) then p=self.p
    if arg_present(sp) then sp=self.sp
    if arg_present(chisq) then chisq=self.chisq

end;autoplot::getproperty
;###############################################################################
;
;NAME:
;        ooIQT::setproperty
;
;PURPOSE:
;
;PARAMETERS:
;
;KEYWORDS:
;
;_EXTRA - is used to pass keywords meant for the superclass.
;
;###############################################################################
pro ooIQT::setproperty, $
                i=i,$
                si=si,$
                q=q,$
                t=t,$
                mask=mask,$
                P=p,$
                sp=sp,$
                chisq=chisq,$
                _Extra=extra


    ooIQT__define,ooIQT
    tags = tag_names(ooIQT)


catch, theError

if theError ne 0 then begin
    catch,/cancel
    ok = error_message(!error_state.msg  $
                       +'Returning . . . ',$
                       traceback=1,/error)
    return
endif

    if n_elements(i) gt 0 then begin
        if ptr_valid(self.i) gt 0 then ptr_free,self.i
        self.i=i
    endif

    if n_elements(si) gt 0 then begin
        if ptr_valid(self.si) gt 0 then ptr_free,self.si
        self.si=si
    endif
    if n_elements(q) gt 0 then begin
        if ptr_valid(self.q) gt 0 then ptr_free,self.q
        self.q=q
    endif
    if n_elements(mask) gt 0 then begin
        if ptr_valid(self.mask) gt 0 then ptr_free,self.mask
        self.mask=mask
    endif
    if n_elements(t) gt 0 then begin
        if ptr_valid(self.t) gt 0 then ptr_free,self.t
        self.t=t
    endif
    if n_elements(p) gt 0 then self.p=p
    if n_elements(sp) gt 0 then self.sp=sp
    if arg_present(chisq) then self.chisq=chisq


end;autoplot::setproperty
;###############################################################################
;
;NAME:
;        ooIQT_cleanup
;
;PURPOSE:
;
;PARAMETERS:
;
;KEYWORDS:
;
;_EXTRA - is used to pass keywords meant for the superclass.
;
;###############################################################################
pro ooIQT_cleanup,id
    widget_control,id,get_uvalue=obj
    print,id
    help,obj
    obj_destroy,obj
end;ooIQT_cleanup
;###############################################################################
;
;NAME:
;        ooIQT::cleanup
;
;PURPOSE:
;
;PARAMETERS:
;
;KEYWORDS:
;
;_EXTRA - is used to pass keywords meant for the superclass.
;
;###############################################################################
pro ooIQT::cleanup
    print,'ooIQT Cleanup.'
    if ptr_valid(self.i) gt 0 then ptr_free,self.i
    if ptr_valid(self.si) gt 0 then ptr_free,self.si
    if ptr_valid(self.t) gt 0 then ptr_free,self.t
    if ptr_valid(self.P) gt 0 then ptr_free,self.P
    if ptr_valid(self.sP) gt 0 then ptr_free,self.sP
    if ptr_valid(self.mask) gt 0 then ptr_free,self.mask

end;ooIQT::cleanup


;###############################################################################
;
;NAME:
;        ooIQT::init
;
;PURPOSE:
;
;PARAMETERS:
;
;KEYWORDS:
;
;_EXTRA - is used to pass keywords meant for the superclass.
;
;RETURN VALUE:
;
;###############################################################################
function ooIQT::init,fn=fn


    if n_elements(fn) ne 0 then begin
        self->read,fn
    endif else self->read

    return,1
end;ooIQT::init


;###############################################################################
;
;NAME:
;        ooIQT__define
;
;PURPOSE:
;
;PARAMETERS:
;
;KEYWORDS:
;
;_EXTRA - is used to pass keywords meant for the superclass.
;
;###############################################################################
pro ooIQT__define,class

    class = {ooIQT, $
                i:ptr_new(),$   ;I(Q,t)
                si:ptr_new(),$   ;sI(Q,t)
                t:ptr_new(),$   ;FOURIER TIMES ;DIFFERENT NUMBERS AND VALUES FOR EACH I(Q,t)
                mask:ptr_new(),$   ;MASKING OF I(Q,t)
                q:0.0d,$   ;1 Q PER I(Q,t)
                P:ptr_new(),$   ;FIT PARAMETERS FOR EACH Q
                sP:ptr_new(),$   ;FIT PARAMETERS ERRORS FOR EACH Q
                chisq:0.0d $
            }


end;ooIQT__define

