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

#
# $Log: not supported by cvs2svn $
# Revision 1.17  2012/10/09 14:44:56  shang
# removed checking trigger delay, since it is different in 92nm lattice (19.07ms) and 132nm lattice (16.07ms).
#
# Revision 1.16  2011/05/18 15:23:31  shang
# added PSTestNegative and PSTestPositive lattices for power supply test.
#
# Revision 1.15  2011/04/22 16:06:14  shang
# To make sure the measurement table and reference table plot the same corrector in each plot, sort both tables by corrector name before plotting.
#
# Revision 1.14  2010/09/24 15:50:07  soliday
# Fixed a problem when trying to detect the booster lattice and the value
# comes back as unknown.
#
# Revision 1.13  2010/08/05 20:37:36  shang
# added "check corrector ramptable" button.
#
# Revision 1.12  2010/07/28 16:54:26  shang
# now uses lattice pv "BOO:LatticeCALC" to obtain the booster lattice.
#
# Revision 1.11  2006/11/15 00:06:26  shang
# added displaying the corrector names for evolation plots.
#
# Revision 1.10  2006/10/02 21:43:36  sereno
# Removed option to load 109 nm lattice corrector ramps.
#
# Revision 1.9  2005/04/07 22:35:36  sereno
# Changed a status message to reflect that loading ramps is now much faster
# than originally.
#
# Revision 1.8  2003/10/03 18:41:56  shang
# added "Get Lattice" button to get the current lattice, automatically link the
# default to current lattice.
#
# Revision 1.7  2003/05/28 18:36:22  shang
# replaced APSMpBoosterSetCorrPowerSuppliesOnOff by APSMpBoosterSetCorrPowerSuppliesOnOffNormal (because of the passing arguments problem in tcl-- which did not pass the state1 value
# from APSMpBoosterSetCorrPowerSuppliesOnOff to APSMpBoosterSetCorrPowerSuppliesOnOffNormal).
# And changed the contextHelp information of Init/Auto/Activation button
#
# Revision 1.6  2003/05/28 15:38:47  shang
# replaced APSMpBoosterSetCorrPowerSuppliesOnOffNormal by APSMpBoosterSetCorrPowerSuppliesOnOff for Init/Auto/Activate, and added completing status for loading ramp tables.
#
# Revision 1.5  2003/04/21 16:15:08  shang
# changed the reference ramptable to be the actuall lattice
#
# Revision 1.4  2003/04/16 22:54:06  shang
# added check booster lattice to get the reference ramptable
#
# Revision 1.3  2002/12/20 01:56:19  sereno
# Added corrector ramp file load button for 92 nm rad lattice.  Renamed corrector
# ramps according to lattice.
#
# Revision 1.2  2002/12/04 23:07:02  sereno
# Fixed minor plotting bug when plotting corrector evolution or monitoring when
# the file does not exist.  N. Sereno.
#
# Revision 1.1  2002/12/04 15:29:16  sereno
# First version tested by sereno, developed by shang and sereno.  Automatically
# sets bpm timing before changing corrector ramps to prevent erros from bcorr
# series of programs.  BPM timing is set so as not to affect booster longitudinal
# correction.  Still uses bcorr series of programs by evans.  N. Sereno
#
# first version, shang

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

set CVSRevisionAuthor "\$Revision: 1.17 $ \$Author: shang $"

APSApplication . -name "BoosterCorrectorCheckOut" -version $CVSRevisionAuthor \
  -overview "checkout Booster correctors."

set MainStatus "Initializing ..."
APSScrolledStatus .status -parent .userFrame -width 60 \
  -textVariable MainStatus 

proc SetMainStatus {text} {
    global MainStatus
    set MainStatus $text
    update
}

