
proc RFGun_KickerValidationInfo {} {
    global execMode
   # set execMode Manual
    return "Validate the operation of the APS linac thermionic-cathod rf gun kickers."
}

proc RFGun_KickerValidationDialog {frame} {
    global status RFGun_KickerValidation 
    set RFGun_KickerValidation(abort) 0
    pack [frame $frame.f1]
    APSRadioButtonFrame .gun -parent $frame.f1 -label "RF Gun:   " -buttonList {1 2} \
      -valueList {RG1 RG2} -variable RFGun_KickerValidation(gun) \
      -contextHelp "select RF gun (1 or 2) for validation." \
      -orientation horizontal
   # APSLabeledEntry .vol -parent $frame.f1 -label "L1 voltage(MV):" \
   #   -textVariable RFGun_KickerValidation(L1Voltage) -width 10
    APSLabeledEntry .tol -parent $frame.f1 -label "Corrector Tolerance (A):" \
      -textVariable RFGun_KickerValidation(tolerance) -width 10 \
      -contextHelp "Enter the tolerance between setpoint and readback of correctors during sweeping experiments."
    APSLabeledEntry .pos -parent $frame.f1 -label "Post Change Pause: (s)" \
      -textVariable RFGun_KickerValidation(postChange) -width 10 \
      -contextHelp "The pause time in seconds after changing correctors before taking measurements during sweeping correctors."
    APSLabeledEntry .num -parent $frame.f1 -label "Number of Average:" \
      -width 10 -textVariable RFGun_KickerValidation(numToAve) \
      -contextHelp "Number of times for reading leakage during each sweeping corrector step."
    APSLabeledEntry .step -parent $frame.f1 -label "Step size: (A)" \
      -textVariable RFGun_KickerValidation(stepSize) -width 10 \
      -contextHelp "The amount of increament in A for next scan during sweeping correctors."
    return
}

