#!/bin/sh
# \
exec oagwish "$0" "$@"
set auto_path [linsert $auto_path 0 /usr/local/oag/apps/lib/$env(HOST_ARCH)]
set auto_path [linsert $auto_path 0 /usr/local/oag/lib_patch/$env(HOST_ARCH)]
APSDebugPath


#
# Program to provide easy interface to sddsprocess and other programs.
#


proc setStatus {text} {
    global status
    set status "[clock format [clock seconds] -format %H:%M:%S]: $text"
    update
}

APSApplication . -name quickSDDSMath -version 1.7 -overview "Allows easily using various features of SDDS math programs."

setStatus Ready...
APSScrolledStatus .status -parent .userFrame -textVariable status -width 65

set filename ""
if [llength $argv] {
    set args $argv
    APSParseArguments {filename}
}

# Creates windows to allow user to select the columns for indep. and dep. variables

proc varSelect {args} {
    set arrayName ""
    set filenameVariable ""
    set type ""
    set slot ""
    set widget ""
    set single 0
    APSParseArguments {arrayName filenameVariable type slot widget single}
    
    global $arrayName 
    global [os editstring S/(/Z) $filenameVariable]
    set $filenameVariable [string trim [string trimright [set $filenameVariable]]]

    if ![string length [set $filenameVariable]] {
        setStatus "Give a filename!"
        return
    }
    if [catch {APSGetSDDSNames -class column -fileName [set $filenameVariable]} varList] {
        setStatus "$varList"
        return
    } 
    set varname Independent
    set multiItem 0
    if [string match y $type] {
        set varname Dependent
        if !$single {
            set multiItem 1
        }
    } 
    set choiceList [APSChooseItemFromList -name "$varname variable" \
                      -itemList $varList -returnList $varList -returnIndices 0 \
                      -multiItem $multiItem]
    set $arrayName\($slot\) [join $choiceList ,]
}
    
# Makes entry box and buttons for variable selection	

proc makeVariableFrame {widget args} {
    set filenameVariable ""
    set arrayName ""
    set parent ""
    set yOnly 0
    set single 0
    APSStrictParseArguments {filenameVariable arrayName parent yOnly single}
    APSFrame $widget -parent $parent -label Variables
    set vf $parent$widget.frame

    global $arrayName
    if !$yOnly {
        APSFrame .x -parent $vf -relief flat
        set w $vf.x.frame
        APSLabeledEntry .xVar -width 30 -label "Independent variable:" \
          -textVariable $arrayName\(xVar\) -parent $w \
          -packOption "-side left" -contextHelp "Enter the name of the independent variable here \
	    or call up selection box with the button."
        APSButton .xselect -parent $w -packOption "-side right" -text "Select..." -command \
          "varSelect -arrayName $arrayName -slot xVar -type x -filenameVariable $filenameVariable -widget $w" \
          -contextHelp "Press to call up x variable selection box."
    }

    APSFrame .y -parent $vf -relief flat
    APSLabeledEntry .yVar -width 30 -label "  Dependent variables:" \
      -textVariable $arrayName\(yVar\) -parent $vf.y.frame \
      -packOption "-side left" -contextHelp "Enter the names of the dependent variables here or call up \
	    selection box with the button."
    APSButton .yselect -parent $vf.y.frame -packOption "-side right" -text "Select..." -command \
      "varSelect -arrayName $arrayName -slot yVar -type y -filenameVariable $filenameVariable -single $single" \
      -contextHelp "Press to call up y variable selection box."
}

proc AddPlotLayoutWidget {widget args} {
    set parent ""
    set variable ""
    APSStrictParseArguments {parent variable}

    APSRadioButtonFrame $widget -parent $parent -label "Plot layout: " \
      -orientation horizontal -variable $variable \
      -buttonList "1x1 1x2 2x1 2x2 3x3 4x4 5x5 6x6" \
      -valueList "-layout=1,1 -layout=1,2 -layout=2,1 -layout=2,2 -layout=3,3 -layout=4,4 -layout=5,5 -layout=6,6" \
      -contextHelp \
      "Selected the plot layout, which gives the number of plots horizontally and vertically on each panel."

}

proc AddSmoothOptions {args} {
    set parent ""
    APSStrictParseArguments {parent}
    global Smooth
    set Smooth(nearestNeighbor,passes) 1
    set Smooth(nearestNeighbor,points) 1
    set Smooth(SavitzkyGolay,passes) 1
    set Smooth(SavitzkyGolay,lrPoints) 1
    set Smooth(SavitzkyGolay,order) 1
    set Smooth(despike,neighbors) 4
    set Smooth(despike,passes) 1
    set Smooth(despike,averageOf) 4
    set Smooth(despike,threshold) 0
    set Smooth(newColumns) 0
    set Smooth(differenceColumns) 0
    set Smooth(outputFile) ""
    set Smooth(layout) "-layout=1,1"
    APSLabeledEntry .output -parent $parent -label "Output file: " -width 90 \
      -commandButton 1 -textVariable Smooth(outputFile) 
    set Smooth(mode) SG
    APSRadioButtonFrame .mode -parent $parent -label "Method: " -orientation horizontal \
      -buttonList {"Nearest-neighbor average" Savitzky-Golay "Despike" \
                     "Nearest-neighbor average+Despike" \
                     "Savitzky-Golay+Despike"} \
      -limitPerRow 3 \
      -variable Smooth(mode) -valueList {NNA SG DS NNADS SGDS} \
      -commandList [list \
    "APSDisableWidget $parent.sg; APSDisableWidget $parent.d; APSEnableWidget $parent.nna" \
    "APSEnableWidget $parent.sg; APSDisableWidget $parent.d; APSDisableWidget $parent.nna" \
    "APSDisableWidget $parent.sg; APSEnableWidget $parent.d; APSDisableWidget $parent.nna" \
    "APSDisableWidget $parent.sg; APSEnableWidget $parent.d; APSEnableWidget $parent.nna" \
    "APSEnableWidget $parent.sg; APSEnableWidget $parent.d; APSDisableWidget $parent.nna" \
    ] \
      -contextHelp "Choose the smoothing algorithms to apply."

    APSFrame .sg -parent $parent -label "Savitzky-Golay Parameters"  \
      -contextHelp "This is the best of the general-purpose smoothing algorithms."
    APSLabeledEntry .lrPoints -parent $parent.sg.frame -label "Points per side: " \
      -textVariable Smooth(SavitzkyGolay,lrPoints) -type integer \
      -contextHelp "Enter the number of points on each side of the point being smoothed to use for fitting of the replacement value."
    APSLabeledEntry .order -parent $parent.sg.frame -label "Order of fit: " \
      -textVariable Smooth(SavitzkyGolay,order)  -type integer \
      -contextHelp "Enter the order of the fits to use for replacing points.  1 is a linear fit, 2 is quadratic, and so on."
    APSLabeledEntry .passes -parent $parent.sg.frame -label "Passes: " -width 10 \
      -type integer -textVariable Smooth(SavitzkyGolay,passes) \
      -contextHelp "The number of times to apply the smoothing algorithms."

    APSFrame .nna -parent $parent -label "Nearest-Neighbor Averaging Parameters" \
      -contextHelp "This is a legacy algorithm.  Its only real virtue is that is simply to understand: each point is replaced by the average of its N nearest-neighbor points."
    APSLabeledEntry .points -parent $parent.nna.frame -label "Neighbors per side: " \
      -textVariable Smooth(nearestNeighbor,points) -type integer \
      -contextHelp "Enter the number of points on each side of the point being smoothed to use in the averaging that computes the replacement value.  The point itself is also included, so entering 1 means 3 values are averaged, entering 2 means 5 values are averaged, and so on."
    APSLabeledEntry .passes -parent $parent.nna.frame -label "Passes: " -width 10 \
      -type integer -textVariable Smooth(nearestNeighbor,passes) \
      -contextHelp "The number of times to apply the smoothing algorithms."

    APSFrame .d -parent $parent -label "Despiking Parameters" \
      -contextHelp "This algorithm is used for removing spikes in data without affecting most data values.  Use it only when most of your values are well-behaved, with a few that stick out."
    APSLabeledEntry .neighbors -parent $parent.d.frame -label "Comparison neighbors: "  \
      -textVariable Smooth(despike,neighbors) -type integer \
      -contextHelp "Number of neighbors to use in computing a value for comparison to the candidate point."
    APSLabeledEntry .threshold -parent $parent.d.frame -label "Threshold: " \
      -textVariable Smooth(despike,threshold) -type real \
      -contextHelp "Threshold value for determining whether a candidate point is a spike.  If it differs from the average of the given number of neighbors by more than the threshold, then it is considered a spike."
    APSLabeledEntry .averageOf -parent $parent.d.frame -label "Replacement neighbors: " \
      -textVariable Smooth(despike,averageOf) -type integer \
      -contextHelp "Number of neighbors to use in computing a new value to replace a point that has been determined to be a spike."
    APSLabeledEntry .passes -parent $parent.d.frame -label "Passes: " \
      -textVariable Smooth(despike,passes) -type integer \
      -contextHelp "Number of times to apply the despiking algorithm."
    APSEnableWidget $parent.sg; APSDisableWidget $parent.d; APSDisableWidget $parent.nna

    APSRadioButtonFrame .newCol -parent $parent -orientation horizontal \
      -label "New columns for smoothed data: " \
      -variable Smooth(newColumns) -buttonList {Yes No} -valueList {1 0} \
      -contextHelp \
      "By default, the smoothed data appears in the output file in columns with the same name as in the input file.  If Yes is chosen, then the smoothed data is instead put in new columns, with names like <oldName>Smoothed."

    APSRadioButtonFrame .difCol -parent $parent -orientation horizontal \
      -label "New columns for difference data: " \
      -variable Smooth(differenceColumns) -buttonList {Yes No} \
      -valueList {1 0} -contextHelp \
      "If Yes is chosen, then the difference between the original and smoothed data appears in the output file in new columns, with names like <oldName>Unsmooth."

    AddPlotLayoutWidget .layouts -parent $parent  -variable Smooth(layout)  
    APSButton .run -parent $parent -text "Run" -command "RunSmooth"
    APSButton .display -parent $parent -text "Display" -command "DisplaySmooth"
}