proc MakeOptionFrame {widget args} {
    global PSCUSampleTime RampStartOffsetTime BoosterTrigger IPTime SetIPTime
    global RampStartDelay ChangeButtonList
    APSParseArguments {parent}
    
    APSFrame $widget -parent $parent -label "BoosterCorrectorCheckOut options" \
      -contextHelp "Frame to specify arguments for booster orbit correction."
    set w0 $parent$widget.frame
    APSFrameGrid .fg -parent $w0 -xList {x1 x2 x3}
    set w1 $w0.fg.x1
    set w2 $w0.fg.x2
    set w3 $w0.fg.x3
    
    APSFrame .pscu -parent $w1 -label "Set PSCU Time"
    set w $w1.pscu.frame
    APSLabeledOutput .sample -parent $w -label "PSCU sample time (us):" \
      -textVariable PSCUSampleTime -width 10 \
      -contextHelp "PSCU sample time in us, Value of It:Ddg3chan3.DLY."
    APSLabeledOutput .offset -parent $w -label "Ramp Start Offset (ms): " \
      -textVariable RampStartOffsetTime -width 10 \
      -contextHelp "ramp start offset time in ms, Value of It:Bs:StartRamp2BsIp."
    APSLabeledOutput .delay -parent $w -label "Ramp Start Delay (ms): " \
      -textVariable RampStartDelay -width 10 \
      -contextHelp "ramp start offset time in ms,Value of Ddg4chan6.DLY"
    APSLabeledOutput .trigger -parent $w -label "Booster trigger (us)" \
      -textVariable BoosterTrigger -width 10 \
      -contextHelp "Booster trigger time (us), Value of It:Bs:Trig2BsIp."
    
    APSLabeledOutput .ramptime -parent $w -label "Ramp time (ms): " \
      -textVariable RampTime -width 10  -contextHelp "ramp time"
    APSLabeledOutput .ip -parent $w -label "Time after IP(ms): " \
      -textVariable IPTime -width 10 \
      -contextHelp "Time after booster injection obtained from IOC "
    APSLabeledEntry .ipset -parent $w -label "Set Time after IP(ms): " \
      -textVariable SetIPTime -width 10 \
      -contextHelp "Set time after boioster injection for setting PSCU sample time."
    APSButton .get -parent $w -text "Get Time" -command "GetPSCUTime" -contextHelp "Get PSCU sample time."
    APSButton .set -parent $w -text "Set Time" -command "SetPSCUTime" -contextHelp "Set PSCU sample time."
    lappend ChangeButtonList $w.set.button
   # APSFrame .setf -parent $w 
   # set w $w.setf.frame
   # $w configure -bd 0 -relief flat
    APSButton .setinj -parent $w -text "Set Injection Time" -command "SetInjectionExtractionTime -mode injection" \
      -contextHelp "Set Injection PSCU time" -packOption "-side top"
    APSButton .setext -parent $w -text "Set Extraction Time" -command "SetInjectionExtractionTime -mode extraction" \
      -contextHelp "Set Extraction PSCU time" -packOption "-side top"
    lappend ChangeButtonList $w.setinj.button
    lappend ChangeButtonList $w.setext.button

    global PowerOn TurnOnPlane Fast RawOnly
    APSFrame .power -parent $w2 -label "Set Power Supplies"
    set w $w2.power.frame
    APSRadioButtonFrame .on -parent $w -label "Power: " -buttonList {on off} -valueList {on off} \
      -variable PowerOn -orientation horizontal \
      -contextHelp "Specifies whether to turn the correctors on or off."
    APSRadioButtonFrame .plane -parent $w -variable TurnOnPlane -label "Plane: " \
      -buttonList {H V Both} -valueList {h v both} -orientation horizontal -contextHelp \
      "Specifies the plane for which the correctors will be turned on/off."
    APSCheckButtonFrame .checkfast -parent $w -orientation horizontal \
      -label "" -buttonList {Fast "Raw Only"} \
      -variableList {Fast RawOnly } \
      -contextHelp \
      "Fast: Does not zero the ramps before turning off, and does not perform the\
       INIT/AUTO/ACTIVATE procedure before turning on.\n\
       Raw Only: Only does the raw supplies (and uses Fast mode)."
    APSButton .turnonbutton -parent $w -text "Set Power Supplies" \
      -command {SetBoosterPowerSupplies} -packOption "-side top" -contextHelp \
      "Turns the raw and individual corrector power supplies on or\
       off for the planes that are checked.  Unless Fast is set, sets the\
       ramps to zero before turning off and performs the INIT/AUTO/ACTIVATE\
       procedure before turning on."
    lappend ChangeButtonList $w.turnonbutton.button
    APSButton .turnoninit -parent $w -text "INIT/AUTO/ACTIVATE" \
      -command {InitBoosterCorrector} -packOption "-side top" -contextHelp \
      "Performs the INIT/AUTO/ACTIVATE procedure to turns on or off horizontal and/or vertical \
        booster corrector power supplies or raw supplies.\
       It turns the booster corrector raw supplies on \
       at 65 Volts, loads zero ramp tables, and either turns \
       correctors on or off.  If off is selected, the  \
       raw supplies are also turned off. \"Fast\" mode does not \
       load zero ramps when turning the supplies off.  \"Fast\" \
       mode will not perform INIT/AUTO/ACTIVATE procedure before \
       turning on.  \"Raw Only\" turns on only the raw supplies, \
      loads 65 Volts as their setpoint and does this in \"Fast\" mode.."
    lappend ChangeButtonList $w.turnoninit.button
    APSFrame .load -parent $w2 -label "Load Ramp Tables"
    set w $w2.load.frame
    global BoosterLatticeState BoosterLattice
    APSRadioButtonFrame .lattice -parent $w -label "" \
	-variable BoosterLattice \
	-buttonList {"High Emittance Lattice - 132 nm rad" "Low Emittance Lattice - 92 nm rad" "PSTestNegative" "PSTestPositive"} \
	-valueList {x11.75-y9.80 x13.75-y5.80 "PSTestNegative" "PSTestPositive"} \
	-packOption {-side top}
    APSButton .loadRamp -parent $w \
      -text "Load Corrector Ramps" \
      -command {LoadBoosterCorrRamps -statusCallback SetStatus} \
      -packOption {-side left} \
      -contextHelp "This button loads the booster corrector ramps for both horizontal and vertical planes."
    APSButton .getlattice -parent $w \
	-text "Get Lattice" \
	-command {GetBoosterLattice} \
	-packOption {-side left} \
	-contextHelp "Get the booster lattice and switch the default lattice to the obtained lattice"
    lappend ChangeButtonList $w.loadRamp.button
    global CorrPlane CorrValues XOrbit CorrName CorrValue
    APSFrame .setcorrs -parent $w3 -label "Set All Corrector Values"
    set w $w3.setcorrs.frame
    APSRadioButtonFrame .plane -parent $w -variable CorrPlane \
      -label "Plane: " -buttonList {V H Both} -orientation horizontal \
      -valueList {v h both} -contextHelp \
      "Specifies the plane for which the correctors will be set."
    APSLabeledEntry .val -parent $w -label "Values:" \
      -textVariable CorrValues -width 10 -contextHelp \
      "Value in Amps at BoosterEP to which all correctors will ramp."
    #APSButton .xorbit -parent $w -command SetXOrbit \
    #  -text "Set Xoribt " \
    #  -contextHelp "Set the Xorbit values instead."
    APSButton .set -parent $w -text "Set Corr" \
	-command {SetAllCorrValues} \
	-contextHelp \
	"Set all the correctors in the specified plane(s) to ramp\
       from zero to the value in the entry box at BoosterEP."
    lappend ChangeButtonList $w.set.button
    APSFrame .setcorr -parent $w3 -label "Set Individual Corrector Value"
    set w $w3.setcorr.frame
    APSLabeledEntry .name -parent $w -label "Name:" -width 10 \
      -textVariable CorrName -contextHelp "Give the corrector name to set/get the values of"
    APSLabeledEntry .val -parent $w -label "Value:" -width 10 \
      -textVariable CorrValue -contextHelp "Give value for setting $CorrName or display the $CorrName value"
    APSButton .get -parent $w -text "Get" \
      -command {GetCorrValue} -contextHelp "Get the value of the specified corrector."
    APSButton .set -parent $w -text "Set" \
      -command {SetCorrValue} -contextHelp "Set the specified corrector to value $CorrValue"
    APSButton .getramp -parent $w -text "GetRampTable" -command {GetRampTable} \
      -contextHelp "Get the ramp table of the specified corrector."
    lappend ChangeButtonList $w.set.button
}