proc RFGun_KickerValidation {args} {
    global status execMode
    set gun RG2
    #set L1Voltage 12
    set tolerance 0.05
    set postChange 2.1
    set numToAve 1
    set stepSize 0.1
    set inputDir /home/helios/oagData/linac/gunKickerValidation
    set scrDir /home/helios/oagData/SCR/snapshots/LPL
    APSStrictParseArguments {gun}
    APSMpStep init \
	-promptDialog RFGun_KickerValidationDialog \
	-vars "gun tolerance postChange numToAve stepSize" -proc "RFGun_KickerValidation"

    set paramString ""
    foreach param {gun tolerance postChange numToAve stepSize} {
        append paramString "$param=\"[set $param]\" "
    }
    catch {APSLogScriptAction -procedure RFGun_KickerValidation -action initialize -state ok -parameters $paramString}

    set startTime [clock seconds] 
    APSMpStep "Step 0a: abort linac beam rf phase global controllaw."
    if [catch {exec cavput -list=L:BPD:RFGUN1:L1L2L4L5RC.ABRT=1,L:BPD:RFGUN2:L1L2L4L5RC.ABRT=1,APS:RunControlFixed0RC.ABRT=1} result] {
	APSMpReturn error "RFGUNK_KickerValiation(1): unable to abort the linac beam rf phase global controllaw: $result"
    }
    set scrSave [lindex [APSSCRMakeSnapshotFilename -machine LPL] 0]
    APSMpStep "Step 0: Save snapshot before starting validaion."
    
    if [catch {APSSaveMachine -machine LPL -snapshot $scrSave \
                   -description "Save before starting kicker validation" } result] {
        APSMpReturn error "RFGUN_KickerValidation: $result"
    }
    APSMpStep "Step 1a: Disable the charge pulse for the kicker to make sure no beam come through"
    set kickerOff 1
    if {$gun == "RG2"} {
        if [catch {APScavput -list=L1:RG2:KIK:chargeTrigC=0 -pend=30} result] {
            APSMpReturn error "Can not turn off the kicker: $result"
        }
    } else {
        if [catch {APScavput -list=L1:RG1:KIK:chargeTrigC=0 -pend=30} result] {
            APSMpReturn error "Can not turn off the kicker: $result"
        }
    }
    set refFile $scrDir/LPL-SysRefHC_${gun}_PAR_BS_325MeV.gz
    if [APSYesNoPopUp "Do you want to do LPL_Configure?"] {
	APSMpStep "Step 1b: Start $gun gun user LPL_Configure pem"
	#set refFile $scrDir/LPL-RF${gun}_Kicker_Validation.gz
	if [catch {LPL_Configure -gun $gun \
		       -PowerSupplies 1 -cycles 4 \
		       -L1 1 -L2 0 -L3 0 -L4 0 -L5 0 \
		       -suspendL1 0 -suspendL2 0 -suspendL3 0 -suspendL4 0 -suspendL5 0 \
		       -startupLTP 0 -startupPAR 0 -startupPTB 0 -startupPARBypass 0 \
		       -modeVal Normal -turnOffDownKlystron 1 \
		       -SCRFile $refFile} result] {
	    APSMpReturn error "$result"
	}
    }
    if [catch {APScavget -list=L1:RFG:RF:SW2:positionMI -pend=30} gun1] {
        APSMpReturn error "$gun1"
    }
    
    if {$gun1!=$gun} {
        APSAlertBox .warning -type warning \
            -errorMessage "$gun1 is selected. Please use LPL_Configure pem with /LPL-RF${gun}_Kicker_Validation.gz pem to switch to $gun."
        APSMpStep "Wait for switching RF gun to $gun"
        set timeout [expr [clock seconds] + 300]
        while {[clock seconds]<$timeout} {
            if [catch {APScavget -list=L1:RFG:RF:SW2:positionMI -pend=30} gun1] {
                APSMpReturn error "$gun1"
            }
            if {[string compare $gun1 $gun]==0} {
                break
            }
            after 2000
        }
        if [catch {APScavget -list=L1:RFG:RF:SW2:positionMI -pend=30} gun1] {
            APSMpReturn error "$gun1"
        }
        if {$gun1!=$gun} {
            APSMpReturn error "RF Gun has not been switched to $gun after waiting for 5 minutes.!"
        }
    }
    
    if [catch {APScavget -list=L1:RFG:DC2ARF.VAL -pend=30 -printErrors} rfPower] {
        APSMpReturn error "Can not get L1 sector forward power: $rfPower"
    }
    if [catch {exec sddsprocess $refFile \
                   -match=col,ControlName=L1:RFG:DC2ARF.VAL  -pipe=out \
                   | sdds2stream -pipe -col=ValueString} refRFPower] {
        APSMpReturn error "$refRFPower"
    }
    if [catch {exec sddsprocess $refFile \
                   -match=col,ControlName=L1:${gun}:beamCurrentAO  -pipe=out \
                   | sdds2stream -pipe -col=ValueString} refCurrent] {
        APSMpReturn error "$refCurrent"
    }
    APSMpStep "Step 2a: check if the RF power is $refRFPower W."
    if {$rfPower <$refRFPower} {
        APSMpStep "Increase the L1 rf gun forward power to $refRFPower W"
        if [catch {APSLINAC_SetKlystronForwardPower -deviceList "1" -KLYFwdPwr  $refRFPower -linacMode Normal} result] {
            APSMpReturn error $result
        }
        
        APSMpStep "Resume L1 power controllaw"
        if [catch {APSLSuspendResumeRFPowerControllaws -klystronList "1" -mode  resume} result] {
            APSMpReturn error $result
        }
        
        APSMpStep "Verify that L1 power controllaw resumed"
        if {[catch {APSDevSend -group LinacKlystron -operation \
                        QueryPowerControlRunning -deviceList "1"} result]} {
            APSMpReturn error "$result"
        }
        if {$result != 1} {
            if {[catch {exec cavput -list=L:L1Stabilizer:SDDS.CMND=1} result]} {
                APSMpReturn error "Unable to automatically resume sector 1 power control."
            }
        }
        
        APSMpStep "Wait for Klystron forward power to reach $refRFPower"
        if {[catch {APSMpLWaitForMinimumValue -deviceList "1" -group LinacKlystron \
			-operation ReadForwardPower -minValue $refRFPower -intervalLimit 90 \
			-intervalTime 1} results]} {
            if {[APSPEMTKDialog .warningDialog -text "Error while waiting for Klystron forward power to reach $refRFPower \n$results"] == 1} {
                APSMpReturn error "$result"
            }
        }
    }
    APSMpStep "Step 2b: check if the $gun gun current reaches $refCurrent."
    if [catch {APScavget -list=L1:${gun}:CM1:measCurrentCM -pend=30 -printErrors} gunCurrent] {
        APSMpReturn error "$gunCurrent"
    }
    if {$gunCurrent<$refCurrent && [expr $refCurrent-$gunCurrent]>0.01} {
        APSMpStep "Wait for the gun current reach 200mA."
        while {1} {
            after 1000
            if [catch {APScavget -list=L1:${gun}:CM1:measCurrentCM -pend=30 -printErrors} gunCurrent] {
                APSMpReturn error "$gunCurrent"
            }
            if {$gunCurrent>0.2 || [expr $refCurrent-$gunCurrent]<=0.01 } {
                break
            }
        }
    }
    APSMpStep "Step 2c: Suspend RF gun current monitor"
    set status "Suspend RF gun current monitor since the current is greater than 200mA."
    if [catch {APScavput -list=L:RFGunBeamIcontrollerRC.SUSP=1 -pend=30} result] {
        APSMpReturn error $result
    }
    
    APSMpStep "Step 2d: shut down L2."
  #  if [catch {APSLSuspendResumeRFPowerControllaws -klystronList "2" -mode suspend} result] {
  #      APSMpReturn error $result
  #  }
  #  if [catch {APSRFGUN_RampDownLLRF -deviceList "2"} result] {
  #      APSMpReturn error $result
  #  }
    if [catch {APSMpShutdownDrive2} result] {
	APSMpReturn error $result
    }
    APSMpStep "Step 3: Make a non-routine SCR save of the LPL system with description of \"$gun Kicker Validation Save 0\""
    set snapshot0 [lindex [APSSCRMakeSnapshotFilename -machine LPL] 0]
    if [catch {APSSaveMachine -machine LPL -snapshot $snapshot0 \
                   -description "$gun Kicker Validation Save 0" } result] {
        APSMpReturn error "RFGUN_KickerValidation: $result"
    }
    
    
    APSMpStep "Step 4: Insert the flag L1:FS1. This shall remain inserted throughout the validation to prevent acceleration of the beam."
    if [catch {APScavput -list=LI:FL:FS1:Act1InC=In -pend=30} result] {
        APSMpReturn error "Can not insert the flag L1:FS1: $result"
    }
    after 2000
    
    APSMpStep "Step 5: turn on the high voltage and enable the charge pulse for the kicker"
    if [catch {APScavput -list=L1:$gun:KIK:OnBO=1 -pend=30} result] {
        APSMpReturn error "Can not turn the high voltage(L1:$gun:KIK:OnBO): $result"
    }
    after 2000
    if {$gun == "RG2"} {
        if [catch {APScavput -list=L1:RG2:KIK:chargeTrigC=1 -pend=30} result] {
            APSMpReturn error "Cannot enable the charge pulse: $result"
        }
    } else {
        if [catch {APScavput -list=L1:RG1:KIK:chargeTrigC=1 -pend=30} result] {
            APSMpReturn error "Cannot enable the charge pulse: $result"
        }
    }
    after 2000
    
    APSMpStep "Step 6: set the timing system to provided 10-Hz beam repetition rate."
   # if [catch {APScavput -list=It:L:RFG:10Hz_rate_bo.VAL=1 -pend=30} result] {
   #     APSMpReturn eorr "RFGun_KickerValidation: $result"
   # }
    
    APSMpStep "Bring up the reference plots of oscilloscope."
    PlotReference
    APSMpStep "Step 8: Configure L1:SCOPE1."
    if [catch {APSConfigureL1Scope -configuration 1} result] {
        APSMpReturn error "RFGUN_KickerValidation: $result"
    }
    #update the EPICS pvs for L1 scope
    if [catch {exec cavput -list=L1:SCOPE1:update1SQ.PROC=1} result] {
	APSMpReturn error "RFGUN_KickerValidation: $result"
    }
    after 3000
    set status "Press continue when checking done"
    set oldMode $execMode
    set execMode Manual
    APSMpStep "check the traces on the oscilloscope to make sure they look like Figure 1"
    
    set answer [APSMultipleChoice [APSUniqueName .] -modal 1 \
                    -question "Please Verify that the traces on the oscilloscope look like the reference Figure 1. If not, use SCR to restore the RF gun and L1 correctors and check it agin. Press one of following buttons for your choice." \
                    -returnList {1 1 0} \
                    -labelList {Check-Is-OK-And-Continue Continue-Anyway Abort} ]
    if !$answer {
        APSMpReturn error "The trace of L1:SCOPE1 and L1CM2 are abnormal, quit validation!"
    }
    set execMode $oldMode
    APSMpStep "Step 9: Launch optimizeInterface screens and run optimize to maximize the L1:P1 current"
    if [APSYesNoPopUp "Would you like to run optimizer to maximize the L1:P1 to maximize the L1:P1 current? select \"No\" if you want to skip it for testing purpose since it takes a while."] {
        catch {exec medm -x -attach -macro RCPV=L:RFG:KickerOptimizeRC ./sr/psApp/APSRunControlSingle.adl &}
        set optConfig $inputDir/optimizeConfig/$gun/current
        catch {exec optimizeInterface -configuration $optConfig -run 1 &} optimizeID
        set status "Press continue when optimization is done."
        set execMode Manual
        APSMpStep "Wait for completion of optimization."
        set execMode $oldMode
        if [catch {WaitForTaskToFinish \
                       -cavget "APScavget -list=L:RFG:KickerOptimizeRC.RUN -label" \
                       -waitLimit 120 \
                       -updateInterval 5 \
                       -checkExpression {$value > 0} } results] {
            APSMpReturn error "RFGUN_KickerValidation: Problem occurred while waiting for optimization done \n$results"
        }
    }
    set desc "$gun Kicker Validation Save 1"
    APSMpStep "Step 10: Make a non-routine SCR save of the LPL system.  Include the phrase \"$desc\""
    set snapshot1 [lindex [APSSCRMakeSnapshotFilename -machine LPL] 0]
    if [catch {APSSaveMachine -machine LPL -description "$desc" -snapshot $snapshot1} result] {
        APSMpReturn error "RFGUN_KickerValidation: $result"
    }
    
    APSMpStep "Step 11 : Configure L1 scope with configuration 2."
    if [catch {APSConfigureL1Scope -configuration 2} result] {
        APSMpReturn error "RFGUN_KickerValidation: $result"
    }
    set execMode manual
    APSMpStep "check the traces on the oscilloscope to make sure they look like Figure 2"
    # if [catch {APSTestCapture -gun $gun} result] {
    #	APSMpReturn error "RFGUN_KickerValidation: $result"
    # }
    set status "Press continue when checking of configuration 2 done."
    set answer [APSMultipleChoice [APSUniqueName .] -modal 1 \
                    -question "Please Verify that the traces on the ocsilloscope look like the reference Figure 2. Adjust the range and offset of the oscilloscope to maximize the resolution of that portion of the signal prior to the kicker firing (shown in red on the Figure). It may help to disable the kicker charge pulse for this step." \
                    -returnList {1 1 0} \
                    -labelList {Check-Is-OK-And-Continue Continue-Anyway Abort} ]
    if !$answer {
        APSMpReturn error "The trace of L1:SCOPE1 and L1CM2 are abnormal, quite validation!"
    }
    APSMpStep "Step 12: scan L1:CM1 and L1:CM2 monitor."
    if [catch {exec cavput -list=L1:CM1:measCurrentCM.SPD=1,L1:CM2:measCurrentCM.SPD=1 } result] {
	APSMpReturn error "RFGUN_KickerValidation: can not turn on the scanning for L1:CM1 and L1:CM2: $result"
    }
    after 1000
    if [catch {exec cavput -list=L1:CM1:measCurrentCM.AQWF=1,L1:CM2:measCurrentCM.AQWF=1} result] {
	APSMpReturn error "RFGUN_KickerValidation: can not start the scanning for L1:CM1 and L1:CM2: $result"
    }
    after 7000
    set execMode $oldMode
    APSMpStep "Step 12: Turn off the kicker charge pulse."
    if {$gun == "RG2"} {
        if [catch {APScavput -list=L1:RG2:KIK:chargeTrigC=0 -pend=30} result] {
            APSMpReturn error "Cannot enable the charge pulse: $result"
        }
    } else {
        if [catch {APScavput -list=L1:RG1:KIK:chargeTrigC=0 -pend=30} result] {
            APSMpReturn error "Cannot enable the charge pulse: $result"
        }
    }
    after 2000
    catch {exec medm -x -attach -macro RCPV=L:RFG:KickerLeakageRC ./sr/psApp/APSRunControlSingle.adl &}
    APSMpStep "Step 13: start the L1 leakage monitor."
    APSExecLog .l1leakage -height 30 -lineLimit 2048 -width 95 \
        -name "RF $gun L1 Leakage monitor" \
        -unixCommand "APSMonitorL1Leakage -gun $gun -runControlPV L:RFG:KickerLeakageRC -limit 0"  
    after 5000
    APSMpStep "Waiting for starting L1 leakage monitor."
    if [catch {WaitForTaskToFinish \
                   -cavget "APScavget -list=L:RFG:KickerLeakageRC.RUN -label" \
                   -waitLimit 12 \
                   -updateInterval 5 \
                   -checkExpression {$value==0} } results] {
        if {[APSPEMTKDialog .warningDialog -text "RFGun_KickerValidation: Problem occurred while waiting for starting L1 leakage monitor \n$results"] == 1} {
            APSMpReturn error "RFGun_KickerValidation: $results"
        }
    }
   
    APSMpStep "Start strip tool for monitoring L1:RFG:VLD:LeakageCC.VAL and L1:RFG:DC2ARF:VAL."
    set stripToolPID [exec StripTool /home/helios/oagData/linac/gunKickerValidation/inputFiles/stripool.cfg &]
    set execMode Manual
    APSMpStep "Press continue after leakage monitor starts running."
    set execMode $oldMode
    APSMpStep "Step 14: read the leakage."
    if [catch {ReadLeakage} leakage0] {
        APSMpReturn error "RFGun_KickerValidation: $leakage0"
    }
    set logFID ""
    if [catch {SetupLeakageLog -gun $gun} logFID] {
        APSMpReturn error "RFGun_KickerValidation: $logFID"
    }
    if [catch {WriteToLogFile -logFID $logFID -step 14 -gun $gun -worstCorrector unknown \
                   -leakage $leakage0 \
                   -description "leakage monitor started." } result] {
        APSMpReturn error "RFGun_KickerValidation: $result"
    }
    set status "The leakage now is ${leakage0}%."
    set onFailed 0
    set offFailed 0
    set offOnFailed 0
    set maxLeakage $leakage0
    if {$leakage0>3} {
        #the kicker has failed its validation and should be locked out
        set status "The kicker has failed its validation and should be locked out, go to step 28"
        set onFailed 1
    } else {
        set answer [APSMultipleChoice [APSUniqueName .] -modal 1 \
                        -question "Would you like to continue on sweeping corrector for gun validation, or skip it for script testing or abort the validation?" \
                        -returnList {Continue Skip Abort} \
                        -labelList {Continue Skip Abort} ]
        if {$answer=="abort"} {
            APSMpReturn error "$gun validataion was aborted."
        }
        if {$answer=="Continue"} {
            APSMpStep "Step 15. Sweep the correctors using sddsexperiment"
            if [catch {SweepCorrectors -inputDir $inputDir/inputFiles -gun $gun -kickerOff $kickerOff \
                           -tolerance $tolerance -postChange $postChange -stepSize $stepSize \
                           -numToAve $numToAve } results] {
                set answer [APSMultipleChoice [APSUniqueName .] -modal 1 \
                                -question "Error occurred during sweeping correctors, $results. Continue or Abort?" \
                                -returnList {1 0} \
                                -labelList {Continue Abort} ]
                if !$answer {
                    if [string length $logFID] {
                        close $logFID
                    }
                    APSMpReturn error "RFGun_KickerValidation: $results"
                }
                APSMpStep "Read leakage ..."
                if [catch {ReadLeakage} maxLeakage1] {
                    if [string length $logFID] {
                        close $logFID
                    }
                    APSMpReturn error $maxLeakage1
                }
                set worstCorrector NA
            } else {
                set maxLeakage1 [lindex $results 0]
                set worstCorrector [lindex $results 0]
            }
            if [catch {WriteToLogFile -logFID $logFID -step 15 -gun $gun \
                           -worstCorrector $worstCorrector \
                           -leakage $maxLeakage1 \
                           -description "sweep correctors with charge pulse disabled." } result] {
                if [string length $logFID] {
                    close $logFID
                }
                APSMpReturn error "RFGun_KickerValidation: $result"
            }
            set status "the maximum leakage obtained in step 15 is $maxLeakage1"
            APSMpStep "Step 16: the maximum leakage obtained in step 15 is $maxLeakage1"
            APSMpStep "Step 17: check if there is increase in leakage."
            set leakage1 $maxLeakage1
            if {$maxLeakage1>$leakage0} {
                APSMpStep "Step 18: Maximize the leakagae using optimize."
                set optConfig $inputDir/optimizeConfig/$gun/leakage
                catch {exec optimizeInterface -configuration $optConfig -run 1 &} optimizeID
                set status "Press continue when optimization is done."
                set execMode Manual
                APSMpStep "Wait for completion of optimization."
                set execMode $oldMode
                if [catch {WaitForTaskToFinish \
                               -cavget "APScavget -list=L:RFG:KickerOptimizeRC.RUN -label" \
                               -waitLimit 120 \
                               -updateInterval 5 \
                               -checkExpression {$value > 0} } results] {
                    if [string length $logFID] {
                        close $logFID
                    }
                    APSMpReturn error "RFGUN_KickerValidation: Problem occurred while waiting for optimization done \n$results"
                }
                APSMpStep "Read leakage ..."
                if [catch {ReadLeakage} leakage1] {
                    if [string length $logFID] {
                        close $logFID
                    }
                    APSMpReturn error "RFGUN_KickerValidation: $leakage1"
                }
                if [catch {WriteToLogFile -logFID $logFID -step 18 -gun $gun \
                               -worstCorrector unknown -leakage $leakage1 \
                               -description "Optimize leakage with charge pulse disabled."} result] {
                    if [string length $logFID] {
                        close $logFID
                    }
                    APSMpReturn error "RFGun_KickerValidation: $result"
                }
                set status "The maximum leakage in step 18 is: $leakage1"
                if {$maxLeakage1>$leakage1} {
                    set leakage1 $maxLeakage1
                }
            }
            if {$leakage1>$maxLeakage} {
                set maxLeakage $leakage1
            }
            APSMpStep "Step 19: Make a non-routine save of the LPL sytem."
            set snapshot2 [lindex [APSSCRMakeSnapshotFilename -machine LPL] 0]
            if [catch {APSSaveMachine -machine LPL -description "$gun Kicker Validation save 2" \
                           -snapshot $snapshot2} result] {
                if [string length $logFID] {
                    close $logFID
                }
                APSMpReturn error "RFGUN_KickerValidation: $result"
            }
            APSMpStep "Step 20: the maximum leakage now is $leakage1."
            if {$leakage1>3} {
                set status "Leakage is greater than 3%, the system has failed."
                set offFailed 1
            } else {
                APSMpStep "Step 21: Restore the RG and L1 power supplies from the SCR save made in Step 10."
                if [catch {RestoreRFGunAndL1Correctors -filename $snapshot1 -gun $gun} result] {
                    if [string length $logFID] {
                        close $logFID
                    }
                    APSMpReturn error "RFGUN_KickerValidation: $result"
                }
                if {$gun == "RG2"} {
                    if [catch {APScavput -list=L1:RG2:KIK:chargeTrigC=1 -pend=30} result] {
                        if [string length $logFID] {
                            close $logFID
                        }
                        APSMpReturn error "Cannot enable the charge pulse: $result"
                    }
                } else {
                    if [catch {APScavput -list=L1:RG1:KIK:chargeTrigC=1 -pend=30} result] {
                        if [string length $logFID] {
                            close $logFID
                        }
                        APSMpReturn error "Cannot enable the charge pulse: $result"
                    }
                }
		set kickerOff 0
                APSMpStep "Step 22: Turn on the kicker charge pulse.  Verify that you have good transmission to L1:P1 and a good beam spot on L1:FS1"
                set answer [APSMultipleChoice [APSUniqueName .] -modal 1 \
                                -question "Please Verify that you have good transmission to L1:P1 and a good beam spot on L1:FS1. Process Continue to continue validation or Abort to exit " \
                                -returnList {Continue Abort} \
                                -labelList {Continue Abort} ]
                if [string compare $answer "Abort"]==0 {
                    if [string length $logFID] {
                        close $logFID
                    }
                    APSMpReturn -error "RFGUN_KickerValidation: validation was canceled."
                }
                after 2000
                APSMpStep "Step 23: Sweep correctors."
                if [catch {SweepCorrectors -inputDir $inputDir/inputFiles -gun $gun -kickerOff $kickerOff \
                               -tolerance $tolerance -postChange $postChange -stepSize $stepSize \
                               -numToAve $numToAve} results] {
                    set answer [APSMultipleChoice [APSUniqueName .] -modal 1 \
                                    -question "Error occurred during sweeping correctors, $results. Continue or Abort?" \
                                    -returnList {1 0} \
                                    -labelList {Continue Abort} ]
                    if !$answer {
                        if [string length $logFID] {
                            close $logFID
                        }
                        APSMpReturn error "RFGun_KickerValidation: $results"
                    }
                    set worstCorrector unknown
                    if [catch {ReadLeakage} maxLeakage2] {
                        if [string length $logFID] {
                            close $logFID
                        }
                        APSMpReturn error "RFGUN_KickerValidation: $maxLeakage2"
                    }
                } else {
                    set maxLeakage2 [lindex $results 0]
                    set worstCorrector [lindex $results 1]
                }
                set status "the maximum leakage obtained in step 22 is $maxLeakage2"
                APSMpStep "Step 24: the maximum leakage obtained in step 23 is $maxLeakage2"
                APSMpStep "Step 25: check if there is increase in leakage."
                if [catch {WriteToLogFile -logFID $logFID -step 23 -gun $gun \
                               -leakage $maxLeakage2 -worstCorrector $worstCorrector \
                               -description "Sweep correctors with charge pulse enabled." } result] {
                    if [string length $logFID] {
                        close $logFID
                    }
                    APSMpReturn error "RFGun_KickerValidation: $result"
                }
                #decide to do this last optimization no matter what
                APSMpStep "Step 26: Optimize correctors."
                set optConfig $inputDir/optimizeConfig/$gun/leakage
                catch {exec optimizeInterface -configuration $optConfig -run 1 &} optimizeID
                set status "Press continue when optimization is done."
                set execMode Manual
                APSMpStep "Wait for completion of optimization."
                set execMode $oldMode
                if [catch {WaitForTaskToFinish \
                               -cavget "APScavget -list=L:RFG:KickerOptimizeRC.RUN -label" \
                               -waitLimit 120 \
                               -updateInterval 5 \
                               -checkExpression {$value > 0} } results] {
                    if [string length $logFID] {
                        close $logFID
                    }
                    APSMpReturn error "RFGUN_KickerValidation: Problem occurred while waiting for optimization done \n$results"
                }
                APSMpStep "Read leakage ..."
                if [catch {ReadLeakage} leakage2] {
                    if [string length $logFID] {
                        close $logFID
                    }
                    APSMpReturn error "RFGUN_KickerValidation: $leakage2"
                }
                if [catch {WriteToLogFile -logFID $logFID -step 26 -gun $gun -leakage $leakage2 \
                               -worstCorrector unknown \
                               -description "Optimize leakage with charge pulse on."} result] {
                    if [string length $logFID] {
                        close $logFID
                    }
                    APSMpReturn error "RFGun_KickerValidation: $result"
                }
                if {$maxLeakage2>$leakage2} {
                    set leakage2 $maxLeakage2
                }
                if {$leakage2>$maxLeakage} {
                    set maxLeakage $leakage2
                }
                APSMpStep "Step 27: Make a non-routine SCR save of LPL system."
                set snapshot3 [lindex [APSSCRMakeSnapshotFilename -machine LPL] 0]
                if [catch {APSSaveMachine -machine LPL -snapshot $snapshot3 \
                               -description "$gun Kicker Validation Save 3"} result] {
                    if [string length $logFID] {
                        close $logFID
                    }
                    APSMpReturn error "RFGUN_KickerValidation: $result"
                }
                if {$leakage2>3} {
                    set offOnFailed 1
                }
            }
        }
    }
    if [string length $logFID] {
        close $logFID
    }
    APSMpStep "Step 28: check the validation."   
    if {$onFailed} {
        bell
        APSMpStep "Step 29: Make a non-routine SCR save of LPL system."
        if [catch {APSSaveMachine -machine LPL \
                       -description "$gun Kicker Validation Save -- Failed "} result] {
            APSMpReturn error "RFGUN_KickerValidation: $result"
        }
        set message "$gun kicker validation failed with kicker pulse on."
        APSAlertBox .warning -errorMessage "$gun kicker validation failed with kicker pulse on."
    } elseif {$offFailed} {
        bell
        set status "$gun kicker failed its validation with the kicker pulse off, the kicker must be locked out and taken out of service."
        set messsage "$gun kicker failed its validation with the kicker pulse off"
        APSAlertBox .warning -errorMessage "$gun kicker failed its validation with the kicker pulse off, the kicker must be locked out and taken out of service. Please\na.Notify the on-shift Operations crew chief of the results of the kicker validation testing, and request that Operations lock out the failed kicker.\nb.Contact the CO-Injectors and the MCR Operations group leader, and inform them of the results of the testing."
    } elseif {$offOnFailed} {
        bell
        set message "$gun kicker passed its validation with the kicker pulse off, but failed validation with the kicker pulse on"
        set status "The kicker passed its validation with the kicker pulse off, but failed validation with the kicker pulse on"
        set answer [APSMultipleChoice [APSUniqueName .] -modal 1 \
                        -question "The kicker passed its validation with the kicker pulse off, but failed validation with the kicker pulse on. Please make choice:\nExit -- request the kicker be locked out with notification and exit.\nRevalidataion -- perform the \"Kicker Re-Validation With Restricted Range Power Supplies\"" \
                        -returnList {Exit Revalidation} \
                        -labelList {Exit Revalidataion} ]
        switch $answer {
            Exit {
                APSAlertBox .warning -errorMessage "$gun kicker passed its validation with the kicker pulse off, but failed validation with the kicker pulse onPlease\na.Notify the on-shift Operations crew chief of the results of the kicker validation testing, and request that Operations lock out the failed kicker.\nb.Contact the CO-Injectors and the MCR Operations group leader, and inform them of the results of the testing."
            }
            Revalidation {
                set execMode Manual
                APSMpStep "Waiting for re-validation, press continue when it is done."
                set execMode $oldMode
            }
        }
    } else {
        set message "$gun kicker validation passed."
        set status "$gun kicker validation passed."
        APSAlertBox .alert -errorMessage "$gun kicker validation passed!" -type done -name "Validation Passed"
    }
    set endTime [clock seconds]
    if [catch {LogValidationResult -gun $gun -startTime $startTime -endTime $endTime -maxLeakage $maxLeakage -result "$message"} result] {
        APSMpReturn error $result
    }
    #abort leakage monitor
    if [catch {APScavput -list=L:RFG:KickerLeakageRC.ABRT=1 -pend=30} result] {
        APSMpReturn error "RFGUN_KickerValidation: $result"
    }
    if [catch {exec sendScopeCommand L1:SCOPE1 ":ACQ:TYPE NORM"} result] {
        APSMpReturn error "RFGUN_KickerValidation: $result"
    }
    #turn channel2 off 
    if [catch {APScavput -list=L1:SCOPE1:chan2EnableBO=0 -pend=30} result] {
        APSMpReturn error "RFGUN_KickerValidation: $result"
    }
    catch {exec kill -9 $stripToolPID} result
    #restore scope setting to MEM #1
    if [catch {exec cavput -list=L1:SCOPE1:recallMO=1 -pend=30} result] {
        APSMpReturn error "RFGUN_KickerValidation: $result"
    }
    if [APSYesNoPopUp "Restore $gun to reference high charge state?"] {
	if [catch {LPL_Configure -gun $gun \
		       -PowerSupplies 1 \
		       -L1 1 -L2 1 -L3 1 -L4 1 -L5 1 \
		       -suspendL1 1 -suspendL2 1 -suspendL3 1 -suspendL4 1 -suspendL5 1 \
		       -startupLTP 0 -startupPAR 0 -startupPTB 0 -startupPARBypass 0 \
		       -modeVal Normal -turnOffDownKlystron 1 \
		       -SCRFile $scrDir/LPL-SysRefHC_${gun}_PAR_BS_325MeV.gz} result] {
	    APSMpReturn error "$result"
	}
    }
    APSInfoWindow .info -name "$gun validation done." -infoMessage "$gun Kicker validation done." -modal 1
    APSMpReturn ok
}