proc RunSmooth {} {
    global Smooth
    if ![string length $Smooth(inputFile)] {
        setStatus "Supply an input filename"
        return
    }
    if ![string length $Smooth(outputFile)] {
        setStatus "Supply an output filename"
        return
    }
    if ![string length $Smooth(yVar)] {
        setStatus "Choose one or more dependent variables"
        return
    }

    APSAddToRecentFileList -filename $Smooth(inputFile)
    APSAddToRecentFileList -filename $Smooth(outputFile)

    set command "sddssmooth -column=[join $Smooth(yVar) ,] "
    foreach item {inputFile outputFile} {
        append command " $Smooth($item) "
    }
    foreach item {differenceColumns newColumns} {
        if $Smooth($item) {
            append command " -$item "
        }
    }
    if [string match *SG* $Smooth(mode)] {
        append command " -savitzkyGolay=$Smooth(SavitzkyGolay,lrPoints),$Smooth(SavitzkyGolay,lrPoints),$Smooth(SavitzkyGolay,order) -passes=$Smooth(SavitzkyGolay,passes) "
    }
    if [string match *NNA* $Smooth(mode)] {
        append command " -pass=$Smooth(nearestNeighbor,passes) -points=$Smooth(nearestNeighbor,points) "
    }
    if [string match *DS* $Smooth(mode)] {
        append command " -despike=neighbors=$Smooth(despike,neighbors),threshold=$Smooth(despike,threshold),averageOf=$Smooth(despike,averageOf),passes=$Smooth(despike,passes) "
    }
    
    setStatus "$command"
    if [catch {eval exec $command} result] {
        setStatus "$result"
        return
    }
    DisplaySmooth 
    setStatus "Done."
}

proc DisplaySmooth {} {
    global Smooth
    if ![string length $Smooth(inputFile)] {
        setStatus "Supply an input filename"
        return
    }
    if ![string length $Smooth(outputFile)] {
        setStatus "Supply an output filename"
        return
    }
    if ![string length $Smooth(yVar)] {
        setStatus "Choose a column to smooth."
        return
    }
    if ![string length $Smooth(xVar)] {
        setStatus "For display, choose a column to plot against."
        return
    }
    set plotOptList ""
    if [string compare $Smooth(xVar) Time]==0 {
        lappend plotOptList -ticks=xtime
    }
    if $Smooth(differenceColumns) {
        lappend plotOptList -layout=1,2 
    }
    foreach yVar [split $Smooth(yVar) ,] {
        if $Smooth(newColumns) {
            lappend plotOptList -column=$Smooth(xVar),${yVar}Smoothed \
              $Smooth(outputFile) -graph=line -legend=specified=Smoothed
        } else {
            lappend plotOptList -column=$Smooth(xVar),$yVar $Smooth(outputFile) -graph=line \
              -legend=specified=Smoothed
        }
        lappend plotOptList -column=$Smooth(xVar),$yVar $Smooth(inputFile) -graph=dot,type=1 \
          -legend=specified=Original -end
        if $Smooth(differenceColumns) {
            lappend plotOptList -column=$Smooth(xVar),${yVar}Unsmooth \
              $Smooth(outputFile) -graph=line -legend=specified=Difference -end
        }
    }
    
    lappend plotOptList $Smooth(layout)
    eval exec sddsplot $plotOptList &
}

proc EquationUpdateNames {args} {
    set lb ""
    set fileName ""
    set varList ""
    set class ""
    set arrayName ""
    APSStrictParseArguments {lb fileName arrayName  class}
    global $arrayName 
    global [os editstring S/(/Z) $fileName]
    
    if ![string length [set $fileName]] {
        setStatus "Give a filename!"
        return
    }
    
    if [ catch { APSGetSDDSNames -class $class -fileName [set $fileName ]} varList ] {
        setStatus $varList
	return
    }
    
    
    $lb delete 0 end
    foreach item  $varList { $lb insert end  $item }
}    
    	
proc EquationAddtoExpr {listboxItem doubleClick } {
    global Equation
    if ![string length $listboxItem] return
    if $doubleClick { 
       lappend Equation(expression) $listboxItem    
    }
   
}

proc RPNSelect {listboxItem doubleClick args } {
    global Equation
    global Rpn
    
    if ![string length $listboxItem] return
    if [info exists Rpn(${listboxItem}Help) ] {      
       setStatus  "$listboxItem: $Rpn(${listboxItem}Help)"
    }   
    if $doubleClick { 
       lappend Equation(expression) $listboxItem
    }
}         