proc SetCorrValue {args} {
    global CorrName CorrValue
    SetBPMTiming
    SetMainStatus "Setting $CorrName to $CorrValue Amps at extraction..."
    if [catch {exec /home/helios/SHANG/epics/extensions/src/rampload/O.linux-x86_64/setbcorr $CorrName $CorrValue} result] {
        SetMainStatus "$result"
        return
    }
    SetMainStatus "Done."
}

proc SetAllCorrValues {args} {
    global CorrPlane CorrValues
    SetBPMTiming
    switch $CorrPlane {
        h {
            set option -h
            SetMainStatus "Setting all horizontal correctors to $CorrValues Amperes at extraction..."
        }
        v {
            set option -v
            SetMainStatus "Setting all vertical correctors to $CorrValues Amperes at extraction..."
        }
        both {
            set option -b
            SetMainStatus "Setting both horizontal and vertical correctors to $CorrValues Amperes at extraction..."
        }
    }
    if [catch {exec setbcorrzero $option $CorrValues} result] {
        SetMainStatus "$result"
    }        
    SetMainStatus "Done."
}

proc GetCorrValue {} {
    global CorrName CorrValue

    if [catch {exec cavget -list=${CorrName}:CurrentAI } result] {
        SetMainStatus "$result"
        return
    }
    set CorrValue $result
}


proc MakeActionFrame {widget args} {
    global PSCUSampleTime RampStartOffsetTime BoosterTrigger IPTime SetIPTime
    global RampStartDelay
    APSParseArguments {parent}

    APSFrame $widget -parent $parent -label "BoosterCorrectorCheckOut options" \
      -contextHelp "Frame to specify arguments for booster orbit correction."
    set w0 $parent$widget.frame
    APSFrameGrid .fg -parent $w0 -yList {x1 x2 x3}
    

}
proc MakeFileFrame {widget args} {
    global CorrFileName MonitorFileName Interval
    set parent ""
    APSParseArguments {parent}
    
    set w $parent$widget.frame
    APSFrame $widget -parent $parent -label "Corrector Evolution and Monitoring Options"
    APSFrame .fileframe -parent $w
    set w $w.fileframe.frame
    APSLabeledEntry .corrfile -parent $w -label "evolution file name: " -width 60 \
      -textVariable CorrFileName -contextHelp "The filename for corrector monitoring"
    APSButton .gen -parent $w.corrfile -text "GEN" -command "GenerateFileName -fileVar CorrFileName" \
      -contextHelp "Automatically generate file name for corrector monitoring."
    APSButton .choose -parent $w.corrfile -text "P" -command "ChooseFileName -fileVar CorrFileName \
	-filter evol" -contextHelp "Choose previous file for plotting"
    APSLabeledEntry .monfile -parent $w -label "monitoring file name:" -width 60 \
      -textVariable MonitorFileName -contextHelp "The filename for bpm monitoring"
    APSButton .gen -parent $w.monfile -text "GEN" -command "GenerateFileName -fileVar MonitorFileName" \
      -contextHelp "Automatically generate file name for bpm monitoring."
    APSButton .choose -parent $w.monfile -text "P" -command "ChooseFileName -fileVar MonitorFileName \
	-filter monitor" -contextHelp "Choose previous file for plotting"
    APSLabeledEntry .interval -parent $w -label "Interval(s): " -width 10 -packOption "-side left" \
      -contextHelp "The interval in sec for the corrector monitoring." \
      -textVariable Interval 
    APSLabeledEntry .time -parent $w -label "Time (s):" -packOption "-side left" \
      -textVariable TotalTime -width 10 -contextHelp \
      "The total time in sec for the next corrector monitoring."
    APSLabeledEntry .min -parent $w -label "Imin (A):" -packOption "-side left" \
      -textVariable Imin -width 15 -contextHelp \
      "The minimum value of current to plot.  If both Imax and Imin are zero 
       it will autoscale."

    APSLabeledEntry .max -parent $w -label "Imax (A):" -packOption "-side left"  \
      -textVariable Imax -width 15 -contextHelp \
      "The maximum value of current to plot.  If both Imax and Imin are zero 
       it will autoscale."
}

