#
# $Log: not supported by cvs2svn $
# Revision 1.21  2012/04/23 21:36:23  shang
# added checking if booster ramp auto-correction aborted before switching lattice.
#
# Revision 1.20  2012/04/23 21:09:47  shang
# fixed problem in setting fft parameters due to "lattice" value check error.
#
# Revision 1.19  2012/04/23 20:38:33  shang
# replaced caput by cavput.
#
# Revision 1.18  2012/04/23 20:32:56  shang
# made extensive changes to SwitchBoosterLattice pem due to hardware and design changes.
#
# Revision 1.17  2012/03/16 19:05:25  shang
# added APSMpBoosterChangeRampDelay pem.
#
# Revision 1.16  2011/02/15 20:27:44  shang
# To avoid the swap/sync error, added checking if swap/sync server is running before click swap/sync button. The swap/sync is clicked only if the
# swap/sync server is not running.
#
# Revision 1.15  2008/10/29 17:07:28  soliday
# Updated code to check for ? in results from cavget before using the
# results in an if statement.
#
# Revision 1.14  2007/03/01 17:24:26  soliday
# Added missing calls to APSLogScriptAction to store initialization values.
#
# Revision 1.13  2006/12/19 16:46:00  soliday
# Changed the procedure name of loadSafetyRamps to loadSafetyRamps2 because
# it was conflicting with a procedure of the same name in
# BRampControlAutoCorrection.tcl that accepted different arguments.
#
# Revision 1.12  2006/12/05 15:56:01  soliday
# Added the ability to relink the safety ramps when changing to and from 132nm
#
# Revision 1.11  2006/11/07 03:59:55  shang
# updated the booster lattice default link in the end of switching lattice pem.
#
# Revision 1.10  2005/04/07 16:28:39  soliday
# Updated to identify limited save files and not allow the operator to use them.
#
# Revision 1.9  2005/03/07 16:09:26  soliday
# Updated description for APSMpBoosterSwitchLattice per Sereno's instructions.
#
# Revision 1.8  2004/10/27 16:23:41  soliday
# Updated machine procedure descriptions per Sereno's request.
#
# Revision 1.7  2003/04/18 22:52:33  shang
# replaced loading ramps by APSMpBoosterLoadCorrectorRamps
#
# Revision 1.6  2003/04/18 22:31:47  shang
# added description for loading ramps
#
# Revision 1.5  2003/04/18 21:55:17  soliday
# Changed so that it does not restore BTS:[AB]BCurrentAO
#
# Revision 1.4  2003/04/18 21:44:07  shang
# filtered out BTS:AB and BTS:BB from restoring file
#
# Revision 1.3  2003/04/18 21:25:35  soliday
# Fixed problem with sddsprocess prior to running burtwb
#
# Revision 1.2  2003/04/18 17:04:47  shang
# comment out the switch default lattice
#
# Revision 1.1  2003/04/16 21:52:20  shang
# first version
#
#First Version Hairong Shang

proc APSMpBoosterSwitchLatticeInfo {} {
    return "For information about common safeguards and check please refer to OPSDoc_Boo_PEM004 under required reading.

This procedure is used to switch the booster lattice based on a file the operator is required to select.  The operator must select either a save file from the main SCR file window or a reference file.  The reference files are labeled according to the booster lattice.  Normally, the lattice used for operations is the 92 nm lattice.  The other lattices are available to use if for some reason the QF supply cannot be run at the high current required for the 92 nm lattice.  The QF current required is lowest for the 132 nm lattice.  The operator also may if desired select beamline category PVs to restore.

This procedure will also load the corrector ramps for the lattice specified in the SCR file.  See document OPSDoc_Boo_PEM002 for a description of the machine procedure that loads booster corrector ramps.
"
}

proc APSMpBoosterSwitchLatticeInitDialog {frame} {
    global APSMpBoosterSwitchLattice   
    set APSMpBoosterSwitchLattice(ShortFilename) ""
    set APSMpBoosterSwitchLattice(IRamp) 1
    set filterList [exec sddssort /home/helios/oagData/SCR/requestFiles/Booster.req -col=Category -unique -pipe=out \
                      | sdds2stream -pipe -col=Category]
    
   # set filterList {AFG BPM Bcontrol Diag ExtPulsedPS ExtTiming GlobalParameter InjPulsedPS InjTiming MainPS Readback Scrapers Setpoint Status SteeringPS SteeringSetpoint Timing TuneMeas}
    set varList ""
    foreach filter $filterList {
        set APSMpBoosterSwitchLattice($filter) 0
        lappend varList APSMpBoosterSwitchLattice($filter)
    }
   
    pack [frame $frame.f1]
    APSAddSCRDialog .scrNew -parent $frame.f1 -system Booster \
      -arrayName APSMpBoosterSwitchLattice \
      -defaultFile $APSMpBoosterSwitchLattice(ShortFilename) \
      -label "Choose Booster SCR file by clicking on the Preferred/Reference Choices"
    
    foreach item {AFG Bcontrol BRamp RampTiming InjTiming InjPulsedPS ExtTiming ExtPulsedPS SteeringPS SteeringSetpoint Booster PTB} {
	set APSMpBoosterSwitchLattice($item) 1
    }
    set APSMpBoosterSwitchLattice(BTS) 0
    set APSMpBoosterSwitchLattice(PAR) 0
    APSCheckButtonFrame .categorys -parent $frame.f1 \
      -label "Select SCR categories\nto restore" \
      -variableList $varList \
	-buttonList $filterList \
	-limitPerRow 7 -orientation horizontal -allNone 1
    APSCheckButtonFrame .beamlines -parent $frame.f1 -label "Select SCR beamline  \nto restore " \
	-variableList {APSMpBoosterSwitchLattice(BTS)    \
                         APSMpBoosterSwitchLattice(PAR) \
			   APSMpBoosterSwitchLattice(Booster)  \
			   APSMpBoosterSwitchLattice(PTB)} \
	-buttonList {BTS PAR Booster PTB} \
        -limitPerRow 7 -orientation horizontal -allNone 1
    APSRadioButtonFrame .iramp -parent $frame.f1 -label "Switch lattice for IRamp or VRamp?" -buttonList {IRamp VRamp} -valueList {1 0} \
      -orientation horizontal -variable APSMpBoosterSwitchLattice(IRamp)
    set APSMpBoosterSwitchLattice(Hz) 2Hz
    APSRadioButtonFrame .hz -parent $frame.f1 -label "Switch to 1Hz or 2Hz for IRamp?   " -buttonList {1Hz 2Hz} -valueList {1Hz 2Hz} \
      -orientation horizontal -variable APSMpBoosterSwitchLattice(Hz)
    APSMpReturn ok
}

proc APSMpBoosterSwitchLattice {args} {
    
    global APSMpBoosterSwitchLattice Lattice
    
    set ShortFilename ""
    set PreferredOnly 1
    set SuffixList {UBP 92nm 109nm 132nm 132nmOff}
    set scrDirectory /home/helios/oagData/SCR/snapshots/Booster
    set IRamp 1
    set Hz 2Hz
    APSStrictParseArguments {Hz ShortFilename IRamp}
    APSMpStep init -promptDialog APSMpBoosterSwitchLatticeInitDialog \
      -vars {ShortFilename IRamp Hz}
    
    if {![string length Lattice] || ![string length $ShortFilename]} {
        APSMpReturn error "APSMpBoosterSwitchLattice: reference file was not chosen."
    }
    
    set paramString ""
    foreach param {ShortFilename} {
        append paramString "$param=\"[set $param]\" "
    }
    catch {APSLogScriptAction \
             -procedure APSMpBoosterSwitchLattice \
             -action initialize \
             -state ok \
             -parameters $paramString}

    APSMpStep "$ShortFilename was chosen"
    if {[catch {exec sdds2stream $scrDirectory/$ShortFilename -parameter=SnapshotDescription -page=1 -noquotes} results]} {
        APSMpReturn error "APSMpBoosterSwitchLattice: Invalid SCR file"
    }    
    if {[string first "Limited save:" $results] != -1} {
        APSMpReturn error "APSMpBoosterSwitchLattice: LIMITED SAVE SCR files cannot be used for this procedure."
    }

    APSMpStep CheckBoosterLattice
    set qd [exec sddsprocess $scrDirectory/$ShortFilename -match=col,ControlName=*QD*Slope*AO* -pipe=out | \
		sdds2stream -pipe -col=ValueString]
    set qf [exec sddsprocess $scrDirectory/$ShortFilename -match=col,ControlName=*QF*Slope*AO* -pipe=out | \
		sdds2stream -pipe -col=ValueString]
    set Lattice [APSMpCheckBoosterLattice -qd $qd -qf $qf]
    APSMpStep "booster lattice: $Lattice"
    if [string compare $Lattice "unknown"]==0 {
	APSMpStep "Can not determine lattice from chosen file, please manually select the lattice!"
	set Lattice ""
	APSDialogBox .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" \
	    -label "Lattice: " -orientation Horizontal
	tkwait window .lattice
	if ![string length $Lattice] {
	    APSMpReturn error "The lattice was not chosen!"
	}
    }
    switch $Lattice {
	x13.75-y5.80 {
	    set lattice 92nm
	}
	x12.75-y9.80 {
	    set lattice 109nm
	}
	x11.75-y9.80 {
	    set lattice 132nm
	}
	default {
	    APSMpReturn error "Unknown lattice: $Lattice"
	}
    }
    if [catch {exec sddsprocess $scrDirectory/$ShortFilename -match=col,ControlName=P:BM:CurrentAO -pipe=out \
                 | sdds2stream -pipe -col=ValueString } parCurrent] {
        APSMpStep "PAR BM current not found in chosen file, please manually select the energy!"
	set energy ""
	APSDialogBox .energy -name "Choose Energy Dialog" \
	    -okCommand "update" -cancelCommand "destroy .energy"
	APSRadioButtonFrame .radio -parent .energy.userFrame -buttonList "325MeV 375MeV" \
	    -variable energy -valueList "325MeV 375MeV" \
	    -label "Energy: " -orientation Horizontal
	tkwait window .energy
	if ![string length $energy] {
	    APSMpReturn error "The energy was not chosen!"
	}
    } else {
        if [expr abs($parCurrent - 267.0)]<=2 {
            set energy 325MeV
        } elseif [expr abs($parCurrent - 310.0)]<=2 {
            set energy 375MeV
        } elseif [expr abs($parCurrent - 357)]<=2 {
            set energy 425MeV
        } elseif [expr abs($parCurrent - 386)]<=2 {
            set energy 450MeV
        } else {
            APSMpReturn error "APSMpBoosterSwitchLattice: the PAR BM energy is not valid in chosen SCR file."
        }
    }
    APSMpStep "Save before switching booster lattice."
    if [catch {APSSaveMachine -machine Booster -description "Saving before switching lattice." } result] {
	APSMpReturn error "Error saving booster SCR: $result"
    }
    
    APSMpStep "$lattice $energy"
    
    APSMpStep "Abort bcontrol and auto-ramp correction."
    if [catch {exec cavput -list=B: -list=BM,QF,QD,SF,SD  -list=bcontrollawRC.ABRT=1 -pend=30 } result] {
	APSMpReturnError "APSMpBoosterSwitchLattice: error in aborting booster bcontrols: $result"
    }
    if [catch {exec cavput -list=B: -list=BM,QF,QD,SF,SD -list=:AutoCorrectionControlRC.ABRT=1 -pend=30} result] {
	return -code error "APSMpBoosterSwitchlattice: error in aborting booster ramp auto correction: $result"
    }
    APSMpStep "Abort booster injection controllaws..."
    if [catch {exec cavput -list=Booster:ControlLawXRC,Booster:ControlLawYRC,Booster:ControlLawLongRC,B:InjTune:ControllawRC \
		   -list=.ABRT=1 -pend=30} result] {
	APSMpReturn error "APSMpBoosterSwitchlattice: error in aborting booster injection controllaws : $result."
    }
    APSMpStep "Wait for auto-correction aborted...."
    while {1} {
        if [catch {APScavget -pend=30 -printErrors -list=B: -list=BM,QF,QD,SF,SD  -list=bcontrollawRC.RUN } valList] {
            APSMpReturn error "APSMpBoosterSwitchlattice: error reading ramp auto-correction runcontrol status: $valList"
        }
        set notRunning 1
        foreach val $valList {
            if $val {
                set notRunning 0
            }
        }
        if $notRunning {
            break
        }
        after 1000
    }
    APSMpStep "Switching booster lattice to $lattice...."
    if [catch {APSMpSwitchDefaultLattice -lattice $lattice -energy $energy -IRamp $IRamp -Hz $Hz -scrFile $ShortFilename} result] {
        APSAlertBox .alert -errorMessage "$result -- the default lattice was not successfully switched"
        APSMpReturn error "APSMpBoosterSwitchLattice: $result"
    }
    if !$IRamp {
        APSMpStep "Loading Safety Ramps..."
        foreach type {BM QF QD SF SD} {
            if [catch {exec rampload /home/helios/oagData/booster/ramps/safety/${type}Vref.afg100} result] {
                APSMpReturn error "APSMpBoosterSwitchLattice: error in loading safety ramp ($type): $result"
            }
        }
        APSMpStep "Load AFG..."
        set tmpFile /tmp/[APSTmpString]
        if [catch {exec sddsprocess $scrDirectory/$ShortFilename $tmpFile \
                     "-match=col,ControlName=B:*RefAO,ControlName=It:*VafgTrigAO,|,ControlName=B:*VoltageRT.GAIN,|" } result] {
            APSMpReturn error "APSMpBoosterSwitchLattice: error1 in loading AFG gain: $result"
        }
        
        if [catch {exec sddscasr -restore $tmpFile} result] {
            APSMpReturn error "APSMpBoosterSwitchLattice: error2 in loading AFG gain: $result"
        }
    }

  # if [catch {APSMpBoosterRampAFG -filename $scrDirectory/$ShortFilename -rampSteps 1 \
  #		   -rampPause 1 -restoreBM 1} result] {
  #	APSMpReturn error "APSMpBoosterSwitchLattice Error in ramp booster ramp AFGs: $result"
  #   }
   
    set rampDir /home/helios/oagData/booster/ramps/correctors/lattices
    set rampTable $rampDir/default/HVCorr.ramp
    APSMpStep "Load Corrector RampTable: $rampTable"
    if [catch {exec ramploadnew $rampTable} results] {
	APSMpReturn error "APSMpBoosterSwitchLattice Error in load booster corrector ramp table: $results"
    }
    APSMpStep RestoreBoosterSettingsFromAFile
    APSMpStep "Restore Booster settings..."
    if [catch {APSMpRestoreBoosterSettings -filename \
                 $scrDirectory/$APSMpBoosterSwitchLattice(ShortFilename) } result] {
        APSAlertBox .alert -errorMessage "APSMpRestoreBoosterSettings: $result"
        APSMpReturn error "APSMpBoosterSwitchLattice: error in restoring booster settings."
    }
    APSMpStep "Save after booster lattice switch."
    if [catch {APSSaveMachine -machine Booster -description "Saving after booster lattice switch." } result] {
        APSMpReturn error "Error saving booster SCR after lattice switch: $result"
    }
    APSMpStep "start booster bcontrol, auto-correction, and injection controllaws..."
    APSInfoWindow .info -name "Restart booster controllaws" -width 60 \
	-infoMessage "Please restart booster bcontrol, auto-ramp correction, and injection controllaws from their controllaw GUI." -modal 1
    
    APSMpReturn ok
}

proc APSMpRestoreBoosterSettings {args} {
    global APSMpBoosterSwitchLattice
    set filename ""
    APSStrictParseArguments {filename}
    if ![file exist $filename] {
        return -code error "$filename does not exist!"
    }
    set pvList ""
    set beamlineList ""
    set filterList [exec sddssort /home/helios/oagData/SCR/requestFiles/Booster.req -col=Category -unique -pipe=out \
                      | sdds2stream -pipe -col=Category]
    foreach filter $filterList {
        if $APSMpBoosterSwitchLattice($filter) {
            lappend pvList $filter
        }
    }
    if $APSMpBoosterSwitchLattice(BTS) {lappend beamlineList BTS}
    if $APSMpBoosterSwitchLattice(Booster) {lappend beamlineList Booster}
    if $APSMpBoosterSwitchLattice(PTB) {lappend beamlineList PTB}
    if $APSMpBoosterSwitchLattice(PAR) {lappend beamlineList PAR}
    set i 0
    set option ""
    set option1 ""
    if {![llength $pvList] && ![llength $beamlineList]} {
        return -code error "no category or beamline is chosen for restore!"
    }
    foreach pv $pvList {
        incr i
        if {$i>1} {
            append option ",Category=$pv,|"
        } else {
            append option "-match=col,Category=$pv"
        }
    }
    set i 0
    foreach pv $beamlineList {
	incr i
	if {$i>1} {
            append option1 ",Beamline=$pv,|"
        } else {
            append option1 "-match=col,Beamline=$pv"
        }
    }
    set tmpFile /tmp/[APSTmpString].restore
    APSAddToTmpFileList -ID booster -fileList $tmpFile
    if [catch {exec sddsprocess $filename $tmpFile $option $option1 \
                 "-match=col,ControlName=*.USEC,!" \
                 "-match=col,ControlName=*Ref*,!" \
                 -match=column,IsReadOnly=+y,! -match=column,IsProtected=+y,! \
                 -match=column,ControlName=BTS:?B:CurrentAO,! } result] {
        return -code error $result
    }
    if [catch {exec sddscasr -restore $tmpFile} result] {
        return -code error $result
    }
}
proc APSMpChooseBoosterRefFile {frame} {
    global APSMpBoosterSwitchLattice
     #do not allow Bcontrol be selected
    set APSMpBoosterSwitchLattice(ShortFilename) ""
    set filterList {BPM Diag ExtPulsedPS ExtTiming GlobalParameter InjPulsedPS InjTiming MainPS Readback Scrapers Setpoint Status SteeringPS SteeringSetpoint Timing TuneMeas}
    foreach filter $filterList {
        set APSMpBoosterSwitchLattice($filter) 0
    }
    APSDialogBox $frame 
    APSAddSCRDialog .scrNew -parent $frame.userFrame -system Booster \
      -arrayName APSMpBoosterSwitchLattice \
      -defaultFile $APSMpBoosterSwitchLattice(ShortFilename) \
      -label "Choose Booster SCR file by clicking on the Preferred/Reference Choices"
    
    APSCheckButtonFrame .categorys -parent $frame \
      -label "Select SCR categories\nto restore" \
      -variableList {APSMpBoosterSwitchLattice(BPM)  \
                       APSMpBoosterSwitchLattice(Diag)  \
                       APSMpBoosterSwitchLattice(ExtPulsedPS) \
                       APSMpBoosterSwitchLattice(ExtTiming) \
                       APSMpBoosterSwitchLattice(GlobalParameter) \
                       APSMpBoosterSwitchLattice(InjPulsedPS) \
                       APSMpBoosterSwitchLattice(InjTiming) \
                       APSMpBoosterSwitchLattice(MainPS) \
                       APSMpBoosterSwitchLattice(Readback) \
                       APSMpBoosterSwitchLattice(Scrapers) \
                       APSMpBoosterSwitchLattice(Setpoint) \
                       APSMpBoosterSwitchLattice(Status) \
                       APSMpBoosterSwitchLattice(SteeringPS) \
                       APSMpBoosterSwitchLattice(SteeringSetpoint) \
                       APSMpBoosterSwitchLattice(Timing) \
                       APSMpBoosterSwitchLattice(TuneMeas)} \
	-buttonList $filterList \
	-limitPerRow 7 -orientation horizontal -allNone 1
    APSCheckButtonFrame .beamlines -parent $frame -label "Select SCR beamline  \nto restore " \
	-variableList {APSMpBoosterSwitchLattice(BTS)    \
			   APSMpBoosterSwitchLattice(Booster)  \
			   APSMpBoosterSwitchLattice(PTB)  \
			   APSMpBoosterSwitchLattice(PTB1)  \
			   APSMpBoosterSwitchLattice(PTB2) \
			   APSMpBoosterSwitchLattice(PTB3)} \
	-buttonList {BTS Booster PTB PTB1 PTB2 PTB3} \
        -limitPerRow 7 -orientation horizontal -allNone 1
    tkwait variable APSMpBoosterSwitchLattice(ShortFilename)
    
}