# Help message for RPN constants and functions
set Rpn(c_cgsHelp)  "speed of light:cm/s"
set Rpn(c_mksHelp)  "speed of light: m/s" 
set Rpn(e_cgsHelp)  "elementray charge: esu" 
set Rpn(e_mksHelp)  "elementary charge: C" 
set Rpn(me_cgsHelp) "electron Mass: g"
set Rpn(me_mksHelp)   "electron Mass: kg" 
set Rpn(re_cgsHelp) "eletron radius: cm" 
set Rpn(re_mksHelp) " electron radius: m" 
set Rpn(kb_cgsHelp) "Boltzmann const: gcm^2/Ks^2"
set Rpn(kb_mksHelp)  "Boltzmann const: J/K" 
set Rpn(mevHelp) "MeV:0.51099906" 
set Rpn(hbar_mksHelp) "Planck const/2/pi:m^2kg/s" 
set Rpn(hbar_MeVsHelp)  "Planck const/2/pi:MeV" 
set Rpn(mp_mksHelp)  "proton rest mass" 
set Rpn(mu_oHelp)	  "Permeability constant of vacuum" 
set Rpn(eps_oHelp)	   "Permittivity of vacuum" 
set Rpn(KasHelp)  "constant for alpha-magnet"
set Rpn(KaqHelp) 	"constant for alpha-magnet"

set Rpn(atanHelp) "two arguments inverse tangent:atan(y/x).\nusage: atan2(y x) or x y atan2 "
set Rpn(JnHelp) "Bessel functions of integer order of the first kind.\nusage: Jn(i x) or x i Jn"
set Rpn(YnHelp) "Bessel functions of integer order of the secnond kind: \n usate: Yn(i x) or "
set Rpn(cei1Help) "1st complete elliptic integrals.\n usage: cei1(x) or x ceil"
set Rpn(cei2Help) "2nd complete elliptic integrals.\n usage: cei2(x) or x cei2"
set Rpn(erfHelp)  "error function.\n usage: erf(x) or x erf"
set Rpn(erfc2Help) "complimentary error function. \n usage:erfc(x) or x erfc"
set Rpn(gamPHelp) " incomplete gamma function. \n usage:gamP(a x) or x a gamP"
set Rpn(gamQHelp) " complimenetary incomplete gamma function. \n usage:gamQ(a x) or x a gamQ"
set Rpn(lngamHelp) "natural log of the gamma function.\usage: lngam(x)"
set Rpn(dtorHelp) "convert degrees to radians."
set Rpn(rtodHelp) "convert radians to degrees "
set Rpn(10xHelp) "10^x"
set Rpn(coshHelp) "hyperbolic cos"
set Rpn(sinhHelp) "heyperbolic sin"
set Rpn(TnHelp) " Chebyshev T polynomial"
set Rpn(hypotHelp) "sqrt(x^2+y^2) .\n usage: hypot(x y)"
set Rpn(interpHelp) "interpolate.\n usage: interp(y1 y0 x1 x0 x) or x x0 x1 y0 y1 interp"
set Rpn(dist2Help) "compute distance between 2 points.\n usage: dist2(y2 x2 y1 x1) or x1 y1 x2 y2 dist2"
set Rpn(kneeHelp) " =(atan(x) + (pi/2))/pi"
set Rpn(recHelp) " 1/x" 
set Rpn(factHelp) " n!"
set Rpn(meanHelp) " calculate the mean of n values.\n usage: mean(n,x1...xn) or x1...xn n mean"
set Rpn(rmsHelp)  "rms of N values.\n usage: rms(n,x1...xn) or x1...xn n rms"
set Rpn(beta.pHelp) "x/sqrt(1+x^2)"
set Rpn(gamma.pHelp) " sqrt(1+x^2)"
set Rpn(p.betaHelp) "x/sqrt(1-x^2)"
set Rpn(p.gammaHelp) "sqrt(x^2-1)"
set Rpn(gamma.betaHelp) "1/sqrt(1-x^2)"
set Rpn(KsprobHelp) "computes a Kolmolgorov-Smirnov t-test significance level"
set Rpn(t2SLHelp) "computes significance level for 2-tailed t distribution"
set Rpn(FSLHelp) " compute significance level for F-test"
set Rpn(rSLHelp) " compute significance level for Pearson's r(linear correlation coeffiecient)."
set Rpn(Chi2SLHelp) "compute significance level for chi-squared"


set Rpn(functionNames) [list sum abs sqrt sqr pow exp ln sin cos acos asin atan atan2 Jn Yn cei1 cei2 erf erfc gamP gamQ lngam \
                                 swap dsin dcos dacos dasin datan datan2 dtor rtod rec  cosh sinh tanh acosh asinh atanh \
                                 10x log_10 Tn hypot max2 min2 interp dist2 fact knee beta.p gamma.p p.beta  p.gamma gamma.beta KSprob \
				 mean rms t2SL FSL rSL Chi2SL ]
set Rpn(constantNames) [ list c_cgs c_mks e_cgs e_mks me_cgs me_mks re_cgs re_mks kb_cgs kb_mks mev hbar_mks hbar_MeVs mp_mks mu_o \
                                  eps_o	 Kas Kaq ]
   