proc CheckCorrectorRampTable {args} {
    global BoosterLattice 
    set BCorrRampDir /home/helios/oagData/booster/ramps/correctors/lattices/$BoosterLattice
    
    set waveformPVs [exec sdds2stream -par=ControlName $BCorrRampDir/HVCorr.ramp]
    set rows [lindex [exec sdds2stream -rows=bar $BCorrRampDir/HVCorr.ramp] 0]
    set tmpRoot /tmp/[APSTmpString]
    if [catch {exec sddswget $tmpRoot.1 -pv=[join $waveformPVs ,] } result] {
        return -code error "CheckCorrectorRampTable(1): $result"
    }
    APSAddToTmpFileList -ID boocheckout -fileList $tmpRoot.1
    if [catch {exec sddsprocess $tmpRoot.1 -pipe=out -clip=$rows,0,invert \
                 | sddsxref -pipe=in $BCorrRampDir/HVCorr.ramp -transfer=par,CorrName \
                 -take=RampTime,RampSetpoint $tmpRoot.2 } result] {
       return -code error $result
    }
    APSAddToTmpFileList -ID boocheckout -fileList $tmpRoot.2
    exec sddsplot -groupby=page -split=page -sep=page \
      -graph=sym,vary=type,connect=type,subtype=type \
      -col=RampTime,Waveform  -title=@TimeStamp \
      -samescale=y   \
      -leg=specified=CurrentTable $tmpRoot.2 \
      -col=RampTime,RampSetpoint -topline=@CorrName -leg=specified=ReferenceTable $tmpRoot.2 &
}

proc MakeActionWidget {widget args} {
    global Plane plane coord Coord brief
    
    APSParseArguments {parent}

    APSFrame $widget -parent $parent \
      -contextHelp "Frame for containing action buttons."
    set w $parent$widget.frame
    $w configure -relief flat
    APSFrame .y1 -parent $parent$widget.frame \
      -contextHelp "Frame for containing action buttons."
    
    set w $parent$widget.frame.y1.frame
    $w configure -relief flat
    APSButton .check -parent $w -text "Check Corr RampTable" \
      -command "CheckCorrectorRampTable" \
      -contextHelp "read corrector ramp tables and compare with reference.\n"
    APSButton .getcorr -parent $w -text "Get Corr Evolution" \
      -command {ChangeButtonState -mode disable; GetCorrectorEvolution; ChangeButtonState -mode enable} \
      -contextHelp "Get corrector readings at several places on the ramp."
    APSButton .plotcorr -parent $w -text "Plot Corr Evolution" \
      -command {PlotCorrEval}  -contextHelp \
      "Plot obtained corrector evolution measurements."
    APSButton .getmon -parent $w -text "Monitor Correctors" \
      -command {MonitorCorrectors} -contextHelp \
      "Get corrector readings at several places on the ramp."
    APSButton .plotmon -parent $w -text "Plot Corr Monitoring" \
      -command {PlotCorrMonitor}  -contextHelp \
      "Plot obtained corrector evolution measurements."
}


proc GetPSCUTime {args} {
    global PSCUSampleTime RampStartOffsetTime BoosterTrigger IPTime RampStartDelay
    global RampTime BPMOffsetTime DipoleZeroRef
    
    if [catch {exec cavget -list=It:Bs:Trig2BsIp -pend=30} BoosterTrigger] {
        return -code error "$BoosterTrigger"
    }
    if [catch {exec cavget -list=It:Bs:StartRamp2BsIp -pend=30} RampStartOffsetTime] {
        return -code error "$RampStartOffsetTime"
    }
    if [catch {exec cavget -list=It:Ddg4chan6.DLY -pend=30} RampStartDelay] {
        return -code error "$RampStartDelay"
    }
    if [catch {exec cavget -list=It:Ddg3chan6.DLY -pend=30} BPMOffsetTime] {
        return -code error "$BPMOffsetTime"
    }
    if {0} {
        #remove this checking since for 92nm lattice, trigger delay is 19.07ms instead of 16.07ms
    if {$RampStartDelay != 16.07} {
	APSErrorDialog .errordialog[APSUniqueNumber] -title Warning \
	  -errorMessage \
	  "StartRampCorrectorDelay is not 16.07\n  Value is $RampStartDelay"
    }
    }
    if [catch {exec cavget -list=B:BM:ZeroRefAO -pend=30} DipoleZeroRef] {
        return -code error "$DipoleZeroRef"
    }
    if [catch {exec cavget -list=It:Ddg3chan3.DLY -pend=30} PSCUSampleTime] {
        return -code error "$PSCUSampleTime"
    }
    set IPTime [expr ($PSCUSampleTime-$BoosterTrigger)/1000.]
    set RampTime [expr $IPTime + $RampStartOffsetTime - $RampStartDelay]

}