proc APSConfigureL1Scope {args} {
    set configuration 1
    set average 5
    APSStrictParseArguments {configuration average}
    set setupDir /home/helios/oagData/linac/gunKickerValidation
    
    global status setScopeCommandVar setScopeProcVar
    APSLogScriptAction -procedure ConfigureScope -action "Configuring L1:SCOPE1" \
        -parameters "?" -state ok
    set status "Configuring scope with configuration $configuration..."
    if [catch {APScavput -list=L1:SCOPE1:stopBO=1} result] {
        return -code error "ConfigureScope: $result"
    }
    set burtwbFile $setupDir/L1Scope1RGSetup${configuration}.snap
    set tmpRoot /tmp/[APSTmpString]
    if [catch {exec sddsbreak $burtwbFile -pipe=out -rowlimit=10 \
		   | sddssplit -pipe=in -binary -rootname=$tmpRoot} result] {
        return -code error "ConfigureScope: $result"
    }
    foreach file [lsort [glob -nocomplain ${tmpRoot}*.sdds]] {
        if [catch {exec sddscasr -restore $file} result] {
            return -code error "ConfigureScope: $result"
        }
        after 2000
        update
    }
    eval file delete [lsort [glob -nocomplain ${tmpRoot}*.sdds]]
    if [catch {exec putScopeSetup L1:SCOPE1 $setupDir/L1Scope1RGSetup${configuration}.sdds} result] {
        APSLogScriptAction -procedure ConfigureScope -action "Error: $result" \
	    -parameters "?" -state error
        return -code error "ConfigureScope: $result"
    } 
    APSWaitWithUpdate -waitSeconds 10 -updateInterval 1
    if [catch {APScavput -list=L1:SCOPE1:stopReadRunSQ.VAL=1 -pend=30} result] {
        return -code error "ConfigureScope: $result"
    }
    if {0} {
	if ![info exist setScopeCommandVar] {
	    if [pv linkw setScopeCommandVar L1:SCOPE1:sendCmdSO 30]==0 {
		return -code error "Unable link to L1:SCOPE1:sendCmdSO"
	    }
	}
	if ![info exist setScopeProcVar] {
	    if [pv linkw setScopeCommandVar L1:SCOPE1:sendCmdSI.PROC 30]==0 {
		return -code error "Unable link to L1:SCOPE1:sendCmdSI"
	    }
	}
    }
    set status "Configure1 L1 scope done."
}