proc AddEquationOptions {args} {
    set parent ""
    APSStrictParseArguments {parent}
    global Equation
    global env
    set Equation(outputFile) ""
    set Equation(defineType) "column"
    set Equation(definTypelist) ""
    set Equation(name) ""
    set Equation(namelist) ""
    set Equation(expression) ""
    set Equation(exprlist) ""
    set Equation(units) ""
    set Equation(dataType) "double"
    set Equation(layout) "-layout=1,1"
    set Equation(order) ""
    set Equation(xVar) ""
    set Equation(eListbox) "$parent.runlist.frame.elist.listbox"
    set Equation(cmdlist) ""
    global Rpn
    
    APSLabeledEntry .output -parent $parent -label "Output file: " -width 90 -commandButton 1 -textVariable Equation(outputFile) \
       -contextHelp "If not provided, the input file will be updated."
    
    APSFrame .selectbox -parent $parent 
    set w $parent.selectbox 
    eval pack $w [ pack info $w] -expand 1 -fill both
    set w $parent.selectbox.frame
    eval pack $w [pack info $w ] -expand 1 -fill both
         
       
    APSFrame .namelist -parent $parent.selectbox.frame -label "Name list:"
    set w $parent.selectbox.frame.namelist 
    eval pack $w [pack info $w] -expand 1   -side left -fill both
    set w $parent.selectbox.frame.namelist.frame 
    eval pack $w [ pack info $w] -expand 1  -fill both
    
    APSFrame .top -parent $w 
    set w2 $w.top
    eval pack $w2 [pack info $w2] -expand 1  -fill x -side top
    set w2 $w.top.frame
    eval pack $w2 [ pack info $w2] -expand 1  -fill x
    
       
    APSButton .pars -parent $w2 -text "Parameters:"    -packOption "-side left " \
       -command " EquationUpdateNames -lb $parent.selectbox.frame.namelist.frame.parslist.listbox -fileName Equation(inputFile)  -arrayName Equation -class parameter " \
       -contextHelp "To get the paramters in the input SDDS file."
           
    APSButton .cols -parent $w2 -text "Columns:   "    -packOption "-side right" \
       -command " EquationUpdateNames -lb $parent.selectbox.frame.namelist.frame.colslist.listbox -fileName Equation(inputFile)  -arrayName Equation -class column" \
       -contextHelp "TO get the columsn in the input SDDS file."
    
         
    APSScrolledList .parslist -parent $w   -height 2 -width 20  -selectMode single \
       -xscroll 1  -packOption "-side left -fill both -expand 1" -callback EquationAddtoExpr 
    APSScrolledList .colslist -parent $w    -height 2 -width 20  \
       -xscroll 1  -callback EquationAddtoExpr  -packOption "-fill both -expand 1"
       
       
    APSFrame .rpnselection -parent $parent.selectbox.frame -label "RPN built-ins:"
    set w $parent.selectbox.frame.rpnselection 
    eval pack $w [pack info $w ] -expand 1  -side right -fill both
    set w $parent.selectbox.frame.rpnselection.frame
    eval pack $w [pack info $w ] -expand 1 -fill both
    
    APSFrame .rpntop -parent $w 
    set w2 $w.rpntop
    eval pack $w2 [pack info $w2] -expand 1  -fill x -side top
    set w2 $w.rpntop.frame
    eval pack $w2 [ pack info $w2] -expand 1  -fill x
    
    
    APSLabel .rpnleft -parent $w2 -text "functions"    -packOption "-side left" \
       -contextHelp "Available functions from $env(RPN_DEFNS)." 
           
    APSLabel .rpnright -parent $w2 -text "constants"    -packOption "-side right" \
       -contextHelp "Availabel constants from $env(RPN_DEFNS)."
    
         
    APSScrolledList .fns -parent $w  -height 2 -width 10  -selectMode single \
       -xscroll 1  -packOption "-side left -fill both -expand 1"  -itemList $Rpn(functionNames) -callback "RPNSelect"
    APSScrolledList .const -parent $w    -height 2  -width 10  \
       -xscroll 1  -itemList $Rpn(constantNames) -callback "RPNSelect"  -packOption "-fill both -expand 1"
       
    APSFrame .newitem -parent $parent -label "New Item:"
    set w $parent.newitem 
    eval pack $w [pack info $w] -expand 1 -fill x  -side top
    set w $parent.newitem.frame 
    eval pack $w [ pack info $w] -expand 1 -fill x 
    
    APSRadioButtonFrame .mode -parent $w -label "Define: "  \
       -variable Equation(defineType) \
       -orientation horizontal \
       -buttonList [list parameter column] \
       -valueList [ list parameter column] \
       -contextHelp "Specifies creation of a new column or parameter."    
    
    APSLabeledEntry .name -parent $w -label "Name:" -width 90 -textVariable Equation(name) \
       -contextHelp "Input the name of the new parameter/column. "
    APSLabeledEntry .expr -parent $w -label "Equation: " -width 90 -textVariable Equation(expression) \
       -contextHelp "The RPN or algeraic expression to create the new parameter/column."    
    APSRadioButtonFrame .mathOrder -parent $w -label "Evaluation Type: " \
       -variable Equation(order)   \
       -orientation horizontal \
       -buttonList [list infix postfix ] \
       -valueList [list algebraic "" ] \
       -contextHelp "Select infix (Algebraic) or postfix (Reverse Polish Notation) expressions"
       
    APSLabeledEntry .unit -parent $w -label "Units:" -width 90 -textVariable Equation(units) \
       -contextHelp "Input the units of the  defined parameter/column." 
    
    APSRadioButtonFrame .type -parent $w -label "Data Type: "  \
       -variable Equation(dataType) \
       -orientation horizontal \
       -buttonList [list short long float double string character] \
       -valueList [ list short long float double string character] \
       -limitPerRow 6 \
       -contextHelp "Select the data type of the defined parameter/column" 
       
    APSButton .reset -parent $w -text "Reset" -command { set Equation(expression) ""; set Equation(name) ""; set Equation(units) "" }
    APSButton .add  -parent $w -text "Add to List" -command "EquationAddList"
    
    APSFrame .runlist -parent $parent -label "Evaluation List"
    set w $parent.runlist
    eval pack $w [pack info $w] -expand 1 -fill both
    set w $parent.runlist.frame
    eval pack $w [pack info $w] -expand 1 -fill both
    APSScrolledList .elist -parent $w -height 3 -width 65 -selectMode multiple -xscroll 1 -packOption "-side left -fill both -expand 1" 
    APSFrame .lstcmd -parent $w  -height 20 -width 20
    set w2 $w.lstcmd
    eval pack $w2 [pack info $w2] -expand 1 -fill both -side right
    set w2 $w.lstcmd.frame
    eval pack $w2 [pack info $w2] -expand 1 -fill both
    APSButton .remove -parent $w2 -text "Remove" -packOption "-side top" -command { \
           set curs [$Equation(eListbox) curselection];\
	   foreach item $curs { $Equation(eListbox) delete $item;\
	      set Equation(exprlist) [lreplace $Equation(exprlist) $item $item ];\
	      set Equation(cmdlist) [lreplace $Equation(cmdlist) $item $item ];  \
	      set Equation(defineTypelist) [lreplace  $Equation(defineTypelist) $item $item ];\
	      set Equation(namelist) [lreplace $Equation(namelist) $item $item] } \
	   }
    APSButton .clear  -parent $w2 -text "Clear"  -packOption "-side bottom" -command { \
           $Equation(eListbox) delete 0 end;\
	   set Equation(exprlist) "";\
	   set Equation(namelist) "";\
	   set Equation(defineTypelist) "";\
	   set Equation(cmdlist) "";}
    
    
    APSFrame .plot -parent $parent
    set w $parent.plot.frame      
    APSLabeledEntry .xvar -parent $w -label "Plot vs."  \
       -width 50 -textVariable Equation(xVar)  -packOption "-side left " \
       -contextHelp "Select the data column to plot angainst."
    APSButton .xvarselect -parent $w -text "Select..."  -packOption "-side right" \
       -contextHelp "Press to call up variable slection box." \
       -command  "varSelect -arrayName Equation -slot xVar -type x -filenameVariable Equation(inputFile) -single 1"      
          
       
    AddPlotLayoutWidget .layouts -parent $parent  -variable Equation(layout)  
    
    APSButton .run -parent $parent -text "Run" -command "RunEquation"  \
       -contextHelp ""
       
    APSButton .display -parent $parent -text "Display" -command "DisplayEquation" 
        
}

proc EquationAddList {} {
    global Equation
    set expression ""
    if ![string length $Equation(name)] {  setStatus "Supply a name for the new data." ;return}
    if ![string length $Equation(expression) ] {setStatus "No expression defined!" ; return}
    
    lappend Equation(exprlist) $Equation(expression)
    lappend Equation(namelist) $Equation(name)
    lappend Equation(defineTypelist) $Equation(defineType)
        
    append expression "-define=$Equation(defineType),$Equation(name),"
    set expression2 $expression
    
    append expression "\"$Equation(expression)\""
    append expression2 \"TO_BE_REPLACED\" 
    if [string length $Equation(order) ] {
       append expression  ",$Equation(order)"
       append expression2 ",$Equation(order)"
    }
    if [string length $Equation(units) ] {
       append expression ",units=$Equation(units)"
       append expression2 ",units=$Equation(units)"
    }
    append expression ",type=$Equation(dataType)"
    append expression2 ",type=$Equation(dataType)"
    
    $Equation(eListbox) insert  end $expression
    lappend Equation(cmdlist) $expression2
    
    
}    
     