proc SetInjectionExtractionTime {args} {
    set mode ""
    global PSCUSampleTime RampStartOffsetTime BoosterTrigger IPTime RampStartDelay
    global RampTime BPMOffsetTime SetIPTime
    APSParseArguments {mode}
    if [catch {GetPSCUTime} result] {
        SetMainStatus "Error: $result"
    }
    SetMainStatus "Setting PSCU time to $mode..."
    switch $mode {
        injection {
            set SetIPTime 0
        }
        extraction {
            set SetIPTime 223
        }
    }
    set PSCUSampleTime [expr $SetIPTime*1000 + $BoosterTrigger]
    if [catch {exec cavput -list=It:Ddg3chan3.DLY=$PSCUSampleTime -pend=30} result] {
        SetMainStatus "$result"
        return
    }
    set IPTime $SetIPTime
    set RampTime [expr $IPTime + $RampStartOffsetTime - $RampStartDelay]
    SetMainStatus "setting done."
}
proc SetPSCUTime {args} {
    global PSCUSampleTime RampStartOffsetTime BoosterTrigger IPTime RampStartDelay
    global RampTime BPMOffsetTime SetIPTime
   
    if [catch {GetPSCUTime} result] {
        SetMainStatus "Error: $result"
    }
    SetMainStatus "Setting PSCU time ..."
    if {![string length $SetIPTime]} {
        SetMainStatus "Error: SetIPTime is not given!"
        return
    }
    if [catch {expr $SetIPTime / 2} result] {
        SetMainStatus "Error: $result"
        return
    }
    set PSCUSampleTime [expr $SetIPTime*1000 + $BoosterTrigger]
   
    if [catch {exec cavput -list=It:Ddg3chan3.DLY=$PSCUSampleTime -pend=30} result] {
        SetMainStatus "$result"
        return
    }
    set IPTime $SetIPTime
    set RampTime [expr $IPTime + $RampStartOffsetTime - $RampStartDelay]
    SetMainStatus "setting done."
}

proc GenerateFileName {args} {
    global CorrFileName MonitorFileName
    set fileVar ""
    APSParseArguments {fileVar}

    if [regexp {Corr} $fileVar] {
        set ext corr.evol
    } elseif [regexp {Monitor} $fileVar] {
        set ext corr.monitor
    } else {
        SetMainStatus "Invalid file variable given!"
        return
    }
    set $fileVar /tmp/[APSTmpString].$ext
    APSAddToTmpFileList -ID BoosterCorrectorCheckOut -fileList [set $fileVar]
}

proc GetCorrectorEvolution {args} {
    global CorrFileName
    global PSCUSampleTime RampStartOffsetTime BoosterTrigger IPTime RampStartDelay DipoleZeroRef

    set delayTime 0
    set full 0 
    #full=1, --- measure full interval (500 msec)
    APSParseArguments {delayTime full}
    
    SetMainStatus "Get corrector evolution ..."
    if [catch {GetBoosterLattice} lattice] {
	return -code error $lattice
    }
    set reference /home/helios/oagData/booster/ramps/correctors/lattices/${lattice}/HVCorr.ramp
    SetMainStatus "the booster reference lattice is $reference"
    set dir /home/helios/oagData/booster/orbitCorr
    if !$full {
        set vexpFile Bcorr.vexp
    } else {
        set vexpFile Bcorr.500.vexp
    }
    if ![string length $CorrFileName] {
        GenerateFileName -fileVar CorrFileName
    }
    if [file exist $CorrFileName] {
        if ![APSYesNoPopUp "file already exist, overwrite it?"] {
            return 
        }
	file delete -force $CorrFileName
    }
    global Scandone
    set scandone 0
    set tmpRoot /tmp/[APSTmpString]
    APSAddToTmpFileList -ID GetCorrectorEvolution -fileList "$tmpRoot"
    APSExecLog .jon1 -width 80 -unixCommand "sddsvexperiment $dir/$vexpFile $tmpRoot \
	  -suffix=$dir/BcorrSuffix.sdds \
	  -rootname=$dir/BcorrRoot.sdds -verbose" \
      -callback {set Scandone done} \
      -abortCallback {set Scandone abort} \
      -cancelCallback {set Scandone cancel}
    tkwait variable Scandone
    
    switch $Scandone {
        cancel {
            SetMainStatus "scan canceled."
            return
        }
        abort {
            SetMainStatus "scan aborted."
            return
        }
        done {
            SetMainStatus "measurement done"
            #get timing
            if [catch {GetPSCUTime} result] {
                SetMainStatus "Error in getting timing: $result; Evolution stopped.!"
                return
            }
            #Adding timing parameters
            if [catch {exec sddsprocess $tmpRoot $CorrFileName -nowarn \
                         -define=parameter,BoosterTrigger,$BoosterTrigger \
                         -define=parameter,RampStartOffset,$RampStartOffsetTime \
                         -define=parameter,RampStartCorrectorDelay,$RampStartDelay \
                         -define=parameter,DipoleZeroRef,$DipoleZeroRef } result] {
                SetMainStatus "Error in processing file: measurement is not saved!"
                return
            }
            PlotCorrEval
        }
    }
}

proc MonitorCorrectors {args} {
    global Interval TotalTime MonitorFileName Imin Imax scandone

    SetMainStatus "Get the individual corrector AI values..."
    set monfile /home/helios/oagData/booster/orbitCorr/bcorr.mon
    if ![string length $MonitorFileName] {
        GenerateFileName -fileVar MonitorFileName
    }
    if [file exist $MonitorFileName] {
        if ![APSYesNoPopUp "Warning: monitor file already exist, overwrite it?"] {
            SetMainStatus "Monitoring was cancelled"
            return
        }
	file delete -force $MonitorFileName
    }
    set scandone 0
    set tmpfile /tmp/[APSTmpString]
    APSAddToTmpFileList -ID BoosterCorrectorCheckOut -fileList $tmpfile
    if [catch {exec sddsconvert $monfile $tmpfile -delete=col,Message } result] {
	return -code error $result
    }
    APSExecLog .jon -width 80 -unixCommand "sddsmonitor -interval=${Interval},s -time=${TotalTime},s \
           $tmpfile  $MonitorFileName -verbose" \
      -callback {set scandone done} \
      -abortCallback {set scandone abort} \
      -cancelCallback {set scandone cancel}
    tkwait variable scandone
    switch $scandone {
        cancel {
            SetMainStatus "scan canceled."
        }
        abort {
            SetMainStatus "scan aborted."
        }
        done {
            SetMainStatus "monitor done"
        }
    }
    PlotCorrMonitor
}

