#!/bin/sh  
# \
exec oagwish "$0" "$@"

# $Log: not supported by cvs2svn $
# Revision 1.1  2009/12/15 17:58:02  soliday
# Tool used for understanding conditioning setpoints.
#
# 
# 

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 ConditionPSWorksheet -contextHelp "Use this tool to plot the conditioning setpoints for degaussing and standardizing power supplies."

set args $argv
set apsu 0
APSStrictParseArguments {apsu}
if {$apsu} {
    set apsUpgrade 1
}
if {[catch {package require BLT} results]} {
    package require tkblt
}


if {$apsUpgrade} {
    ########### Tri-Degauss settings ##############
    #imax         - peak current for the first cycle
    set B 10
    #cycles       - number of cycles
    set C 10
    #imin         - peak current for last cycle
    set D 0
    #step time    - time between output steps
    set E 1
    #max amp size - max amp size between steps
    set F 1
} else {
    ########### Degauss settings ##############
    #decaymin   - minutes for one decay cycle
    set B 1
    #decaysec   - seconds for one decay cycle
    set C 0
    #periodsec  - seconds for one sine wave period
    set D 10
    #imax       - max current for degaussing function
    set E 5
    #decaytimes - number of decay times
    set F 5
}

if {$apsUpgrade} {
    ########## Standardize settings ############
    # from     - low end of standardization cycle span
    set BB 0
    # to       - upper end of standardization cycle span
    set CC 200
    # min      - ramp rate
    set DD 3
    # %        - ramp transition percentage
    set EE 20
    # ncycles  - number of cycles in standardization (0 or more)
    set FF 2
    # finish   - end standardization at this setpoint
    set GG 100
    # approach - 0 means approach finish from below
    #            1 means approach finish from above
    set HH 1
    #dwell time
    set II 20
    # initial setpoint
    set initialSetpoint 100.0
} else {
    ########## Standardize settings ############
    # from     - low end of standardization cycle span
    set BB 0
    # to       - upper end of standardization cycle span
    set CC 5
    # min      - time in minutes to transition (from..to)
    set DD 1
    # sec      - time in seconds to transition (from..to)
    set EE 0
    # ncycles  - number of cycles in standardization (0 or more)
    set FF 3
    # finish   - end standardization at this setpoint
    set GG 1.0
    # approach - 0 means approach finish from below
    #            1 means approach finish from above
    set HH 0
    #dwell time
    set II 0
    # initial setpoint
    set initialSetpoint 1.0
}

#status     - 0 means routine has not completed or not run
           #             1 means routine has run and completed (from
           #             start to end)
set I 0    



set currentSetpoint ""
set periodConst ""
set decayTime ""
set nSteps ""
set cSteps ""
set cycles ""
set stepsize ""
set fSteps ""
set iSteps ""
set direction ""
set initial ""

set CurrentList ""
set TimeList ""
set t 0
set totalTime 0
set maxRateOfChange 0

proc degaussProc {args} {
    global B C D E F I
    global currentSetpoint periodConst decayTime nSteps
    global cSteps cycles
    global t TimeList CurrentList totalTime maxRateOfChange

    set CurrentList ""
    set TimeList ""
    set t 0

    set I 0
    set cycles $F
    set decayTime [expr $B * 60.0 + $C]
    set nSteps [expr $decayTime * $cycles + 1]
    set currentSetpoint 0.0
    set periodConst [expr (2 * 3.14159) / $D]
    
    lappend CurrentList $currentSetpoint
    lappend TimeList $t

    incr t 2
    for {set cSteps 0} {$cSteps < $nSteps} {incr cSteps} {
        set currentSetpoint [expr $E * exp(-$cSteps/$decayTime) * sin($cSteps * $periodConst)]
        lappend CurrentList $currentSetpoint
        lappend TimeList $t
        incr t
    }
    incr t -1
    set totalTime $t
    set maxRateOfChange "[format %.5f [lindex $CurrentList 2]]/sec"
}