proc APSMpLoadBoosterRampTable {args} {
    set rampTable ""
    APSStrictParseArguments {rampTable}
    if ![string length $rampTable] {
        return -code error "the rampTable is not given"
    }
    if ![file exist $rampTable] {
        return -code error "rampTable $rampTable does not exist!"
    }
    
    APSMpStep "Loading ramp" -desc "Load ramp"
    if [catch {exec ramploadnew $rampTable} results] {
	APSMpReturn error "APSMpLoadBoosterRampTable: $results"
    }
    APSMpReturn ok
    #setting AFG foreground and set currentAO values no longer needed for new AFGs.
    APSMpStep "Setting AFG foreground" -desc "Set AFG foreground"
    if [catch {exec setbcorr -fg -q 2> /dev/null} results] {
	APSMpReturn error "APSMpLoadBoosterRampTable: $results"
    }
    APSMpStep "Setting CurrentAO values" -desc "Set CurrentAO values"
    if [catch {exec setbramp2ao -b} results] {
	APSMpReturn error "APSMpLoadBoosterRampTable: $results"
    }

    APSMpReturn ok
}

proc APSMpSwitchDefaultLattice {args} {
    set lattice ""
    set latticeDir /home/helios/oagData/booster/orbitControllaw/lattices
    set rampDir /home/helios/oagData/booster/ramps
    set correctorDir /home/helios/oagData/booster/ramps/correctors/lattices
    set controllawDir /home/helios/oagData/controllaw
    set energy ""
    set IRamp 1
    set Hz 2Hz
    set scrFile ""
    APSStrictParseArguments {lattice energy IRamp Hz scrFile} 
    switch $lattice {
	92nm {
	    set lattice1 x13.75-y5.80
	}
	109nm {
	    set lattice1 x12.75-y9.80
            set energy ""
	}
	132nm {
	    set lattice1 x11.75-y9.80
	}
	default {
	    return -code error "Unknow lattice -- $lattice provided."
	}
    }
    set oldDir [pwd]
    cd $latticeDir
    if [catch {file delete -force default} result] {
        cd $oldDir
        return -code error $result
    }
    if [catch {exec ln -s $lattice1 default} result] {
        cd $oldDir
        return -code error $result
    }
    cd /home/helios/oagData/booster/lattices
    if [catch {file delete -force default} result] {
        cd $oldDir
        return -code error $result
    }
    if [catch {exec ln -s ${lattice1} default} result] {
        cd $oldDir
        return -code error $result
    }
    
    cd $correctorDir
    catch {file delete -force default}
    if $IRamp {
        exec ln -s ${lattice1}-$Hz default 
    } else {
        exec ln -s ${lattice1} default
    }
    cd $rampDir
    if $IRamp {
        catch {exec rm IRamp}
        exec ln -s IRamp-${lattice}-$Hz IRamp
    }
    cd $controllawDir
    catch {file delete -force BOOSTER}
    if $IRamp {
        exec ln -s BOOSTER-IRamp-${lattice}-${energy}-$Hz BOOSTER
    } else {
        exec ln -s BOOSTER-VRamp-${lattice}-${energy} BOOSTER 
    }
    # run B3C2P1/B3C2P2 settings after switching booster controllaw
    if [catch {exec BBPMHistWaveformSetup} result] {
        return -code error "Error running BBPMHistWaveformSetup: $result"
    }
    if {0} {
    if { $lattice == "132nm" } {
	if [catch {exec cavput -list=B3C2P1:fftPeakSearchStart2P=300,B3C2P1:fftPeakSearchStop2P=500,B3C2P2:fftPeakSearchStartP=150,B3C2P2:fftPeakSearchStopP=300 -pend=30} result] {
	    return -code error "error in setting fft range1: $result"
	}
    }
    if {$lattice == "92nm" } {
	if [catch {exec cavput -list=B3C2P1:fftPeakSearchStart2P=150,B3C2P1:fftPeakSearchStop2P=300,B3C2P2:fftPeakSearchStartP=300,B3C2P2:fftPeakSearchStopP=500 -pend=30} result] {
	    return -code error "error in setting fft range2: $result"
	}
    }    
    }
    if [catch {exec BBPMHistWaveformSetup -lattice $lattice} result] {
        return -code error "Error in setting booster BPM fft parameters: $result"
    }
    cd $oldDir
    if $IRamp {
        APSMpStep "switch to booster IRamp $Hz ..."
        if [catch {APSMpSwitchIRamp -switchTo $Hz -energy $energy -scrFile $scrFile -popup 0} result] {
            APSMpReturn error "Error in switching to $Hz IRamp: $result"
        }
    } else {
        cd /home/helios/oagData/booster/ramps/VRamp
        catch {exec rm current}
        catch {exec rm safety}
        exec ln -s current-$lattice current
        exec ln -s safety-$lattice $safety
         APSMpStep "Load VRamp safety ramps..."
        if [catch {APSBoosterLoadSafetyRamp -BM 1 -QF 1 -QD 1 -SF 1 -SD 1 -IRamp 0 \
                     -description "load VRamp safety ramps from switching to VRamp PEM" } result] {
            APSMpReturn error "Error in loading VRamp safety ramps: $result"
        }
    }
    APSMpReturn ok
}

proc APSMpBoosterRampAFG {args} {
    set filename ""
    set rampSteps 10
    set rampPause 1
    set restoreBM 0
    APSStrictParseArguments {filename rampSteps rampPause restoreBM}

    if ![file exist $filename] {
	return -code error "$filename file does not exist!"
    }
    
    set tmpFile /tmp/[APSTmpString]
    APSAddToTmpFileList -ID Booster -fileList "$tmpFile.bcontrol $tmpFile.AFG"
    if !$restoreBM {
	if [catch {exec sddsprocess $filename $tmpFile.bcontrol \
		       "-match=col,Category=Bcontrol,ControlName=*RefAO,&,ControlName=*VafgTrigAO,|" \
		       "-match=col,ControlName=*BM*,!"} result] {
	    return -code error $result
	}
    } else {
	if [catch {exec sddsprocess $filename $tmpFile.bcontrol \
		       "-match=col,Category=Bcontrol,ControlName=*RefAO,&,ControlName=*VafgTrigAO,|" } result] {
	    return -code error $result
	}
    }
    if [catch {exec sddsprocess $filename $tmpFile.AFG \
		   "-match=col,Category=AFG,ControlName=*VoltageRT.GAIN,&" } result] {
	return -code error $result
    }
    set afgPV [exec sdds2stream $tmpFile.AFG -col=ControlName]
    set afgValue [exec sdds2stream $tmpFile.AFG -col=ValueString]
    if [catch {exec cavget -list=[join $afgPV ,] -pend=30} afgInitial] {
	return -code error "$afgInitial"
    }
    set swappvs {B:BM:VoltageRT.SWAP B:QF:VoltageRT.SWAP B:QD:VoltageRT.SWAP B:SF:VoltageRT.SWAP B:SD:VoltageRT.SWAP}
    foreach swap $swappvs {
	if {!$restoreBM && [string match *BM* $swap] } {continue}
	lappend swapcomm $swap=1
    }
    if [catch {exec sddscasr -restore $tmpFile.bcontrol} result] {
	return -code error $result
    }
    for {set step 0} {$step<$rampSteps} {incr step} {
	set putcommand ""
	foreach pv $afgPV val1 $afgInitial val2 $afgValue {
	    if {!$restoreBM && [string match *BM* $pv] } { continue}
	    set val [expr $val1+($val2-$val1)*$step/$rampSteps ]
	    lappend putcommand $pv=$val
	}
	if [catch {exec cavput -list=[join $putcommand ,] -pend=30} result] {
	    return -code error $result
	}
	#check if swap/sync server is running
	if [catch {exec cavget -list=B:SwapSyncRC.RUN -pend=10 -printErrors} swap] {
	    return -code error "can not read swap sync server runcontrol: $swap"
	}
	if !$swap {
	    if [catch {exec cavput -list=[join $swapcomm ,] -pend=30} result] {
		return -code error $result
	    }
	    if [catch {exec cavput -list=B:PSAFG100SyncBO=1 -pend=30} result] {
		return -code error $result
	    }
	}
	after [expr $rampPause * 1000]
    }
}

proc APSMpCheckBoosterLattice {args} {
    set snapshotDir /home/helios/oagData/SCR/snapshots/Booster
    set qf ""
    set qd ""
    APSStrictParseArguments {qf qd }
    
    set lattice92 $snapshotDir/Booster-LowE2Reference325.gz
    set lattice109 $snapshotDir/Booster-LowE1Reference325.gz
    set lattice132 $snapshotDir/Booster-Reference325.gz
    set qf92 [exec sddsprocess $lattice92 -match=col,ControlName=*QF*Slope*AO* -pipe=out | \
		  sdds2stream -pipe -col=ValueString]
    set qd92 [exec sddsprocess $lattice92 -match=col,ControlName=*QD*Slope*AO* -pipe=out | \
		  sdds2stream -pipe -col=ValueString]
    set qf109 [exec sddsprocess $lattice109 -match=col,ControlName=*QF*Slope*AO* -pipe=out | \
		  sdds2stream -pipe -col=ValueString]
    set qd109 [exec sddsprocess $lattice109 -match=col,ControlName=*QD*Slope*AO* -pipe=out | \
		   sdds2stream -pipe -col=ValueString]
    set qf132 [exec sddsprocess $lattice132 -match=col,ControlName=*QF*Slope*AO* -pipe=out | \
		   sdds2stream -pipe -col=ValueString]
    set qd132 [exec sddsprocess $lattice132 -match=col,ControlName=*QD*Slope*AO* -pipe=out | \
		   sdds2stream -pipe -col=ValueString]
    
    if {$qf < [expr $qf92*1.1] && $qf > [expr $qf92 * 0.9] && $qd < [expr $qd92 *1.1] && \
	    $qd > [expr $qd92 *0.9] } {
	return "x13.75-y5.80"
    }
    if {$qf < [expr $qf109*1.05] && $qf > [expr $qf109 * 0.95] && $qd < [expr $qd109 *1.05] && \
	    $qd > [expr $qd109 *0.95] } {
	return "x12.75-y9.80"
    }
    if {$qf < [expr $qf132*1.05] && $qf > [expr $qf132 * 0.95] && $qd < [expr $qd132 *1.05] && \
	    $qd > [expr $qd132 *0.95] } {
	return "x11.75-y9.80"
    }
    return "unknown"
}

proc APSCheckBControlStatus {args} {
    
    set statePVs {B:BM:ZeroPushMBBO B:QF:BconLockedMBBO B:QD:BconLockedMBBO B:SF:ZeroPushMBBO B:SD:BconLockedMBBO }
    if [catch {exec cavget -list=[join $statePVs ,] -num -pend=30} result] {
	return -code error $result
    }
    foreach val $result {
	if $val {
	    return 1
	}
    }
    return 0
}

proc APSMpBoosterChangeRampDelayInitDialog {frame} {
    global APSMpBoosterChangeRampDelay
    set APSMpBoosterChangeRampDelay(deltaDelay) 3
    pack [frame $frame.f1]
    APSLabeledEntry .delay -parent $frame.f1 -label "change delay by (delta delay) (ms):" -width 15 -textVariable APSMpBoosterChangeRampDelay(deltaDelay) \
	-contextHelp "enter delta delay (integer numner) to change by."
    APSMpReturn ok

}

proc APSMpBoosterChangeRampDelayInfo {} {
    return "change booster ramp delay pem."
}

proc APSMpBoosterChangeRampDelay {args} {
    global APSMpBoosterChangeRampDelay
    set deltaDelay 3
    APSStrictParseArguments {deltaDelay}
    APSMpStep init -promptDialog APSMpBoosterChangeRampDelayInitDialog \
	-vars {deltaDelay}
    catch {APSLogScriptAction \
             -procedure APSMpBoosterChangeRampDelay \
             -action initialize \
             -state ok \
             -parameters "deltaDelay=$deltaDelay"}
    if ![string length $deltaDelay] {
	APSMpReturn error "delta delay not provided."
    }
    
    set plusList {B:BM:ZeroRefAO B:QF:ZeroRefAO B:QD:ZeroRefAO B:SF:ZeroRefAO B:SD:ZeroRefAO It:Bs:StartRamp2BsIp.VAL}
    set minusList {It:Bs:BmVafgTrigAO.VAL It:Bs:QfVafgTrigAO.VAL It:Bs:QdVafgTrigAO.VAL It:Bs:SfVafgTrigAO.VAL It:Bs:SdVafgTrigAO.VAL}
    if [catch {exec cavput -list=[join $plusList ,] -list==$deltaDelay -deltaMode -pend=30 } result] {
	APSMpReturn error "Error in changing booster ramp delay(1): $result"
    }
    if [catch {exec cavput -list=[join $minusList ,] -list==[expr -1.0 * $deltaDelay] \
		   -deltaMode -pend=30 } result] {
	APSMpReturn error "Error in changing booster ramp delay(2): $result"
    }
    if [catch {exec cavput -list=BRF:KLY:TIM:boosterRFDly.DLY=[expr 1000.0 * $deltaDelay] -pend=30 -deltaMode } result] {
	APSMpReturn error "Error in changing booster ramp delay(3): $result"
    }
    APSMpReturn ok
}

proc APSMpSwitchToVRampInfo {} {
    return "changed the booster controllaw directory links to V-ramp."
}

proc APSMpSwitchToVRamp {args} {
    APSMpStep "Abort booster controllaws..."
    if [catch {exec cavput -list=B: -list=BM,QF,QD,SF,SD -list=bcontrollawRC.ABRT=1 -pend=10
        exec cavput -list=B: -list=BM,QF,QD,SF,SD -list=:AutoCorrectionControlRC.ABRT=1 -pend=10
        exec cavput -list=B:InjTune:ControllawRC.ABRT=1 -pend=10} result] {
        APSMpReturn error "Error aborting booster controllaws ..."
    }
    cd /home/helios/oagData/controllaw
    catch {exec rm bcontrollaw}
    exec ln -s bcontrollaw-VRamp bcontrollaw
    catch {exec rm BOOSTER}
    exec ln -s BOOSTER-92nm-375MeV BOOSTER
    # run B3C2P1/B3C2P2 settings after switching booster controllaw
    if [catch {exec BBPMHistWaveformSetup} result] {
        return -code error "Error running BBPMHistWaveformSetup: $result"
    }
    #load SD safety since SD ramp has a bump in IRamp, much different from VRamp
    if [catch {APSBoosterLoadSafetyRamp -SD 1 -description "loading SD VRamp safety ramp after switching to VRamp." } results] {
        APSMpReturn error "Error of loadSafetyRamps for SD: $results"
    }
    #APSMpStep "Reset QF, QD trigger offset..."
    #if [catch {exec cavput -list=B: -list=QF,QD -list=:IRampDelayOffsetAI=0 -pend=10} result] {
    #    APSMpReturn error "Error in reseting QF, QD trigger offset: $result"
    #}
    APSMpStep "load VRamp safety ramps..."
    if [catch {APSBoosterLoadSafetyRamp -BM 1 -QF 1 -QD 1 -SF 1 -SD 1 -IRamp 0 \
                 -description "load VRamp safety ramps from switching to VRamp PEM" } result] {
        APSMpReturn error "Error in loading VRamp safety ramps: $result"
    }
    APSInfoWindow .info -name "Restart booster controllaws" -width 60 \
      -infoMessage "Please retore booster bcontrol, auto-ramp correction, and injection controllaws from their controllaw GUI." -modal 1
    exec BRampControlAutoCorrection &
    APSMpReturn ok
}

proc APSMpSwitchToIRampInfo {} {
    return "changed the booster controllaw directory links to I-ramp."
}