proc PlotCorrEval {args} {
    global CorrFileName
    
    if [catch {GetBoosterLattice} lattice] {
	return -code error $lattice
    }
    set refRamp /home/helios/oagData/booster/ramps/correctors/lattices/${lattice}/HVCorr.ramp
    set delay 0.0
    if {![string length $CorrFileName] || ![file exist $CorrFileName]} {
        SetMainStatus "Corr evolution filename is not given or file does not exist."
        return
    }
    set tmpRoot /tmp/[APSTmpString]
    if [catch {exec sddsregroup $CorrFileName -pipe=out -newcolumns=PSCUSampleTime \
                 -newparameters=Rootname \
                 | sddsprocess -pipe=in $tmpRoot.1 \
                 "-redefine=col,PSCUSampleTime,PSCUSampleTime 1000 /,units=ms" } result] {
        SetMainStatus "sddsprocess: $result"
        return
    }
    if [catch {exec sddsxref $tmpRoot.1 $CorrFileName -pipe=out \
                 -transfer=param,TimeStamp,BoosterTrigger,RampStartOffset,RampStartCorrectorDelay,DipoleZeroRef \
                 -reuse=page -leave='*' \
                 | sddsprocess -pipe=in $tmpRoot.2 \
                 "-define=col,BoosterIPTime,PSCUSampleTime BoosterTrigger 100 / -"  \
                 "-define=col,RampTime,PSCUSampleTime BoosterTrigger 1000 / - RampStartOffset + RampStartCorrectorDelay - $delay -" } result] {
        SetMainStatus "sddsprocess: $result"
        return
    }
    if [catch {exec sddsprocess $refRamp -pipe=out  \
                 "-redefine=col,RampSetpoint,RampSetpoint 19.0 *,units=Amps" \
		   | sddssort -pipe -par=CorrName \
		   | sddsconvert -pipe=in $tmpRoot.3 \
		   -retain=param,TimeStamp,CorrName } result] {
        SetMainStatus "sddsprocess1: $result"
        return
    }
    if [catch {exec sddssort -par=Rootname $tmpRoot.2 $tmpRoot.2a} result] {
	return -code error "PlotCorrEvolution4: $result"
    }
    exec sddsplot -groupby=page -split=page -sep=page \
      -graph=sym,vary=type,connect=type,subtype=type \
      -col=RampTime,:CurrentAI -title=@TimeStamp \
      -samescale=y   \
      -leg=specified=Measured $tmpRoot.2a \
      -col=RampTime,RampSetpoint -topline=@CorrName -leg=specified=RampTable $tmpRoot.3 &
    
}

proc PlotCorrMonitor {args} {
    global MonitorFileName Imax Imin TotalTime

    if {![string length $MonitorFileName] || ![file exist $MonitorFileName]} {
        SetMainStatus "Monitor file name is not given or file does not exist."
        return
    }
    exec sddsplot $MonitorFileName \
	  -mode=x=offset \
	  "-col=Time,B1*H:CurrentAI" -graph=line,vary -leg -title=@TimeStamp \
	  -scale=0,${TotalTime},${Imin},${Imax}  -filename $MonitorFileName -end \
	  "-col=Time,B2*H:CurrentAI" -graph=line,vary -leg -title=@TimeStamp \
	  -scale=0,${TotalTime},${Imin},${Imax}  -filename $MonitorFileName -end \
	  "-col=Time,B3*H:CurrentAI" -graph=line,vary -leg -title=@TimeStamp \
	  -scale=0,${TotalTime},${Imin},${Imax}  -filename $MonitorFileName -end \
	  "-col=Time,B4*H:CurrentAI" -graph=line,vary -leg -title=@TimeStamp \
	  -scale=0,${TotalTime},${Imin},${Imax}  -filename $MonitorFileName -end \
	  "-col=Time,B1*V:CurrentAI" -graph=line,vary -leg -title=@TimeStamp \
	  -scale=0,${TotalTime},${Imin},${Imax}  -filename $MonitorFileName -end \
	  "-col=Time,B2*V:CurrentAI" -graph=line,vary -leg -title=@TimeStamp \
	  -scale=0,${TotalTime},${Imin},${Imax}  -filename $MonitorFileName -end \
	  "-col=Time,B3*V:CurrentAI" -graph=line,vary -leg -title=@TimeStamp \
	  -scale=0,${TotalTime},${Imin},${Imax}  -filename $MonitorFileName -end \
	  "-col=Time,B4*V:CurrentAI" -graph=line,vary -leg -title=@TimeStamp \
	  -scale=0,${TotalTime},${Imin},${Imax}  -filename $MonitorFileName -end &
    return
}

proc SetBoosterPowerSupplies {args} { 
    global PowerOn TurnOnPlane Fast RawOnly CorrNames
    
    set FastChoice [subst $Fast]
    set RawOnlyChoice [subst $RawOnly]
    set state $PowerOn
    switch $TurnOnPlane {
	h -
	v {
	    set selection $TurnOnPlane
	}
	both {
	    set selection b
	}
    }
    if {(${FastChoice}==1) && (${RawOnlyChoice}==0)} {
	SetMainStatus "Turning $state $selection power supplies and raw supplies in \"Fast\" mode..."
	set OnOffCommand "setbcorrps -${state} -${selection} -f"
	APSExecLog .setCorrState -unixCommand $OnOffCommand
	after 2000
	SetMainStatus "done"
    } elseif {((${FastChoice}==0) && (${RawOnlyChoice}==1)) || ((${FastChoice}==1) && (${RawOnlyChoice}==1))} {
	SetMainStatus "Turning $state raw supplies in \"Fast\" mode..."
	set OnOffCommand "setbcorrps -${state} -${selection} -r"
	APSExecLog .setCorrState -unixCommand $OnOffCommand
	after 2000
	SetMainStatus "done"
    } else {
	SetMainStatus "Turning $state $selection power supplies and raw supplies and loading zero ramps..."
	set OnOffCommand "setbcorrps -${state} -${selection}"
	APSExecLog .setCorrState -unixCommand $OnOffCommand
	after 2000
	SetMainStatus "Done.  This procedure will take a few seconds to complete."
    }
}