proc tridegaussProc {args} {
    global B C D E F I
    global currentSetpoint periodConst decayTime nSteps
    global cSteps cycles
    global t TimeList CurrentList totalTime maxRateOfChange

    set roundingAllowance .001

    set CurrentList ""
    set TimeList ""
    set t 0

    set I 0
    set cycles $C
    set imax [expr abs($B)]
    set imin [expr abs($D)]
    set maxstep $F
    if {($maxstep < .1) || ($maxstep > 20)} {
        set maxstep 20
    }
    set period $E
    if {$period < .1} {
        set period .1
    }
    set currentSetpoint 0.0
    set nextPeak $imax
    set ramp UP

    set stepsPerPeak [expr int((2 * $imax) / $maxstep) + 1]
    if {[expr ${stepsPerPeak}%2]} {
        incr stepsPerPeak
    }
    set stepSize [expr (1.0 * $imax / $stepsPerPeak) * 2]
    set initStepSize $stepSize
    set peakDelta [expr 1.0 * ($imax - $imin) / (2 * $cycles - 1)]

    lappend CurrentList $currentSetpoint
    lappend TimeList $t
    set t [expr $t + 2]

    while {1} {
        if {$ramp == "UP"} {
            if {[expr $currentSetpoint + $stepSize] > [expr $nextPeak + $roundingAllowance]} {
                set ramp DOWN
                set thisPeak $nextPeak
                set nextPeak [expr ($nextPeak - $peakDelta) * -1.0]
                set stepSize [expr 1.0 * ($thisPeak - $nextPeak) / $stepsPerPeak]
                set currentSetpoint [expr $currentSetpoint - $stepSize]
            } else {
                set currentSetpoint [expr $currentSetpoint + $stepSize]
            }
            lappend CurrentList $currentSetpoint
            lappend TimeList $t
        } elseif {$ramp == "DOWN"} {
            if {[expr $currentSetpoint - $stepSize] < [expr $nextPeak - $roundingAllowance]} {
                set ramp UP
                set thisPeak $nextPeak
                set nextPeak [expr 1.0 * ($nextPeak + $peakDelta) * -1]
                set stepSize [expr (-1.0 * $thisPeak + $nextPeak) / $stepsPerPeak]
                if {$nextPeak < $imin} {
                    set ramp LAST
                    set nextPeak 0.0
                    set stepSize [expr 1.0 * ($thisPeak / $stepsPerPeak) * 2]
                }
                set currentSetpoint [expr $currentSetpoint + $stepSize]
            } else {
                set currentSetpoint [expr $currentSetpoint - $stepSize]
            }            
            lappend CurrentList $currentSetpoint
            lappend TimeList $t
        } else {
            set currentSetpoint [expr $currentSetpoint - $stepSize]
            if {($nextPeak == 0.0) && ($currentSetpoint > 0.0)} {
                set currentSetpoint 0.0
            }
            lappend CurrentList $currentSetpoint
            lappend TimeList $t
            break
        }
        set t [expr $t + $period]
    }
    set totalTime $t
    set maxRateOfChange "[format %.5f [expr $initStepSize / $period]]/sec"
}