proc APSMpSwitchToIRampInitDialog {frame} {
    global APSMpSwitchToIRamp
    set APSMpSwitchToIRamp(ShortFilename) ""
    pack [frame $frame.f1]
    APSAddSCRDialog .scrIRamp -parent $frame.f1 -system Booster \
      -arrayName APSMpSwitchToIRamp \
      -defaultFile $APSMpSwitchToIRamp(ShortFilename) \
      -label "Choose Booster SCR file by clicking on the lastest IRamp SCR file."
    APSMpReturn ok
}
proc APSMpSwitchToIRamp {args} {
    global APSMpSwitchToIRamp
    set ShortFilename ""
    APSMpStep init -promptDialog  APSMpSwitchToIRampInitDialog  -vars {ShortFilename}
    APSMpStep "Abort booster controllaws..."
    
    if [catch {exec cavput -list=B: -list=BM,QF,QD,SF,SD -list=bcontrollawRC.ABRT=1 -pend=10
        exec cavput -list=B: -list=BM,QF,QD,SF,SD -list=:AutoCorrectionControlRC.ABRT=1 -pend=10
        exec cavput -list=B:InjTune:ControllawRC.ABRT=1 -pend=10} result] {
        APSMpReturn error "Error aborting booster controllaws: $result"
    }
    cd /home/helios/oagData/controllaw
    catch {exec rm bcontrollaw}
    exec ln -s bcontrollaw-IRamp bcontrollaw
    catch {exec rm BOOSTER}
    exec ln -s BOOSTER-IRamp-92nm-375MeV BOOSTER
    
    APSMpStep "load IRamp safety ramps..."
    if [catch {APSBoosterLoadSafetyRamp -BM 1 -QF 1 -QD 1 -SF 1 -SD 1 -IRamp 1 \
                 -description "load VRamp safety ramps from switching to IRamp PEM" } result] {
        APSMpReturn error "Error in loading IRamp safety ramps: $result"
    }
    
    APSMpStep "Load IRamp gain and delay from SCR..."
    set tmpRoot /tmp/[APSTmpString]
    if [catch {exec sddsprocess /home/helios/oagData/SCR/snapshots/Booster/$ShortFilename $tmpRoot.restore \
                 "-match=col,ControlName=*IRampDelayOffsetAI,ControlName=*IRampGainSetAI,|" } result] {
        APSMpReturn error "Error $ShortFilename does not have IRamp gain and delay parameters: $result"
    }
    
    if [catch {exec sddscasr -restore $tmpRoot.restore} result] {
        APSMpReturn error "Error restoring IRamp gain and delay: $result"
    }
    APSAddToTmpFileList  -ID booster -fileList $tmpRoot.restore
    APSInfoWindow .info -name "Restart booster controllaws" -width 60 \
      -infoMessage "Please retore booster bcontrol, auto-ramp correction, and injection controllaws from their controllaw GUI." -modal 1
    
    exec BRampControlAutoCorrection &
    APSMpReturn ok
}

proc APSMpSwitchTo2HzIRampInfo {} {
    return "changed the booster controllaw and ramp directory links to 2Hz I-ramp."
}

proc APSMpSwitchTo2HzIRampInitDialog {frame} {
    global APSMpSwitchTo2HzIRamp
    set APSMpSwitchTo2HzIRamp(ShortFilename) ""
    pack [frame $frame.f1]
    APSAddSCRDialog .scrIRamp -parent $frame.f1 -system Booster \
      -arrayName APSMpSwitchTo2HzIRamp \
      -defaultFile $APSMpSwitchTo2HzIRamp(ShortFilename) \
      -label "Choose Booster SCR file by clicking on the lastest 2Hz IRamp SCR file."
    APSMpReturn ok
}


proc APSMpSwitchTo1HzIRampInfo {} {
    return "changed the booster controllaw and ramp directory links to 1Hz I-ramp."
}

proc APSMpSwitchTo1HzIRampInitDialog {frame} {
    global APSMpSwitchTo1HzIRamp
    set APSMpSwitchTo1HzIRamp(ShortFilename) ""
    pack [frame $frame.f1]
    APSAddSCRDialog .scrIRamp -parent $frame.f1 -system Booster \
      -arrayName APSMpSwitchTo1HzIRamp \
      -defaultFile $APSMpSwitchTo1HzIRamp(ShortFilename) \
      -label "Choose Booster SCR file by clicking on the lastest 1Hz IRamp SCR file."
    APSMpReturn ok
}

proc APSMpSwitchIRamp {args} {
    set switchTo 2Hz
    set scrFile ""
    set popup 1
    set energy 375MeV
    APSStrictParseArguments {switchTo scrFile popup energy}

    switch $switchTo {
        1Hz {
            set mode 1
            set linacSeq 55
            set rfSeq 60
            #for bunch cleaning start time delay (P:DG1:aDelayAO)
            set bunchDelay 780000
            set parMode 1
            set parTimingFile /home/helios/oagData/par/bunchCleaning/parChargeRegionTiming1Hz.sdds
        }
        2Hz {
            set mode 0
            set linacSeq 25
            set rfSeq 30
            #for bunch cleaning start time delay (P:DG1:aDelayAO)
            set bunchDelay 350000
            set parMode 0
            set parTimingFile /home/helios/oagData/par/bunchCleaning/parChargeRegionTiming2Hz.sdds
        }
        default {
            APSMpReturn error "APSMpSwitchIRamp1: invalid argument value -- $switchTo"
        }
    }
    APSMpStep "Abort booster controllaws..."
    
    if [catch {exec cavput -list=B: -list=BM,QF,QD,SF,SD -list=bcontrollawRC.ABRT=1 -pend=10
        exec cavput -list=B: -list=BM,QF,QD,SF,SD -list=:AutoCorrectionControlRC.ABRT=1 -pend=10 } result] {
        APSMpReturn error "APSMpSwitchIRamp2: Error aborting booster controllaws: $result"
    }
    APSMpStep "Change to $switchTo  mode..."
    if [catch {exec cavput -list=It:L:1HzNot2Hz_bo.VAL=$mode,P:DG1:aDelayAO=$bunchDelay,PAR:awg:timingModeBO=$parMode  -pend=30
        after 1000
        exec cavput -list=It:L:seq_len_lo.VAL=$linacSeq,It:L:rfseq_len_lo.VAL=$rfSeq -pend=30 } result] {
        APSMpReturn error "APSMpSwitchIRamp3: Error changing mode pv and linac sequence: $result"
    }
    if [catch {exec cavput -list=It:L:B0 -range=begin=0,end=8,interval=2 -list=_rfenb_bo.VAL=1
        exec cavput -list=It:L:B0 -range=begin=1,end=9,interval=2 -list=_rfenb_bo.VAL=0
        exec cavput -list=It:L:B -range=begin=10,end=58,interval=2 -list=_rfenb_bo.VAL=1
        exec cavput -list=It:L:B -range=begin=11,end=59,interval=2 -list=_rfenb_bo.VAL=0 } result] {
        APSMpReturn error "APSMpSwitchIRamp4: Error changing rf sequence: $result"
    }
    if [catch {exec sddscasr -restore $parTimingFile -pend=30} result] {
        APSMpReturn error "APSMpSwitchIRamp4a: error restoring par region timing: $result"
    }
    APSMpStep "Change IRamp link..."
    cd /home/helios/oagData/booster/ramps
    if [catch {file readlink IRamp} result] {
        APSMpReturn -error "APSMpSwitchIRamp3a: Error reading IRamp link: $result"
    }
    if [regexp {92} $result] {
        set lat 92
    } elseif [regexp {132} $result] {
        set lat 132
    } else {
        APSMpReturn error "APSMpSwitchIRamp3b(Error) - invaliding IRamp link -- $result"
    }
    catch {exec rm IRamp}
    exec ln -s IRamp-${lat}nm-$switchTo IRamp
    #change single turn setpoint reference link
    cd /home/helios/oagData/SCR/snapshots/Booster
    exec rm Booster-SingleTurnPreferred.gz
    exec ln -s Booster-SingleTurnPreferred${switchTo}.gz Booster-SingleTurnPreferred.gz
    
    #change controllaw dir
    cd /home/helios/oagData/controllaw
    catch {exec rm BOOSTER}
    exec ln -s BOOSTER-IRamp-${lat}nm-$energy-$switchTo BOOSTER
    
    if [catch {APSMpBoosterSwitchSD -ShortFilename $scrFile} result] {
        APSMpReturn error "Error switch SD/SDU: $result"
    }
    # run B3C2P1/B3C2P2 settings after switching booster controllaw
    if [catch {exec BBPMHistWaveformSetup} result] {
        return -code error "Error running BBPMHistWaveformSetup: $result"
    }
    APSMpStep "load BM/QF/QD IRamp safety ramps..."
    if [catch {APSBoosterLoadSafetyRamp -BM 1 -QF 1 -QD 1 -SF 0 -SD 0 -IRamp 1 \
                 -description "load VRamp safety ramps from switching to IRamp PEM" } result] {
        APSMpReturn error "APSMpSwitchIramp4: Error in loading IRamp safety ramps: $result"
    }
    APSMpStep "load SF-U IRamp safety ramps..."
    if [catch {APSBoosterLoadSDUSafetyRamp -magnet SF-U } result] {
        APSMpReturn error "APSMpSwitchIramp4: Error in loading SF-U IRamp safety ramps: $result"
    }

    APSMpStep "Load BM/QF/QD/SF-U IRamp gain and delay from SCR..."
    set tmpRoot /tmp/[APSTmpString]
    if [catch {exec sddsprocess /home/helios/oagData/SCR/snapshots/Booster/$scrFile $tmpRoot.restore \
                 -match=col,IsProtected=n -match=col,IsReadOnly=n \
                 "-match=col,ControlName=*SD*,!" \
                 "-match=col,ControlName=*.USEC,!" \
                 "-match=col,ControlName=*Ref*,!" \
                 "-match=col,ControlName=*IRampDelayOffsetAI,ControlName=*IRampGainSetAI,|,Category=RampTiming,|,Category=InjTiming,|,Category=InjPulsedPS,|,Category=AFG,|,Category=Bcontrol,|,Category=ExtTiming,|,Category=BRamp,|" } result] {
        APSMpReturn error "APSMpSwitchIramp5: Error $scrFile does not have IRamp gain and delay parameters: $result"
    }
    if [catch {exec sddscasr -restore $tmpRoot.restore -waveform=directory=/home/helios/oagData/SCR/snapshots/Booster,onefile,extension=.waveform.gz,rootname=[file root $scrFile] } result] {
        APSMpReturn error "APSMpSwitchIramp6: Error restoring IRamp gain and delay: $result"
    }
    APSAddToTmpFileList  -ID booster -fileList $tmpRoot.restore
    
    APSMpStep "Load BM/QF/QD/SF-U  IRamp reference ..."
    set tmpRoot /tmp/[APSTmpString]
    set refDir /home/helios/oagData/booster/ramps/IRamp/current-IRamp
    foreach magnet {BM QF QD SF-U} {
        if [catch {exec sddsconvert $refDir/IRef -pipe=out \
                     -retain=col,Index,B:${magnet}:CurrentWF -retain=par,${magnet}* \
                     | sddsconvert -pipe -rename=col,B:${magnet}:CurrentWF=Waveform \
                     | sddsprocess -pipe=in -reprint=par,WaveformPV,B:${magnet}:IRampRefWF $tmpRoot.$magnet} result] {
            APSMpReturn error "APSMpSwitchIramp7: $result"
        }
        set gain [exec sdds2stream -par=${magnet}AfgGain $tmpRoot.$magnet]
        set delay [exec sdds2stream -par=${magnet}TriggerDelay $tmpRoot.$magnet]
        if [catch {exec cavput -list=B:${magnet}:RefAfgGain=$gain,B:${magnet}:RefTriggerDelay=$delay -pend=20
            exec sddswput $tmpRoot.$magnet -pend=20 } result] {
            APSMpReturn "APSMpSwitchIramp8: error in setting reference pvs: $result"
        }
    }

    set files [glob $tmpRoot.*]
    APSAddToTmpFileList -ID ramp -fileList $files
    if $popup {
        APSInfoWindow .info -name "Restart booster controllaws" -width 60 \
          -infoMessage "Please retore booster bcontrol, auto-ramp correction, and injection controllaws from their controllaw GUI." -modal 1
        
        exec BRampControlAutoCorrection &
    }
    APSMpReturn ok
        
}

proc APSMpSwitchTo1HzIRamp {args} {
    global APSMpSwitchTo1HzIRamp
    
    set ShortFilename ""
    APSMpStep init -promptDialog  APSMpSwitchTo1HzIRampInitDialog  -vars {ShortFilename}
    
    if [catch {APSMpSwitchIRamp -switchTo 1Hz -scrFile $ShortFilename } result] {
        APSMpReturn error "Error switching to 1Hz: $result"
    }
    APSMpReturn ok
}

proc APSMpSwitchTo2HzIRamp {args} {
    global APSMpSwitchTo2HzIRamp
    
    set ShortFilename ""
    APSMpStep init -promptDialog  APSMpSwitchTo2HzIRampInitDialog  -vars {ShortFilename}
    if [catch {APSCheckBoosterIRampMode} mode] {
        APSMpReturn error "APSMpSwitchTo2HzIRamp0: error checking IRamp mode."
    }
    if {$mode=="LongRamp"} {
        APSMpReturn error "APSMpSwitchTo2HzIRamp0a: can not switch to 2Hz ramp from long IRamp."
    }
    APSMpStep "2Hz SCR File: $ShortFilename"
    if [catch {APSMpSwitchIRamp -switchTo 2Hz -scrFile $ShortFilename } result] {
        APSMpReturn error "Error switching to 2Hz: $result"
    }
    APSMpReturn ok
}

proc APSMpSwitchToLongIRampInitDialog {args} {
    global APSMpSwitchToLongIRamp
    set APSMpSwitchToLongIRamp(ShortFilename) ""
    pack [frame $frame.f1]
    APSAddSCRDialog .scrIRamp -parent $frame.f1 -system Booster \
      -arrayName APSMpSwitchToLongIRamp \
      -defaultFile $APSMpSwitchToLongIRamp(ShortFilename) \
      -label "Choose Booster SCR file by clicking on the lastest Long IRamp SCR file."
    APSMpReturn ok
}

proc APSMpSwitchToLongIRamp {args} {
    global APSMpSwitchToLongIRamp
    set ShortFilename ""
    APSMpStep init -promptDialog  APSMpSwitchToLongIIRampInitDialog  -vars {ShortFilename}
    
    if [catch {APSCheckBoosterIRampMode} mode] {
        APSMpReturn error "APSMpSwitchToLongIRamp0: error checking IRamp mode."
    }
    if {$mode=="2Hz"} {
        APSMpReturn error "APSMpSwitchToLongIRamp0a: can not switch to long ramp from 2Hz IRamp."
    }
    APSMpStep "Step 1: switch to 1 Hz IRamp..."
    if [catch {APSMpSwitchIRamp -switchTo 1Hz -scrFile Booster-1HzPreferred.gz} result] {
        APSMpReturn error "APSMpSwitchToLongIRamp1: Error switching to 1Hz: $result"
    }
    APSMpStep "Step 2: Reduce the AFG gains to 0.2 ..."
    if [catch {exec cavput -list=B: -list=BM,QF,QD,SF,SD -list=:VoltageRT.GAIN=0.2 -ramp=step=5,pause=1 } result] {
        APSMpReturn error "APSMpSwitchToLongIRamp2: Error reduce the AFG gain: $result"
    }
    APSMpStep "Step 3: Change Jumpers..."
    APSInfoWindow .info -name "Change Jumpers" -width 60 \
      -infoMessage "Change jumpers (AFG clock and V490 sample clock) in B102 iocramp front panel. Click Ok when done." -modal 1
    set scrDirectory /home/helios/oagData/SCR/snapshots/Booster
    set tmpRoot /tmp/[APSTmpString]
    if [catch {exec sddsprocess /home/helios/oagData/SCR/snapshots/Booster/$ShortFilename $tmRoot.restore \
                 -match=col,IsProtected=n -match=col,IsReadOnly=n \
                 "-match=col,ControlName=*.USEC,!" \
                 "-match=col,Category=BRamp,Category=RampTiming,|,Category=ExtTiming,|" } result] {
        APSMpReturn error "APSMpSwitchToLongIRamp3: $result"
    }
    APSMpStep "Step 4: Loading BRamp,BRampTiming and ExtTiming ..."
    if [catch {exec sddscasr -restore $tmpRoot.restore -waveform=directory=/home/helios/oagData/SCR/snapshots/Booster,onefile,extension=.waveform.gz,rootname=[file root $ShortFilename] } result] {
        APSMpReturn error "APSMpSwitchToLongIRamp4: Error restoring IRamp gain and delay: $result"
    }
    APSMpStep "Step 5: Link long ramp directory..."
    cd /home/helios/oagData/booster/ramps
    catch {exec rm IRamp}
    exec ln -s IRamp-1Hz-long IRamp
    cd /home/helios/oagData/bcontrollaw
    catch {exec rm bcontrollaw}
    exec ln -s bcontrollaw-IRamp-long bcontrollaw
    
    APSMpStep "Step 6: Loading safety ramps..."
    if [catch {APSBoosterLoadSafetyRamp -BM 1 -QF 1 -QD 1 -SF 1 -SD 1 -IRamp 1 \
                 -description "load safety ramps from SwithToLongRamp pem" } result] {
        APSMpReturn error  "APSMpSwitchToLongIRamp7: error in loading safety ramps: $result"
    }
    APSMpStep "Step 7: Ramp AFG gains to 0.6.."
    if [catch {exec cavput -list=B: -list=BM,QF,QD,SF,SD -list=:VoltageRT.GAIN=0.6 -ramp=step=5,pause=1 } result] {
        APSMpReturn error "APSMpSwitchToLongIRamp8: Error change the AFG gain to 0.6: $result"
    }
    APSMpStep "Step 8: Load bcontrol, AFG and injTiming from a long ramp mode SCR file."
    if [catch {exec sddsprocess $scrDir/$ShortFilename $tmpRoot.restore1 \
                 -match=col,IsProtected=n -match=col,IsReadOnly=n \
                 "-match=col,ControlName=*.USEC,!" \
                 "-match=col,Category=Bcontrol,Category=AFG,|,Category=InjTiming,|" } result] {
        APSMpReturn error "APSMpSwitchToLongIRamp8: $result"
    }
    if [catch {exec sddscasr -restore $tmpRoot.restore1 -waveform=directory=/home/helios/oagData/SCR/snapshots/Booster,onefile,extension=.waveform.gz,rootname=[file root $ShortFilename] } result] {
        APSMpReturn error "APSMpSwitchToLongIRamp9: Error restoring IRamp Bcontrol, AFG gain and InjTiming: $result"
    }
    
    APSMpStep "Step 9: Load long IRamp reference..."
    foreach magnet {BM QF QD SF SD} {
        if [catch {exec sddsconvert $refDir/IRef -pipe=out \
                     -retain=col,Index,B:${magnet}:CurrentWF -retain=par,${magnet}* \
                     | sddsconvert -pipe -rename=col,B:${magnet}:CurrentWF=Waveform \
                     | sddsprocess -pipe=in -reprint=par,WaveformPV,B:${magnet}:IRampRefWF $tmpRoot.$magnet} result] {
            APSMpReturn error "APSMpSwitchToLongIRamp10: $result"
        }
        set gain [exec sdds2stream -par=${magnet}AfgGain $tmpRoot.$magnet]
        set delay [exec sdds2stream -par=${magnet}TriggerDelay $tmpRoot.$magnet]
        if [catch {exec cavput -list=B:${magnet}:RefAfgGain=$gain,B:${magnet}:RefTriggerDelay=$delay -pend=20
            exec sddswput $tmpRoot.$magnet -pend=20 } result] {
            APSMpReturn error "APSMpSwitchToLongIRamp11: error in setting reference pvs: $result"
        }
    }
    APSMpStep "Step 10: Start bcontrol and autoRampCorrection"
    APSInfoWindow .info -name "Start bcontrol and autoRampCorrection" -width 60 \
	-infoMessage "Please start bcontrol and auto ramp correction now." -modal 1
    set files [glob $tmpRoot.*]
    eval file delete -force $files
    APSMpReturn ok
}