proc RunEquation {} {
    global Equation
    if ![string length $Equation(inputFile)] {
        setStatus "Supply an input filename"
        return
    }
        
    APSAddToRecentFileList -filename $Equation(inputFile)
    
    set command "sddsprocess "
    append command " $Equation(inputFile) "
    if [string length $Equation(outputFile)] {
        append command " $Equation(outputFile) "
        APSAddToRecentFileList -filename $Equation(outputFile)
    } 
    
    if ![ eval expr [ $Equation(eListbox) size ] ] { setStatus "Evaluation list is empty! Nothing processed." ; return }
    set cmdshow $command
    
    set elist [$Equation(eListbox) get 0 end ]
    
    set ii 0 
    foreach item $elist i2 $Equation(cmdlist) {
        
        append cmdshow $item; append cmdshow " "
	set j0 [string first \" $i2]
	set j1 [string last \" $i2]
	set i2 [string replace $i2 $j0 $j1  "\[lindex \$Equation(exprlist) $ii\]" ] 
	append command  $i2 ; append command " "
	incr ii
    }
	
     
    setStatus $cmdshow  
    if [catch {  eval exec $command } result] {
         setStatus "$result"
         return
    }
      
    DisplayEquation
    setStatus "Done."
}
    
proc DisplayEquation {} {
    global Equation
    if ![string length $Equation(inputFile)] {
        setStatus "Supply an input filename"
        return
    }
    if ![string length $Equation(name)] {
        setStatus "Supply a name for the new data."
	return
    }
    
    if ![string length $Equation(expression)] {
        setStatus "No expression defined!"
	return
    }
    
    set filename $Equation(inputFile)
    if [string length $Equation(outputFile) ] {
          set filename $Equation(outputFile)
    }
    
    if ![ eval expr [ $Equation(eListbox) size ] ] { setStatus "Not processed yet. Nothing to plot." ; return }
    
    
    
    if ![string length $Equation(xVar)] {
       setStatus "Select a column to plot angainst."
       return
    }   
    set plotOptList ""
    set mode -ticks=xfactor=1
    if [string compare $Equation(xVar) Time]==0 {
        set mode -ticks=xtime
    }
    lappend plotOptList $mode
    foreach name $Equation(namelist) type $Equation(defineTypelist) {
       if { $type == "parameter" } {
       catch { eval exec sddsprintout $filename -parameters=$name } printout
       setStatus "$printout"
       }
       if { $type == "column" } {lappend plotOptList -column=$Equation(xVar),$name $filename -graph=line -legend=specified=$name -end}
    }
    lappend plotOptList $Equation(layout)
    
    eval exec sddsplot $plotOptList &
    
    
}    
    
       
proc AddIntegralOptions {args} {
    set parent ""
    APSStrictParseArguments {parent}
    global Integral
    set Integral(outputFile) ""
    set Integral(excludeWildcard) ""
    set Integral(errPropag) 0
    set Integral(ysigma) ""
    set Integral(xsigma) ""
    set Integral(results) ""
    set Integral(layout) "-layout=1,1"
    APSLabeledEntry .output -parent $parent -label "Output file: " -width 90 \
      -commandButton 1 -textVariable Integral(outputFile)
    
    APSLabeledEntry .excldWildcard -parent "$parent.vf.frame" -label "     Exclude wildcard:" \
      -width 50 -textVariable Integral(excludeWildcard)  \
      -contextHelp "Exclude wildcard string may be used to exclude variables from integral that are matched by a wild card string if used in the dependent variables."
    
    APSRadioButtonFrame .err -parent "$parent.vf.frame" -label "       Error propagation?" \
       -orientation horizontal   \
       -variable Integral(errPropag) \
       -buttonList [ list Yes No] \
       -valueList [list 1 0 ] \
       -commandList [ list "APSEnableWidget $parent.vf.frame.xs.frame.xsigma; APSEnableWidget $parent.vf.frame.ys.frame.ysigma; APSDisableWidget $parent.vf.frame.excldWildcard"\
                           "APSDisableWidget $parent.vf.frame.xs.frame.xsigma; APSDisableWidget $parent.vf.frame.ys.frame.ysigma;APSEnableWidget $parent.vf.frame.excldWildcard" \
                    ]\
       -contextHelp  "It will perform error propagation if error bars are provided in the data set."
    
    APSFrame .xs -parent "$parent.vf.frame" -relief flat
    set w "$parent.vf.frame.xs.frame"
    APSLabeledEntry .xsigma -parent $w -label "        SigmaX:"  \
       -width 30 -textVariable Integral(xsigma)  -packOption "-side left " \
       -contextHelp "Select the name of the column containing the error of the independent variable." 
    APSButton .xsgmselect -parent $w -text "Select..."  -packOption "-side right" \
       -contextHelp "Press to call up xSigma variable slection box." \
       -command  "varSelect -arrayName Integral -slot xsigma -type x -filenameVariable Integral(inputFile) -single 1"    
                
    APSFrame .ys -parent "$parent.vf.frame" -relief flat
    set w "$parent.vf.frame.ys.frame"
    APSLabeledEntry .ysigma -parent $w -label "        SigmaY:"  \
       -width 30 -textVariable Integral(ysigma)  -packOption "-side left " \
       -contextHelp "Select the name of the column/columns containing the error of the dependent variable/variables." 
    APSButton .ysgmselect -parent $w -text "Select..."  -packOption "-side right" \
       -contextHelp "Press to call up ySigma variable slection box." \
       -command  "varSelect -arrayName Integral -slot ysigma -type y -filenameVariable Integral(inputFile) -single 0"    
    
    APSDisableWidget $parent.vf.frame.xs.frame.xsigma      
    APSDisableWidget $parent.vf.frame.ys.frame.ysigma     
    
    
    
    AddPlotLayoutWidget .layouts -parent $parent  -variable Integral(layout)
    
       
    APSButton .run -parent $parent -text "Run" -command "RunIntegral"  \
       -contextHelp "Only trapizoidal rule integration method is supported now"
       
    APSButton .display -parent $parent -text "Display" -command "DisplayIntegral"    
    
    
    
   
}


proc RunIntegral {} {
    global Integral
    if ![string length $Integral(inputFile)] {
        setStatus "Supply an input filename"
        return
    }
    if ![string length $Integral(outputFile)] {
        setStatus "Supply an output filename"
        return
    }
    if ![string length $Integral(xVar)] {
        setStatus "Choose a column as independent variable."
        return
    }
    if ![string length $Integral(yVar)] {
        setStatus "Choose one or more columns as dependent variable."
        return
    }
    
    APSAddToRecentFileList -filename $Integral(inputFile)
    APSAddToRecentFileList -filename $Integral(outputFile) 
    
    set command "sddsinteg $Integral(inputFile) $Integral(outputFile) "
    
    set y [split [join $Integral(yVar) ,]  ,]
    
    if !$Integral(errPropag) {
         
         foreach item $y  {
              append command " -integrate=$item "
         }
	 if [string length $Integral(excludeWildcard) ] {
              append command " -exclude=[join $Integral(excludeWildcard) ,] "
         }
         append command "-versus=$Integral(xVar)"

    }  else {
         if [string length $Integral(ysigma)] {
               set ysigma [split [join $Integral(ysigma) ,] ,]
               foreach item $y err $ysigma {
                    append command "-integrate=$item,$err "
	       }
         } else { 
	       foreach item $y { append command "-integrate=$item " }
	 }
	 append command "-versus=$Integral(xVar)"
	 if [string length $Integral(xsigma)] {
	       append command ",$Integral(xsigma) "
	 }      
    }     
    append command " -printFinal"
    setStatus $command   
    if [catch { eval exec $command } result] {
         setStatus "\nIntegral Results:\n$result\nDone."
    }
    DisplayIntegral
}

proc DisplayIntegral {} {
    global Integral
    if ![string length $Integral(inputFile)] {
        setStatus "Supply an input filename"
        return
    }
    if ![string length $Integral(yVar)] {
        setStatus "Choose a column/columns to integrate."
        return
    }
    if ![string length $Integral(xVar)] {
        setStatus "Choose a column as independent variable."
        return
    }
    set plotOptList ""
    set mode -ticks=xfactor=1
    if [string compare $Integral(xVar) Time]==0 {
        set mode -ticks=xtime
    }
    lappend plotOptList $mode
    
           
       
    if [catch {APSGetSDDSNames -fileName $Integral(outputFile) -class column} varList] {
        setStatus "$varList"
        return
    }
    set xVar [lindex $varList 0 ]
    set yVar [lrange $varList 1 end ]
    if !$Integral(errPropag) {
        foreach y $yVar {
             lappend plotOptList -column=$xVar,$y $Integral(outputFile) -graph=line -legend=specified=$y -end
	}     
    } else {
        foreach {y yerr} $yVar {
	     lappend plotOptList  -column=$xVar,$y,$yerr $Integral(outputFile) -graph=error,subtype=1,connect=2 -legend=specified=$y  -end
        }
    }
    
    lappend plotOptList $Integral(layout)
    eval exec sddsplot $plotOptList &
    
}



proc AddDerivativeOptions {args} {
    set parent ""
    APSStrictParseArguments {parent}
    global Derivative
    set Derivative(outputFile) ""
    set Derivative(excludeWildcard) ""
    set Derivative(errPropag) 0
    set Derivative(ysigma) ""
    set Derivative(SG,use) 0
    set Derivative(SG,left) 1
    set Derivative(SG,right) 1 
    set Derivative(SG,fitOrder) 1
    set Derivative(SG,derivOrder) 1
    set Derivative(interval) 2
    set Derivative(layout) "-layout=1,1"
    APSLabeledEntry .output -parent $parent -label "Output file: " -width 90 \
      -commandButton 1 -textVariable Derivative(outputFile)
    
    APSLabeledEntry .excldWildcard -parent "$parent.vf.frame" -label "     Exclude wildcard:" \
      -width 50 -textVariable Derivative(excludeWildcard)  \
      -contextHelp "Exclude wildcard string may be used to exclude variables from derivative that are matched by a wild card string if used in the dependent variables."
    
    APSRadioButtonFrame .err -parent "$parent.vf.frame" -label "       Error propagation?" \
       -orientation horizontal   \
       -variable Derivative(errPropag) \
       -buttonList [ list Yes No] \
       -valueList [list 1 0 ] \
       -commandList [ list "APSEnableWidget $parent.vf.frame.ys.frame.ysigma; APSDisableWidget $parent.vf.frame.excldWildcard"\
                           "APSDisableWidget $parent.vf.frame.ys.frame.ysigma;APSEnableWidget $parent.vf.frame.excldWildcard" \
                    ]\
       -contextHelp  "It will perform error propagation if error bars are provided in the data set."
    
         
    APSFrame .ys -parent "$parent.vf.frame" -relief flat
    set w "$parent.vf.frame.ys.frame"
    APSLabeledEntry .ysigma -parent $w -label "        SigmaY:"  \
       -width 30 -textVariable Derivative(ysigma)  -packOption "-side left " \
       -contextHelp "Select the name of the column/columns containing the error of the dependent variable/variables." 
    APSButton .ysgmselect -parent $w -text "Select..."  -packOption "-side right" \
       -contextHelp "Press to call up ySigma variable slection box." \
       -command  "varSelect -arrayName Derivative -slot ysigma -type y -filenameVariable Derivative(inputFile) -single 0"      
       
    APSDisableWidget $parent.vf.frame.ys.frame.ysigma
    
    
    APSRadioButtonFrame .method -parent $parent -label "Savitzky-Golay Smoothing Filter?" \
       -orientation horizontal \
       -variable Derivative(SG,use) \
       -buttonList [ list Yes No] \
       -valueList [ list 1 0 ] \
       -commandList [ list "APSDisableWidget $parent.intvfr ; APSEnableWidget $parent.sg" \
                           "APSEnableWidget $parent.intvfr ; APSDisableWidget $parent.sg" \
                    ] \
       -contextHelp "Choose the diverivative algorithms to apply."
       
    APSFrame .intvfr -parent $parent -relief flat 
    APSLabeledEntry .interval  -parent "$parent.intvfr.frame" -label "Interval:"   -width 15  \
       -textVariable Derivative(interval) \
       -contextHelp "Specifies the spacing of the data points used to approximate the derivative. The default value of 2 specifies that the derivative for each point will be obtained from values 1 row above and 1 row below the point."
       
    APSFrame .sg -parent $parent -label "Savitzky-Golay Parameters" \
       -contextHelp "Specifyies the paramters for Savitzky-Golay smoothing filter to  perform the derivative."
    set w "$parent.sg.frame"
    APSLabeledEntry .sgleft -parent $w -label "Points on left:" -width 15 \
       -textVariable Derivative(SG,left) \
       -contextHelp "Enter the number of points on left side to be used for smoothing."
       
    APSLabeledEntry .sgright -parent $w -label "Points on right:" -width 15 \
       -textVariable Derivative(SG,right) \
       -contextHelp "Enter the number of points on right side to be used for smoothing."    
       
    APSLabeledEntry .sgfitOrder -parent $w -label "Fit Order:" -width 15 \
       -textVariable Derivative(SG,fitOrder) \
       -contextHelp "Enter the order of the fits to use for replacing points.  1 is a linear fit, 2 is quadratic, and so on."  
    
    APSLabeledEntry .sgDerivOrder -parent $w -label "Derivative Order:" -width 15 \
       -textVariable Derivative(SG,derivOrder) \
       -contextHelp "Derivative Order is 1 by default and gives the order of derivative to take."     
       
    APSEnableWidget $parent.intvfr ; APSDisableWidget $parent.sg    
    
    AddPlotLayoutWidget .layouts -parent $parent  -variable Derivative(layout)
    
    APSButton .run -parent $parent -text "Run" -command "RunDerivative"
    APSButton .display -parent $parent -text "Display" -command "DisplayDerivative"
    
       
}

proc RunDerivative {} {
    global Derivative
    if ![string length $Derivative(inputFile)] {
        setStatus "Supply an input filename"
        return
    }
    if ![string length $Derivative(outputFile)] {
        setStatus "Supply an output filename"
        return
    }
    if ![string length $Derivative(xVar)] {
        setStatus "Choose a column as independent variable."
        return
    }
    if ![string length $Derivative(yVar)] {
        setStatus "Choose one or more columns as dependent variable."
        return
    }
    
    APSAddToRecentFileList -filename $Derivative(inputFile)
    APSAddToRecentFileList -filename $Derivative(outputFile)
    set command "sddsderiv $Derivative(inputFile) $Derivative(outputFile) "
    
    if $Derivative(SG,use) {
         append command " -SavitzkyGolay=$Derivative(SG,left),$Derivative(SG,right),$Derivative(SG,fitOrder),$Derivative(SG,derivOrder)"
    } else { 
         append command " -interval=$Derivative(interval) " 
    }
    
   
    set y [split [join $Derivative(yVar) ,]  ,]
    
    if !$Derivative(errPropag) {
         
         foreach item $y  {
              append command " -differentiate=$item "
         }
	 if [string length $Derivative(excludeWildcard) ] {
              append command " -exclude=[join $Derivative(excludeWildcard) ,] "
         }
         

    }  else {
         if [string length $Derivative(ysigma)] {
               set ysigma [split [join $Derivative(ysigma) ,] ,]
               foreach item $y err $ysigma {
                    append command "-differentiate=$item,$err "
	       }
         } else { 
	       foreach item $y { append command "-differentiate=$item " }
	 }
    }     
      
    append command "-versus=$Derivative(xVar)"  	           

    
    setStatus $command   
    if [catch { eval exec $command } result] {
         setStatus "$result"
         return
    }
    setStatus "Done."
    DisplayDerivative
}    

proc DisplayDerivative {} {
    global Derivative
    if ![string length $Derivative(inputFile)] {
        setStatus "Supply an input filename"
        return
    }
    if ![string length $Derivative(outputFile)] {
        setStatus "Supply an output filename"
        return
    }
    if ![string length $Derivative(xVar)] {
        setStatus "Choose a column as the dependent variable"
        return
    }
    if ![string length $Derivative(yVar)] {
        setStatus "Choose a column to defferentiate"
        return
    }
    set plotOptList ""
    if [string compare $Derivative(xVar) Time]==0 {
        lappend plotOptList -ticks=xtime
    }
    
    if [catch {APSGetSDDSNames -fileName $Derivative(outputFile) -class column} varList] {
        setStatus "$varList"
        return
    }
    
    set xVar [lindex $varList 0 ]
    set yVar [lrange $varList 1 end ]
    if !$Derivative(errPropag) {
        foreach y $yVar {
             lappend plotOptList -column=$xVar,$y $Derivative(outputFile) -graph=line -legend=specified=$y -end
	}     
    } else {
        foreach {y yerr} $yVar {
	     lappend plotOptList  -column=$xVar,$y,$yerr $Derivative(outputFile) -graph=error,subtype=1,connect=2 -legend=specified=$y  -end
        }
    }	
    lappend plotOptList $Derivative(layout)
    eval exec sddsplot $plotOptList &
	
}


proc AddPeakfindOptions {args} {
    set parent ""
    APSStrictParseArguments {parent}
    global Peakfind
    set Peakfind(threshold,type) "None"
    set Peakfind(threshold,value) 0
    set Peakfind(threshold,parameter) ""
    set Peakfind(changeThresholdGiven) 0
    set Peakfind(changeThreshold) 0.0
    set Peakfind(exclusionZoneGiven) 0
    set Peakfind(exclusionZone) 0.0
    set Peakfind(fivePoint) ""
    set Peakfind(outputFile) ""
    set Peakfind(layout) "-layout=1,1"
    APSLabeledEntry .output -parent $parent -label "Output file: " -width 90 \
      -commandButton 1 -textVariable Peakfind(outputFile) 

    APSFrame .threshold -parent $parent -label "Threshold" 
    set w $parent.threshold.frame

    APSRadioButtonFrame .mode -parent $w -label "Mode: " -orientation horizontal \
      -buttonList {None Value Parameter} \
      -valueList {None Value Parameter} \
      -variable Peakfind(threshold,type) \
      -commandList [list \
    "APSDisableWidget $w.thresValue; APSDisableWidget $w.thresParam" \
    "APSEnableWidget $w.thresValue; APSDisableWidget $w.thresParam" \
    "APSDisableWidget $w.thresValue; APSEnableWidget $w.thresParam" \
    ] \
      -contextHelp "Choose the threshold mode for peakfinding.  With no threshold, you may get many false peaks that are just noise."

    APSLabeledEntry .thresValue -parent $w -label "Value: " \
      -textVariable Peakfind(threshold,value) \
      -type real -contextHelp \
      "Enter the value for the threshold.  Apparent peaks that are smaller than this will be ignored."
    APSLabeledEntry .thresParam -parent $w -label "Parameter: " \
      -textVariable Peakfind(threshold,parameter) \
      -contextHelp \
      "Enter the parameter from which the threshold value should be taken.  This parameter must exist in your input file. Apparent peaks that are smaller than this will be ignored."
    APSDisableWidget $w.thresValue
    APSDisableWidget $w.thresParam

    APSRadioButtonFrame .method -parent $w -label "Method: " \
      -variable Peakfind(fivePoint) -buttonList "Three-point Five-point" \
      -valueList [list "" -fivePoint] -orientation horizontal \
      -contextHelp \
      "Choose whether to use three- or five-point algorithm for finding peaks.  If you use five-point, you may miss very narrow peaks.  If your peaks are all relatively large, then five-point is recommended to avoid choosing noise spikes."

    APSLabeledEntry .chThres -parent $w -label "Change threshold: " \
      -textVariable Peakfind(changeThreshold) -enableVariable Peakfind(changeThresholdGiven) \
      -width 25 -contextHelp \
      "Specifies a threshold for elimination of candidate peaks by looking at the fractional change between the peak value and its nearest neighbors.  If the fractional change is less than the given amount, then the peak is not included in the output.  This can help in selecting only sharp features."
    APSLabeledEntry .exclusionZone -parent $w -label "Exclusion zone: " \
      -textVariable Peakfind(exclusionZone) -enableVariable Peakfind(exclusionZoneGiven) \
      -width 25 -contextHelp \
      "Specifies a zone around any peak within which no other peaks will be recognized.  The zone is specified as a fraction of the length of the data table.  E.g., if you have 1000 points and a zone of 0.01, then there will be only one peak selected in any successive group of 10 points."

    AddPlotLayoutWidget .layouts -parent $parent  -variable Peakfind(layout)  
    APSButton .run -parent $parent -text "Run" -command "RunPeakfind"
    APSButton .display -parent $parent -text "Display" -command "DisplayPeakfind"
}

proc RunPeakfind {} {
    global Peakfind
    if ![string length $Peakfind(inputFile)] {
        setStatus "Supply an input filename"
        return
    }
    if ![string length $Peakfind(outputFile)] {
        setStatus "Supply an output filename"
        return
    }
    if ![string length $Peakfind(yVar)] {
        setStatus "Choose a column to smooth."
        return
    }

    APSAddToRecentFileList -filename $Peakfind(inputFile)
    APSAddToRecentFileList -filename $Peakfind(outputFile)
    set command "sddspeakfind -column=[join $Peakfind(yVar) ,] "
    foreach item {inputFile outputFile fivePoint} {
        if [string length $Peakfind($item)] {
            append command " $Peakfind($item) "
        }
    }
    switch $Peakfind(threshold,type) {
        Value {
            append command " -threshold=$Peakfind(threshold,value) "
        }
        Parameter {
            append command " -threshold=@$Peakfind(threshold,parameter) "
        }
        default {
        }
    }
    foreach item {changeThreshold exclusionZone} {
        if [set Peakfind\(${item}Given\)] {
            append command " -$item=$Peakfind($item) "
        }
    }

    setStatus "$command"
    if [catch {eval exec $command} result] {
        setStatus "$result"
        return
    }
    DisplayPeakfind
    setStatus "Done."
}

proc DisplayPeakfind {} {
    global Peakfind
    if ![string length $Peakfind(inputFile)] {
        setStatus "Supply an input filename"
        return
    }
    if ![string length $Peakfind(outputFile)] {
        setStatus "Supply an output filename"
        return
    }
    if ![string length $Peakfind(yVar)] {
        setStatus "Choose a column to smooth."
        return
    }
    if ![string length $Peakfind(xVar)] {
        setStatus "For display, choose a column to plot against."
        return
    }
    set mode -ticks=xfactor=1
    if [string compare $Peakfind(xVar) Time]==0 {
        set mode -ticks=xtime
    }
    exec sddsplot $mode \
      -column=$Peakfind(xVar),$Peakfind(yVar) $Peakfind(inputFile) \
      -column=$Peakfind(xVar),$Peakfind(yVar) $Peakfind(outputFile) \
      -graph=symbol,scale=0.5,subtype=1 $Peakfind(layout) &
}

proc AddNormalizeOptions {args} {
    set parent ""
    APSStrictParseArguments {parent}
    
    global Normalize
    set Normalize(inputFile)
    set Normalize(outputFile) ""
    set Normalize(excludeWildcard) ""
    set Normalize(newclmn) 0
    set Normalize(suffix) ""
    set Normalize(mode) "largest"
    set Normalize(layout) "-layout=1,1"
    
    APSLabeledEntry .excldWildcard -parent "$parent.vf.frame" -label "      Exclude wildcard:" \
      -width 30 -packOption "-side left" -textVariable Normalize(excludeWildcard) \
      -contextHelp "Exclude wildcard string may be used to exclude variables from normalization that are matched by a wild card string if used in the dependent variables."
      
    APSLabeledEntry .output -parent $parent -label "Output file: " -width 70 \
      -commandButton 1 -textVariable Normalize(outputFile)
    
      
    
    APSRadioButtonFrame .options -parent $parent -label "  Normalization Mode" \
       -variable Normalize(mode) \
       -buttonList [list Minimum Maximum Largest "Signed largest" Spread RMS "Standard Deviation"] \
       -valueList [ list minimum maximum largest signedlargest spread rms standarddeviation ] \
       -orientation vertical \
       -contextHelp "The mode refers to the factor used for normalization Largest (the default) is max(abs(min), abs(max)). SignedLargest is largest with the sign of the value retained. Spread is max-min. Rms is the root-mean-square of the values, while Standard deviation is the n-1 weighted standard deviation of the values."
       
         
    APSFrame .newclmn -parent $parent -label "Create New Columns for Normalized Data?" 
     
    APSLabeledEntry .suffix -parent "$parent.newclmn.frame" -label "Suffix:" -width 30 -textVariable Normalize(suffix) \
       -enableVariable Normalize(newclmn) \
       -contextHelp "The suffix is a string that is appended to the column name to make the new column name.  If left blank, the original column is  replaced."  
     
    
    AddPlotLayoutWidget .layouts -parent $parent  -variable Normalize(layout)   
    
    APSButton .run -parent $parent -text "Run" -command "RunNormalize"
    APSButton .display -parent $parent -text "Display" -command "DisplayNormalize"  \
       -contextHelp "Open output file with sddsEditNew to display the normalized data columns"
       
}

proc RunNormalize {} {
    global Normalize
    if ![string length $Normalize(inputFile)] {
         setStatus "Supply an input filename"
         return
    }
    if ![string length $Normalize(outputFile)] {
         setStatus "Supply an output filename"
         return
    }
    if ![string length $Normalize(yVar)] {
         setStatus "Choose one or more columns to normalize."
         return
    }

    APSAddToRecentFileList -filename $Normalize(inputFile)
    APSAddToRecentFileList -filename $Normalize(outputFile)
    
    set command "sddsnormalize $Normalize(inputFile) $Normalize(outputFile) -columns=[join $Normalize(yVar) ,],mode=$Normalize(mode),"
        
    if $Normalize(newclmn) { append command "suffix=$Normalize(suffix)," }
    
    append command "exclude=[join $Normalize(excludeWildcard) ,]" 
    
    
    setStatus "$command"
    if [catch { eval exec $command } result] {
         setStatus "$result"
         return
    }
    setStatus "Done."
    DisplayNormalize
}

proc DisplayNormalize {} {
    global Normalize
    if ![string length $Normalize(inputFile)] {
        setStatus "Supply an input filename"
        return
    }
    if ![string length $Normalize(outputFile)] {
        setStatus "Supply an output filename"
        return
    }
    if ![string length $Normalize(yVar)] {
        setStatus "Choose a column/columns to normalize."
        return
    }
    if ![string length $Normalize(xVar)] {
        setStatus "To display, choose a column to plot against."
        return
    }
    
    set plotOptList ""
    set mode -ticks=xfactor=1
    if [string compare $Normalize(xVar) Time]==0 {
        set mode -ticks=xtime
    }
    lappend plotOptList $mode
    
    if [catch {APSGetSDDSNames -fileName $Normalize(inputFile) -class column} varList] {
        setStatus "$varList"
        return
    }
    set yVar [split [join $Normalize(yVar) ,] ,]
    foreach var $varList {
         foreach y $yVar {
	     if { [string match $y $var] && ![string match $Normalize(excludeWildcard) $var] } {
	         set varNew $var
		 if $Normalize(newclmn) { append varNew $Normalize(suffix) } 
		 lappend plotOptList -column=$Normalize(xVar),$varNew $Normalize(outputFile) -graph=line -legend=specified=$varNew -end
                 break
             }
	 }
    }	
    lappend plotOptList $Normalize(layout)        
    eval exec sddsplot $plotOptList &
    
}       

proc FillTabFrame {widget args} {
    set type ""
    set filename ""
    set yOnly 0
    set single 0
    APSStrictParseArguments {type filename yOnly single}
    APSLabeledEntry .file -parent $widget -textVariable $type\(inputFile\) \
      -width 70 -commandButton 1 -label "Filename: " 
    makeVariableFrame .vf -parent $widget -filenameVariable $type\(inputFile\) \
      -arrayName $type -yOnly $yOnly -single $single
    
    if [string length $filename] {
        global $type
        set $type\(inputFile\) $filename
    }
    catch {Add${type}Options -parent $widget}
}

proc FillEquationTabFrame {widget args} {
    set type ""
    set filename ""
    APSStrictParseArguments {type filename}
    APSLabeledEntry .file -parent $widget -textVariable $type\(inputFile\) \
      -width 70 -commandButton 1 -label "Filename: " 
      
    if [string length $filename] {
        global $type
        set $type\(inputFile\) $filename
    }
    catch {Add${type}Options -parent $widget}
}

set tabLabelList [list Equation Integral Derivative Smooth Peakfind Normalize]
set yOnlyList [list 0 0 0 0 0 0]
set singleList [list 0 0 0 0 1 0]
set tabWidgetList [APSTabFrame .main -parent .userFrame -label "" \
                     -labelList $tabLabelList -width 700 -height 650]
foreach tabWidget $tabWidgetList label $tabLabelList yOnly $yOnlyList single $singleList {
    if [string compare $label Equation]==0 {
        FillEquationTabFrame $tabWidget -type $label -filename $filename

    } else {
        FillTabFrame $tabWidget -type $label -filename $filename -yOnly $yOnly -single $single
    }
}

setStatus "Note: This is version 1.7."