proc standardizeProc {args} {
    global BB CC DD EE FF GG HH I
    global currentSetpoint nSteps cSteps stepsize fSteps iSteps
    global direction cycles initial initialSetpoint
    global t TimeList CurrentList totalTime2 maxRateOfChange2

    set CurrentList ""
    set TimeList ""
    set t 0

    set I 0
    set initial 1
    set cycles $FF
    set nSteps [expr $DD * 60 + $EE]
    set cSteps $nSteps
    set stepsize [expr (1.0 * ($CC - $BB)) / $nSteps]
    set currentSetpoint $initialSetpoint
    if {!$HH} {
        #approach finish from below
        if {$currentSetpoint > $CC} {
            #go down first
            set direction DOWN
            set iSteps [expr int(1.0 * ($currentSetpoint - $CC) / ($CC - $BB) * $nSteps)]
        } else {
            #go up first
            set direction UP
            set iSteps [expr int(1.0 * ($CC - $currentSetpoint) / ($CC - $BB) * $nSteps)]
        }
        if {$iSteps == 0} {
            set iSteps 1
        }
        if {($cycles == -1) && ($currentSetpoint <= $GG)} {
            set fSteps [expr int(1.0 * ($GG - $currentSetpoint) / ($CC - $BB) * $nSteps)]
            set iSteps 0
        } else {
            set fSteps [expr int(1.0 * ($GG - $BB) / ($CC - $BB) * $nSteps)]
        }
    } else {
        if {$currentSetpoint < $BB} {
            #go up first
            set direction UP
            set iSteps [expr int(1.0 * ($BB - $currentSetpoint) / ($CC - $BB) * $nSteps)]
        } else {
            #go down first
            set direction DOWN
            set iSteps [expr int(1.0 * ($currentSetpoint - $BB) / ($CC - $BB) * $nSteps)]
        }
        if {$iSteps == 0} {
            set iSteps 1
        }
        if {($cycles == -1) && ($currentSetpoint >= $GG)} {
            set fSteps [expr int(1.0 * ($currentSetpoint - $GG) / ($CC - $BB) * $nSteps)]
            set iSteps 0
        } else {
            set fSteps [expr int(1.0 * ($CC - $GG) / ($CC - $BB) * $nSteps)]
        }
    }
    if {$cycles == -1} {
        set cycles 0
    }

    lappend CurrentList $currentSetpoint
    lappend TimeList $t
    incr t

    while {$iSteps > 0} {
        incr iSteps -1
        if {$direction == "UP"} {
            set currentSetpoint [expr $currentSetpoint + $stepsize]
        } else {
            set currentSetpoint [expr $currentSetpoint - $stepsize]
        }
        if {$iSteps == 0} {
            if {!$HH} {
                if {$initial} {
                    set direction DOWN
                    set currentSetpoint $CC
                } else {
                    set direction UP
                    set currentSetpoint $BB
                }
            } else {
                if {$initial} {
                    set direction UP
                    set currentSetpoint $BB
                } else {
                    set direction DOWN
                    set currentSetpoint $CC
                }
            }
            if {$initial} {
                set iSteps $nSteps
                set initial 0
            }
        }
        lappend CurrentList $currentSetpoint
        lappend TimeList $t
        incr t
    }
    
    while {$cycles > 0} {
        incr cSteps -1
        if {$direction == "UP"} {
            set currentSetpoint [expr $currentSetpoint + $stepsize]
            if {$cSteps == 0} {
                set cSteps $nSteps
                set direction DOWN
                if {$HH} {
                    incr cycles -1
                }
            }
        } else {
            set currentSetpoint [expr $currentSetpoint - $stepsize]
            if {$cSteps == 0} {
                set cSteps $nSteps
                set direction UP
                if {!$HH} {
                    incr cycles -1
                }
            }
        }
        lappend CurrentList $currentSetpoint
        lappend TimeList $t
        incr t
    }

    if {$cycles == 0} {
        while {$fSteps > 0} {
            incr fSteps -1
            if {!$HH} {
                set currentSetpoint [expr $currentSetpoint + $stepsize]
            } else {
                set currentSetpoint [expr $currentSetpoint - $stepsize]
            }
            lappend CurrentList $currentSetpoint
            lappend TimeList $t
            incr t
        }
    }
    incr t -1
    set totalTime2 $t
    set maxRateOfChange2 "[format %.5f $stepsize]/sec"

}