proc SetGlobals {args} {
    global nameList logFID logFileString setupDir formatList  pvList unitsList
    global gunHeaterPowerThreshold changeLogPID L1CM2Calibration RGCMCalibration runControlPV
  
    set changeLogPID ""
    set logFID ""
    set logFileString ""
    set nameList [list HeaterPower KickerEnabled \
                    L1KlystronPower GunCMMax L1CM2Max GunCMInteg2 L1CM2Integ1 L1CM2Integ2 Leakage]
    set pvList [list "" "" "" "" "" L1:RFG:VLD:GunCMInt2 L1:RFG:VLD:L1CM2Int1 L1:RFG:VLD:L1CM2Int2 L1:RFG:VLD:LeakageCC]
    set formatList [list %.5f %.0f %.3g %.4f %.4f %.4f %.4f %.4f %.4f]
    set unitsList [list W "binary" W mA mA mA*ns mA*ns mA*ns "%"]
    set setupDir /home/helios/oagData/linac/gunKickerValidation
    set gunHeaterPowerThreshold(RG1) 21
    set gunHeaterPowerThreshold(RG2) 12
    set L1CM2Calibration(RG1) 0.41
    set L1CM2Calibration(RG2) 0.41
    set RGCMCalibration(RG1) 1.1
    set RGCMCalibration(RG2) 1.1
    set runControlPV L:RFG:KickerLeakageRC
}

proc APSTestCapture {args} {
    set gun RG2
    set nameList ""
    set setupDir /home/helios/oagData/linac/gunKickerValidation
    APSStrictParseArguments {gun nameList setupDir}

    if ![string length $nameList] {
	set nameList [list HeaterPower KickerEnabled \
			  L1KlystronPower GunCMMax L1CM2Max GunCMInteg2 L1CM2Integ1 L1CM2Integ2 Leakage]
    }
    APSLogScriptAction -procedure APSTestCapture -action "Testing L1:SCOPE1 capture" \
      -parameters "?" -state ok

    set gun1 [exec cavget -list=L1:RFG:RF:SW2:positionMI]
    if {$gun1 != $gun} {
        return -code error "APSTestCapture: $gun is not in operation!"
    }
    APSDateBreakDown -dayVariable day -monthVariable month -julianDayVariable jday \
	-yearVariable year -twoDigitYear 0 -leadingZeros 0
    set fileName [APSNextGenerationedName -name \
		      $setupDir/${gun}Data/Test-[format %04d-%03d-%02d%02d $year $jday $month $day].0000 \
		      -newFile 1 -separator .]
    if [catch {APSGetL1ScopeWaveforms -fileName $fileName -gun $gun} result] {
	return -code error $result
    }
    if [catch {APSProcessL1ScopeWaveforms -fileName $fileName -gun $gun \
                 -nameList $nameList } dataList] {
        return -code error "APSTestCapture: Problem acquiring data: $dataList"
    } else {
        exec sddsplot "-topline=test figure of configuration 1" \
	    -layout=1,2 -title=@TimeStamp \
	    -same=x,global -graph=line,vary -factor=yMultiplier=-1 \
	    -column=t,GunCM $fileName.proc -end \
	    -column=t,L1CM2 -filter=col,t2,-1e6,0 $fileName.proc \
	    -column=t,L1CM2 -filter=col,t1,-1e6,0  $fileName.proc &
    }
}