proc APSMpSwitchTo1HzIRampFromLongRampInitDialog {args} {
    global APSMpSwitchTo1HzIRampFromLongIRamp
    set APSMpSwitchTo1HzIRampFromLongIRamp(ShortFilename) ""
    pack [frame $frame.f1]
    APSAddSCRDialog .scrIRamp -parent $frame.f1 -system Booster \
      -arrayName  APSMpSwitchTo1HzIRampFromLongIRamp\
      -defaultFile $APSMpSwitchTo1HzIRampFromLongIRamp(ShortFilename) \
      -label "Choose 1Hz Booster SCR file."
    APSMpReturn ok

}

proc APSMpSwitchTo1HzIRampFromLongRamp {args} {
    global APSMpSwitchTo1HzIRampFromLongIRamp
    set ShortFilename ""
    APSMpStep init -promptDialog  APSMpSwitchTo1HzIRampFromLongIRampInitDialog  -vars {ShortFilename}
    
    APSMpStep "Step 1: reduce AFG gain to 0.2 in steps..."
    if [catch {exec cavput -list=B: -list=BM,QF,QD,SF,SD -list=:VoltageRT.GAIN=0.6 -ramp=step=5,pause=1 } result] {
        APSMpReturn error "APSMpSwitchTo1HzIRampFromLongRamp1: Error reduce the AFG gain to 0.2: $result"
    }
    set scrDir /home/helios/oagData/SCR/snapshots/Booster
    APSMpStep "Step 2: restore BRamp+RampTiming+extTiming from selected 1Hz SCR file..."
    set tmpRoot /tmp/[APSTmpString]
    if [catch {exec sddsprocess $scrDir/$ShortFilename $tmpRoot.restore \
                 -match=col,IsProtected=n -match=col,IsReadOnly=n \
                 "-match=col,ControlName=*.USEC,!" \
                 "-match=col,Category=BRamp,Category=RampTiming,|,Category=ExtTiming,|" } result] {
         APSMpReturn error "APSMpSwitchTo1HzIRampFromLongRamp2: $result"
    }
    if [catch {exec sddscasr -restore $tmpRoot.restore  -waveform=directory=/home/helios/oagData/SCR/snapshots/Booster,onefile,extension=.waveform.gz,rootname=[file root $ShortFilename] } result] {
       APSMpReturn error "APSMpSwitchTo1HzIRampFromLongRamp3: error store BRamp etc: $result" 
    }
    
    APSMpStep "Step 3: relink 1Hz ramp directory and controllaw directory..."
    cd /home/helios/oagData/booster/ramps
    catch {exec rm IRamp}
    exec ln -s IRamp-1Hz IRamp
    cd /home/helios/oagData/bcontrollaw
    catch {exec rm bcontrollaw}
    exec ln -s bcontrollaw-IRamp bcontrollaw
    APSMpStep "Step 4: Loading safety ramps..."
    if [catch {APSBoosterLoadSafetyRamp -BM 1 -QF 1 -QD 1 -SF 1 -SD 1 -IRamp 1 \
                 -description "load safety ramps from SwithTo1HzIRampFromLongIRamp pem" } result] {
        APSMpReturn error  "APSMpSwitchTo1HzIRampFromLongRamp4: error in loading safety ramps: $result"
    }
    APSMpStep "Step 5: change jumpers..."
    APSInfoWindow .info -name "Change Jumpers" -width 60 \
      -infoMessage "Change jumpers (AFG clock and V490 sample clock tp 15KHz) in B102 iocramp front panel. Click Ok when done." -modal 1
    
    APSMpStep "Step 6: Bring AFG gains in steps for 0.9 for BM/QF/SD, and 0.6 for QD/SF."
    if [catch {exec cavput -list=B: -list=BM,QF,SD -list=:VoltageRT.GAIN=0.9 -ramp=step=5,pause=1 
        exec cavput -list=B: -list=QD,SF -list=:VoltageRT.GAIN=0.6 -ramp=step=5,pause=1 } result] {
        APSMpReturn error "APSMpSwitchTo1HzIRampFromLongRamp5: Error in increasing AFG gain1: $result"
    }
    APSMpStep "Step 7: restore AFG+Bcontrol from selected 1Hz SCR file."
    if [catch {exec sddsprocess $scrDir/$ShortFilename $tmpRoot.restore1 \
                 -match=col,IsProtected=n -match=col,IsReadOnly=n \
                 "-match=col,ControlName=*.USEC,!" \
                 "-match=col,Category=AFG,Category=BControl,|" } result] {
         APSMpReturn error "APSMpSwitchTo1HzIRampFromLongRamp6: $result"
    }
    if [catch {exec sddscasr -restore $tmpRoot.restore1  } result] {
       APSMpReturn error "APSMpSwitchTo1HzIRampFromLongRamp7: error store BRamp etc: $result" 
    }
    
    APSMpStep "Step 8:start bcontrollaw and ramp correction."
    APSInfoWindow .info -name "Start bcontrol and autoRampCorrection" -width 60 \
      -infoMessage "Please start bcontrol and auto ramp correction now." -modal 1
    set files [glob $tmpRoot.*]
    eval file delete -force $files
    APSMpReturn ok

}

proc APSCheckBoosterIRampMode {args} {
    set pvList {B:SampleperiodAI B:BM:VoltageRT.USEC B:QF:VoltageRT.USEC B:QD:VoltageRT.USEC B:SF:VoltageRT.USEC B:SD:VoltageRT.USEC}
    set varList {samplePeriod BMclock QFclock QDclock SFclock SDclock}
    if [catch {exec cavget -list=[join $pvList ,] -printErrors -pend=20} valList] {
        return -code error "APSCheckBoosterIRampMode1: Error reading BRamp parameter PVs: $valList"
    }
    foreach var $varList val $valList {
        set $var [expr int($val)]
    }
    set longRamp 0
    switch $samplePeriod {
        476 {
            if {$BMclock!=66 || $QFclock!=66 || $QDclock!=66 || $SFclock!=66 || $SDclock !=66} {
                return -code error "APSCheckBoosterIRampMode2: BM|QF|QD|SF|SD clock rate do not match regular samplePeriod ($samplePeriod)"
            }
            set longRamp 0
        }
        952 {
            if {$BMclock!=133 || $QFclock!=133 || $QDclock!=133 || $SFclock!=133 || $SDclock !=133} {
                return -code error "APSCheckBoosterIRampMode3: BM|QF|QD|SF|SD clock rate do not match long ramp samplePeriod ($samplePeriod)"
            }
            set longRamp 1
        }
        default {
            return -code error "APSCheckBoosterIRampMode: invalid sample period ($samplePeriod) found."
        }
    }
    if $longRamp {
        return "LongRamp"
    }
    cd /home/helios/oagData/booster/ramps
    set link [file readlink IRamp]
    if [regexp "2Hz" $link] {
        return "2Hz"
    } else {
        return "1Hz"
    }
}

proc APSMpSwitchBTXBeamEnergyInfo {args} {
    return "switch BTX beam energy."
}

proc APSMpSwitchBTXBeamEnergyInitDialog {frame} {
    global APSMpSwitchBTXBeamEnergy
    set APSMpSwitchBTXBeamEnergy(ShortFilename) ""

    pack [frame $frame.f1]
    APSAddSCRDialog .scrNew -parent $frame.f1 -system Booster \
      -arrayName  APSMpSwitchBTXBeamEnergy \
      -defaultFile $APSMpSwitchBTXBeamEnergy(ShortFilename) \
      -label "Choose Booster SCR file by clicking on the Preferred/Reference Choices"
    
    APSMpReturn ok
}

proc APSMpSwitchBTXBeamEnergy {args} {
    set ShortFilename ""

    APSMpStep init -promptDialog APSMpSwitchBTXBeamEnergyInitDialog \
      -vars {ShortFilename}
    
    if ![string length $ShortFilename] {
        APSMpReturn error "APSMpSwitchBTXBeamEnergy1: SCR file was not chosen."
    }
    
    set paramString ""
    foreach param {ShortFilename} {
        append paramString "$param=\"[set $param]\" "
    }
    catch {APSLogScriptAction \
             -procedure APSMpSwitchBTXBeamEnergy \
             -action initialize \
             -state ok \
             -parameters $paramString}

    APSMpStep "$ShortFilename was chosen"
    APSMpStep "Stop booster extraction"
    if [catch {SetPulsedMagnetEnables -state 0 -location BoosterExt } result] {
        APSMpReturn error "APSMpSwitchBTXBeamEnergy2: error stop booster extraction: $result"
    }
    APSMpStep "Check BTS status"
    if [catch {exec cavget -list=BTS:BX:PS:SetCurrentC -pend=20 } BTX] {
        APSMpReturn error "APSMpSwitchBTXBeamEnergy3: $BTX"
    }
    
    if {$BTX>269} {
        #already in dump state, do nothing
    } else {
        APSMpStep "Switch to BTX dump (wait for about 30 seconds)..."
        if [catch {exec cavput -list=BTS:BX:PS:SetCurrentC=319 -ramp=step=10,pause=2 -pend=30} result] {
            APSMpReturn error "Error switch to BTX dump: $result"
        }
    }
    
    APSMpStep "Ramp pvs..."
    set tmpFile /tmp/[APSTmpString]
    set turns [exec sddsprocess /home/helios/oagData/SCR/snapshots/Booster/$ShortFilename -pipe=out \
                 -match=col,ControlName=Mt:BoosterRampTurns* \
                 | sdds2stream -pipe -col=ValueString]
    if [catch {exec sddsprocess /home/helios/oagData/SCR/snapshots/Booster/$ShortFilename -pipe=out \
                 "-match=col,ControlName=BTS:BX:PS:SetCurrentC,ControlName=BTS:AH1:CurrentAO,|,ControlName=BTS:AH2:CurrentAO,|,ControlName=BTS:AV1:CurrentAO,|,ControlName=BTS:AV2:CurrentAO,|,ControlName=BTS:AQ1:CurrentAO,|,ControlName=BTS:AQ2:CurrentAO,|,ControlName=BTS:AQ3:CurrentAO,|" \
                 -scan=col,Value,ValueString,%lf \
                 | sddsconvert -pipe -retain=col,ControlName,Value \
                 | sddsprocess -pipe=in $tmpFile.ramp  "-redefine=col,Value,Value 10.0 /"} result] {
        APSMpReturn error "APSMpSwitchBTXBeamEnergy3: error processing pv values: $result"
    }
    for {set i 1} {$i<=10} {incr i} {
        APSMpStep "Ramp step $i..."
        if [catch {exec sddsprocess $tmpFile.ramp -pipe=out \
                     "-redefine=col,Value,Value $i *"  \
                     | sddsprocess -pipe=in $tmpFile.ramp.$i -reprint=col,ValueString,%lf,Value } result] {
            APSMpReturn error "APSMpSwitchBTXBeamEnergy3a: error processing pv values: $result"
        }
        if [catch {exec sddscasr -restore $tmpFile.ramp.$i -pend=20} result] {
            APSMpReturn error "APSMpSwitchBTXBeamEnergy4: error ramping BTS pvs: $result"
        }
        APSWaitWithUpdate -waitTime 2
    }
    if [catch {exec cavput -list=Mt:BoosterRampTurnsAO=$turns -pend=10} result] {
        APSMpReturn error "Error setting extraction turns: $result"
    }
    set files [glob $tmpFile.*]
    APSAddToTempFileList $files
  
    APSMpReturn ok
}

proc APSMpBoosterRampRFFrequencyInfo {} {
    return "Ramp booster RF frequency."
}

proc APSMpBoosterUpdateRFFreq {args} {
    set saveFile ""
    APSStrictParseArguments {saveFile}
    global APSMpBoosterRampRFFrequency
    
    set APSMpBoosterRampRFFrequency(rfCurrentValue) [exec cavget -list=BRF:S:Hp8657RefFreqAO -floatFormat=%.0f]
  
    set APSMpBoosterRampRFFrequency(rfFinalValue) [format %.0f [expr $APSMpBoosterRampRFFrequency(rfCurrentValue) + $APSMpBoosterRampRFFrequency(rfTotalChange)]]
    
    set controlFile /home/helios/oagData/booster/rfFreqScan/monitorFiles/ChangeControl
    #change control value is corresponding to total RF change = 10000 Hz
    set tmpRoot /tmp/[APSTmpString]
    # set APSMpBoosterRampRFFrequency(controlInitFile) $tmpRoot.initial
    set APSMpBoosterRampRFFrequency(steps) [expr int(ceil( $APSMpBoosterRampRFFrequency(rfTotalChange)/$APSMpBoosterRampRFFrequency(rfStepSize)))]
    if ![string length $saveFile] {
        set saveFile $tmpRoot.initial
    }
    if [catch {exec sddsprocess $controlFile -pipe=out \
                 "-redefine=col,FinalValue,FinalValue 10000 / $APSMpBoosterRampRFFrequency(rfTotalChange) *" \
                 | sddsprocess -pipe "-redefine=col,StepSize,FinalValue InitialValue - $APSMpBoosterRampRFFrequency(steps) 1 - /" \
                 | sddscasr -save -pipe \
                 | sddsprocess -pipe -scan=col,CurrentValue,ValueString,%lf \
                 | sddsprocess -pipe=in $saveFile \
                 "-redefine=col,FinalValue,FinalValue CurrentValue +" \
             } result] {
        return -code error "Error creating initial runcontrol file: $result"
    }
    
    set pvs [exec sdds2stream -col=ControlName $saveFile]
    set initValues [exec sdds2stream -col=CurrentValue $saveFile]
    set finalValues [exec sdds2stream -col=FinalValue $saveFile]
    foreach pv $pvs init $initValues final $finalValues {
        set APSMpBoosterRampRFFrequency($pv.init) [format %.5f $init]
        set APSMpBoosterRampRFFrequency($pv.final) [format %.5f $final]
    }
    update
}