proc standardizeProcAPSU {args} {
    global BB CC DD EE FF GG HH II
    global initialSetpoint
    global t TimeList CurrentList totalTime2

    set Imin $BB
    set Imax $CC
    set MaxRampRate $DD
    set TransitionPercentage [expr ($EE * .01)]
    set Cycles $FF
    set IFinal $GG
    set finalApproach $HH
    set DwellTime $II

    if {$Imin > $Imax} {
        set Imin $CC
        set Imax $BB
    }
    if {$TransitionPercentage > .5} {
        set TransitionPercentage .5
    }
    if {$TransitionPercentage < 0} {
        set TransitionPercentage 0
    }
    if {$MaxRampRate < 0} {
        set MaxRampRate [expr abs($MaxRampRate)]
    }
    if {$MaxRampRate == 0} {
        set MaxRampRate .5
    }
    if {$Cycles < 0} {
        set Cycles 0
    }
    if {$DwellTime < 0} {
        set DwellTime 0
    }

    set NormalRampTime [expr ((1.0 * $Imax - $Imin) / $MaxRampRate) / (1 - $TransitionPercentage)]
    set TransitionTime [expr $TransitionPercentage * $NormalRampTime]
    set TransitionDeltaCurrent2x [expr ($MaxRampRate * $TransitionTime)]
 
    set stage "PRE"
    set halfCycles 0
    set t 0
    set tt 0
    set CurrentList $initialSetpoint
    set TimeList $t
    while {1} {
        set tt 0
        if {$stage == "PRE"} {
            set rampStartSetpoint $initialSetpoint
            if {$finalApproach} {
                set direction UP
                set rampEndSetpoint $Imax
                if {$rampStartSetpoint > $rampEndSetpoint} {
                    set direction "DOWN"
                    set stage "PRE-OUT-OF-BOUNDS"
                }
            } else {
                set direction DOWN
                set rampEndSetpoint $Imin
                if {$rampStartSetpoint < $rampEndSetpoint} {
                    set direction "UP"
                    set stage "PRE-OUT-OF-BOUNDS"
                }
            }
        } elseif {$stage == "CYCLE"} {
            if {$direction == "UP"} {
                set rampStartSetpoint $Imin
                set rampEndSetpoint $Imax
            } else {
                set rampStartSetpoint $Imax
                set rampEndSetpoint $Imin
            }
        } else {
            if {$direction == "UP"} {
                set rampStartSetpoint $Imin
                set rampEndSetpoint $IFinal
                if {$rampStartSetpoint > $rampEndSetpoint} {
                    set direction "DOWN"
                }
            } else {
                set rampStartSetpoint $Imax
                set rampEndSetpoint $IFinal
                if {$rampStartSetpoint < $rampEndSetpoint} {
                    set direction "UP"
                }
            }
            set DwellTime 0
        }
        if {$direction == "UP"} {
            if {[expr $rampEndSetpoint - $rampStartSetpoint] > $TransitionDeltaCurrent2x} {
                set RampTime [expr (2 * $TransitionTime + (((1.0 * $rampEndSetpoint - $rampStartSetpoint - $TransitionDeltaCurrent2x) / $MaxRampRate)))]
                set t2 $TransitionTime
                set t3 [expr $RampTime - $TransitionTime]
            } else {
                set Imiddle [expr (($rampEndSetpoint + $rampStartSetpoint) / 2.0)]
                set tMid [expr sqrt(($Imiddle - $rampStartSetpoint) * 2.0 * $TransitionTime / $MaxRampRate)]
                set RampTime [expr (2 * $tMid)]
                set t2 $tMid
                set t3 $tMid
            }
        } else {
            if {[expr $rampStartSetpoint - $rampEndSetpoint] > $TransitionDeltaCurrent2x} {
                set RampTime [expr (2 * $TransitionTime + (((1.0 * $rampStartSetpoint - $rampEndSetpoint - $TransitionDeltaCurrent2x) / $MaxRampRate)))]
                set t2 $TransitionTime
                set t3 [expr $RampTime - $TransitionTime]
            } else {
                set Imiddle [expr (($rampStartSetpoint + $rampEndSetpoint) / 2.0)]
                set tMid [expr sqrt(($Imiddle - $rampEndSetpoint) * 2.0 * $TransitionTime / $MaxRampRate)]
                set RampTime [expr (2 * $tMid)]
                set t2 $tMid
                set t3 $tMid
            }
        }
        set t1 0
        set t4 $RampTime
        set t5 [expr $RampTime + $DwellTime]

        while {1} {
            set t [expr $t + 1]
            set tt [expr $tt + 1]
            if {($tt > $t1) && ($tt <= $t2)} {
                if {$direction == "UP"} {
                    set I [expr ($rampStartSetpoint + ($MaxRampRate * $tt * $tt / (2.0 * $TransitionTime)))]
                } else {
                    set I [expr ($rampStartSetpoint - ($MaxRampRate * $tt * $tt / (2.0 * $TransitionTime)))]
                }
            } elseif {($tt > $t2) && ($tt <= $t3)} {
                if {$direction == "UP"} {
                    set I [expr ($rampStartSetpoint + ($MaxRampRate * $TransitionTime / 2.0) + ($MaxRampRate * ($tt - $t2)))]
                } else {
                    set I [expr ($rampStartSetpoint - ($MaxRampRate * $TransitionTime / 2.0) - ($MaxRampRate * ($tt - $t2)))]
                }
            } elseif {($tt > $t3) && ($tt < $t4)} {
                if {$direction == "UP"} {
                    set I [expr ($rampEndSetpoint - ($MaxRampRate * ($t4 - $tt) * ($t4 - $tt) / (2.0 * $TransitionTime)))]
                } else {
                    set I [expr ($rampEndSetpoint + ($MaxRampRate * ($t4 - $tt) * ($t4 - $tt) / (2.0 * $TransitionTime)))]
                }
            } elseif {($tt >= $t4) && ($tt <= $t5)} {
                set I $rampEndSetpoint
            } else {
                set I $rampEndSetpoint
                lappend CurrentList $I
                lappend TimeList $t
                break
            }
            lappend CurrentList $I
            lappend TimeList $t
        }

        if {$direction == "UP"} {
            set direction "DOWN"
        } else {
            set direction "UP"
        }
        if {$stage == "PRE-OUT-OF-BOUNDS"} {
            set stage "CYCLE"
            if {$direction == "UP"} {
                set direction "DOWN"
            } else {
                set direction "UP"
            }
        } elseif {$stage == "PRE"} {
            if {$Cycles == 0} {
                set stage "POST"
            } else {
                set stage "CYCLE"
            }
        } elseif {$stage == "CYCLE"} {
            incr halfCycles
            if {$halfCycles == [expr (2 * $Cycles)]} {
                set stage "POST"
            }
        } else {
            set totalTime2 $t
            return
        }
    }
}