proc ProcessExpDataAndSetCorrector {args} {
    set filename ""
    set corrector ""
    APSStrictParseArguments {filename corrector}
    if ![string length $filename] {
        return -code error "ProcessExpDataAndSetCorrector: filename is not given!"
    }
    APSAddToTmpFileList -ID sweepcorr -fileList $filename.proc
    if [catch {exec sddsprocess $filename -pipe=out \
                 -process=L1Leakage,max,maxPoint,functionOf=$corrector,position \
                 -process=L1Leakage,min,MinLeakage \
                 -process=L1Leakage,max,MaxLeakage \
                 | sddsprocess -pipe=in $filename.proc \
                 "-define=par,deltaLeakage,MaxLeakage MinLeakage -" } result] {
        return -code error "ProcessExpDataAndSetCorrector: $result"
    }
    if [catch {exec sdds2stream $filename.proc -par=deltaLeakage} delta] {
        return -code error "ProcessExpDataAndSetCorrector: $delta"
    }
    if [catch {exec sdds2stream $filename.proc -par=MaxLeakage} maxLeakage] {
        return -code error "ProcessExpDataAndSetCorrector: $maxLeakage"
    }
    if {$delta<0.1 || $maxLeakage<0.1} {
        return "$maxLeakage $delta"
    }
    if [catch {exec sdds2stream $filename.proc -par=maxPoint} maxPoint] {
        return -code error "ProcessExpDataAndSetCorrector: $maxPoint"
    }
    if [catch {APScavput -list=$corrector=$maxPoint -pend=30} result] {
        retur -code error "ProcessExpDataAndSetCorrector: $result"
    }
    set pv [regsub {CurrentAO} $corrector {CurrentAI}]
    set pv [regsub {SetDacCurrentC} $pv {MeasCurrentM}]
    set low [expr $maxPoint - 0.05]
    set upper [expr $maxPoint + 0.05]
    catch {exec cawait -waitFor=$pv,lowerLimit=$low,upperLimit=$upper \
             -interval=2 -timeLimit=30 }
    return "$maxLeakage $delta"
}

proc RestoreRFGunAndL1Correctors {args} {
    set filename ""
    set gun ""
    set scrDir /home/helios/oagData/SCR/snapshots/LPL
    APSStrictParseArguments {filename gun}
    set snapshot $scrDir/$filename
    if ![file exist $snapshot] {
        set snapshot $scrDir/${filename}.gz
        if ![file exist $snapshot] {
            return -code error "RestoreRFGunAndL1Correctors: snapshot $filename does not exist!"
        }
    }
    set tmpRoot /tmp/[APSTmpString]
    set corrFile /home/helios/oagData/linac/gunKickerValidation/inputFiles/${gun}Correctors.sdds
    
    APSAddToTmpFileList -ID kickerValidation -fileList "$tmpRoot.restore$gun $tmpRoot.log$gun"
    if [catch {exec sddsselect $snapshot $corrFile \
                 $tmpRoot.restore$gun -match=ControlName } result] {
        return -code error "RestoreRFGunAndL1Correctors: $result"
    }
    set logFile $tmpRoot.log$gun
    if [catch {exec sddscasr -restore $tmpRoot.restore$gun} result] {
        return -code error "RestoreRFGunAndL1Correctors: $result"
    }
    return $tmpRoot.restore$gun
}

proc SweepCorrectors {args} {
    set setupDir /home/helios/oagData/linac/gunKickerValidation
    set inputDir /home/helios/oagData/linac/gunKickerValidation/inputFiles
    set stepSize 0.1
    set postChange 3
    set numToAve 1
    set gun ""
    set tolerance 0.05
    set kickerOff 0
    APSStrictParseArguments {inputDir stepSize postChange gun numToAve tolerance kickerOff}
    global status RFGun_KickerValidation
    if ![string length $gun] {
        return -code error "RF gun is not given!"
    }
    switch $gun {
	RG2 {
	    set threshold 0.1
	}
	RG1 {
	    set threshold 0.3
	}
    }
    if $kickerOff {
	set kickerLow -0.5
	set kickerUpper 0.5
        set kickerOn 0
    } else {
	set kickerLow 0.5
	set kickerUpper 1.5
        set kickerOn 1
    }
    set tmpRoot /tmp/[APSTmpString]${gun}
    set inputfile $inputDir/KickerValidationTemplate.exp
    set monFile $inputDir/${gun}KickerValidation.mon
    set corrFile $inputDir/${gun}Correctors.sdds
    if [catch {exec sddscasr -save $corrFile $tmpRoot.corr} result] {
        return -code error "SweepCorrectors: $result"
    }
    if [catch {exec replaceText $monFile $tmpRoot.mon "-orig=<lower>,<upper>,<kickerOn>" -repl=$kickerLow,$kickerUpper,$kickerOn} result] {
	return -code error "SweepCorrectors: $result"
    }
    APSAddToTmpFileList -ID 1 -fileList $tmpRoot.corr
    set correctorList [exec sdds2stream -col=ControlName $tmpRoot.corr]
    set valueList [exec sdds2stream -col=ValueString $tmpRoot.corr]
    global scanDone LowerLimit UpperLimt OrigValue
    global drvl drvh
    foreach corr $correctorList val $valueList {
        if [pv linkw "drvl drvh" "${corr}.DRVL ${corr}.DRVH"] {
            return -code error "Unable to connect to ${corr}.DRVL and/or ${corr}.DRVH"
        }
        set LowerLimit($corr) $drvl
        set UpperLimit($corr) $drvh
        set OrigValue($corr) $val
    }
    set maxLeakage 0
    set worstCorrector ""
    set worstCorrFile ""
    set delta 0
    global Tolerance PostChange dialogBoxChoice
    set Tolerance $tolerance
    set PostChange $postChange
    set correctors [llength $correctorList]
    set outputRoot $setupDir/${gun}Data/[exec date +%Y-%m%d-%H%M%S]
    for {set index 0} {$index<$correctors} {incr index} {
        if $RFGun_KickerValidation(abort) {
            set RFGun_KickerValidation(abort) 0
            return -code error "Sweeping correctors was requested to abort."
        }
        if [catch {APScavget -list=L1:LL:lockRfCtrlBI -numeric -pend=30} L1on] {
            return -code eorr $result
        }
        if !$L1on {
            APSAlertBox .error -errorMessage "L1 rf is tripped off, please restart it and continue sweeping experiment."
            set index [expr $index -1]
            if [string length $output] {
                file delete -force $output
            }
            continue
        }
        if [catch {APScavget -list=L:RFG:KickerLeakageRC.RUN -pend=30} running] {
            return -code error "$running"
        }
        if {$running=="?"} {
            return -code error "unable to read L:RFG:KickerLeakageRC.RUN!"
        }
        if {!$running} {
            APSAlertBox .error -errorMessage "L1 Leakage Monitor is not running! Please resume it using the medm screen if it was suspended, otherwise, use APSMpRFGun_LeakageMonitor pem to start it."
            set index [expr $index -1]
            if [string length $output] {
                file delete -force $output
            }
            continue
        }
        set corrector [lindex $correctorList $index]
        set low $LowerLimit($corrector)
        set upper $UpperLimit($corrector)
        set origVal $OrigValue($corrector)
        set readback [regsub {CurrentAO} $corrector {CurrentAI}]
	set readback [regsub {SetDacCurrentC} $readback {MeasCurrentM}]
        set steps [format %.0f [expr ($upper-$low)/$stepSize +1]]
        
        if [catch {APScavput -list=$corrector=$low -pend=30} result] {
            return -code error "SweepCorrectors: $result"
        }
        catch {exec cawait -waitFor=$readback,lowerLimit=[expr $low - $Tolerance],upperLimit=[expr $low + $Tolerance] \
                 -interva=2 -timeLimit=200}
        set output $outputRoot.$corrector
        if [file exist $output] {
            file delete -force $output
        }
        APSAddToTmpFileList -ID sweepcorr -fileList "$output $output.proc"
        set macro -macro=postChange=$PostChange,steps=$steps,initialValue=$low,finalValue=$upper,numToAve=$numToAve,corrector=$corrector,monFile=$tmpRoot.mon,readback=$readback,tolerance=$Tolerance
        set scanDone 0
        APSExecLog .sweepCorrectors -width 80 \
          -unixCommand "sddsexperiment $inputfile $output -verbose $macro" \
          -callback "set scanDone done" \
          -abortCallback "set scanDone abort" \
          -cancelCallback "set scanDone cancel"
        if !$scanDone {
            tkwait variable scanDone
        }
        set dialogBoxChoice 0
        if [string compare $scanDone "done"]==0 {
            if {![file exist $output] || [exec sdds2stream $output -rows=bar]==0} {
                APSAlertBox .error1 -errorMessage "Error occurred during processing experiment output;\n It may be because that the tolerance is too small and/or  postChange is too short for the readback to reach the setpoint of $corrector. Provide new tolerance and postChange, press Ok button in following dialog box to rescan this corrector or cancel to exit."
                APSDialogBox .error -name "Reset Tolerance" \
                  -okCommand "set dialogBoxChoice ok" \
                  -cancelCommand "set dialogBoxChoice cancel"
                APSLabeledEntry .tol -parent .error.userFrame -label "Tolerance: (A)" \
                  -textVariable Tolerance -width 10
                APSLabeledEntry .post -parent .error.userFrame -label "Post Change Pause: (s)" \
                  -textVariable PostChange -width 10 \
                  -contextHelp "The pause time after changing correctors before taking measurement."
                
                update
                tkwait window .error
                update
                if [string compare $dialogBoxChoice "cancel"]==0 {
                    if [catch {ASPcavput -list=$corrector=$origVal -pend=30} result] {
                        return -code error $result
                    }
                    return -code error "Error occurred during scaning $corrector, and rescan request was cancelled."
                }
                set index [expr $index -1]
                file delete -force $output
                continue
            }
            set needScanCorrList ""
            for {set i $index} {$i<$correctors} {incr i} {
                lappend needScanCorrList [lindex $correctorList $i]
            }
            if [catch {TestCorrectors -gun $gun -needScanCorrList "$needScanCorrList"} newList] {
                return -code error "SweepCorrectors: $newList"
            }
            if [llength $newList] {
                set correctorList $newList
                set correctors [llength $newList]
                set index -1
                continue
            }
            if [catch {exec sddsprocess $output -pipe=out \
                         -process=L1Leakage,max,maxPoint,functionOf=$corrector,position \
                         -process=L1Leakage,min,MinLeakage \
                         -process=L1Leakage,max,MaxLeakage \
                         | sddsprocess -pipe=in $output.proc \
                         "-define=par,deltaLeakage,MaxLeakage MinLeakage -" } result] {
                return -code error "SweepCorrectors: $result"
            }
            set maxLeakage1 [exec sdds2stream $output.proc -par=MaxLeakage]
            set delta1 [exec sdds2stream $output.proc -par=deltaLeakage]
            if {$delta1<$threshold || $maxLeakage1<$threshold } {
                set setValue $origVal
            } else {
                set setValue [exec sdds2stream $output.proc -par=maxPoint]
            }
            if {$maxLeakage1>$maxLeakage} {
                set maxLeakage $maxLeakage1
            }
            if {$delta1>$delta} {
                set delta $delta1
                set worstCorrector $corrector
                set worstCorrFile $output.proc
            }
            file delete -force $output
            #set corrector to setValue
            if [catch {APScavput -list=$corrector=$setValue -pend=30} result] {
                return -code error "SweepCorrectors: $result"
            }
            catch {exec cawait -waitFor=$readback,lowerLimit=[expr $setValue - 0.05],upperLimit=[expr $setValue + 0.05] -interval=2 -timeLimit=200}
        } else {
            if [catch {ASPcavput -list=$corrector=$origVal -pend=30} result] {
                return -code error $result
            }
            return -code error "SweepCorrectors: Sweeping correctors was canceled."
        }
        set Tolerance $tolerance
    }
    if [string length $worstCorrFile] {
        if [catch {exec sddsprocess $worstCorrFile $outputRoot.worstcorrector \
                       -reprint=par,WorstCorrector,$worstCorrector} result] {
            return -code error "SweepCorrectors: $result"
        }
    }
    return [list $maxLeakage $worstCorrector]
}