proc GetRampTable {} {
    global CorrName
    
    set tmpRoot /tmp/[APSTmpString]
    APSAddToTmpFileList -ID GetRampTable \
      -fileList "$tmpRoot $tmpRoot.print $tmpRoot.1 $tmpRoot.time $tmpRoot.ramp"
    if [catch {exec sddswget -pvName=$CorrName:rampRAMPTABLE.TIMA $tmpRoot.time
        exec sddswget -pvName=$CorrName:rampRAMPTABLE $tmpRoot.ramp} result] {
        return -code error $result
    }
    if [catch {exec cavget -list=$CorrName:rampRAMPTABLE.HIGH -pend=30} rate] {
        return -code error $rate
    }
    if [catch {exec sddsprocess $tmpRoot.ramp \
                 "-define=col,RampCurrent,Waveform $rate *" -pipe=out | \
                 sddsconvert -pipe=in $tmpRoot.1 -rename=col,Waveform=RampSetpoint 
        exec sddsxref $tmpRoot.1 $tmpRoot.time -take=Waveform -pipe=out | \
                 sddsconvert -pipe=in $tmpRoot -rename=col,Waveform=RampTime } result] {
        return -code error $result
    }
    if [catch {exec sddsprintout $tmpRoot $tmpRoot.print -par -col } result] {
        return -code error $result
    }
    APSFileDisplayWindow [APSUniqueName .] -fileName $tmpRoot.print \
      -deleteOnClose 1 -width 60 -height 30 -printCommand "enscript -r"
}

