#!/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)]

APSApplication . -name ArbitraryWaveformEditor -contextHelp "Use this tool to load a waveform, edit it, and save it."


package require BLT
package require sdds
package require rpn

proc LoadDefaultWaveform {args} {
    global default status
    set count $default(count)
    set offset $default(offset)
    set xmin $default(xmin)
    set xmax $default(xmax)
    APSStrictParseArguments {count offset xmin xmax}
    set interval [expr ($xmax - $xmin) / ($count - 1.0)]
    $::X seq $xmin $xmax $interval
    for {set n 1} {$n <= $count} {incr n} {
        append WaveformList "$offset "
    }
    $::Y set $WaveformList
    $::X2 set [$::X range 0 end]
    $::Y2 set [$::Y range 0 end]
    $::X3 set [$::X range 0 end]
    $::Y3 set [$::Y range 0 end]
    $::X4 set [$::X range 0 end]
    $::Y4 set [$::Y range 0 end]
    ZoomOut
    set status "Default waveform loaded"
}

proc LoadPVWaveform {args} {
    global loadpv status savefile
    set pv $loadpv(name)
    set xmin $loadpv(xmin)
    set xinterval $loadpv(xinterval)
    APSStrictParseArguments {pv xmin xinterval}
    if {[catch {exec caget $pv} results]} {
        set status "Unable to load $pv : $results"
        return
    }
    set WaveformList [lrange $results 2 end]
    set count [lindex $results 1]
    set x $xmin
    for {set n 1} {$n <= $count} {incr n} {
        append IndexList "$x "
	incr x $xinterval
    }
    $::X set $IndexList
    $::Y set $WaveformList
    $::X2 set [$::X range 0 end]
    $::Y2 set [$::Y range 0 end]
    $::X3 set [$::X range 0 end]
    $::Y3 set [$::Y range 0 end]
    $::X4 set [$::X range 0 end]
    $::Y4 set [$::Y range 0 end]
    ZoomOut
    set savefile(pv) $pv
    set status "PV $pv loaded"
}

proc LoadWaveform {args} {
    global savefile status
    set name $savefile(name)
    set pv $savefile(pv)
    APSStrictParseArguments {name pv}
    if {[catch {sdds load $name data} results]} {
	set status "Error: $results"
	return
    }
    if {[info exists data(Column.X)]} {
	$::X set [lindex $data(Column.X) 0]
    } else {
	$::X set [lindex $data(Column.Index) 0]
    }
    $::Y set [lindex $data(Column.Waveform) 0]
    $::X2 set [$::X range 0 end]
    $::Y2 set [$::Y range 0 end]
    $::X3 set [$::X range 0 end]
    $::Y3 set [$::Y range 0 end]
    $::X4 set [$::X range 0 end]
    $::Y4 set [$::Y range 0 end]
    ZoomOut
    set savefile(pv) [lindex $data(Parameter.WaveformPV) 0]
    set status "$name loaded"
}

proc SaveWaveform {args} {
    global savefile status
    set name $savefile(name)
    set pv $savefile(pv)
    APSStrictParseArguments {name pv}
    set x [$::X2 range 0 end]
    set y [$::Y2 range 0 end]

    set data(ParameterNames) "WaveformPV"
    set data(ColumnNames) "Index X Waveform"
    set data(ParameterInfo.WaveformPV) "type SDDS_STRING"
    set data(ColumnInfo.Index) "type SDDS_LONG"
    set data(ColumnInfo.Waveform) "type SDDS_FLOAT"
    set data(ColumnInfo.X) "type SDDS_FLOAT"
    set data(Parameter.WaveformPV) [list $pv]
    set count [llength $x]
    set IndexList ""
    for {set n 0} {$n < $count} {incr n} {
	append IndexList "$n "
    }
    set data(Column.Index) [list $IndexList]
    set data(Column.X) [list $x]
    set data(Column.Waveform) [list $y]
    if {[catch {sdds save $name data} results]} {
	set status "Error: $results"
    } else {
	set status "Waveform saved to $name"
    }
}