proc APSMpBoosterRampRFFrequencyInitDialog {frame} {
    global APSMpBoosterRampRFFrequency
     
    set controlFile /home/helios/oagData/booster/rfFreqScan/monitorFiles/ChangeControl
    set mainDir /home/helios/oagData/booster/rfFreqScan
    set controlPVs [exec sdds2stream -col=ControlName $controlFile]
    set controlInitValues [exec sdds2stream -col=InitialValue $controlFile]
    set controlFinalValues [exec sdds2stream -col=FinalValue $controlFile]
    set rfPV BRF:S:Hp8657RefFreqAO
    set APSMpBoosterRampRFFrequency(rfPV) $rfPV
    set APSMpBoosterRampRFFrequency(rampTime) 90
   # set APSMpBoosterRampRFFrequency(rfStepSize) 1
    set APSMpBoosterRampRFFrequency(rampSteps) 90
    set APSMpBoosterRampRFFrequency(rfTotalChange) 6834.6
    set APSMpBoosterRampRFFrequency(rfCurrentValue) [exec cavget -list=BRF:S:Hp8657RefFreqAO -floatFormat=%.0f]
    set APSMpBoosterRampRFFrequency(rfFinalValue) [format %.0f [expr $APSMpBoosterRampRFFrequency(rfCurrentValue) + $APSMpBoosterRampRFFrequency(rfTotalChange)]]
    set APSMpBoosterRampRFFrequency(state) On
    set APSMpBoosterRampRFFrequency(waitTime) 20
    
    set APSMpBoosterRampRFFrequency(rampSteps) 90
    set APSMpBoosterRampRFFrequency(rampInterval) 5
    set APSMpBoosterRampRFFrequency(longControllaw) 1
    set APSMpBoosterRampRFFrequency(xControllaw) 1
    set APSMpBoosterRampRFFrequency(injControllaw) 1
    pack [frame $frame.f1]
    # APSFrameGrid .grid -parent $frame.f1 -xList {x1 x2}
   
    #APSLabeledEntry .steps -parent $frame.f1.grid.x1 -label "Steps for ramping RF back to initial value:" \
    #  -textVariable  APSMpBoosterRampRFFrequency(rampSteps) -width 20
    #APSLabeledEntry .interval -parent $frame.f1.grid.x2 -label "Interval (seconds) for ramping RF:" \
    #  -textVariable  APSMpBoosterRampRFFrequency(rampInterval) -width 20

    set APSMpBoosterRampRFFrequency(logData) 0
    APSRadioButtonFrame .log -parent $frame.f1 -label "Log waveform data while ramping RF frequency?" \
      -buttonList {Yes No} -valueList {1 0} -orientation horizontal -variable APSMpBoosterRampRFFrequency(logData)
    APSLabeledEntryFrame .wait -parent $frame.f1 \
      -label "Ramp Time (s)/Ramp Steps" -width 20 -variableList {APSMpBoosterRampRFFrequency(rampTime) APSMpBoosterRampRFFrequency(rampSteps)} \
      -orientation horizontal) 
   # pack [frame $frame.f1]
    
    APSLabeledEntryFrame .rf -parent $frame.f1 -label "RF frequency(Hz): TotalChange/CurrentValue" -width 20 \
      -variableList {APSMpBoosterRampRFFrequency(rfTotalChange) APSMpBoosterRampRFFrequency(rfCurrentValue)} \
      -orientation horizontal -fg blue 
    APSLabel .label -parent $frame.f1 -text "Note: drf -6834.6 Hz gives dp/p 0.2%" -font {times 11 bold}
   # APSDisableWidget $frame.f1.rf.frame.entry1
    APSDisableWidget $frame.f1.rf.frame.entry2
  #  APSDisableWidget $frame.f1.rf.frame.entry4
  #  bind $frame.f1.rf.frame.entry2 <Leave> "set APSMpBoosterRampRFFrequency(rfFinalValue) [expr $APSMpBoosterRampRFFrequency(rfCurrentValue) + $APSMpBoosterRampRFFrequency(rfTotalChange)];update"
    APSCheckButtonFrame .check -parent $frame.f1 -label "Run controllaw?" -buttonList {longitudinal horizontal injectionTune} \
      -variableList {APSMpBoosterRampRFFrequency(longControllaw) APSMpBoosterRampRFFrequency(xControllaw) APSMpBoosterRampRFFrequency(injControllaw)} \
      -allNone 1 -orientation horizontal -contextHelp "check to keep the controllaw running during ramping RF frequency."
    set APSMpBoosterRampRFFrequency(rf5Voltage) 28700
    set APSMpBoosterRampRFFrequency(changeModAnodeVoltage) 0
    set APSMpBoosterRampRFFrequency(changeModAnodeVoltageStepSize) 500
    APSRadioButtonFrame .reduce -parent $frame.f1 -label "Reduce Mod Anode voltage?" -variable APSMpBoosterRampRFFrequency(changeModAnodeVoltage) \
      -buttonList {Yes No} -valueList {1 0} -orientation horizontal
    APSLabeledEntryFrame .vol -parent $frame.f1 -label "Reduce Mod Anode voltage to (volts)/StepSize:" -width 20 \
      -variableList {APSMpBoosterRampRFFrequency(rf5Voltage) APSMpBoosterRampRFFrequency(changeModAnodeVoltageStepSize)} \
      -orientation horizontal
}

proc APSMpBoosterRampRFFrequency {args} {
    set rfStepSize 1000
    set rfTotalChange 10000
    set rfPV BRF:S:Hp8657RefFreqAO
    set waitTime 10
    set rampSteps 100
    set rampInterval 2
    set rf5Voltage 28700
    global APSMpBoosterRampRFFrequency
    set mainDir /home/helios/oagData/booster/rfFreqScan
    set longControllaw 1
    set xControllaw 1
    set injControllaw 1
    set changeModAnodeVoltage 0
    set changeModAnodeVoltageStepSize 500
    set rampSteps 90
    set rampTime 90
    set logData 0
    APSMpStep init -promptDialog APSMpBoosterRampRFFrequencyInitDialog \
      -vars {rfStepSize rfTotalChange waitTime rampSteps rampInterval rf5Voltage longControllaw injControllaw xControllaw \
               changeModAnodeVoltage changeModAnodeVoltageStepSize rampSteps rampTime logData}
    set rfSteps [expr int(ceil(abs($rfTotalChange/$rfStepSize)))]
    set rfStepSize [expr $rfTotalChange/($rfSteps*1.0)]
    
    global APSMpBoosterRampRFFrequencyAbort
    set APSMpBoosterRampRFFrequencyAbort 0
    
    #bring up the medm screen of par timing feedforwar runcontrol
    exec medm  -x -attach -macro RCPV=OAG190RC \
                             ./sr/psApp/APSRunControlSingle.adl & 

    APSMpStep "reduce RF5 voltage..."
    
    if $changeModAnodeVoltage {
        if [catch {exec cavget -list=BRF:P5:modAnodeVoltageAdj -pend=30 } rf5Voltage0] {
            APSMpReturn error "Error reading BRF:P5:modAnodeVoltageAdj: $rf5Voltage0"
        }
        if {$rf5Voltage0>$rf5Voltage} {
            set steps [expr int(ceil(abs($rf5Voltage0 - $rf5Voltage)/$changeModAnodeVoltageStepSize)) + 1]
            APSMpStep " cavput -list=BRF:P5:modAnodeVoltageAdj=$rf5Voltage -ramp=step=$steps,pause=3 -pend=30"
            if [catch {exec cavput -list=BRF:P5:modAnodeVoltageAdj=$rf5Voltage -ramp=step=$steps,pause=3 -pend=30} result] {
                APSMpReturn error "Error ramping BRF:P5:modAnodeVoltageAdj to $rf5Voltage: $result"
            }
        }
    }
    
    while {1} {
        if [catch {exec cavget -list=BRF:K5:ED1:Ch1KWatt -pend=30 -printErrors } klystronPower] {
            APSMpReturn error "APSMpBoosterRampRFFrequency0: $result"
        }
        if {$klystronPower>275} {
            set answer [APSMultipleChoice [APSUniqueName .] -modal 1 \
                          -question "Booster klystron power is too high (>275 kw), please lower it to around 250 kw, then continue." \
                          -labelList {Check-Again Continue-Anyway Abort} \
                          -returnList {CheckAgain Continue Abort}]
            if  {$answer=="Abort"} {
                APSMpReturn error "Aborted."
            } elseif {$answer=="Continue"} {
                break
            }
        } else {
            break
        }
    }
    
    set timeStamp [clock format [clock seconds] -format %Y-%j-%m%d:%H%M%S]
    APSMpStep "Reading initial values..."
    set APSMpBoosterRampRFFrequency(rfInitialValue) [exec cavget -list=BRF:S:Hp8657RefFreqAO -floatFormat=%.0f]
    if [catch {APSSaveMachine -machine PAR -description "Saving PAR timing before ramping booster RF." } result] {
        APSMpReturn error "Error saving PAR SCR: $result"
    }
    if [catch {APSSaveMachine -machine Booster -description "Saving PAR timing before ramping booster RF." } result] {
        APSMpReturn error "Error saving booster SCR: $result"
    }
    if [catch {APSSaveMachine -machine BRF -description "Saving PAR timing before ramping booster RF." } result] {
        APSMpReturn error "Error saving BRF SCR: $result"
    }
    
    if [catch {APSMpStartParTimingFeedforward} result] {
        APSMpReturn error "Error starting par timing feedforward: $result"
    }

    APSMpStep "checking if booster injection controllaw is running..."
    while {1} {
        if [catch {APScavget -list=B:InjTune:ControllawRC,Booster:ControlLawLongRC,Booster:ControlLawXRC -list=.RUN -pend=30 -printError} injControllaws] {
            APSMpReturn error "Error reading booster injection tune controllaw status: $injTune"
        }
        set injControllaw1 [lindex $injControllaws 0]
        set longControllaw1 [lindex $injControllaws 1]
        set xControllaw1 [lindex $injControllaws 2]
        set msg ""
        if {$injControllaw && !$injControllaw1} {
            set msg "injection tune controllaw"
        }
        if {$xControllaw && !$xControllaw1} {
            if [string length $msg] {
                append msg ", horizontal controllaw"
            } else {
                set msg "Horizontal controllaw"
            }
        }
        if {$longControllaw && !$longControllaw1} {
            if [string length $msg] {
                append msg ", longitudinal controllaw"
            } else {
                set msg "Longitudinal controllaw"
            }
        }
        if [string length $msg] {
            set answer [APSMultipleChoice [APSUniqueName .] -modal 1 \
                          -question "Booster $msg is (are) not running, please start them and check again or abort." \
                          -labelList {Start-And-Check-Again Abort} \
                          -returnList {CheckAgain Abort}]
            if  {$answer=="Abort"} {
                APSMpReturn error "Aborted."
            }
        } else {
            break
        }
    }
    
    set tmpRoot /tmp/[APSTmpString]
    
    set APSMpBoosterRampRFFrequency(abort) 0
    if [catch {exec cavget -list=PAR:awg:timingModeBO -num -pend=20} 1Hz] {
        APSMpReturn error "APSMpBoosterRampRFFrequency1a: $1Hz"
    }
    if {$1Hz} {
        set deltaT [expr 28.636e-3 * 2]
    } else {
         set deltaT 28.636e-3
    }
    
    set rootname $mainDir/data/$timeStamp
    set reflPVList {BRF:INJ:ED1:Ch1KWatt BRF:INJ:ED2:Ch1KWatt BRF:EXT:ED1:Ch1KWatt BRF:EXT:ED2:Ch1KWatt}
    APSMpStep "start monitoring pvs ..."
    if $logData {
        set logTime [eppr $rampTime + $rampSteps * 25]
    } else {
        set logTime [expr $rampTime + 10]
    }
    catch {exec sddsmonitor /home/helios/oagData/booster/rfFreqScan/monitorFiles/rfFreqRamp.mon ${rootname}.mon.sdds -time=$logTime,seconds &} monID
    after 1000
    #plot 
    if {0} { exec sddsplot ${rootname}.mon.sdds  -graph=line,vary -leg -yscalesgroup=namestring  \
      "-col=Time,(RfFrequency,PTBCharge,BooChargeRmsReg3,RevPowerBooCav1,RevPowerBooCav2,RevPowerBooCav3,RevPowerBooCav4,P1IKInjectionTriggerTime)" \
      -repeat "-device=motif,-movie true -keep 1"  &  
    }
    exec sddsplot ${rootname}.mon.sdds  -graph=line,vary -leg -tick=xtime \
      "-col=Time,(LTPCharge,PTBCharge,BooChargeRmsReg3)" -ys=namestring  -endp \
      -col=Time,RefPowerBooCav* -ys=units -endp \
      -repeat "-device=motif,-movie true -keep 1"  &  
    
    set pause [expr int((1.0*$rampTime)/$rampSteps)]
    set rfStepSize [expr $rfTotalChange/($rampSteps*1.0)]
    for {set i 0} {$i<$rampSteps} {incr i} {
        #change rf frequency
        APSMpStep "Start step $i"
        APSMpStep "check injection controllaw ..."
        if [catch {APSCheckBoosterInjectionControllaw -xControllaw $xControllaw -injControllaw $injControllaw -longControllaw $longControllaw} result] {
            APSMpReturn error "Error checking injection controllaw: $result"
        }
        APSMpStep "Change rf requency by $rfStepSize Hz... "
        if [catch {APScavput -list=$rfPV=$rfStepSize -delta -pend=30} result] {
            APSMpReturn error "APSMpBoosterRampRFFrequency2: $result"
        }
       
        #wait 
        if $APSMpBoosterRampRFFrequencyAbort {
            APSMpReturn error "APSMpBoosterRampRFFrequency: aborted"
        }
        APSMpStep "Wait for $pause seconds..."
        if [catch {APSWaitWithUpdate -waitSeconds $pause -abortVariable APSMpBoosterRampRFFrequencyAbort } result] {
            APSMpReturn error "APSMpBoosterRampRFFrequency4: $result"
        }

        APSMpStep "Check RF5 cavity reflected power..."
        while {1} {
            if [catch {APScavget -list=[join $reflPVList ,] -pend=30 -printErrors} reflValueList] {
                APSMpReturn error "APSMpBoosterRampRFFrequency2a: error reading RF reflected power: $reflValueList"
            }
            set alarm 0
            set message ""
            foreach pv $reflPVList val $reflValueList {
                if {$val>10} {
                    append messsage "$pv > 10.0 KW; "
                    incr alram
                }
            }
            if {$alarm} {
                set answer [APSMultipleChoice [APSUniqueName .] -modal 1 \
                              -question "Booster RF reflected power $message . Please choose tp  wait and check again or continue at your own risk or abort." \
                              -labelList {Check-Again Continue-Anyway Abort} \
                              -returnList {CheckAgain Continue Abort}]
                if  {$answer=="Abort"} {
                    APSMpReturn error "Aborted."
                } elseif {$answer=="Continue"} {
                    break
                }
            } else {
                break
            }
        }
        if $logData {
            APSMpStep "Reading par current waveform ..."
            if [catch {exec sddswmonitor -pvnames=PAR:awg:rms:gtr:waveform0,PAR:awg:rms:gtr:waveform1 ${rootname}.parCurrentWF.step$i -erase} result] {
                APSMpReturn error "APSMpBoosterRampRFFrequency5: $result"
            }
            if [catch {exec sddsprocess  ${rootname}.parCurrentWF.step$i -nowarnings "-redefine=col,time,Index $deltaT *,units=ms" \
                         "-redefine=par,Step,$i,type=long" } result] {
                APSMpReturn error "APSMpBoosterRampRFFrequency6: $result"
            }
            APSMpStep "Reading booster current waveform with 20 steps..."
            if [catch {exec sddswmonitor -steps=20 -pvname=B:diag1:Xaxes.VALB,B:diag1:boxCarRmsAS.VALB $rootname.booBeamCurrentWF.step$i -erase } result] {
                APSMpReturn error "APSMpBoosterRampRFFrequency7: $result"
            }
            if [catch {exec sddsprocess $rootname.booBeamCurrentWF.step$i -nowarnings "-redefine=col,time,Index $deltaT *,units=ms" \
                         "-redefine=par,Step,$i,type=long" \
                         "-redefine=col,charge,B:diag1:boxCarRmsAS.VALB 0.004254219 *,units=nC" } result] {
                APSMpReturn error "APSMpBoosterRampRFFrequency8: $result"
            }
            APSMpStep "Reading par scope waveform data..."
            if [catch {exec getHP9000ScopeData -ring PAR -filename $rootname.parScopeWF.step$i } result] {
                APSMpReturn error "APSMpBoosterRampRFFrequency9: $result"
            }
        }
        
    }
    
    if {0} {
        APSMpStep "Booster rf change done. Ramp rf to orignal value..."
        
        if [catch {APSRampPVs -PVList $rfPV -valueList $APSMpBoosterRampRFFrequency(rfInitialValue) \
                     -steps $rampSteps -pause $rampInterval } result] {
            APSMpReturn error "APSMpBoosterRampRFFrequency10: $result"
        }
        if [catch {exec cavput -list=OAG190RC.ABRT=1 -pend=30
            exec cawait -waitfor=OAG190RC.RUN,equal=0 -timelimit=120
            exec cavput -list=OAG190RC.CLR=1 -pend=30} result] {
            APSMpReturn error "Error aborting par timing feedforward: $result"
        }
    }
    if [catch {exec cavget -list=OAG190RC.RUN -pend=30 -printErrors } parFeedforward] {
        APSMpReturn error "Error reading par timing feedforward status: $parFeedforward"
    }
    if [catch {APSSaveMachine -machine PAR -description "Saving PAR timing after ramping booster RF." } result] {
        APSMpReturn error "Error saving PAR SCR: $result"
    }
    if [catch {APSSaveMachine -machine Booster -description "Saving PAR timing after ramping booster RF." } result] {
        APSMpReturn error "Error saving Booster SCR: $result"
    }
    if [catch {APSSaveMachine -machine BRF -description "Saving PAR timing after ramping booster RF." } result] {
        APSMpReturn error "Error saving BRF SCR: $result"
    }
    if [catch {APSMpStopParTimingFeedforward} result] {
        APSMpReturn error "Error stop par timing feedforward: $result"
    }
    APSMpReturn ok

}

proc APSMpBoosterRFFreqScanReviewInfo {} {
    return "review the scan data of RF freq scan."
}

proc SetRFFreqScanReviewFile {index} {
    global APSMpBoosterRFFreqScanReview
    set APSMpBoosterRFFreqScanReview(Filename) [lindex $APSMpBoosterRFFreqScanReview(FileList) $index]
    update
}
proc APSMpBoosterRFFreqScanReviewInitDialog {frame} {
    global  APSMpBoosterRFFreqScanReview
    set APSMpBoosterRFFreqScanReview(Filename) ""
    pack [frame $frame.f1]
    set dataDir /home/helios/oagData/booster/rfFreqScan/data
    set oldDir [pwd]
    cd $dataDir
    set files [lsort -decreasing [glob *.mon.sdds]]
    set APSMpBoosterRFFreqScanReview(FileList) $files
    set tmpFile /tmp/[APSTmpString]
    if [catch {exec sddsmakedataset $tmpFile -col=FileName,type=string -data=[join $files ,] } result] {
        APSMpReturn error "Error creating file:$result"
    }
    cd $oldDir
    global APSSCRMakePrefLBoxTextLine apsSCRMakeLBoxTextLineMaxWidth
    set apsSCRMakeLBoxTextLineMaxWidth 0
    APSSDDSListbox .preflist -parent $frame.f1 -height 15 \
      -widthLimit 200 -trim 1 -label "Select a File to Review" \
      -fileName $tmpFile \
      -labelMaker APSSCRMakePrefLBoxTextLine \
      -arrayName APSMpBoosterRFFreqScanReview \
      -page 0 \
      -callback "SetRFFreqScanReviewFile" \
      -columnList {FileName} \
      -contextHelp "Double-click to select a file." -doneButton 0
    
   # APSLabeledEntry .file -parent $frame.fl -label "File to review:" \
   \#   -width 50 -textVariable APSMpBoosterRFFreqScanReview(Filename)
    APSMpReturn ok
}
proc APSMpBoosterRFFreqScanReview {args} {
    set Filename ""
    set dataDir /home/helios/oagData/booster/rfFreqScan/data
    APSMpStep init -promptDialog APSMpBoosterRFFreqScanReviewInitDialog \
      -vars {Filename}

    if ![string length $Filename] {
        APSMpReturn error "no file is chosen!"
    }
    APSMpStep "$Filename"
    set file $dataDir/$Filename
    exec sddsplot $file -layout=1,2 -grap=line,vary -leg -tick=xtime \
      "-col=Time,(LTPCharge,PTBCharge,BooChargeRmsReg3)" -ys=namestring  -endp \
      -col=Time,RefPowerBooCav* -ys=units -endp &
    APSMpReturn ok
}