proc ChooseFileName {args} {
    global CorrFileName MonitorFileName
    set fileVar ""
    set filter ""
    APSParseArguments {fileVar filter}
    
    set files [glob -nocomplain /tmp/*.$filter]
    if ![llength $files] {
	return -code error "The $filter file has been generated yet."
    }
    APSScrolledListWindow .process -name "files for $filter" \
	-label "Select a file" \
	-itemList $files -selectionVar $fileVar
}
proc LoadBoosterCorrRamps {args} {

    global BoosterLattice BoosterLatticeState
    
    set BCorrRampDir /home/helios/oagData/booster/ramps/correctors/lattices/$BoosterLattice
    set BCorrRampLoadCommand "loadbramp $BCorrRampDir/HVCorr.ramp"
    if {0} {
        if {$BoosterLatticeState == "109nm"} {
            file delete -force /home/helios/oagData/booster/ramps/correctors/HVCorr.ramp
            file link -symbolic /home/helios/oagData/booster/ramps/correctors/HVCorr.ramp /home/helios/oagData/booster/ramps/correctors/lattices/x12.75-y9.80/HVCorr.ramp
        } elseif {$BoosterLatticeState == "92nm"} {
            file delete -force /home/helios/oagData/booster/ramps/correctors/HVCorr.ramp
            file link -symbolic /home/helios/oagData/booster/ramps/correctors/HVCorr.ramp /home/helios/oagData/booster/ramps/correctors/lattices/x13.75-y5.80/HVCorr.ramp
        } else {
            file delete -force /home/helios/oagData/booster/ramps/correctors/HVCorr.ramp
            file link -symbolic /home/helios/oagData/booster/ramps/correctors/HVCorr.ramp /home/helios/oagData/booster/ramps/correctors/lattices/x11.75-y9.80/HVCorr.ramp
        }
    }
    
    SetMainStatus "Loading the booster corrector ramps $BoosterLattice..."
    SetMainStatus "This procedure will take a few seconds to complete."
    APSExecLog .bCorrRampLoad -unixCommand $BCorrRampLoadCommand -callback "SetMainStatus \"Done\""
}

proc ChangeButtonState {args} {
    global ChangeButtonList
    set mode ""
    APSStrictParseArguments {mode} 
    switch $mode {
        enable {
            foreach button $ChangeButtonList {
                APSEnableButton $button 
            }
        }
        disable {
            foreach button $ChangeButtonList {
                APSDisableButton $button
            }
        }
    }
}

proc SetBPMTiming {args} {
    global N M

    if {![string length $N] || ![string length $M] } {
        return -code error "Either N or M is not given"
    }
    set bpmList [SelectedBPMList]
    if ![llength $bpmList] {
        return -code error "No bpms are selected!"
    }
    SetMainStatus "Set bpm timing ..."
    set config /home/helios/oagData/booster/orbitControllaw/lattices/config.sdds
    set data(ColumnNames) "Name"
    set data(ColumnInfo.Name) "type SDDS_STRING"
    set data(Column.Name) [list $bpmList]
    set tmpRoot /tmp/[APSTmpString]
    APSAddToTmpFileList -ID BoosterBPMConfig -fileList "$tmpRoot"
    if [catch {sdds save $tmpRoot data} result] {
        return -code error $result
    }
    if [catch {exec sddsprocess $config -pipe=out -match=par,NameType=MonitorNames | \
                 sddsselect -pipe $tmpRoot -match=Name | \
                 sddssort -pipe -column=Timing -unique | \
                 sdds2stream -pipe=in -col=Timing} result] {
        return -code error $result
    }
    set putList1 ""
    set putList2 ""
    foreach timing $result {
        lappend putList1 B:bpmT${timing}:Cycle_count_lo=$M
        lappend putList2 B:bpmT${timing}:Delay_count_lo=$N
    }
    if [catch {exec cavput -list=[join $putList1 ,] -pend=30
        exec cavput -list=[join $putList2 ,] -pend=30 } result] {
        return -code error $result
    }
    SetMainStatus "done."
}

proc SelectedBPMList {args} {
    
    set names ""
    set sectorCount 4
    set bpmItemList {C0P1 C0P2 C1P1 C1P2 C2P1 C2P2 C3P1 C3P2 C4P1 \
                       C4P2 C5P1 C5P2 C6P1 C6P2 C7P1 C7P2 C8P1 C8P2 C9P1 C9P2}
    for {set sector 1} {$sector<=$sectorCount} {incr sector} {
        foreach suffix $bpmItemList {
            lappend names B${sector}$suffix
        }
    }
    return $names
}

proc GetBoosterLattice {args} {
    if [catch {exec cavget -list=BOO:LatticeCALC -pend=10} lattice] {
	return -code error "Unable to read lattice: $lattice"
    }
    global Lattice
    switch $lattice {
	132 {
	    set Lattice x11.75-y9.80
	}
	109 {
	    set Lattice x12.75-y9.80
	}
	92 {
	    set Lattice x13.75-y5.80
	}
	default {
            set Lattice "unknown"
	}
    }
    if [string compare $Lattice "unknown"]==0 {
	SetMainStatus "Can not decide the lattice from chosen file, please choose one!"
	set Lattice ""
	APSDialog .lattice -name "Choose Lattice Dialog" \
	    -okCommand "update" -cancelCommand "destroy .lattice"
	APSRadioButtonFrame .radio -parent .lattice.userFrame -buttonList "92nm 109nm 132nm" \
	    -variable Lattice -valueList "x13.75-y5.80 x12.75-y9.80 x11.75-y9.80"
	tkwait window .lattice
	if ![string length $Lattice] {
	    return -code error "The lattice was not chosen!"
	}
    }
    if [catch {file readlink /home/helios/oagData/booster/ramps/correctors/HVCorr.ramp} oldLink] {
        set oldLink ""
    }
    if {![string length $oldLink] || ![string match *$Lattice* $oldLink]} {
	if [catch {file delete -force /home/helios/oagData/booster/ramps/correctors/HVCorr.ramp
	    file link -symbolic /home/helios/oagData/booster/ramps/correctors/HVCorr.ramp /home/helios/oagData/booster/ramps/correctors/lattices/$Lattice/HVCorr.ramp } result] {
	    SetMainStatus "Unable to link the corrector ramp default dir to $Lattice, please link it manually: $result"
	}
    }
    global BoosterLattice 
    set BoosterLattice $Lattice
    SetMainStatus "The lattice now is $Lattice, [GetLatticeDescription $Lattice]"
    return $Lattice
}

proc InitBoosterCorrector {args} {
    global Fast RawOnly TurnOnPlane PowerOn
    
    SetMainStatus "Init/Auto/Activate booster corrector..."
    SetMainStatus "power=$PowerOn"
   
    if [catch {APSMpBoosterSetCorrPowerSuppliesOnOffNormal -selection $TurnOnPlane \
		   -Fast $Fast -RawOnly $RawOnly -state1 $PowerOn } result] {
	return -code error $result
    }
    SetMainStatus "done"
}
proc GetLatticeDescription {lattice} {
    switch $lattice {
	"x11.75-y9.80" {
	    set BoosterLatticeState "High Emittance Lattice - 132 nm rad"
	}
	"x12.75-y9.80"  {
	    set BoosterLatticeState "Low Emittance Lattice - 109 nm rad"
	}
	"x13.75-y5.80" {
	    set BoosterLatticeState "Low Emittance Lattice - 92 nm rad"
	}
	default {
	    set BoosterLatticeState "unknown"
	}
    }
    return $BoosterLatticeState
}
set CorrNames {B1C0 B1C1 B1C2 B1C3 B1C4 B1C5 B1C6 B1C7 B1C8 B1C9 \
                 B2C0 B2C1 B2C2 B2C3 B2C4 B2C5 B2C6 B2C7 B2C8 B2C9 \
                 B3C0 B3C1 B3C2 B3C3 B3C4 B3C5 B3C6 B3C7 B3C8 B3C9 \
                 B4C0 B4C1 B4C2 B4C3 B4C4 B4C5 B4C6 B4C7 B4C8 B4C9}
#set BoosterLatticeState 109nm
#set BoosterLattice x12.75-y9.80
set CorrFileName ""
set MonitorFileName ""
set Interval 1
set TotalTime 60
set Imin -10.0
set Imax  10.0
set N 0
set M 68
set CorrName B1C0H
set Xorbit 0
set CorrValues 0
set CorrValue 0.0
set CorrPlane both
set TurnOnPlane both
set Fast 0
set RawOnly 0
set PowerOn on
set SetIPTime ""
set ChangeButtonList ""

set BoosterLattice [GetBoosterLattice]

MakeOptionFrame .options -parent .userFrame
MakeFileFrame .files -parent .userFrame
MakeActionWidget .actions -parent .userFrame