#Procedure for Kicker Re-Validation with Restricted-Range Power Supplies
#If, after executing the RFGUN_KickerValidataion, the kicker passes validation 
#with the kicker pulse off, but fails its validation (i.e. leakage current 
#is greater than 3%), with the kicker pulse on, the only available options are:
#    * remove the kicker (and associated gun) from service, or
#    * restrict the gun-to-alpha beamline power supplies such that 
#       the kicker will pass validation with the imposed restrictions.

#It must be understood that the second option is an interim measure only, 
#intended to permit continued safe operation of the APS injector system 
#in a restricted fashion until the fundamental cause of the leakage can 
#be determined and corrected.  If, following this procedure, the kicker
# system leakage exceeds 3% even with power supply limit restrictions, 
#the kicker must be removed from service until it is repaired and revalidated.

#This portion of the procedure assumes that the RFGUN_KickerValidatiaon has been completed, 
#and that the kicker has passed validation with the kicker pulse off.
proc RFGun_KickerReValidation {args} {
    set snapshot3 ""
    set gun ""
    set badCorrectors ""
    APSStrictParseArguments {snapshot3 gun badCorrectors}

    if ![string length $snapshot3] {
        return -code error "The saved SCR snapshot 3 in RFGUN_KickerValidation is not given."
    }
    if ![file exist $snapshot3] {
        return -code error "The SCR snapshot 3 in RFGUN_KickerValidation does not exist."
    }
    set corrFile /home/helios/oagData/linac/gunKickerValidation/inputFiles/${gun}Correctors.sdds
   
    if ![llength $badCorrectors] {
        set badCorrectors [exec sdds2stream -col=ControlName $corrFile]
    }
    APSMpStep "Step 1: Restore the SCR snapshot3"
    if [catch {RestoreRFGunAndL1Correctors -filename $snapshot3 -gun $gun} restoreFile] {
        APSMpReturn error "RFGUN_KickerReValidation: $restoreFile"
    }
    after 2000
    APSMpStep "Step 2: determine the power supply, which resulted in the greatest increase in the leakage current."
    set stepSize 0.1
    set tmpRoot /tmp/[APSTmpString]
    APSAddToTmpFileList -ID revalidation -fileList "$tmpRoot.1"
    if [catch {exec sddsxref $corrFile $restoreFile \
                 -match=ControlName -take=ValueString $tmpRoot.1} result] {
        APSMpReturn error "RFGUN_KickerReValidation: $result"
    }
    set corrList [exec sdds2stream -col=ControlName $tmpRoot.1]
    set valList [exec sdds2stream -col=ValueString $tmpRoot.1]
    
    if [catch {APScavget -list=L1:RFG:VLD:LeakageCC \
                 -repeat=number=5,pause=1,average -pend=30} leakage0] {
        APSMpReturn error "RFGUN_KickerReValidation: $leakage0"
    }
    APSMpStep "Step 3: Adjust the power supply setpoint so as to lower the leakage current to below 2.5%."
    foreach corrector $badCorrectors {
        
    }

}

proc ChangeCorrLimits {args} {
    set correctorList ""
    set lowerLimitList ""
    set upperLimitList ""
    set gun ""
    APSStrictParseArguments {correctorList lowerLimitList upperLimitList gun}
    set inputDir /home/helios/oagData/linac/gunKickerValidation
    set file1 $inputDir/inputFiles/${gun}Correctors.sdds
    set file2 $inputDir//optimizeConfig/$gun/current/variables
    set file3 $inputDir//optimizeConfig/$gun/leakage/variables
    set tmpRoot /tmp/[APSTmpString]GunLimit
    APSAddToTmpFileList -ID changLimit -fileList "$tmpRoot.1 $tmpRoot.2 $tmpRoot.3"
    if [catch {exec sddsmakedataset -pipe=out \
                 -col=ControlName,type=string -data=[join $correctorList ,] \
                 -col=LowerLimit1,type=double -data=[join $lowerLimitList ,] \
                 -col=UpperLimit1,type=double -data=[join $upperLimitList ,] \
                 | sddssort -pipe=in $tmpRoot.1 -col=ControlName -unique} result] {
        return -code error "ChangeCorrLimits: $result"
    }
    if [catch {exec sddsxref $file1 $tmpRoot.1 -pipe=out -match=ControlName -pipe=out -nowarnings \
                  -take=LowerLimit1,UpperLimit1 \
                 | sddsprocess -pipe=in $tmpRoot.3 \
                 "-define=col,LowerChanged,LowerLimit LowerLimit1 == ? 0 : 1 $ " \
                 "-define=col,UpperChanged,UpperLimit UpperLimit1 == ? 0 : 1 $ " \
                 -process=LowerChanged,max,lowerChanged \
                 -process=UpperChanged,max,upperChanged  } result] {
        return -code error "ChangeCorrLimits: $result"
    }
    set lowerChanged [exec sdds2stream -par=lowerChanged $tmpRoot.3]
    set upperChanged [exec sdds2stream -par=upperChanged $tmpRoot.3]
    if {$lowerChanged || $upperChanged} {
        if [catch {exec sddsxref $file1 $tmpRoot.1 -match=ControlName -pipe=out -nowarnings -fillIn \
                     -take=LowerLimit1,UpperLimit1 \
                     | sddsprocess -pipe \
                     "-define=col,LowerChanged,LowerLimit1 0 == ? 0 : 1 $ " \
                     "-define=col,UpperChanged,UpperLimit1 0 == ? 0 : 1 $ " \
                     "-define=col,LowerNotChanged,LowerChanged 0 > ? 0 : 1 $ " \
                     "-define=col,UpperNotChanged,UpperChanged 0 > ? 0 : 1 $ " \
                     "-redefine=col,LowerLimit,LowerLimit LowerNotChanged * LowerLimit1 LowerChanged * +" \
                     "-redefine=col,UpperLimit,UpperLimit UpperNotChanged * UpperLimit1 UpperChanged * +" \
                     | sddsconvert -pipe=in $tmpRoot.2 -del=col,*1,*Changed } result] {
            return -code error "ChangeCorrLimits: $result"
        }
        for {set i 1} {$i<=3} {incr i} {
            set file [set file$i]
            set files [glob -nocomplain ${file}.????]
            set len [llength $files]
            set index [format %04d [expr $len + 1]]
            exec cp $file ${file}.$index
            exec cp $tmpRoot.2 $file
        }
    }
    APSDeleteTmpFileList -ID changeLimit
}

proc ReadLeakage {args} {
    if [catch {APScavget -list=L:RFG:KickerLeakageRC.RUN -pend=30} running] {
        return -code error "ReadLeakage: $running"
    }
    if {$running=="?"} {
        return -code error "ReadLeakage: unable to read L:RFG:KickerLeakageRC.RUN!"
    }
    if {!$running} {
        return -code error "L1 Leakage Monitor is not running, leakage is not being updated!"
    }
    if [catch {APScavget -list=L1:RFG:VLD:LeakageCC -pend=30 \
                 -repeat=number=4,pause=1,average} leakage] {
        return -code error "ReadLeakage: $leakage"
    }
    if {$leakage=="?"} {
        return -code error "ReadLeakage: unable to read value of L1:RFG:VLD:LeakageCC"
    }
    return $leakage
}