proc ApplyEquation {args} {
    set mode add
    set segment 1
    set type sine
    APSStrictParseArguments {mode segment type}
    global sine cosine linear exponential gaussian custom status applyToAll
    global zoomleftpositionstart zoomrightpositionstart leftedge rightedge zoomrangewidth
    set y2 ""
    foreach x [$::X2 range 0 end] y [$::Y2 range 0 end] {
	if {$type == "sine"} {
	    set value [expr $sine(amplitude) * sin($sine(frequency) * $x + $sine(phase)) + $sine(offset)]
	} elseif {$type == "cosine"} {
	    set value [expr $cosine(amplitude) * cos($cosine(frequency) * $x + $cosine(phase)) + $cosine(offset)]
	} elseif {$type == "linear"} {
	    set value [expr $linear(slope) * $x + $linear(yintercept)]
	} elseif {$type == "exponential"} {
	    set value [expr $exponential(amplitude) * pow($exponential(basis),$exponential(multiplier) * $x) + $exponential(offset)]
	} elseif {$type == "gaussian"} {
	    set value [expr $gaussian(a) * exp(-(pow($x - $gaussian(b),2)) / (2 * pow($gaussian(c),2))) + $gaussian(d)]
	} elseif {$type == "custom"} {
            set a $custom(a)
            set b $custom(b)
            set c $custom(c)
            set d $custom(d)
            if {$custom(rpn)} {
                set value [eval rpn expr \"$custom(equation)\"]
                rpn clear
            } else {
                set value [expr $custom(equation)]
            }
	}
	if {$mode == "view"} {
	    append y2 "$value "
	} elseif {$mode == "replace"} {
	    append y2 "$value "
	} elseif {$mode == "add"} {
	    append y2 "[expr $y + $value] "
	} elseif {$mode == "subtract"} {
	    append y2 "[expr $y - $value] "
	}
    }
    set leftzoom [expr ($zoomleftpositionstart - $leftedge) * 1.0 / $zoomrangewidth]
    set rightzoom [expr ($zoomrightpositionstart - $rightedge) * 1.0 / $zoomrangewidth]
    set range [expr [$::X2 length] - 1]
    if {$mode == "view"} {
	$::Y4 set $y2
        $::X4 set [$::X2 range 0 end]
	#$::X2 dup $::X4
	$::X3 set [$::X4 range [expr round($leftzoom * $range)] [expr $range - round($rightzoom * $range)]]
	$::Y3 set [$::Y4 range [expr round($leftzoom * $range)] [expr $range - round($rightzoom * $range)]]
	.userFrame.g element configure Equation -hide no
    } else {
	if {$applyToAll} {
	    $::Y2 set $y2
	} else {
	    set y3 [$::Y2 range 0 end]
	    $::Y2 set [join [lreplace $y3 [expr round($leftzoom * $range)] [expr $range - round($rightzoom * $range)] [lrange $y2 [expr round($leftzoom * $range)] [expr $range - round($rightzoom * $range)]]]]
	}
	$::Y set [$::Y2 range [expr round($leftzoom * $range)] [expr $range - round($rightzoom * $range)]]
	.userFrame.g element configure Equation -hide no
    }
}

proc HideEquation {args} {
    .userFrame.g element configure Equation -hide yes
}

proc PackZoomWidget {args} {
    global leftedge rightedge zoomleftpositionstart zoomrightpositionstart zoomrangewidth 
    frame .userFrame.zoomrange -height 20 -bg grey75
    pack .userFrame.zoomrange -fill x -pady 10
    
    set leftedge 30
    set rightedge 110
    update
    for {set n 0} {$n < 200} {incr n} {
        if {[.userFrame.g inside $n 200] == 1} {
            set leftedge [expr $n - 10]
            break
        }
    }
    for {set n 800} {$n > 200} {incr n -1} {
        if {[.userFrame.g inside $n 200] == 1} {
            set rightedge [expr 800 - $n]
            break
        }
    }
    
    frame .userFrame.zoomrange.left -width $leftedge
    place .userFrame.zoomrange.left -in .userFrame.zoomrange -x 0 -y 0 -relheight 1.0
    frame .userFrame.zoomrange.zoomleft -bg blue -height 20 -width 10 -relief raised -bd 2
    place .userFrame.zoomrange.zoomleft -in .userFrame.zoomrange -x $leftedge 
    frame .userFrame.zoomrange.zoomright -bg blue -height 20 -width 10 -relief raised -bd 2
    place .userFrame.zoomrange.zoomright -in .userFrame.zoomrange -relx 1.0 -x -$rightedge
    frame .userFrame.zoomrange.right -height 20 -width [expr $rightedge - 10]
    place .userFrame.zoomrange.right -in .userFrame.zoomrange -relx 1.0 -x -[expr $rightedge - 10]
    
    set zoomleftpositionstart $leftedge
    set zoomrangewidth [expr [winfo width .] - $leftedge - $rightedge]
    bind .userFrame.zoomrange.zoomleft <ButtonPress-1> {
        set zoomleftstart %X
        set zoomrangewidth [expr [winfo width .] - $leftedge - $rightedge]
    }
    bind .userFrame.zoomrange.zoomleft <B1-Motion> {
        set diff [expr %X - $zoomleftstart]
        set position [expr $zoomleftpositionstart + $diff]
        if {$position < $leftedge} {
            set position $leftedge
        } elseif {$position >= [expr $leftedge + $zoomrangewidth + $rightedge - $zoomrightpositionstart - 10]} {
            set position [expr $leftedge + $zoomrangewidth + $rightedge - $zoomrightpositionstart - 11]
        }
        place configure .userFrame.zoomrange.zoomleft -x $position
    }
    bind .userFrame.zoomrange.zoomleft <ButtonRelease-1> {
        set diff [expr %X - $zoomleftstart]
        set position [expr $zoomleftpositionstart + $diff]
        if {$position < $leftedge} {
            set position $leftedge
        } elseif {$position >= [expr $leftedge + $zoomrangewidth + $rightedge - $zoomrightpositionstart - 10]} {
            set position [expr $leftedge + $zoomrangewidth + $rightedge - $zoomrightpositionstart - 11]
        }
        place configure .userFrame.zoomrange.zoomleft -x $position
        set zoomleftpositionstart $position
        
        ZoomIn
    }
    

    set zoomrightpositionstart $rightedge
    bind .userFrame.zoomrange.zoomright <ButtonPress-1> {
        set zoomrightstart %X
        set zoomrangewidth [expr [winfo width .] - $leftedge - $rightedge]
    }
    bind .userFrame.zoomrange.zoomright <B1-Motion> {
        set diff [expr $zoomrightstart - %X]
        set position [expr $zoomrightpositionstart + $diff]
        if {$position < $rightedge} {
            set position $rightedge
        } elseif {$position >= [expr $rightedge + $zoomrangewidth + $leftedge - $zoomleftpositionstart - 10]} {
            set position [expr $rightedge + $zoomrangewidth + $leftedge - $zoomleftpositionstart - 11]
        }
        place configure .userFrame.zoomrange.zoomright -x -$position
    }
    bind .userFrame.zoomrange.zoomright <ButtonRelease-1> {
        set diff [expr $zoomrightstart - %X]
        set position [expr $zoomrightpositionstart + $diff]
        if {$position < $rightedge} {
            set position $rightedge
        } elseif {$position >= [expr $rightedge + $zoomrangewidth + $leftedge - $zoomleftpositionstart - 10]} {
            set position [expr $rightedge + $zoomrangewidth + $leftedge - $zoomleftpositionstart - 11]
        }
        place configure .userFrame.zoomrange.zoomright -x -$position
        set zoomrightpositionstart $position
        
        ZoomIn
    }
}

proc ZoomIn {args} {
    global zoomleftpositionstart zoomrightpositionstart leftedge rightedge zoomrangewidth status

    set leftzoom [expr ($zoomleftpositionstart - $leftedge) * 1.0 / $zoomrangewidth]
    set rightzoom [expr ($zoomrightpositionstart - $rightedge) * 1.0 / $zoomrangewidth]
    set range [expr [$::X2 length] - 1]
    set a [expr round($leftzoom * $range)]
    set b [expr $range - round($rightzoom * $range)]
    $::X set [$::X2 range $a $b]
    $::Y set [$::Y2 range $a $b]
    $::X3 set [$::X4 range $a $b]
    $::Y3 set [$::Y4 range $a $b]

    set status "Viewable range [$::X index 0] to [$::X index end]"
}

proc ZoomOut {args} {
    global zoomleftpositionstart zoomrightpositionstart leftedge rightedge status
    update
    for {set n 0} {$n < 200} {incr n} {
        if {[.userFrame.g inside $n 200] == 1} {
            set leftedge [expr $n - 10]
            break
        }
    }
    set zoomleftpositionstart $leftedge
    set zoomrightpositionstart $rightedge
    place configure .userFrame.zoomrange.left -width $leftedge
    place configure .userFrame.zoomrange.zoomleft -x $leftedge
    place configure .userFrame.zoomrange.zoomright -x -$rightedge
    set status "Viewable range [$::X index 0] to [$::X index end]"
}

proc PackNotebookPanel {args} {
    global default loadpv savefile sine cosine linear exponential gaussian custom applyToAll
    pack [ttk::notebook .userFrame.nb]
    .userFrame.nb add [frame .userFrame.nb.f0] -text "Load Default"
    .userFrame.nb add [frame .userFrame.nb.f6] -text "Load PV"
    .userFrame.nb add [frame .userFrame.nb.f7] -text "Load File"
    .userFrame.nb add [frame .userFrame.nb.f8] -text "Save File"
    .userFrame.nb add [frame .userFrame.nb.f1] -text "Sine"
    .userFrame.nb add [frame .userFrame.nb.f2] -text "Cosine"
    .userFrame.nb add [frame .userFrame.nb.f3] -text "Linear"
    .userFrame.nb add [frame .userFrame.nb.f4] -text "Exponential"
    .userFrame.nb add [frame .userFrame.nb.f5] -text "Gaussian"
    .userFrame.nb add [frame .userFrame.nb.f9] -text "Custom"
    
    #################LOADDEFAULT######################
    set default(count) 101
    set default(offset) 0
    set default(xmin) 0
    set default(xmax) 100
    APSLabeledEntry .le1 -parent .userFrame.nb.f0 -label "    Count:" -textVariable default(count) -packOption "-fill x -expand yes"
    APSLabeledEntry .le2 -parent .userFrame.nb.f0 -label "   Offset:" -textVariable default(offset) -packOption "-fill x -expand yes"
    APSLabeledEntry .le3 -parent .userFrame.nb.f0 -label "X Minimum:" -textVariable default(xmin) -packOption "-fill x -expand yes"
    APSLabeledEntry .le4 -parent .userFrame.nb.f0 -label "X Maximum:" -textVariable default(xmax) -packOption "-fill x -expand yes"
    APSButton .b1 -parent .userFrame.nb.f0 -text "Load" -command "LoadDefaultWaveform" -packOption "-anchor nw"
    #################LOADPV######################
    set loadpv(name) ""
    set loadpv(xmin) 0
    set loadpv(xinterval) 1
    APSLabeledEntry .le1 -parent .userFrame.nb.f6 -label "   PV Name:" -textVariable loadpv(name) -packOption "-fill x -expand yes"
    APSLabeledEntry .le2 -parent .userFrame.nb.f6 -label " X Minimum:" -textVariable loadpv(xmin) -packOption "-fill x -expand yes"
    APSLabeledEntry .le3 -parent .userFrame.nb.f6 -label "X Interval:" -textVariable loadpv(xinterval) -packOption "-fill x -expand yes"
    APSButton .b1 -parent .userFrame.nb.f6 -text "Load" -command "LoadPVWaveform" -packOption "-anchor nw"
    #################LOADFILE######################
    set savefile(name) ""
    set savefile(pv) ""
    APSLabeledEntry .le1 -parent .userFrame.nb.f7 -label "Filename:" -textVariable savefile(name) -fileSelectButton 1 -fileSelectValidity 1 -width 60 -packOption "-fill x -expand yes"
    APSButton .b1 -parent .userFrame.nb.f7 -text "Load" -command "LoadWaveform" -packOption "-anchor nw"
    #################SAVEFILE######################
    APSLabeledEntry .le1 -parent .userFrame.nb.f8 -label "Filename:" -textVariable savefile(name) -fileSelectButton 1 -fileSelectValidity 0 -width 60 -packOption "-fill x -expand yes"
    APSLabeledEntry .le2 -parent .userFrame.nb.f8 -label " PV Name:" -textVariable savefile(pv) -packOption "-fill x -expand yes"

    APSButton .b1 -parent .userFrame.nb.f8 -text "Save" -command "SaveWaveform" -packOption "-anchor nw"
    #################SINE######################
    set sine(amplitude) 1
    set sine(frequency) 1
    set sine(phase) 0
    set sine(offset) 0
    set sine(equation) "Amplitude * sin(Freq * x + Phase) + Offset"
    set applyToAll 1
    APSLabeledOutput .lo1 -parent .userFrame.nb.f1 -label " Equation:" -textVariable sine(equation) -width 63 -packOption "-fill x -expand no -anchor nw"
    APSLabeledEntry .le1 -parent .userFrame.nb.f1 -label Amplitude: -textVariable sine(amplitude) -packOption "-fill x -expand yes"
    APSLabeledEntry .le2 -parent .userFrame.nb.f1 -label Frequency: -textVariable sine(frequency) -packOption "-fill x -expand yes"
    APSLabeledEntry .le3 -parent .userFrame.nb.f1 -label "    Phase:" -textVariable sine(phase) -packOption "-fill x -expand yes"
    APSLabeledEntry .le4 -parent .userFrame.nb.f1 -label "   Offset:" -textVariable sine(offset) -packOption "-fill x -expand yes"
    APSCheckButtonFrame .cbf1 -parent .userFrame.nb.f1 -label "" -buttonList "{Apply to whole waveform}" -variableList applyToAll -packOption "-side top -anchor ne"
    APSButton .b1 -parent .userFrame.nb.f1 -text "View" -command "ApplyEquation -mode view -type sine" -packOption "-side left -anchor nw"
    APSButton .b2 -parent .userFrame.nb.f1 -text "Hide" -command "HideEquation" -packOption "-side left -anchor nw"
    APSButton .b3 -parent .userFrame.nb.f1 -text "Replace" -command "ApplyEquation -mode view -type sine ; ApplyEquation -mode replace -type sine" -packOption "-side left -anchor nw"
    APSButton .b4 -parent .userFrame.nb.f1 -text "Add" -command "ApplyEquation -mode view -type sine ; ApplyEquation -mode add -type sine" -packOption "-side left -anchor nw"
    APSButton .b5 -parent .userFrame.nb.f1 -text "Subtract" -command "ApplyEquation -mode view -type sine ; ApplyEquation -mode subtract -type sine" -packOption "-side left -anchor nw"
    #################COSINE######################
    set cosine(amplitude) 1
    set cosine(frequency) 1
    set cosine(phase) 0
    set cosine(offset) 0
    set cosine(equation) "Amplitude * cos(Freq * x + Phase) + Offset"
    APSLabeledOutput .lo1 -parent .userFrame.nb.f2 -label " Equation:" -textVariable cosine(equation) -width 63 -packOption "-fill x -expand no -anchor nw"
    APSLabeledEntry .le1 -parent .userFrame.nb.f2 -label Amplitude: -textVariable cosine(amplitude) -packOption "-fill x -expand yes"
    APSLabeledEntry .le2 -parent .userFrame.nb.f2 -label Frequency: -textVariable cosine(frequency) -packOption "-fill x -expand yes"
    APSLabeledEntry .le3 -parent .userFrame.nb.f2 -label "    Phase:" -textVariable cosine(phase) -packOption "-fill x -expand yes"
    APSLabeledEntry .le4 -parent .userFrame.nb.f2 -label "   Offset:" -textVariable cosine(offset) -packOption "-fill x -expand yes"
    APSCheckButtonFrame .cbf1 -parent .userFrame.nb.f2 -label "" -buttonList "{Apply to whole waveform}" -variableList applyToAll -packOption "-side top -anchor ne"
    APSButton .b1 -parent .userFrame.nb.f2 -text "View" -command "ApplyEquation -mode view -type cosine" -packOption "-side left -anchor nw"
    APSButton .b2 -parent .userFrame.nb.f2 -text "Hide" -command "HideEquation" -packOption "-side left -anchor nw"
    APSButton .b3 -parent .userFrame.nb.f2 -text "Replace" -command "ApplyEquation -mode view -type cosine ; ApplyEquation -mode replace -type cosine" -packOption "-side left -anchor nw"
    APSButton .b4 -parent .userFrame.nb.f2 -text "Add" -command "ApplyEquation -mode view -type cosine ; ApplyEquation -mode add -type cosine" -packOption "-side left -anchor nw"
    APSButton .b5 -parent .userFrame.nb.f2 -text "Subtract" -command "ApplyEquation -mode view -type cosine ; ApplyEquation -mode subtract -type cosine" -packOption "-side left -anchor nw"
    #################LINEAR######################
    set linear(slope) 1
    set linear(yintercept) 0
    set linear(equation) "Slope * x + YIntercept"
    APSLabeledOutput .lo1 -parent .userFrame.nb.f3 -label "  Equation:" -textVariable linear(equation) -width 62 -packOption "-fill x -expand no -anchor nw"
    APSLabeledEntry .le1 -parent .userFrame.nb.f3 -label "     Slope:" -textVariable linear(slope) -packOption "-fill x -expand yes"
    APSLabeledEntry .le2 -parent .userFrame.nb.f3 -label YIntercept: -textVariable linear(yintercept) -packOption "-fill x -expand yes"
    APSCheckButtonFrame .cbf1 -parent .userFrame.nb.f3 -label "" -buttonList "{Apply to whole waveform}" -variableList applyToAll -packOption "-side top -anchor ne"
    APSButton .b1 -parent .userFrame.nb.f3 -text "View" -command "ApplyEquation -mode view -type linear" -packOption "-side left -anchor nw"
    APSButton .b2 -parent .userFrame.nb.f3 -text "Hide" -command "HideEquation" -packOption "-side left -anchor nw"
    APSButton .b3 -parent .userFrame.nb.f3 -text "Replace" -command "ApplyEquation -mode view -type linear ; ApplyEquation -mode replace -type linear" -packOption "-side left -anchor nw"
    APSButton .b4 -parent .userFrame.nb.f3 -text "Add" -command "ApplyEquation -mode view -type linear ; ApplyEquation -mode add -type linear" -packOption "-side left -anchor nw"
    APSButton .b5 -parent .userFrame.nb.f3 -text "Subtract" -command "ApplyEquation -mode view -type linear ; ApplyEquation -mode subtract -type linear" -packOption "-side left -anchor nw"
    #################EXPONENTIAL######################
    set exponential(amplitude) 1
    set exponential(basis) 1
    set exponential(multiplier) 1
    set exponential(offset) 0
    set exponential(equation) "Amplitude * Basis^(Multiplier * x) + Offset"
    APSLabeledOutput .lo1 -parent .userFrame.nb.f4 -label "  Equation:" -textVariable exponential(equation) -width 62 -packOption "-fill x -expand no -anchor nw"
    APSLabeledEntry .le1 -parent .userFrame.nb.f4  -label " Amplitude:" -textVariable exponential(amplitude) -packOption "-fill x -expand yes"
    APSLabeledEntry .le2 -parent .userFrame.nb.f4  -label "     Basis:" -textVariable exponential(basis) -packOption "-fill x -expand yes"
    APSLabeledEntry .le3 -parent .userFrame.nb.f4  -label "Multiplier:" -textVariable exponential(multiplier) -packOption "-fill x -expand yes"
    APSLabeledEntry .le4 -parent .userFrame.nb.f4  -label "    Offset:" -textVariable exponential(offset) -packOption "-fill x -expand yes"
    APSCheckButtonFrame .cbf1 -parent .userFrame.nb.f4 -label "" -buttonList "{Apply to whole waveform}" -variableList applyToAll -packOption "-side top -anchor ne"
    APSButton .b1 -parent .userFrame.nb.f4 -text "View" -command "ApplyEquation -mode view -type exponential" -packOption "-side left -anchor nw"
    APSButton .b2 -parent .userFrame.nb.f4 -text "Hide" -command "HideEquation" -packOption "-side left -anchor nw"
    APSButton .b3 -parent .userFrame.nb.f4 -text "Replace" -command "ApplyEquation -mode view -type exponential ; ApplyEquation -mode replace -type exponential" -packOption "-side left -anchor nw"
    APSButton .b4 -parent .userFrame.nb.f4 -text "Add" -command "ApplyEquation -mode view -type exponential ; ApplyEquation -mode add -type exponential" -packOption "-side left -anchor nw"
    APSButton .b5 -parent .userFrame.nb.f4 -text "Subtract" -command "ApplyEquation -mode view -type exponential ; ApplyEquation -mode subtract -type exponential" -packOption "-side left -anchor nw"
    #################GAUSSIAN######################
    set gaussian(a) 1
    set gaussian(b) 10
    set gaussian(c) 3
    set gaussian(d) 0
    set gaussian(equation) "a*e^(-((x-b)^2)/(2*c^2))+d"
    APSLabeledOutput .lo1 -parent .userFrame.nb.f5 -label " Equation:" -textVariable gaussian(equation) -width 63 -packOption "-fill x -expand no -anchor nw"
    APSLabeledEntry .le1 -parent .userFrame.nb.f5  -label "        a:" -textVariable gaussian(a) -packOption "-fill x -expand yes"
    APSLabeledEntry .le2 -parent .userFrame.nb.f5  -label "        b:" -textVariable gaussian(b) -packOption "-fill x -expand yes"
    APSLabeledEntry .le3 -parent .userFrame.nb.f5  -label "        c:" -textVariable gaussian(c) -packOption "-fill x -expand yes"
    APSLabeledEntry .le4 -parent .userFrame.nb.f5  -label "        d:" -textVariable gaussian(d) -packOption "-fill x -expand yes"
    APSCheckButtonFrame .cbf1 -parent .userFrame.nb.f5 -label "" -buttonList "{Apply to whole waveform}" -variableList applyToAll -packOption "-side top -anchor ne"
    APSButton .b1 -parent .userFrame.nb.f5 -text "View" -command "ApplyEquation -mode view -type gaussian" -packOption "-side left -anchor nw"
    APSButton .b2 -parent .userFrame.nb.f5 -text "Hide" -command "HideEquation" -packOption "-side left -anchor nw"
    APSButton .b3 -parent .userFrame.nb.f5 -text "Replace" -command "ApplyEquation -mode view -type gaussian ; ApplyEquation -mode replace -type gaussian" -packOption "-side left -anchor nw"
    APSButton .b4 -parent .userFrame.nb.f5 -text "Add" -command "ApplyEquation -mode view -type gaussian ; ApplyEquation -mode add -type gaussian" -packOption "-side left -anchor nw"
    APSButton .b5 -parent .userFrame.nb.f5 -text "Subtract" -command "ApplyEquation -mode view -type gaussian ; ApplyEquation -mode subtract -type gaussian" -packOption "-side left -anchor nw"
    #################CUSTOM######################
    set custom(a) 0
    set custom(b) 0
    set custom(c) 0
    set custom(d) 0
    set custom(rpn) 0
    set custom(equation) "\$a + \$b + \$c + \$d + \$x"
    APSLabeledEntry .le0 -parent .userFrame.nb.f9 -label " Equation:" -textVariable custom(equation)  -packOption "-fill x -expand yes"
    APSLabeledEntry .le1 -parent .userFrame.nb.f9  -label "        a:" -textVariable custom(a) -packOption "-fill x -expand yes"
    APSLabeledEntry .le2 -parent .userFrame.nb.f9  -label "        b:" -textVariable custom(b) -packOption "-fill x -expand yes"
    APSLabeledEntry .le3 -parent .userFrame.nb.f9  -label "        c:" -textVariable custom(c) -packOption "-fill x -expand yes"
    APSLabeledEntry .le4 -parent .userFrame.nb.f9  -label "        d:" -textVariable custom(d) -packOption "-fill x -expand yes"
    APSCheckButtonFrame .cbf0 -parent .userFrame.nb.f9 -label "" -buttonList "{RPN format}" -variableList custom(rpn) -packOption "-side top -anchor ne"
    APSCheckButtonFrame .cbf1 -parent .userFrame.nb.f9 -label "" -buttonList "{Apply to whole waveform}" -variableList applyToAll -packOption "-side top -anchor ne"
    APSButton .b1 -parent .userFrame.nb.f9 -text "View" -command "ApplyEquation -mode view -type custom"
    APSButton .b2 -parent .userFrame.nb.f9 -text "Hide" -command "HideEquation"
    APSButton .b3 -parent .userFrame.nb.f9 -text "Replace" -command "ApplyEquation -mode view -type custom ; ApplyEquation -mode replace -type custom"
    APSButton .b4 -parent .userFrame.nb.f9 -text "Add" -command "ApplyEquation -mode view -type custom ; ApplyEquation -mode add -type custom"
    APSButton .b5 -parent .userFrame.nb.f9 -text "Subtract" -command "ApplyEquation -mode view -type custom ; ApplyEquation -mode subtract -type custom"
}

proc PackPlotWidget {args} {
    graph .userFrame.g -width 800 -title "Waveform Setpoints"
    pack .userFrame.g -expand 1 -fill both
    .userFrame.g grid configure -hide no
    
    set ::X [vector \#auto]
    set ::Y [vector \#auto]
    set ::X2 [vector \#auto]
    set ::Y2 [vector \#auto]
    set ::X3 [vector \#auto]
    set ::Y3 [vector \#auto]
    set ::X4 [vector \#auto]
    set ::Y4 [vector \#auto]

    .userFrame.g element create Setpoints -xdata $::X -ydata $::Y -symbol circle -pixels 2 -linewidth 1
    .userFrame.g element create Equation -xdata $::X3 -ydata $::Y3 -symbol circle -pixels 2 -linewidth 1 -color green
}

namespace import ::blt::vector
namespace import ::blt::graph

set status "Ready..."
APSScrolledStatus .status -parent .userFrame -textVariable status -packOption "-fill x" -width 60
PackPlotWidget
PackZoomWidget
PackNotebookPanel
LoadDefaultWaveform