proc UpdateDegaussGraph {args} {
    global TimeList CurrentList

    degaussProc
    
    $::X set $TimeList
    $::Y set $CurrentList
    
    .userFrame.g configure -title "Degauss Setpoints"
}

proc UpdateTriDegaussGraph {args} {
    global TimeList CurrentList

    tridegaussProc
    
    $::X set $TimeList
    $::Y set $CurrentList
    
    .userFrame.g configure -title "Tri-Degauss Setpoints"
}

proc UpdateStandardizeGraph {args} {
    global TimeList CurrentList apsUpgrade

    if {$apsUpgrade} {
        standardizeProcAPSU
    } else {
        standardizeProc
    }

    $::X set $TimeList
    $::Y set $CurrentList
    
    .userFrame.g configure -title "Standardize Setpoints"
}

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

if {$apsUpgrade} {
    graph .userFrame.g -width 1400 -title "Tri-Degauss Setpoints"
} else {
    graph .userFrame.g -width 800 -title "Degauss Setpoints"
}
pack .userFrame.g -expand 1 -fill both
.userFrame.g grid configure -hide no

set ::X [vector #auto]
set ::Y [vector #auto]

if {$apsUpgrade} {
    standardizeProcAPSU
} else {
    degaussProc
}

$::X set $TimeList
$::Y set $CurrentList

.userFrame.g element create Setpoints -xdata $::X -ydata $::Y -symbol circle -pixels 2 -linewidth 1

if {$apsUpgrade} {
    APSFrame .options -parent .userFrame -label "TriDegauss Worksheet"
    APSLabeledEntry .b -parent .userFrame.options.frame -label "             Peak current for first cycle:(.B):" -textVariable B
    APSLabeledEntry .c -parent .userFrame.options.frame -label "                         Number of cycles:(.C):" -textVariable C
    APSLabeledEntry .d -parent .userFrame.options.frame -label "              Peak current for last cycle:(.D):" -textVariable D
    APSLabeledEntry .e -parent .userFrame.options.frame -label "                Time between output steps:(.E):" -textVariable E
    APSLabeledEntry .f -parent .userFrame.options.frame -label "  Max Amp step size between two setpoints:(.F):" -textVariable F
    
    APSLabeledOutput .totaltime -parent .userFrame.options.frame -label "                                    Total Time:" -textVariable totalTime
    APSLabeledOutput .maxrateofchange -parent .userFrame.options.frame -label "                        Maximum rate of change:" -textVariable maxRateOfChange
    
    APSButton .update -parent .userFrame.options.frame -text Update -command UpdateTriDegaussGraph
} else {
    APSFrame .options -parent .userFrame -label "Degauss Worksheet"
    APSLabeledEntry .b -parent .userFrame.options.frame -label "              Minutes for one decay cycle:(.B):" -textVariable B
    APSLabeledEntry .c -parent .userFrame.options.frame -label "              Seconds for one decay cycle:(.C):" -textVariable C
    APSLabeledEntry .d -parent .userFrame.options.frame -label "         Seconds for one sine wave period:(.D):" -textVariable D
    APSLabeledEntry .e -parent .userFrame.options.frame -label "      Max current for degaussing function:(.E):" -textVariable E
    APSLabeledEntry .f -parent .userFrame.options.frame -label "                    Number of decay times:(.F):" -textVariable F
    
    APSLabeledOutput .totaltime -parent .userFrame.options.frame -label "          Total Time = (.B * 60 + .C) * .F + 2:" -textVariable totalTime
    APSLabeledOutput .maxrateofchange -parent .userFrame.options.frame -label "                        Maximum rate of change:" -textVariable maxRateOfChange
    
    APSButton .update -parent .userFrame.options.frame -text Update -command UpdateDegaussGraph
}

if {$apsUpgrade} {
    APSFrame .options2 -parent .userFrame -label "Standardize Worksheet"
    APSLabeledEntry .a -parent .userFrame.options2.frame -label "                              Initial setpoint:" -textVariable initialSetpoint
    APSLabeledEntry .b -parent .userFrame.options2.frame -label "                              Lower Limit:(.B):" -textVariable BB
    APSLabeledEntry .c -parent .userFrame.options2.frame -label "                              Upper Limit:(.C):" -textVariable CC
    APSLabeledEntry .d -parent .userFrame.options2.frame -label "                    Ramp Rate Amps/Second:(.D):" -textVariable DD
    APSLabeledEntry .e -parent .userFrame.options2.frame -label "               Ramp Transition Percentage:(.E):" -textVariable EE
    APSLabeledEntry .f -parent .userFrame.options2.frame -label "                         Number of cycles:(.F):" -textVariable FF
    APSLabeledEntry .g -parent .userFrame.options2.frame -label "                           Final setpoint:(.G):" -textVariable GG
    APSLabeledEntry .h -parent .userFrame.options2.frame -label "Approach finish from below(0) or above(1):(.H):" -textVariable HH
    APSLabeledEntry .i -parent .userFrame.options2.frame -label "                    Dwell time in seconds:(.I):" -textVariable II
    APSLabeledOutput .totaltime -parent .userFrame.options2.frame -label "                                    Total Time:" -textVariable totalTime2
} else {
    APSFrame .options2 -parent .userFrame -label "Standardize Worksheet"
    APSLabeledEntry .a -parent .userFrame.options2.frame -label "                              Initial setpoint:" -textVariable initialSetpoint
    APSLabeledEntry .b -parent .userFrame.options2.frame -label "                              Lower Limit:(.B):" -textVariable BB
    APSLabeledEntry .c -parent .userFrame.options2.frame -label "                              Upper Limit:(.C):" -textVariable CC
    APSLabeledEntry .d -parent .userFrame.options2.frame -label "                   Minutes for half cycle:(.D):" -textVariable DD
    APSLabeledEntry .e -parent .userFrame.options2.frame -label "                   Seconds for half cycle:(.E):" -textVariable EE
    APSLabeledEntry .f -parent .userFrame.options2.frame -label "                         Number of cycles:(.F):" -textVariable FF
    APSLabeledEntry .g -parent .userFrame.options2.frame -label "                           Final setpoint:(.G):" -textVariable GG
    APSLabeledEntry .h -parent .userFrame.options2.frame -label "Approach finish from below(0) or above(1):(.H):" -textVariable HH
    APSLabeledOutput .totaltime -parent .userFrame.options2.frame -label "                                    Total Time:" -textVariable totalTime2
    APSLabeledOutput .maxrateofchange -parent .userFrame.options2.frame -label "                                Rate of change:" -textVariable maxRateOfChange2
}


APSButton .update -parent .userFrame.options2.frame -text Update -command UpdateStandardizeGraph