proc APSGetL1ScopeWaveforms {args} {
    set fileName ""
    set gun RG2
    set setupDir /home/helios/oagData/linac/gunKickerValidation
    set calFactor ""
    set rgCal ""
    APSStrictParseArguments {fileName gun setupDir calFactor rgCal}
    
    if {![string length $calFactor] } {
	set calFactor 0.41
    }
    if ![string length $rgCal] {
	set rgCal 1.1
    }
    
    if [catch {APScavput -list=L1:SCOPE1:stopReadRunSQ.SCAN=Passive
        after 500
        APScavput -list=L1:SCOPE1:stopReadRunSQ.VAL=1
        after 500
        exec sddswmonitor $fileName -erase -steps=1 \
                 -scalars=$setupDir/L1Scope1Scalars.sdds \
                 -pvname=L1:SCOPE1:scaledTimeAxisWF,L1:SCOPE1:chan2ScaledWaveWF,L1:SCOPE1:chan4ScaledWaveWF
        exec sddsprocess -nowarning $fileName $fileName.1 \
                 "-define=column,t,L1:SCOPE1:scaledTimeAxisWF,units=ns" \
                 "-define=column,L1CM2,L1:SCOPE1:chan2ScaledWaveWF Chan2VPerDiv * Chan2Offset + chs 1e3 * $calFactor *,units=mA" \
                 "-define=column,GunCM,L1:SCOPE1:chan4ScaledWaveWF Chan4VPerDiv * Chan4Offset + chs 1e3 * $rgCal *,units=mA"
        file delete $fileName~ } result] {
        APSLogScriptAction -procedure APSGetL1ScopeWaveforms -action "Error: $result" \
          -parameters "?" -state error
        return -code error "APSGetL1ScopeWaveforms: $result"
    }
    exec mv $fileName.1 $fileName
}

proc APSProcessL1ScopeWaveforms {args} {
    set fileName ""
    set gun ""
    set nameList ""
    APSStrictParseArguments {fileName gun nameList pvList}
    
    if [catch {exec sddsprocess $fileName -pipe=out \
                 -process=*CM*,ave,%sBaseline,head=150 \
                 "-redefine=col,%s,%s %sBaseline -,select=*CM*,units=V" \
                 | sddsprocess -pipe \
                 -process=*CM*,max,%sMax \
                 -process=*CM*,max,%sMaxPos,func=t,position \
                 -process=t,spread,tSpread \
                 "-define=parameter,dt,tSpread n_rows 1 - /,units=ns" \
                 "-define=parameter,tCutoff1,GunCMMaxPos 100 - " \
                 "-define=column,t1,t tCutoff1 -" \
                 "-define=parameter,tCutoff2,GunCMMaxPos 100 + " \
                 "-define=column,t2,t tCutoff2 -" \
                 -process=L1CM2,sum,L1CM2Sum1,func=t1,lower=-700,upper=0 \
                 -process=L1CM2,sum,L1CM2Sum2,func=t2,lower=-900,upper=0 \
                 -process=GunCM,sum,GunCMSum2,func=t2,lower=-900,upper=0 \
                 "-define=parameter,L1CM2Integ1,L1CM2Sum1 dt *,units=V ns" \
                 "-define=parameter,L1CM2Integ2,L1CM2Sum2 dt *,units=V ns" \
                 "-define=parameter,GunCMInteg2,GunCMSum2 dt *,units=V ns" \
                 "-define=parameter,Leakage,L1CM2Integ1 GunCMInteg2 / 100 *,units=%" \
                 | tee $fileName.proc \
                 | sdds2stream -param=${gun}[join $nameList ,] -pipe} dataList] {
        APSLogScriptAction -procedure APSProcessL1ScopeWaveforms -action "Error: $dataList" \
          -parameters "?" -state error
        return -code error "APSProcessL1Waveforms: $dataList"
    }
    return "$dataList"
}

proc PlotReference {args} {
    set gun RG2
    APSStrictParseArguments {gun}
    
    set dataDir /home/helios/oagData/linac/gunKickerValidation/${gun}Data
    set file1 $dataDir/Test-2002-050-0219.0002.proc
    set file2 $dataDir/Test-2002-050-0219.0004.proc
    exec sddsplot "-topline=Figure 1 -- typical figure for configuration 1" \
	-layout=1,2 -title=@TimeStamp \
	-same=x,global -graph=line,vary -factor=yMultiplier=-1 \
	-column=t,GunCM $file1 -end \
	-column=t,L1CM2 -filter=col,t2,-1e6,0 $file1 \
	-column=t,L1CM2 -filter=col,t1,-1e6,0  $file1 &
    exec sddsplot "-topline=Figure 2 -- typical figure for configuration 2" \
	-layout=1,2 -title=@TimeStamp \
	-same=x,global -graph=line,vary -factor=yMultiplier=-1 \
	-column=t,GunCM $file1 -end \
	-column=t,L1CM2 -filter=col,t2,-1e6,0 $file2 \
	-column=t,L1CM2 -filter=col,t1,-1e6,0  $file2 &
}

proc LogValidationResult {args} {
    set gun ""
    set maxLeakage ""
    set startTime ""
    set endTime ""
    set result ""
    set setupDir /home/helios/oagData/linac/gunKickerValidation
    APSStrictParseArguments {gun maxLeakage startTime endTime result}
  
    global env
    set valLogID ""
    if ![string length $gun] {
        return -code error "SetupValidationLog: RG gun is not provided!"
    }
    set filename $setupDir/${gun}Data/validation.log
    if [file exist $filename] {
        if [catch {open $filename "a+"} valLogID] {
            return -code error "SetupValidationLog: $valLogID"
        }
    } else {
        if [catch {open $filename w} valLogID] {
            return -code error $valLogID
        }
        puts $valLogID "SDDS1"
        puts $valLogID "&column name=User type=string &end"
        puts $valLogID "&column name=StartTimeStamp type=string &end"
        puts $valLogID "&column name=EndTimeStamp type=string &end"
        puts $valLogID "&column name=StartTime type=double &end"
        puts $valLogID "&column name=EndTime type=double &end"
        puts $valLogID "&column name=MaximumLeakage type=double &end"
        puts $valLogID "&column name=ValidationResult type=string &end"
        puts $valLogID "&data mode=ascii no_row_counts=1 &end"
    }
    puts $valLogID "$env(USER) \"[clock format $startTime]\" \"[clock format $endTime]\" $startTime $endTime $maxLeakage \"$result\""
    close $valLogID
}
proc SetupLeakageLog {args} {
    set gun ""
    set setupDir /home/helios/oagData/linac/gunKickerValidation
    APSStrictParseArguments {gun}
    
    if ![string length $gun] {
        return -code error "SetupLeakageLog: RG gun is not provided!"
    }
    APSDateBreakDown -dayVariable day -monthVariable month -julianDayVariable jday \
      -yearVariable year -twoDigitYear 0 -leadingZeros 0
    set fileName [APSNextGenerationedName -name \
                    $setupDir/${gun}Data/LeakageLog-[format %04d-%03d-%02d%02d $year $jday $month $day].0000 \
                    -newFile 1 -separator .]
    set corrFile $setupDir/inputFiles/${gun}Correctors.sdds
    set correctors [exec sdds2stream -col=ControlName $corrFile]
    set logFID ""
    if [catch {open $fileName w} logFID] {
        return -code error $logFID
    }
    puts $logFID "SDDS1"
    puts $logFID "&column name=ValidationStep type=long &end"
    puts $logFID "&column name=StepDescription type=string &end"
    puts $logFID "&column name=Time type=double units=s &end"
    puts $logFID "&column name=Leakage type=double &end"
    puts $logFID "&column name=WorstCorrector type=string &end"
    foreach corr $correctors {
        puts $logFID "&column name=$corr type=double units=A &end"
    }
    puts $logFID "&data mode=ascii no_row_counts=1 &end"
    flush $logFID
    return $logFID
}

proc WriteToLogFile {args} {
    set step ""
    set logFID ""
    set gun ""
    set leakage 0.0
    set worstCorrector unknown
    set description unknown
    APSStrictParseArguments {step logFID gun leakage worstCorrector description} 
    
    if ![string length $step] {
        return -code error "WriteToLogFile: validation step is not given.!"
    }
    if ![string length $logFID] {
        return -code error "WriteToLogFile: log file ID is not provided.!"
    }
    if ![string length $gun] {
        return -code error "WriteToLogFile: RF gun is not provided.!"
    }
    
    set setupDir /home/helios/oagData/linac/gunKickerValidation
    set corrFile /home/helios/oagData/linac/gunKickerValidation/inputFiles/${gun}Correctors.sdds
    set tmpfile /tmp/[APSTmpString].$gun.corr
    APSAddToTmpFileList -ID kickervalidation -fileList $tmpfile
    if [catch {exec sddscasr -save $corrFile $tmpfile} result] {
        return -code error "WriteToLogFile: $result"
    }
    set correctors [exec sdds2stream $tmpfile -col=ControlName]
    set values [exec sdds2stream $tmpfile -col=ValueString]
    if [catch {APScavget -list=L1:RFG:VLD: -list=LeakageCC,GunCMInt2,L1CM2Int1,L1CM2Int2 \
                 -pend=30 -repeat=number=5,pause=1,average } valueList] {
        return -code error "WriteToLogFile: $valueList"
    }
    puts $logFID "[concat $step \"$description\" [clock seconds] $leakage \"$worstCorrector\" [join $values]]"
    flush $logFID
    return $logFID
}

proc GetL1L2DriveKryston {args} {
    if [catch {APScavget -list=LRFSCS:MODSEL: -list=0,1,2,3,4 -numeric -pend=30} valueList] {
        return -code error "GetL1L2DriveKryston: $valueList"
    }
    #1/9/2024 changed to allow L3 is enabled per Greg's request, Shang
    if [lindex $valueList 0] {
        #L1 is driven by K1, L2 is driven by K2
        return "L1 L2"
    } elseif [lindex $valueList 1] {
        #K1 is down, L1 is driven by K3, L2 is driven by K2
        return "L3 L2"
    } elseif [lindex $valueList 2] {
        #k2 is down, L1 is driven by K1, L2 is driven by K3
        return "L1 L3"
    } elseif [lindex $valueList 4] {
        #L1 is driven by K1, L2 is driven by K2
        return "L1 L2"
    } else {
        return -code error "GetL1L2DriveKryston: error: none of the LRFSCS mode is selected."
    }
}