proc APSMpStartParTimingFeedforward {args} {
    if [catch {exec cavget -list=OAG190RC.RUN -pend=30 -printErrors } parFeedforward] {
        APSMpReturn "Error reading par timing feedforward status: $parFeedforward"
    }
    APSMpStep "Start par timing feedforward..."
    if !$parFeedforward {
        if [catch {exec cavput -list=OAG190RC.ABRT=1 -pend=30
            exec cawait -waitfor=OAG190RC.RUN,equal=0 -timelimit=120
            exec cavput -list=OAG190RC.CLR=1 -pend=30} result] {
            APSMpReturn error "Error aborting par timing feedforward: $result"
        }
        if [catch {exec PARTimingFeedforward & } result] {
            APSMpReturn error "Error starting par timing feedforward: $result"
        }
        set timeout [expr [clock seconds] + 15]
        while {[clock seconds]<$timeout} {
            if [catch {exec cavget -list=OAG190RC.RUN -pend=30 -printErrors } parFeedforward] {
                APSMpReturn error "Error reading par timing feedforward status: $parFeedforward"
            }
            if !$parFeedforward {
                after 1000
                continue
            } else {
                break
            }
        }
    }
    if [catch {exec cavget -list=OAG190RC.RUN -pend=30 -printErrors } parFeedforward] {
        APSMpReturn error "Error reading par timing feedforward status: $parFeedforward"
    }
    if !$parFeedforward {
        APSMpReturn error "Error: par timing feedforward is not running."
    }
    APSMpReturn ok
}

proc APSMpStopParTimingFeedforward {args} {
    APSMpStep "abort par timing feedforward..."
    if [catch {exec cavput -list=OAG190RC.ABRT=1 -pend=30
        exec cawait -waitfor=OAG190RC.RUN,equal=0 -timelimit=120
        exec cavput -list=OAG190RC.CLR=1 -pend=30} result] {
        APSMpReturn error "Error aborting par timing feedforward: $result"
    }
    APSMpReturn ok
}

proc APSMpBoosterSwitchSDInfo {} {
    return "switch SD PS group between SD and SD-U"
}


proc APSMpBoosterSwitchSDInitDialog {frame} {
    set APSMpBoosterSwitchSD(ShortFilename) ""
    pack [frame $frame.f1]
 
    APSAddSCRDialog .scrNew -parent $frame.f1 -system Booster \
      -arrayName APSMpBoosterSwitchSD \
      -defaultFile $APSMpBoosterSwitchSD(ShortFilename) \
      -label "Choose Booster SCR file by clicking on the Preferred/Reference Choices"
    
    
    APSMpReturn ok
}

proc APSMpBoosterSwitchSD {args} {
    set ShortFilename ""
    APSStrictParseArguments {ShortFilename}
    
    APSMpStep init -promptDialog APSMpBoosterSwitchSDInitDialog \
      -vars {ShortFilename}

    set SCRDir /home/helios/oagData/SCR/snapshots/Booster
    
    if ![string length $ShortFilename] {
        APSMpReturn error "SCR file not chosen!"
    }
    set switchTo [exec sddsprocess $SCRDir/$ShortFilename -pipe=out -match=col,ControlName=B:SD-U:PoweredM \
                    | sdds2stream -pipe -col=ValueString]
    
    if [catch {exec cavget -list=B:SD-U:PoweredM -pend=10 -printErrors} SDstatus] {
        APSMpReturn error "Error reading SD status: $SDstatus"
    }
    if [string compare $SDstatus $switchTo]!=0 {
        APSMpReturn error "Error SDstatus is $SDstatus, can not switch to $switchTo!"
    }
    
    if {$switchTo=="B:SD-U"} {
        APSMpStep "abort SD auto ramp correction and bcontrol."
        if [catch {exec cavput -list=B:SD:AutoCorrectionControlRC.ABRT=1,B:SDbcontrollawRC.ABRT=1 -pend=30} result] {
            APSMpReturn error "Error abort SD ramp correction and bcontrol: $result"
        }
    } 
    #check switchTo status
    if {$switchTo=="B:SD"} {
        if [catch {exec cavget -list=B:SD:Bit7BI -num -pend=10} psStatus] {
            APSMpReturn "Error reading B:SD power supply status: $psStatus"
        }
        if $psStatus {
            #turn on power supply
            APSMpStep "turn on SD power supply..."
            if [catch {exec cavput -list=B:SD:VoltageRT.GAIN=0.4,It:Ddg4chan4.GATE=0  -pend=20} result] {
                APSMpReturn error "Error disabling SD: $result"
            }
            
            if [catch {exec cavput -list=B:SD:VoltageRT.MODE=AUTO -pend=10} result] {
                APSMpReturn "Error setting SD mode to auto: $result"
            }
            if [catch {exec cavput -list=B:SD:ResetSEQ=1 -pend=20} result] {
                APSMpReturn error "Error turning on SD: $result"
            }
            after 10000
        }
        if [catch {exec cavget -list=B:SD:StatusCALC -printErrors -pend=10} status] {
            APSMpReturn "Error reading B:SD:StatusCALC: $status"
        }
        if {$status} {
            APSMpReturn error "SD status has error! can not switch to SD!"
        }
        if [catch {exec cavget -list=B:SD:ACVoltageAI -printErrors -pend=10} voltage] {
            APSMpReturn "Error reading B:SD-U:ACVoltageAI: $voltage"
        }
        if {$voltage<100} {
            APSMpReturn error "SD AC voltage is too slow, can not switch to SD!"
        }
    }
    APSMpStep "switch bcontrolSD to $switchTo"
    cd /home/helios/oagData/controllaw/bcontrollaw
    set SDcontrol [file readlink bcontrolSD]
    if {$SDcontrol=="bcontrolSD-D" && $switchTo=="B:SD"} {
        APSMpStep "no need to switch SD bcontrol, since it is already in $switchTo state."
    } elseif {$SDcontrol=="bcontrolSD-U" && $switchTo=="B:SD-U"} {
        APSMpStep "no need to switch SD bcontrol, since it is already in $switchTo state."
    } else {
        catch {exec rm bcontrolSD}
        switch $switchTo {
            B:SD {
                set newcontrol bcontrolSD-D
            }
            B:SD-U {
                set newcontrol bcontrolSD-U
            }
        }
        exec ln -s $newcontrol bcontrolSD
        APSMpStep "bcontrolSD switched to $newcontrol."
    }
    
    APSMpStep "switch IRamp..."
    cd /home/helios/oagData/booster/ramps
    exec rm IRamp-132nm-1Hz
    exec rm IRamp-132nm-2Hz
    if {$switchTo=="B:SD-U"} {
        exec ln -s IRamp-132nm-1Hz-SD-U IRamp-132nm-1Hz
        exec ln -s IRamp-132nm-2Hz-SD-U IRamp-132nm-2Hz
    } else {
        exec ln -s IRamp-132nm-1Hz-SD IRamp-132nm-1Hz
        exec ln -s IRamp-132nm-2Hz-SD IRamp-132nm-2Hz
    }
    if {0} {
        APSMpStep "Load SCR for SD/SDU"
        if [catch {exec sddsprocess $SCRDir/$ShortFilename -pipe=out "-match=col,ControlName=*WF*,!" "-match=col,ControlName=*RT,!" \
                     "-match=col,IsReadOnly=n" \
                     "-match=col,Category=AFG,Category=InjTiming,|,Category=Bcontrol,|" \
                     | sddscasr -pipe=in -restore -pend=20 } result] {
            APSMpReturn error "Error restore SCR for $switchTo: $result"
        }
    }
    APSMpStep "Load It:Ddg9chan3.DLY from SCR..."
    if [catch {exec sddsprocess $SCRDir/$ShortFilename -pipe=out "-match=col,ControlName=It:Ddg9chan3.DLY" \
                 | sddscasr -pipe=in -restore -pend=20} result] {
        APSMpReturn error "Error restore SCR for $switchTo: $result"
    }
    APSMpStep "Switch to $switchTo"
    
    if {$switchTo=="B:SD-U"} {
        set magnet SD-U
        
        APSMpStep "Load SD-U safety ramp..."
        if [catch { APSBoosterLoadSDUSafetyRamp } result] {
            APSMpReturn error "Error loading SD-U safety ramp: $result"
        }
        if [catch {exec cavput -list=B:SD-U:CurrentRT.MODE=AUTO -pend=30} result] {
            APSMpReturn error "Error setting SD-U mode to auto: $result"
        }
        if [catch {exec cavget -list=B:SD-U:StatusCALC -num -pend=10 -printErrors } status] {
            APSMpReturn error "Error reading SDU status: $status"
        }
        if $status {
            APSMpStep "Turn on SD-U power supply..." 
            if [catch {exec cavput -list=B:SD-U:CurrentRT.GAIN=0.2,It:Ddg9chan3.GATE=0 -pend=10} result] {
                APSMpReturn error "Error disable SDU ramp: $result"
            }
            if [catch {exec cavput -list=B:SD-U:Reset=1 -pend=10} result] {
                APSMpReturn error "Error reset SD-U: $result"
            }
            after 2000
            if [catch {exec cavput -list=B:SD-U:OnSEQ=1 -pend=10} result] {
                APSMpReturn error "Error turn on SD-U: $result"
            }
            after 2000
            if [catch {exec cavget -list=B:SD-U:StatusCALC -num -printErrors -pend=20} SDUstatus] {
                APSMpReturn error "Error reading B:SD-U:StatusCALC: $SDUstatus"
            }
            if !$SDUstatus {
                if [catch {exec cavput -list=It:Ddg9chan3.GATE=1 -pend=10 } result] {
                    APSMpReturn error "Error enable ramp after turning on SD-U: $result"
                }
            } else {
                if {$statusCallback!=""} {
                    APSMpReturn error  "SD-U is not turned on, please check."
                }
            }
            APSMpStep "Load SD-U AFG gain and delay from SCR..."
            
            set SDUgain [exec sddsprocess $SCRDir/$ShortFilename -pipe=out -match=col,ControlName=B:SD-U:CurrentRT.GAIN \
                           | sdds2stream -pipe -col=ValueString]
            set SDUdelay [exec sddsprocess $SCRDir/$ShortFilename -pipe=out -match=col,ControlName=It:Ddg9chan3.DLY \
                           | sdds2stream -pipe -col=ValueString]
            if [catch {exec cavput -list=B:SD-U:CurrentRT.GAIN=$SDUgain,It:Ddg9chan3.DLY=$SDUdelay -ramp=step=5,pause=5  -pend=10} result] {
                APSMpReturn error "Error disable SDU ramp: $result"
            }
        }
    } else {
        #change the It:Ddg9chan3.DLY back to 9.0 for SD (it is the trigger delay for SD-U, loaded by safety)
        #if [catch {exec cavput -list=It:Ddg9chan3.DLY=9.0 -pend=10} result] {
        #    APSMpReturn error "Error set It:Ddg9chan3.DLY: $result"
        #}
        APSMpStep "Ramp SD gain..."
        if [catch {exec cavput -list=B:SD:VoltageRT.GAIN=0.4 -pend=20} result] {
            APSMpReturn error "Error set SD gain to 0.4: $result"
        }
        #enabled SD ramp, disable SD-U ramp (It:Ddg9chan3.GATE)
        if [catch {exec cavput -list=It:Ddg4chan4.GATE=1,It:Ddg9chan3.GATE=0 -pend=20} result] {
            APSMpReturn error "Error enable SD ramp: $result"
        }
        APSMpStep "Load SD safety ramp..."
        if [catch {APSBoosterLoadSafetyRamp -SD 1 -IRamp 1} result] {
            APSMpReturn error "Error loading safety for QD: $result"
        }
        set SDgain [exec sddsprocess $SCRDir/$ShortFilename -pipe=out -match=col,ControlName=B:SD:VoltageRT.GAIN \
                      | sdds2stream -pipe -col=ValueString]
        set SDdelay [exec sddsprocess $SCRDir/$ShortFilename -pipe=out -match=col,ControlName=It:Bs:SdVafgTrigAO \
                      | sdds2stream -pipe -col=ValueString]
        APSMpStep "Load SD AFG gain and delay from SCR..."
        if [catch {exec cavput -list=It:Bs:SdVafgTrigAO=$SDdelay -pend=10} result] {
            APSMpReturn error "Error setting SD AFG trigger delay: $result"
        }
        if [catch {exec cavput -list=B:SD:VoltageRT.GAIN=$SDgain -ramp=step=5,pause=2 -pend=10} result] {
            APSReturn error "Error setting SD gain to 0.8: $result"
        }
       
        set magnet SD
    }
    APSMpStep "Load $magnet IRamp Reference..."
    set tmpRoot /tmp/[APSTmpString]
    set refDir /home/helios/oagData/booster/ramps/IRamp/current-IRamp
    if [catch {exec sddsconvert $refDir/IRef -pipe=out \
                 -retain=col,Index,B:${magnet}:CurrentWF -retain=par,${magnet}* \
                 | sddsconvert -pipe -rename=col,B:${magnet}:CurrentWF=Waveform \
                 | sddsprocess -pipe=in -reprint=par,WaveformPV,B:${magnet}:IRampRefWF $tmpRoot.$magnet} result] {
        APSMpReturn error "Error loading IRamp ref1: $result"
    }
    set gain [exec sdds2stream -par=${magnet}AfgGain $tmpRoot.$magnet]
    set delay [exec sdds2stream -par=${magnet}TriggerDelay $tmpRoot.$magnet]
    if [catch {exec cavput -list=B:${magnet}:RefAfgGain=$gain,B:${magnet}:RefTriggerDelay=$delay -pend=20
        exec sddswput $tmpRoot.$magnet -pend=20 } result] {
        APSMpReturn "Error loading IRamp ref2: error in setting reference pvs: $result"
    }
    APSMpStep "done."
    after 1000
    APSMpReturn ok
}

proc APSBoosterLoadSDUSafetyRamp {args} {
    set magnet SD-U
    APSStrictParseArguments {magnet}
    switch $magnet {
        SD-U {
            set rampPV It:Ddg9chan3
        }
        SF-U {
            set rampPV It:Ddg9chan2
        }
        default {
            return
        }
    }
    set rampDir /home/helios/oagData/booster/ramps/IRamp/safety
    
    if ![file exist $rampDir/${magnet}Iref.afg100] {
        return -code error "APSBoosterLoadSDUSafetyRamp1: $rampDir/${magnet}Iref.afg100 does not exist!"
    }
    set afgGain [exec sdds2stream -par=afgGain $rampDir/${magnet}Iref.afg100]
    set afgTrigger [exec sdds2stream -par=afgTrigger $rampDir/${magnet}Iref.afg100]
    if [catch {exec cavget -list=B:${magnet}:CurrentRT.GAIN} gain] {
        return -code error "Error in reading $magnet afg gain: $gain"
    }
    
    if [catch {exec cavput -list=B:${magnet}:CurrentRT.GAIN=$afgGain -pend=30} result] {
        return -code error "Error in restore afg gain: $result"
    }
    
    if [catch {exec cavput -list=B:${magnet}:CurrentRT.MODE=AUTO -pend=10 } result] {
        return -code error "Error changed $magnet mode to AUTO: $result"
    }
    if [catch {exec cavput -list=$rampPV.DLY=$afgTrigger \
                 -pend=30} result] {
        return -code error "Error loading $magnet trigger: $result"
    }
    if [catch {exec rampload $rampDir/${magnet}Iref.afg100 } result] {
        return -code error "Error loading $magnet safety: $result"
    }
    #check if swapsync server is running
    if [catch {exec cavget -list=B:SwapSyncRC.RUN -pend=30 -printErrors} swap] {
        return -code error "Error reading B:SwapSyncRC.RUN: $swap"
    }
    if !$swap {
        if [catch {exec cavput -list=B:${magnet}:CurrentRT.SWAP=1
            exec cavput -list=B:PSAFG100SyncBO=1 -numerical } result] {
            return -code error "Error swap/sync $magnet ramp: $result"
        }
    }
}

proc APSMpBoosterSDUSetFullPower {args} {
    set SCRFile ""
    set magnet SD-U
    APSStrictParseArguments {SCRFile magnet}
    switch $magnet {
        SD-U {
            set rampPV It:Ddg9chan3
            set bcontrol SD
        }
        SF-U {
            set rampPV It:Ddg9chan2
            set bcontrol SF
        }
        default {
            return
        }
    }
    set SCRDir /home/helios/oagData/SCR/snapshots/Booster
    if [catch {exec sddsprocess $SCRDir/[file tail $SCRFile] -pipe=out \
                 -match=col,ControlName=B:${magnet}:PoweredM \
                 | sdds2stream -pipe -col=ValueString } SDscrState] {
        APSMpReturn error "APSMpBoosterSDUSetFullPower1: error get SDU state from SCR file $SCRFile: $SDscrState"
    }
    if {$SDscrState!="B:${magnet}"} {
        APSMpReturn error "APSMpBoosterSDUSetFullPower2: error $SCRFile state is $SDscrState not ${magnet}, can not be used to set ${magnet} full power"
    }
    
    if [catch {exec cavget -list=B:${magnet}:PoweredM -pend=10 -printErrors} SDstatus] {
        APSMpReturn error "APSMpBoosterSDUSetFullPower3: Error reading SD status: $SDstatus"
    }
    
    if {$SDstatus!="B:${magnet}"} {
        APSMpReturn error "APSMpBoosterSDUSetFullPower4: current state is SD not ${magnet}, can not set full power for ${magnet}!"
    }
    if [catch {exec cavget -list=B:${magnet}:StatusCALC -printErrors -pend=20} SDUstatus] {
        APSMpReturn "Error reading B:${magnet}:StatusCALC: $SDUstatus"
    }
    if $SDUstatus {
        APSMpStep "set ${magnet} gain to 0.2"
        if [catch {exec cavput -list=B:${magnet}:CurrentRT.GAIN=0.2 -pend=20} result] {
            APSMpReturn error "APSMpBoosterSDUSetFullPower5: error setting ${magnet} gain to 0.2: $result"
        }
        APSMpStep "Disable ${magnet} ramp"
        if [catch {exec cavput -list=$rampPV.GATE=0 -pend=10 } result] {
            APSMpReturn error "APSMpBoosterSDUSetFullPower6: Error disable ramp before turning on ${magnet}: $result"
        }
        APSMpStep "Load ${magnet} safety ramp"
        if [catch {exec rampload /home/helios/oagData/booster/ramps/IRamp/safety/${magnet}Iref.afg100 } result] {
            APSMpReturn error "APSMpBoosterSDUSetFullPower7: error loading ${magnet} safety ramp: $result" 
        }
        APSMpStep "Turn ${magnet} PS"
        if [catch {exec cavput -list=B:${magnet}:Reset=1 -pend=10} result] {
            APSMpReturn error "APSMpBoosterSDUSetFullPower7: Error reset ${magnet}: $result"
        }
        after 2000
        if [catch {exec cavput -list=B:${magnet}:OnSEQ=1 -pend=10} result] {
            APSMpReturn error "APSMpBoosterSDUSetFullPower8: Error turn on ${magnet}: $result"
        }
        after 3000
        if [catch {exec cavget -list=B:${magnet}:StatusCALC -printErrors -pend=20} SDUstatus] {
            APSMpReturn error "APSMpBoosterSDUSetFullPower9: Error reading B:${magnet}:StatusCALC: $SDUstatus"
        }
        if !$SDUstatus {
            APSMpStep "Enable ${magnet} ramp"
            if [catch {exec cavput -list=$rampPV.GATE=1 -pend=10 } result] {
                APSMpReturn error "APSMpBoosterSDUSetFullPower10:Error enable ramp after turning on ${magnet}: $result"
            }
        } else {
            APSMpReturn error "${magnet} was not turned on, please check."
        }
    }
    APSMpStep "Restore ${magnet} afg gain and trigger delay from SCR $SCRFile"
    if [catch {exec cavput -list=B:${magnet}:CurrentRT.GAIN=0.4 -pend=20} result] {
        APSMpReturn error "APSMpBoosterSDUSetFullPower11: error setting ${magnet} gain to 0.2: $result"
    }
    after 2000
    if [catch {exec sddsprocess $SCRDir/[file tail $SCRFile] -pipe=out \
                 "-match=col,ControlName=B:${magnet}:CurrentRT.GAIN,ControlName=$rampPV.DLY,|" \
                 | sddscasr -pipe=in -restore -pend=30} result] {
        APSMpReturn error "APSMpBoosterSDUSetFullPower12: error restore ${magnet} AFG gain and trigger delay from SCR ($SCRFile): $result"
    }
    if [catch {exec cavput -list=B:${bcontrol}bcontrollawRC.SUSP=Resume  -pend=20} result] {
        APSMpReturn error "APSMpBoosterSDUSetFullPower13: error resuming  $bcontrol bcontrollaw."
    }
    APSMpStep "Set ${magnet} full power done."
    APSMpReturn ok
}

proc APSMpBoosterSDUSetStandbyPower {args} {
    set magnet SD-U
    APSStrictParseArguments {magnet}
    
    switch $magnet {
        SD-U {
            set rampPV It:Ddg9chan3
        }
        SF-U {
            set rampPV It:Ddg9chan2
        }
        default {
            return
        }
    }
    set mag [string range $magnet 0 1]
    
    if [catch {exec cavget -list=B:${magnet}:StatusCALC -printErrors -pend=20} SDUstatus] {
        APSMpReturn "Error reading B:${magnet}:StatusCALC: $SDUstatus"
    }
    if $SDUstatus {
        APSMpStep "${magnet} is  off, can not set it to standby mode."
        APSMpReturn ok
    }
    APSMpStep "suspend $magnet bcontrol"
    if [catch {exec cavput -list=B:${mag}bcontrollawRC.SUSP=Suspend } result] {
        APSMpReturn error "APSMpBoosterSDUSetStandyPower1: error suspending SD bcontrollaw."
    }
    APSMpStep "Set SDU afg gain to 0.2"
    if [catch {exec  cavput -list=B:${magnet}:CurrentRT.GAIN=0.4 -pend=20} result] {
        APSMpReturn error "APSMpBoosterSDUSetStandyPower3:error setting ${magnet} gain to 0.2: $result"
    }
    after 2000
    if [catch {exec  cavput -list=B:${magnet}:CurrentRT.GAIN=0.2 -pend=20} result] {
        APSMpReturn error "APSMpBoosterSDUSetStandyPower3:error setting ${magnet} gain to 0.2: $result"
    }
    
    APSMpStep "Set $magnet standby power done."
    
    APSMpReturn ok
}

proc APSMpBoosterSDUSetNoPower {args} {
    set magnet SD-U
    APSStrictParseArguments {magnet}
    switch $magnet {
        SD-U {
            set rampPV It:Ddg9chan3
        }
        SF-U {
            set rampPV It:Ddg9chan2
        }
        default {
            return
        }
    }
    set mag [string range $magnet 0 1]
    if [catch {exec cavget -list=B:${magnet}:StatusCALC -printErrors -pend=20} SDUstatus] {
        APSMpReturn "Error reading B:${magnet}:StatusCALC: $SDUstatus"
    }
    if $SDUstatus {
        APSMpStep "$magnet is aleady off."
        APSMpReturn ok
    }
    APSMpStep "Suspend $magnet bcontrol"
    if [catch {exec cavput -list=B:${mag}bcontrollawRC.SUSP=Suspend -pend=20} result] {
        APSMpReturn error "APSMpBoosterSDUSetNoPower1: error suspending SD bcontrollaw."
    }
    if [catch {exec  cavput -list=B:${magnet}:CurrentRT.GAIN=0.4 -pend=20} result] {
        APSMpReturn error "APSMpBoosterSDUSetStandyPower3:error setting ${magnet} gain to 0.2: $result"
    }
    after 2000
    if [catch {exec  cavput -list=B:${magnet}:CurrentRT.GAIN=0.2 -pend=20} result] {
        APSMpReturn error "APSMpBoosterSDUSetStandyPower3:error setting ${magnet} gain to 0.2: $result"
    }
    APSMpStep "Turn off SDU."
    if [catch {exec cavput -list=$rampPV.GATE=0 -pend=10} result] {
        APSMpReturn error "Error disable ramp before turn off ${magnet}: $result"
    }
    if [catch {exec cavput -list=B:${magnet}:OffSEQ=1 -pend=10} result] {
        APSMpReturn error "Error turn off ${magnet}: $result"
    }
    APSMpStep "Set $magnet no power done."
    APSMpReturn ok
}

proc APSCheckBoosterInjectionControllaw {args} {
    set xControllaw 0
    set injControllaw 0
    set longControllaw 0
    APSStrictParseArguments {xControllaw injControllaw longControlla}

    if {!$xControllaw && !$injControllaw && !$longControllaw} {
        return
    }
    set tmpRoot /tmp/[APSTmpString]
    set tries 6
    if {$xControllaw} {
        set testFile /home/helios/oagData/controllaw/BOOSTER/transBooster/Horizontal/B3C2P1/xBooster.tests
        set times 0
        
        while {$times<$tries} {
            if [catch {exec sddssnapshot $testFile -pipe=output \
                         | sddsprocess -pipe "-def=col,InBounds,MinimumValue Value < pop pop ? Value MaximumValue < pop pop ? 1 : 0 $ : 0 $,type=long" \
                         | sddsprocess "-test=col,InBounds 0 ==" -pipe=in $tmpRoot.1 -nowarnings } result] {
                return -code error "Error checking xBooster.test: $result"
            }
            set rows [exec sdds2stream -rows=bar $tmpRoot.1]
            if {$rows} {
                if {$times==[expr $tries-1]} {
                    return -code error "Horizontal controllaw test failed after $tries correction!"
                }
                set pvList [exec sdds2stream -col=ControlName $tmpRoot.1]
                set minList [exec sdds2stream -col=MinimumValue $tmpRoot.1]
                set maxList [exec sdds2stream -col=MaximumValue $tmpRoot.1]
                set beamLow 0
                set putList ""
                foreach pv $pvList min $minList max $maxList {
                    switch $pv {
                        B:IK:VoltageSetSendAO -
                        B:IS:VoltageSetSendAO {
                            lappend putList $pv=[expr ($min + $max)/2.0]
                        }
                        PTB:H4:CurrentAO -
                        PTB:CM:measCurrentCM -
                        B3C2P1:sum.RVAL -
                        B3C2P1:olddata_sum_bi.VAL {
                            set beamLow 1
                        }
                        default {
                            if {$times==[expr $tries - 1]} {
                                return -code error "Booster horizontal controllaw test failed because of $pv!"
                            } else {
                                #do nothing, continue check
                            }
                        }
                    }
                }
                if $beamLow {
                    #turn on beam
                    if [catch {TogglePulsedMagnetEnables -location GuntoBoosterExt} result] {
                        return -code error "Error turning on booster beam!"
                    }
                }
                if [llength $putList] {
                    if [catch {exec cavput -list=[join $putList ,] -pend=30} result] {
                        return -code error "Error setting booster kicker in range: $result"
                    }
                }
                after 5000
            } else {
                break
            }
            incr times
        }
    }
    if {$longControllaw} {
        set testFile /home/helios/oagData/controllaw/BOOSTER/longBooster/B3C2P1/longBooster.tests
        set times 0
        
        while {$times<$tries} {
            if [catch {exec sddssnapshot $testFile -pipe=output \
                         | sddsprocess -pipe "-def=col,InBounds,MinimumValue Value < pop pop ? Value MaximumValue < pop pop ? 1 : 0 $ : 0 $,type=long" \
                         | sddsprocess "-test=col,InBounds 0 ==" -pipe=in $tmpRoot.1 -nowarnings } result] {
                return -code error "Error checking xBooster.test: $result"
            }
            set rows [exec sdds2stream -rows=bar $tmpRoot.1]
            if {$rows} {
                if {$times==[expr $tries-1]} {
                    return -code error "longitudinal controllaw test failed after $tries correction!"
                }
                set pvList [exec sdds2stream -col=ControlName $tmpRoot.1]
                set minList [exec sdds2stream -col=MinimumValue $tmpRoot.1]
                set maxList [exec sdds2stream -col=MaximumValue $tmpRoot.1]
                set beamLow 0
                set phaseOut 0
                foreach pv $pvList min $minList max $maxList {
                    switch $pv {
                        PAR:RF12:PhsShft2Ch2_3AO {
                            set phaseOut 1
                        }
                        PTB:CM:measCurrentCM -
                        B3C2P1:sum.RVAL -
                        B3C2P1:olddata_sum_bi.VAL {
                            set beamLow 1
                        }
                        default {
                            if {$times==[expr $tries -1]} {
                                return -code error "Booster longitudinal controllaw test failed because of $pv!"
                            } else {
                                #do nothing, continue checking
                            }
                        }
                    }
                }
                if $beamLow {
                    #turn on beam
                    if [catch {TogglePulsedMagnetEnables -location GuntoBoosterExt} result] {
                        return -code error "Error turning on booster beam!"
                    }
                }
                if [llength $phaseOut] {
                    #run full start to restart longitudinal controllaw
                    if [catch {APSStartLongBoosterControllawFull -subDir B3C2P1} result] {
                        return -code error "Error start booster longitudinal controllaw in full: $result"
                    }
                }
                after 5000
            } else {
                break
            }
            incr times
        }
    }
    
    if {$injControllaw} {
        set testFile /home/helios/oagData/controllaw/BOOSTER/injTune/injTune.tests
        set times 0
        
        while {$times<$tries} {
            if [catch {exec sddssnapshot $testFile -pipe=output \
                         | sddsprocess -pipe "-def=col,InBounds,MinimumValue Value < pop pop ? Value MaximumValue < pop pop ? 1 : 0 $ : 0 $,type=long" \
                         | sddsprocess "-test=col,InBounds 0 =="  -pipe=in $tmpRoot.1 -nowarnings } result] {
                return -code error "Error checking xBooster.test: $result"
            }
            set rows [exec sdds2stream -rows=bar $tmpRoot.1]
            if {$rows} {
                if {$times==[expr $tries-1]} {
                    return -code error "Injection tune controllaw test failed after $tries correction!"
                }
                set pvList [exec sdds2stream -col=ControlName $tmpRoot.1]
                set minList [exec sdds2stream -col=MinimumValue $tmpRoot.1]
                set maxList [exec sdds2stream -col=MaximumValue $tmpRoot.1]
                set valueList [exec sdds2stream -col=Value $tmpRoot.1]
                set beamLow 0
                set QD 0
                set QF 0
                foreach pv $pvList min $minList max $maxList value $valueList {
                    switch $pv {
                        PTB:CM:measCurrentCM -
                        B:diag1:rms:A:region4  -
                        B3C2P1:sum.RVAL -
                        B3C2P1:olddata_sum_bi.VAL -
                        B3C2P2:olddata_sum_bi.VAL {
                            set beanLow 1
                        }
                        B3C2P1:ffsFrequencyM {
                            #xtune (QF)
                            if {$value>=$max} {
                                set QF -0.05
                            } elseif {$value<=$min} {
                                set QF 0.05
                            }
                        }
                        B3C2P2:fftFrequencyM {
                            #ytune (QD)
                            if {$value>=$max} {
                                set QD -0.05
                            } elseif {$value<=$min} {
                                set QD 0.05
                            }
                        }
                        default {
                            if {$times==[expr $tries - 1]} {
                                return -code error "Booster horizontal controllaw test failed because of $pv!"
                            } else {
                                #do nothing, continue testing
                            }
                        }
                    }
                }
                if $beamLow {
                    #turn on beam
                    if [catch {TogglePulsedMagnetEnables -location GuntoBoosterExt} result] {
                        return -code error "Error turning on booster beam!"
                    }
                }
                if {$QF} {
                    if [catch {exec cavput -list=B:QF:IRampDelayOffsetAI=$QF -delta -pend=30} result] {
                        return -code error "Error changing QF offset for y tune: $result"
                    }
                }
                if {$QD} {
                    if [catch {exec cavput -list=B:QD:IRampDelayOffsetAI=$QD -delta -pend=30} result] {
                        return -code error "Error changing QD offset for x tune: $result"
                    }
                }
                after 5000
            } else {
                break
            }
            incr times
        }
    }
    
}

proc APSStartLongBoosterControllawFull {args} {
    set subDir ""
    APSStrictParseArguments {subDir}

    if [catch {exec cavget -list=PAR:RF12:PhsShft2Ch2_3AO -printErrors -pend=10} parPhase] {
        return -code error "Something wrong with PAR:RF12:PhsShft2Ch2_3AO."
    }
    set low [format %.0f [expr $parPhase - 15]]
    set high [format %.0f [expr $parPhase + 15]]
    set tmpFile /tmp/[APSTmpString]
    set oldDir [pwd]
    set controllawDir /home/helios/oagData/controllaw/BOOSTER/longBooster
    cd $controllawDir
    if [catch {exec sddsprocess longBooster.tests $tmpFile -match=col,ControlName=PAR:RF12:PhsShft2Ch2_3AO} result] {
        return -code error "PAR:RF12:PhsShft2Ch2_3AO does not exist in longBooster.tests file."
    }
    set low1 [format %.0f [exec sdds2stream -col=MinimumValue $tmpFile]]
    set high1 [format %.0f [exec sdds2stream -col=MaximumValue $tmpFile]]
    if {[expr abs($low-$low1)]>5 || [expr abs($high-$high1)]>5} {
        set file [file readlink longBooster.tests]
        set newFile [APSNextGenerationedName -name $file -separator - -newFile 1]
        if [catch {exec sddsprocess $tmpFile $tmpFile.1 -redefine=col,MinimumValue,$low -redefine=col,MaximumValue,$high
            exec sddsprocess longBooster.tests $tmpFile.2 "-match=col,ControlName=PAR:RF12:PhsShft2Ch2_3AO,!"
            exec sddscombine $tmpFile.2 $tmpFile.1 -merge $newFile} result] {
            cd $oldDir
            return -code error $result
        }
        exec rm longBooster.tests
        exec ln -s $newFile longBooster.tests
    } 
    #start longitudinal controllaw
    if [catch {exec cavput -list=Booster:ControlLawLongRC.ABRT=1 -pend=30 } result] {
        return -code error "APSStartLongBoosterControllawFull: error abort longitudinal controllaw: $result"
    }
    if [catch {exec cawait -waitFor=Booster:ControlLawLongRC.RUN,equal=0 -time=30} result] {
         return -code error "APSStartLongBoosterControllawFull: error aborting longitudinal controllaw: $result"
    }
    if [catch {exec cavput -list=Booster:ControlLawLongRC.CLR=1 -pend=30} result] {
        return -code error "APSStartLongBoosterControllawFull: error clear booster longitudinal controllaw: $result"
    }
    catch {exec sddscontrollaw $subDir/longBooster.matrix -controlQuantityDefinition=B3C2P1/longBooster.def -testValues=B3C2P1/longBooster.tests -deltaLimits=file=B3C2P1/longBooster.deltaLimits -runControlDescription=string=boosterLongControllaw-B3C2P1 -runControlPV=string=Booster:ControlLawLongRC -interval=3.1 -gain=0.15 -steps=3000000 -integral -warning -ezcaTiming=0.1,100 -averageNumber=5,interval=0.5  & }
    
    cd $oldDir
    #start longitudinal controllaw -- need use debug mode to find the command -- leave it and find it on machine studies  
}