proc GetRFGunSelection {args} {
    if [catch {APScavget -list=LRFSCS:GUNSEL: -list=0,1,3 -numeric -pend=30} valueList] {
        return -code error "GetRFGunSelection: $valueList"
    }
    if [lindex $valueList 0] {
        return RG1
    } elseif [lindex $valueList 1] {
        return RG2
    } elseif [lindex $valueList 2] {
        return PG1
    } else {
        return -code error "GetRFGunSelection: error: none of the LRFSCS gun is selected."
    }
}

#this procedure is called after each corrector scan to test if any correctors tripped off
proc TestCorrectors {args} {
    set gun ""
    set needScanCorrList ""
    APSStrictParseArguments {gun needScanCorrList}
    set inputDir /home/helios/oagData/linac/gunKickerValidation/inputFiles
    set testFile $inputDir/${gun}Correctors.test
    
    set tmpfile /tmp/[APSTmpString].$gun.test
    APSAddToTmpFileList -ID 1 -fileList $tmpfile
    if [catch {exec sddscasr $testFile -save -pipe=out \
                 | sddsprocess -pipe -scan=col,Value,ValueString,%lf \
                 -reedit=col,ControlName,%/:StatusCC/:CurrentAO/ \
                 | sddsprocess -pipe=in $tmpfile -nowarnings \
                 "-test=col,Value LowerLimit < Value UpperLimit > ||" } result] {
        return -code error $result
    }
    set rows [exec sdds2stream $tmpfile -rows=bar]
    if $rows {
        set badCorrectors [exec sdds2stream $tmpfile -col=ControlName]
        global LowerLimit UpperLimit
        APSDialogBox .newLimit -name "Reset Scan Limits" \
          -okCommand "set dialogBoxChoice ok" \
          -cancelCommand "set dialogBoxChoice cancel"
        APSLabel .dis -parent .newLimit.userFrame -text "These correctors tripped off, please reduce the limits for re-scanning."
        
        set index 0
        foreach corr $badCorrectors {
            APSFrame .f$index -parent .newLimit.userFrame
            APSLabel .c$corr -parent .newLimit.userFrame.f${index}.frame \
              -text "$corr  " -packOption "-side left"
            APSLabeledEntry .l$corr -parent .newLimit.userFrame.f${index}.frame \
              -label "Lower Limit" -packOption "-side left" -textVariable LowerLimit($corr) -width 10
            APSLabeledEntry .u$corr -parent .newLimit.userFrame.f${index}.frame \
              -label "Upper Limit" -packOption "-side left" -textVariable UpperLimit($corr) -width 10
            incr index
        }
        tkwait window .newLimit
        if [llength $needScanCorrList] {
            set corrList ""
            foreach corr $badCorrectors {
                if [lsearch -exact $needScanCorrList $corr]<0 {
                    lappend corrList $corr
                }
            }
            set corrList [concat $corrList $needScanCorrList]
        } else {
            set corrList $badCorrectors
        }
        return $corrList
    }
    return ""
}

proc StartRFGun_LeakageMonitorInfo {args} {
    return "this pem is for starting leakage monitor for selected rf gun (RG1 or RG2)."
}
proc StopRFGun_LeakageMonitorInfo {args} {
    return "this pem is for stopping leakage monitor for selected rf gun (RG1 or RG2)."
}
proc StartRFGun_LeakageMonitorInitDialog {frame} {
    global StartRFGun_LeakageMonitor
    pack [frame $frame.f1]
    APSRadioButtonFrame .gun -parent $frame.f1 -label "RF Gun:   " -buttonList {1 2} \
        -valueList {RG1 RG2} -variable StartRFGun_LeakageMonitor(gun) \
        -contextHelp "select RF gun (1 or 2) for start leakage monitor." \
        -orientation horizontal
}

proc StartRFGun_LeakageMonitor {args} {
    global status execMode 
    set gun ""
    set leakageControlPV L:RFG:KickerLeakageRC
    APSStrictParseArguments {gun}
    
    APSMpStep init \
        -promptDialog StartRFGun_LeakageMonitorInitDialog \
        -vars "gun"

    set paramString ""
    foreach param {gun} {
        append paramString "$param=\"[set $param]\" "
    }
    catch {APSLogScriptAction -procedure StartRFGun_LeakageMonitor -action initialize -state ok -parameters $paramString}

    if ![string length $gun] {
        APSMpReturn error "RF gun is not selected."
    }
    if [catch {APScavget -list=L1:RFG:RF:SW2:positionMI -pend=30} gun1] {
        APSMpReturn error "$gun1"
    }
    if {$gun1!=$gun} {
        APSMpReturn error "The selected gun - $gun is not in operation now."
    }
    if [catch {exec cavget -list=L:RFG:KickerLeakageRC.RUN -pend=30} running] {
        APSMpReturn error "$running."
    }
    if $running {
        APSMpReturn error "RF gun leakage monitor is already running."
    }
    catch {exec medm -x -attach -macro RCPV=L:RFG:KickerLeakageRC ./sr/psApp/APSRunControlSingle.adl &}
    exec APSMonitorL1Leakage -gun $gun -runControlPV L:RFG:KickerLeakageRC -limit 0 &
    APSMpReturn ok
}

proc StopRFGun_LeakageMonitor {args} {
    if ![APSYesNoPopUp "Are you sure to stop rf gun leakage monitor?"] {
        APSMpReturn ok
    }
    if [catch {exec cavput -list=L:RFG:KickerLeakageRC.ABRT=1 -pend=30} result] {
        APSMpReturn error $result
    }
    APSMpReturn ok
}
 
proc AbortSweepingCorrectors {args} {
    global status RFGun_KickerValidation 
    if [APSYesNoPopUp "Are sure to abort sweeping correctors?"] {
	set status "Request aborting RFGun kicker validataion (it is valid during sweeping correctors)..."
	set RFGun_KickerValidation(abort) 1  
    }
    APSMpReturn ok
}

proc APSMpShutdownDrive2 {args} {
    
    global status
    if [catch {GetL1L2DriveKryston} driveList] {
	APSMpReturn error "APSMpShutdownDrive2: $driveList"
    }
    set drive1 [lindex $driveList 0]
    set drive2 [lindex $driveList 1]
    set status "L1 is driven by $drive1, L2 is driven by $drive2"
    switch $drive2 {
	L2 {
	    #k2 is driving
	    set setpoint L2:SD:DC1ARF:SetpointP
	    set errorPV L2:SD:DC1ARF:ErrorM
	    set controlPV L:L2Stabilizer:SDDS
	    set LLRF L2:LL:lockRfOffBO
	    set readback L-K2:LLRF:KlyFwd_PwrRemoteM
	}
	L3 {
	    #k3 is driving
	    set setpoint L3:KY:DC2ARF:SetpointP
	    set controlPV L:L3Stabilizer:SDDS
	    set errorPV  L3:KY:DC2ARF:ErrorM
	    set LLRF L3:LL:lockRfOffBO
	    set readback L3:KY:DC2ARF.VAL
	} 
    }
    
    APSMpStep "Shut down $drive2 ..."
    APSMpStep "Set $drive2 power to zero before shut off the low level RF to $drive2..."
    #APSMpStep "waiting for checking..."
    if [catch {APScavput -list=$setpoint=0 -pend=30} result] {
	APSMpReturn error "APSMpShutdownDrive2: $result"
    }
    if [catch {APScavget -list=${controlPV}.RUN -numeric -pend=30 -printErrors} L2running] {
	APSMpReturn error "APSMpShutdownDrive2: $running"
    }
    if [catch {LMOCS_PowerControlLawSetup -deviceList $drive2 -mode high} result] {
	APSMpReturn error "APSMpShutdownDrive2: $result"
    }
    if {!$L2running} {
	if [catch {APScavput -list=${controlPV}.CMND=1 -pend=30} result] {
	    APSMpReturn error "APSMpShutdownDrive2: $result"
	}
	after 2000
    }
    if [catch {APScavget -list=${controlPV}.SUSP -pend=30 -numeric -printErrors} suspended] {
	APSMpReturn error "APSMpShutdownDrive2: $suspended"
    }
    if {$suspended} {
	if [catch {APScavput -list=${controlPV}.SUSP=0 -pend=30} result] {
	    APSMpReturn error "APSMpShutdownDrive2: $result"
	}
    }
    while {1} {
	if [catch {exec cavget -list=L2:MA:klyPosAI -printErrors -pend=30} attn] {
	    APSMpReturn error "APSMpShutdownDrive2: $attn"
	}
	if {$attn>=3.0} {
	    if [catch {exec cavput -list=L2:MA:incKlyBO=0 -pend=30} result] {
		APSMpReturn error "APSMpShutdownDrive2: $result"
	    }
	    break
	}
	if [catch {exec cavput -list=L2:MA:incKlyBO=1 -pend=30} result] {
	    APSMpReturn error "APSMpShutdownDrive2: $result"
	}
	after 5000
    }
 
    APSMpStep "Waiting for $drive2 power come to zero..."
    if [catch {WaitForTaskToFinish \
		   -cavget "APScavget -list=$readback -label" \
		   -waitLimit 20 \
		   -updateInterval 5 \
		   -checkExpression {($value < -1.0) || ($value > 1.0)} } results] {
	if {[APSPEMTKDialog .warningDialog -text "APSMpShutdownDrive2: Problem occurred while waiting for L2 power reaching to zero \n$results"] == 1} {
	    APSMpReturn error "APSMpShutdownDrive2: $results"
	}
    }
    
    if [catch {APScavput -list=${controlPV}.SUSP=1 -pend=30} result] {
	APSMpReturn error "APSMpShutdownDrive2: $result"
    }
    
    if [catch {LMOCS_PowerControlLawSetup -deviceList $drive2 -mode low} result] {
	APSMpReturn error "APSMpShutdownDrive2: $result"
    }
    APSMpStep "Shut off the low level RF to $drive2. This shall remain off throughout the validation to prevent acceleration of the beam."
    if [catch {APScavput -list=$LLRF=1 -pend=30} result] {
	APSMpReturn error "APSMpShutdownDrive2: Can not shutoff LLRF $drive2: $result"
    }
    after 2000
    APSMpReturn ok
}