#####
proc APSMpOperator1Hz2HzSwitchInitDialog {frame} {
    global APSMpBoosterSwitchLattice APSMpPARHighChargeSetup
    set APSMpBoosterSwitchLattice(ShortFilename) ""
    set APSMpPARHighChargeSetup(ShortFilename) ""
    set APSMpBoosterSwitchLattice(boosterIRamp) 1
    
    set APSMpBoosterSwitchLattice(Hz) 1Hz
    APSRadioButtonFrame .hz -parent $frame -label "Switch to 1Hz or 2Hz?   " -buttonList {1Hz 2Hz} -valueList {1Hz 2Hz} \
      -orientation horizontal -variable APSMpBoosterSwitchLattice(Hz)
    
    set wList [APSTabFrame .tab -parent $frame -label "" -labelList {"LPL SCR" "Booster SCR"} \
		   -width 900 -height 600]
    set w1 [lindex $wList 0]
    set w2 [lindex $wList 1]
    #LPL SCR parameters
    set APSMpPARHighChargeSetup(FFmod) oper
    APSAddSCRDialog .lplscr -parent $w1 -system LPL \
      -arrayName APSMpPARHighChargeSetup \
      -defaultFile $APSMpPARHighChargeSetup(ShortFilename) \
      -label "Choose LPL  SCR file by clicking on the Preferred/Reference Choices"
    set categoryList [exec sddssort /home/helios/oagData/SCR/requestFiles/LPL.req -col=Category -unique -pipe=out \
			| sdds2stream -pipe -col=Category]
    set varList ""
    set APSMpPARHighChargeSetup(CategoryList) $categoryList
    set APSMpPARHighChargeSetup(FFmode) oper
    foreach filter $categoryList {
	set APSMpPARHighChargeSetup($filter) 0
	lappend varList APSMpPARHighChargeSetup($filter)
    }
    foreach item {BunchCleaning HarmonicRF SteeringPS SteeringSetpoint StreakCamera Timing} {
	set APSMpPARHighChargeSetup($item) 1
    }
   # set APSMpPARHighChargeSetup(Timing) 0
    set APSMpPARHighChargeSetup(beamlines) {PAR LTP PTB Linac}
    set APSMpPARHighChargeSetup(PAR) 1
    set APSMpPARHighChargeSetup(LTP) 0
    set APSMpPARHighChargeSetup(Linac) 0
    set APSMpPARHighChargeSetup(PTB) 0
    APSCheckButtonFrame .categorys -parent $w1 \
	-label "Select SCR categories\nto restore" \
	-variableList $varList \
	-buttonList $categoryList \
	-limitPerRow 7 -orientation horizontal -allNone 1
    APSCheckButtonFrame .beamlines -parent $w1 -label "Select SCR beamline  \nto restore " \
	-variableList {APSMpPARHighChargeSetup(LTP)    \
			   APSMpPARHighChargeSetup(Linac) \
			   APSMpPARHighChargeSetup(PAR)  \
			   APSMpPARHighChargeSetup(PTB)} \
	-buttonList {LTP Linac PAR PTB} \
        -limitPerRow 7 -orientation horizontal -allNone 1
    

    #booster parameters GUI
    APSAddSCRDialog .booscr -parent $w2 -system Booster \
      -arrayName APSMpBoosterSwitchLattice \
      -defaultFile $APSMpBoosterSwitchLattice(ShortFilename) 
    foreach item {AFG Bcontrol BRamp RampTiming InjTiming InjPulsedPS ExtTiming ExtPulsedPS SteeringPS SteeringSetpoint Booster PTB} {
	set APSMpBoosterSwitchLattice($item) 1
    }
    
    set APSMpBoosterSwitchLattice(BTS) 0
    set APSMpBoosterSwitchLattice(PAR) 0
    set APSMpBoosterSwitchLattice(IRamp) 1
    set filterList [exec sddssort /home/helios/oagData/SCR/requestFiles/Booster.req -col=Category -unique -pipe=out \
                      | sdds2stream -pipe -col=Category]
    
   
    set varList ""
    foreach filter $filterList {
        set APSMpBoosterSwitchLattice($filter) 0
        lappend varList APSMpBoosterSwitchLattice($filter)
    }
    foreach item {AFG Bcontrol BRamp RampTiming InjTiming InjPulsedPS ExtTiming ExtPulsedPS SteeringPS SteeringSetpoint Booster PTB} {
	set APSMpBoosterSwitchLattice($item) 1
    }
    APSCheckButtonFrame .categorys -parent $w2 \
      -label "Select SCR categories\nto restore" \
      -variableList $varList \
	-buttonList $filterList \
	-limitPerRow 7 -orientation horizontal -allNone 1
    APSCheckButtonFrame .beamlines -parent $w2 -label "Select SCR beamline  \nto restore " \
	-variableList {APSMpBoosterSwitchLattice(BTS)    \
                         APSMpBoosterSwitchLattice(PAR) \
			   APSMpBoosterSwitchLattice(Booster)  \
			   APSMpBoosterSwitchLattice(PTB)} \
	-buttonList {BTS PAR Booster PTB} \
        -limitPerRow 7 -orientation horizontal -allNone 1
    
    
    
    APSMpReturn ok
}

proc APSMpOperator1Hz2HzSwitchInfo {} {
    return "switch operational (7GeV) injectors between 1Hz and 2Hz."
}
proc APSMpOperator1Hz2HzSwitch {args} {
    global APSMpPARHighChargeSetup APSMpBoosterSwitchLattice Lattice env
    set ShortFilename ""
    set Hz 1Hz
    APSStrictParseArguments {boosterSCR LPLSCR Hz}

    APSMpStep init -promptDialog APSMpOperator1Hz2HzSwitchInitDialog \
	-vars {ShortFilename  Hz}
    
    set boosterSCR $APSMpBoosterSwitchLattice(ShortFilename)
    set LPLSCR $APSMpPARHighChargeSetup(ShortFilename)
    set Hz $APSMpBoosterSwitchLattice(Hz)
    APSMpStep $boosterSCR
    APSMpStep $LPLSCR
    if {![string length $boosterSCR] || ![string length $LPLSCR]} {
	APSMpReturn error "APSMpOperator1Hz2HzSwitch1: booster or LPL SCR file not chosen!"
    }
    if [catch {exec logMessage  -sourceId=Injector1Hz2HzSwitch -tag=User $env(USER) -tag=Host $env(HOST) \
		   -tag=BoosterSCR $boosterSCR -tag=LPLSCR $LPLSCR -tag=SwitchTo $Hz -tag=Action Start \
             } result ] {
        APSAlertBox .alert -errorMessage "APSMpOperator1Hz2HzSwitch0: Error with logMessage: $result"
        APSMpReturn -code error "APSMpOperator1Hz2HzSwitch0: Error with logMessage: $result"
    }
    APSMpStep "Checking timing mode in SCR..."
    set tmpFile /tmp/[APSTmpString]
    APSAddToTmpFileList -ID injectorswitch -fileList $tmpFile.booster $tmpFile.LPL
    if [catch {exec sddsprocess /home/helios/oagData/SCR/snapshots/Booster/$boosterSCR -pipe=out \
		   -match=col,ControlName=It:L:1HzNot2Hz_bo \
		   | sdds2stream -pipe=in -col=ValueString } booHz] {
	#booster SCR does not have this PV 
	APSMpReturn error "Error the 1Hz mode pv not found in booster SCR: $booHz"
    }
   
    #check if this SCR is corrector
    APSMpStep "Booster SCR mode: $booHz"
    if { [regexp "1 Hz" $booHz] && $Hz=="2Hz"} {
	APSMpReturn error "APSMpOperator1Hz2HzSwitch2: 1Hz booster SCR instead of 2Hz was chosen!"
    }
    if { [regexp "2 Hz" $booHz] && $Hz=="1Hz"} {
	APSMpReturn error "APSMpOperator1Hz2HzSwitch3: 2Hz booster SCR instead of 1Hz was chosen!"
    }
    
    if [catch {exec sddsprocess /home/helios/oagData/SCR/snapshots/LPL/$LPLSCR -pipe=out \
		   -match=col,ControlName=It:L:1HzNot2Hz_bo \
	       | sdds2stream -pipe=in -col=ValueString } LPLHz] {
	#LPL SCR does not have this PV 
	APSMpReturn error "Error the 1Hz mode pv not found in LPL SCR: $LPLHz"
    } 
    APSMpStep "LPL SCR mode: $LPLHz"
	
    if { [regexp "1 Hz" $LPLHz] && $Hz=="2Hz"} {
	APSMpReturn error "APSMpOperator1Hz2HzSwitch4: 1Hz LPL SCR instead of 2Hz was chosen!"
    }
    if { [regexp "2 Hz" $LPLHz] && $Hz=="1Hz"} {
	APSMpReturn error "APSMpOperator1Hz2HzSwitch5: 2Hz LPL SCR instead of 1Hz was chosen!"
    }
    
    APSMpStep "Checking booster energy..."
    if [catch {exec sddsprocess  /home/helios/oagData/SCR/snapshots/Booster/$boosterSCR -pipe=out \
		   -match=col,IsProtected=n \
		   -match=col,ControlName=B:EK:VoltageSetSendAO \
		   | sdds2stream -pipe=in -col=ValueString } BEK] {
	APSMpReturn error "APSMpOperator1Hz2HzSwitch4a: error obtaining booster energy: $BEK"
    }
    if {[expr abs($BEK-20)]>0.5} {
	APSMpReturn error "APSMpOperator1Hz2HzSwitch4b: booster energy is off (not 7GeV), BEK=[format %0.1f $BEK]!"
    }
    APSMpStep "Disable beam before switch..."
    if [catch {SetPulsedMagnetEnables -state 0 -location GuntoBoosterExt } result] {
	APSMpReturn -code error "APSMpOperator1Hz2HzSwitch4c: error disabling beam: $result"
    }
    APSMpStep "Switch par to $Hz ..."
    if [catch {APSMpPARHighChargeSetup -mode $Hz -ShortFilename $LPLSCR -highCharge 0 -useLPL 1 -Timing 0} result] {
	APSMpReturn error "APSMpOperator1Hz2HzSwitch4: Error switching PAR to $Hz: $result"
    }
    APSMpStep "LPL->PAR switched to $Hz.."
    set oldDir [pwd]
    
    cd /home/helios/oagData/SCR/snapshots/LPL
    catch {exec rm LPL-OpPref.gz}
    exec ln -s LPL-OpPref${Hz}.gz LPL-OpPref.gz
    APSMpStep "LPL UBOP is switched to $Hz."
    cd $oldDir
    
    set Lattice Unknown
    APSMpStep "Switch booster to $Hz..."
    if [catch {APSMpBoosterSwitchLattice -ShortFilename $boosterSCR -IRamp 1 -Hz $Hz} result] {
	APSMpReturn error "APSMpOperator1Hz2HzSwitch5: error in switching booster lattice to $Hz: $result"
    }
    #need change the BTS:AH1 setpoint, it is different between 1Hz and 2Hz
    if [catch {exec sddsprocess /home/helios/oagData/SCR/snapshots/Booster/$boosterSCR -pipe=out \
		   -match=col,ControlName=BTS:AH1:CurrentAO \
		   | sdds2stream -pipe=in -col=ValueString } BTSAH1] {
	APSMpReturn error "APSMpOperator1Hz2HzSwitch5a: error obtaining BTS:AH1 from $boosterSCR: $BTSAH1"
    }
    APSMpStep "set BTS:AH1:CurrentAO to $BTSAH1..."
    if [catch {exec cavput -list=BTS:AH1:CurrentAO=$BTSAH1 -pend=10} result] {
	APSMpReturn error "APSMpOperator1Hz2HzSwitch5a: error set BTS:AH1:CurrentAO to $BTSAH1: $result"
    }
    cd /home/helios/oagData/SCR/snapshots/Booster
    catch {exec rm Booster-UserBeamPreferred.gz}
    exec ln -s Booster-UserBeamPreferred${Hz}.gz Booster-UserBeamPreferred.gz

    APSMpStep "Booster UBOP is switched to $Hz."
    APSMpStep "siwitch B:ES2 and B:ES1 FF links..."
    cd /home/helios/oagData/feedForwardFiles
    eval file delete -force SIS1.6GeV.response SIS1.7GeV.response BES2.6GeV.response BES2.7GeV.response 
    exec ln -s SIS1.6GeV-${Hz}.response SIS1.6GeV.response
    exec ln -s SIS1.7GeV-${Hz}.response SIS1.7GeV.response 
    exec ln -s BES2.6GeV-${Hz}.response BES2.6GeV.response
    exec ln -s BES2.7GeV-${Hz}.response BES2.7GeV.response
    cd $oldDir
    APSMpStep "Restart SIS1 and BES feedforard..."
    set id1 [APSMpParallel \
               -procedure "APSMpStopBES2Feedforward" \
               -mode Automatic]
    if [catch {APSMpJoin $id1} results] {
	APSMpReturn error "APSMpOperator1Hz2HzSwitch6: $results"
    }
    set id1 [APSMpParallel \
               -procedure "APSMpStartBES2Feedforward" \
               -mode Automatic]
    if [catch {APSMpJoin $id1} results] {
	APSMpReturn error "APSMpOperator1Hz2HzSwitch7: $results"
    }

    set id1 [APSMpParallel \
		 -procedure "APSMpStopSIS1Feedforward" \
		 -mode Automatic]
    if [catch {APSMpJoin $id1} results] {
	APSMpReturn error "APSMpOperator1Hz2HzSwitch8: $results"
    }
    set id1 [APSMpParallel \
		 -procedure "APSMpStartSIS1Feedforward" \
		 -mode Automatic]
    if [catch {APSMpJoin $id1} results] {
	APSMpReturn error "APSMpOperator1Hz2HzSwitch9: $results"
    }
    #APSMpStep "Enable beam after switch..."
    #if [catch {TogglePulsedMagnetEnables -location GuntoBoosterExt} result] {
    #	APSMpReturn error "APSMpOperator1Hz2HzSwitch10: Error enabling beam: $result"
    #    }
    if [catch {exec logMessage  -sourceId=Injector1Hz2HzSwitch -tag=User $env(USER) -tag=Host $env(HOST) \
		   -tag=BoosterSCR $boosterSCR -tag=LPLSCR $LPLSCR -tag=SwitchTo $Hz -tag=Action Done \
             } result ] {
        APSAlertBox .alert -errorMessage "APSMpOperator1Hz2HzSwitch0: Error with logMessage: $result"
        APSMpReturn -code error "APSMpOperator1Hz2HzSwitch0: Error with logMessage: $result"
    }
    APSMpStep "Injector switch is done!"
    APSMpReturn ok
}

proc APSMpVerifyInjectorFileLinks {args} {
    return "verify LPL and Booster UBOP links."
}

proc APSMpVerifyInjectorFileLinksInitDialog {frame} {
    global APSMpVerifyInjectorFileLinks
    set APSMpVerifyInjectorFileLinks(mode) 1Hz
    APSRadioButtonFrame .mode -parent $frame -label "mode"  -buttonList {1Hz 2Hz} -valueList {1Hz 2Hz} \
	-variable APSMpVerifyInjectorFileLinks(mode)

   # APSButton .verify -parent $frame -text "Verify File Links" -command APSMpVerifyInjectorFileLinks 
}

proc APSMpVerifyInjectorFileLinks {args} {
    set mode ""
    APSStrictParseArguments {mode}
    global APSMpVerifyInjectorFileLinks
    APSMpStep init -promptDialog APSMpVerifyInjectorFileLinksInitDialog \
	-vars {mode}
    
    if ![string length $mode] {
	set mode $APSMpVerifyInjectorFileLinks(mode)
    }
    set oldDir [pwd]
    set scrdir /home/helios/oagData/SCR/snapshots
    set error 0
    set message "check $mode links...\n"
    foreach system {LPL Booster} ubop {LPL-OpPref.gz Booster-UserBeamPreferred.gz} {
	APSMpStep "Check $system link..."
	cd $scrdir/$system
	set link [file readlink $ubop]
	if [regexp "2Hz" $link] {
	    APSMpStep "$system UBOP is linked to 2Hz UBOP"
	} else {
	    APSMpStep "$system UBOP is linked to 2Hz UBOP"
	}
	if {$mode=="1Hz" && [regexp "2Hz" $link]} {
	    incr error
	    append message "error: $system UBOP is linked to 2Hz.\n"
	}
	if {$mode=="2Hz" && [regexp "1Hz" $link]} {
	    incr error
	    append message "error: $system UBOP is linked to 1Hz.\n"
	}
	if [catch {exec sddsprocess /home/helios/oagData/SCR/snapshots/$system/$link -pipe=out \
		       -match=col,ControlName=It:L:1HzNot2Hz_bo \
		       | sdds2stream -pipe=in -col=ValueString } scrmode] {
	    #LPL SCR does not have this PV 
	    APSMpReturn error "Error the 1Hz mode pv not found in LPL SCR: $LPLmode"
	}
	APSMpStep "$system UBOP mode is $scrmode"
	if { [regexp "1 Hz" $scrmode] && $mode=="2Hz"} {
	    incr error
	    append message "error: $system SCR is 1Hz.\n"
	}
	if { [regexp "2 Hz" $scrmode] && $mode=="1Hz"} {
	    incr error
	    append message "error: $system SCR is 2Hz.\n"
	}
    }
    if $error {
	APSMpStep "$message"
	APSMpStep "$mode verification failed.\n"
	append message "\n$mode verification failed."
	#APSMpReturn error "$message"
    } else {
	append message "\n$mode verifcation pass."
	APSMpStep "$mode verification pass.\n"
    }
    APSInfoWindow .info -name "Injector Soft link check" -width 60 \
	-infoMessage "$message." -modal 1
    APSMpReturn ok
}
