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

# $Log: not supported by cvs2svn $
# Revision 1.65  2011/12/12 17:13:23  shang
# increased the runcontrol ping timeout due to network slowing down.
#
# Revision 1.64  2011/04/14 19:48:32  shang
# removed checking and reseting slope/zero status MBBO since they are no longer being managed by bcontrol.
#
# Revision 1.63  2011/04/11 15:22:21  shang
# added reset auto-correction count to zero in CheckSFBMStatus to help avoid loading safety ramp when run in energy-saver-mode.
#
# Revision 1.62  2011/04/08 19:28:28  shang
# added reset auto-correction count to zero when BM ramp is off during reading magnet parameters, this should make sure that
# the count is reset to zero when BM ramp is off.
#
# Revision 1.61  2011/04/05 17:55:52  shang
# added displaying message for reset the auto-correction count.
#
# Revision 1.60  2011/04/04 14:53:02  shang
# reset the auto-correction count to zero when BM ramp is disabled.
#
# Revision 1.59  2011/03/08 17:18:43  shang
# fixed a bug in calling logMessage.
#
# Revision 1.58  2011/02/28 16:55:11  shang
# per CY's request, removed topup checking and commented out safety load count checking so that that ramp
# correction won't stop because of too many safety loads.
#
# Revision 1.57  2011/02/28 16:44:12  shang
# fixed a bug in loading safety ramp and simplified the logMessage command.
#
# Revision 1.56  2011/02/25 17:06:37  shang
# removed checking bcontrol lock state since new bcontrollaw does not lock bcontrol state, and removed unused procedures.
#
# Revision 1.55  2011/02/24 21:28:55  shang
# changed the bcontrol runcontrol name to use the new bcontrollaw runcontrol.
#
# Revision 1.54  2011/02/17 17:25:39  shang
# changed the slop/zero error pvs (calculated by bcontrol) to use the error calculation PVs in IOC which update along with the measurement, because bcontrol
# usually updates slower than measurement.
#
# Revision 1.53  2010/12/17 20:07:53  shang
# reset the auto correction count to zero when the ramp goes to sleep to avoid the safety ramp being loaded after 50 continuous corrections.
#
# Revision 1.52  2010/12/10 22:28:03  shang
# added BM conditioning check to suspend BM auto correction during BM conditioning, and added date information to the status display.
#
# Revision 1.51  2010/10/05 21:17:52  shang
# added option to change the wait time after correction instead of waiting fixed 10 seconds.
#
# Revision 1.50  2010/09/30 15:04:28  shang
# increased the gain limit to 5% per CY's request.
#
# Revision 1.49  2010/09/30 14:26:57  shang
# zero out the first glitches on all magnet ramps.
#
# Revision 1.48  2010/09/29 18:28:08  shang
# implemented start and stop ramp correction limits, instead of using one limit.
#
# Revision 1.47  2010/08/10 19:11:24  shang
# added loading AFG gain and trigger when loading safety ramp.
#
# Revision 1.46  2010/08/03 21:59:07  shang
# increased the zero error limit for SF to 0.10.
#
# Revision 1.45  2010/08/03 19:19:40  shang
# modified to use the new VcorrectAndCheck library procedure and skip SF correction when BM ramp is off.
#
# Revision 1.44  2010/06/11 18:17:09  shang
# added labeling for logMessage error to help debugging.
#
# Revision 1.43  2010/06/11 18:10:24  shang
# fixed a bug in loading safety ramp that bcontrolstate variable was not defined.
#
# Revision 1.42  2010/03/22 18:38:08  shang
# added waiting for 2 seconds before applying swap and sync.
#
# Revision 1.41  2010/03/22 17:50:19  shang
# added "swap and sync" after loading ramp table if bcontrol is not running.
#
# Revision 1.40  2010/03/16 17:21:33  shang
# zero any setpoints that is below zero and before 5 ms, changed by CY
#
# Revision 1.39  2009/05/27 14:07:53  shang
# added BControlSlopeGain argument to be able to change it.
#
# Revision 1.38  2008/01/31 21:16:14  shang
# added displaying message when the PARTOBTS efficiency is greater than 75%.
#
# Revision 1.37  2006/07/05 14:21:31  shang
# replaced "global lastPing 0" by "set lastPing 0" (typo).
#
# Revision 1.36  2006/07/05 14:19:12  shang
# fixed a typo in lastPing expr expression.
#
# Revision 1.35  2006/07/05 14:17:45  shang
# removed "{" inside the expr expression.
#
# Revision 1.34  2006/07/03 18:38:08  soliday
# Changed the code so that it will not ping the run control faster than 30Hz.
#
# Revision 1.33  2006/02/08 22:35:15  sereno
# Changed dipole shift parameter from 11 to 11.5 ms to reduce glitch at 50 ms.
#
# Revision 1.32  2006/01/31 16:15:29  shang
# now returns error the booster lattice is not one of 92, 132 and 109.
#
# Revision 1.31  2006/01/25 19:46:05  sereno
# Changed dipole shift parameter back to 12 ms from 11 ms.
#
# Revision 1.30  2006/01/23 23:02:23  shang
# added archive feature to before and after auto-correction and changed the dipole shift parameter from 11 to 12.
#
# Revision 1.29  2005/12/02 20:12:33  shang
# added checking the PTB to BTS efficiency for topup mode. When running at
# topup mode, auto-correction is done only when efficiency is <75% and dI/I
# rms value is > limit. For non-topup mode, only dI/I rms is used.
#
# Revision 1.28  2005/11/29 23:02:29  shang
# removed the despike since the range value is used for removing spikes.
#
# Revision 1.27  2005/11/29 21:08:03  shang
# now uses the range of values to remove spike points and it works well.
#
# Revision 1.26  2005/11/21 22:47:26  shang
# changed the BM limit from 0.034 to 0.0365
#
# Revision 1.25  2005/03/30 17:26:48  shang
# corrected spelling errors in log messages
#
# Revision 1.24  2005/03/16 06:21:00  sereno
# Changed the SD threshold dI/I for correction from 0.025 to 0.035 to avoid
# unnecessary corrections when switching to direct injection.
#
# Revision 1.23  2005/03/02 22:57:20  soliday
# Updated so that APSRunControlLogMessage is run every loop to clear out
# any suspend messages that may exist in the run control record.
#
# Revision 1.22  2005/03/02 22:23:00  soliday
# Added the APSRunControlLogMessage command
#
# Revision 1.21  2005/02/23 23:39:10  shang
# replaced cavget with desipke feature by APScavget since the bug in APScavget was
# fixed.
#
# Revision 1.20  2005/02/23 23:36:27  shang
# changed the waiting time from 5 seconds back to 1 second since the CPU over load
# problem was solved.
#
# Revision 1.19  2005/02/23 22:58:25  shang
# fixed a typeo
#
# Revision 1.18  2005/02/23 22:46:09  shang
# the booster lattice now is obtained through BOO:LatticeCALC pv directly and
# fixed the big CPU load problem when booster ramp auto correction is running, since
# APSMpCheckBoosterLattice proc was used to get the booster lattice, where
# APSMpCheckBoosterLattice does six sddsprocess commands using the file server to check
# the booster lattice which takes too long and increases the CPU load a lot.
#
# Revision 1.17  2005/02/21 22:28:33  shang
# modified to read the AFG gain limits from reference file only once in the beginning
#
# Revision 1.16  2005/02/15 10:12:32  shang
# made it work for SF and SD
#
# Revision 1.15  2004/12/21 20:45:01  sereno
# Changed BM dI/I rms correction threshold from 0.033 to 0.034 to reduce
# the number of times the ramp is corrected.
#
# Revision 1.14  2004/12/15 18:38:57  shang
# added deleting tmp files created in VcorrectAndCheck proc
#
# Revision 1.13  2004/12/15 18:27:47  shang
# added back slash before the special characters for log description
#
# Revision 1.12  2004/12/15 18:19:07  shang
# fixed a typo error in PVTests proc
#
# Revision 1.11  2004/12/15 17:11:22  shang
# added GetAFGGainLimit proc to get the AFG gain limits and SetVcorrectAndCheckParameters
# proc to setup the parameters for VcorrectAndCheck. Both procedures are called only once
# in the beggining. Modified PVTests proc to use APScavget; Removed setting parameters
# part in VcorrectAndCheck procedure; Modified PingRunControl error message when it is
# called inside other procedures to clarify the error source; added PingRunControl to
# each channel-access statement; Changed the ping timeout of runcontrol from 20 seconds
# to 30 seconds and changed the pendIOtime from 30 seconds to 20 seconds to avoid
# runcontrol ping time out.
#
# Revision 1.10  2004/12/14 15:57:54  shang
# moved "starting auto-correction" log message to before calling StartAutoCorrection proc.
#
# Revision 1.9  2004/12/14 15:51:29  shang
# added log messages to GetBControlSupplyValues proc so that the error message
# that dI is out of range 0-0.30 will be logged.
#
# Revision 1.8  2004/12/14 15:37:37  shang
# added log message to ShutdownSystem proc if shutdown is successful.
#
# Revision 1.7  2004/12/14 15:24:40  shang
# changed the shut-down message.
#
# Revision 1.6  2004/12/14 15:11:10  shang
# added description argument to loadSafetyRamps proc to log the message for loading
# safety ramp.
#
# Revision 1.5  2004/12/13 23:41:42  shang
# fixed a log message error
#
# Revision 1.4  2004/12/13 22:47:00  shang
# fixed a typo
#
# Revision 1.3  2004/12/13 22:34:52  shang
# added catch statements to every executable statement; added log error messages to
# ShutDownSystem proc to log the occurred error message before shutting down auto-correction.
# replaced cavget/cavput by APScavget/APScavput
#
# Revision 1.2  2004/12/13 17:13:52  shang
# deleted the tmpfiles to clean up the disk
#
# Revision 1.1  2004/12/10 22:19:16  shang
# renamed from BRampControlAutoCorrection.tcl
#
# Revision 1.1  2004/12/10 16:41:50  shang
# booster ramp automatic correction application, first version
#

set auto_path [linsert $auto_path 0 /usr/local/oag/apps/lib/$env(HOST_ARCH)]
set auto_path [linsert $auto_path 0 /usr/local/oag/lib_patch/$env(HOST_ARCH)]

APSStandardSetup
#source /home/oxygen/SHANG/oag/apps/src/tcltkapp/oagapp/boosterRamp.tcl
set CVSRevisionAuthor "\$Revision: 1.66 $ \$Author: shang $"
set args $argv
set supply ""
set repeat 5
set triggerType rms
set pingTimeout 60
#pkLimit actually is limit for both Peak and rms
set slopeErrorLimit 0.005
set zeroErrorLimit 0.050
set SFzeroErrorLimit 0.100
set BControlSlopeGain 0.1
set waitTime 4
set IRamp 0
set usage {usage: BRampAutoCorr -supply <string> -triggerType <rms|peak> -pingTimeout <seconds> -BControlSlopeGain <value>}
APSParseArguments {supply triggerType topUpRunning pkLimit BControlSlopeGain SFzeroErrorLimit waitTime IRamp}

if $IRamp {
    set slopeErrorLimit 0.01
    set zeroErrorLimit 0.15
    set SFzeroErrorLimit 0.15
}
if $IRamp {
    set desc IRamp
} else {
    set desc VRamp
}
APSSCRDefineVariables 
global apsScriptCommand apsScritUser apsScritpHost

set limitPVList [list B:$supply:RampCorrStartLimitAO B:$supply:RampCorrStopLimitAO]
set limitVarList {rmsStartLimit rmsStopLimit}
if [pv linkw $limitVarList $limitPVList 30] {
    puts stderr "Error link limit pvs: $errorCode"
    exit 1
}


proc SetStatus {text} {
    puts stderr "[exec date] $text"
}

proc ReadAFGGainLimit {args} {
    global L92 L109 L132
    set dir /home/helios/oagData/SCR/snapshots/Booster
    set fileList {Booster-LowE2Reference375.gz Booster-LowE1Reference325.gz Booster-Reference325.gz} 
    foreach name {L92 L109 L132} file $fileList {
	foreach supply {BM QF QD SF SD} {
	    if [catch {exec sddsprocess $dir/$file -match=col,ControlName=B:$supply:VoltageRT.GAIN \
			   -pipe=out | sdds2stream -pipe -col=ValueString} gain] {
		return -code error $gain
	    }
	    set ${name}($supply) $gain
	}
    }
}

proc PVTests {args} {
    global runControlPV supply desc IRamp
    if {$supply=="SF" || $supply=="SD"} {
        #do not test AFG gain for SF and SD per CY's request, due to their big changes.
        return
    }
    if [catch {PingRunControl -runControlPV $runControlPV} result] {
        return -code error "Error of PingRunControl in PVtests before reading gain value: $result"
    }
    if [catch {GetBoosterAFGGain -supply $supply} gain] {
        return -code error $gain
    }
    set upper [expr $gain * 1.05]
    set lower [expr $gain * 0.95]
    set name B:${supply}:VoltageRT.GAIN
    if [catch {APScavget -list=$name -pend=20} gain] {
        return -code error "Unable to read value of $name : $gain"
    }
    if [catch {PingRunControl -runControlPV $runControlPV} result] {
        return -code error "Error of PingRunControl in PVtests after reading gain value: $result"
    }
    if {$gain=="?"} {
        return -code error "Unable to read value of $name"
    }
    
    if {$gain>$upper || $gain<$lower} {
        #load saftey ramp
        SetStatus "$supply AFG gain out of range, loading safety ramps..."
        if [catch {APSBoosterLoadSafetyRamp -$supply 1 -IRamp $IRamp -description "$supply AFG gain out of range, loading $desc safety ramp." } results] {
            return -code error "Error of loadSafetyRamps in PVtest: $results"
        }
        if [catch {PingRunControl -runControlPV $runControlPV} results] {
            return -code error "Error of pingRunControl in PVtest after loadSafetRamps: $results"
        }
    }
}
proc CheckArguments {args} {
    set supply ""
    set triggerType ""
    APSParseArguments {supply triggerType}
    global usage rmsPV IRamp
    if ![string length $supply] {
        return -code error "Error: no supply was given.\n$usage\n"
    }
    if $IRamp {
        #set rmsPV B:${supply}:CurrentRefRMS
        set rmsPV B:${supply}:IRampRMSAI
    } else {
        set rmsPV B:${supply}:DeltaIrmsAO
    }
    switch $supply {
        BM -
        QF -
        QD -
        SF -
        SD {
        }
        default {
            return -code error "Invalid supply -- $supply given\n"
        }
    }
}

proc ReadRMSValues {args} {

    set supply ""
    APSParseArguments {supply}
    global rmsPV pk
   
    if [catch {APScavget  -list=$rmsPV \
                 -statistics=number=4,pause=0.5,format=tagvalue } rmsValue] {
        return -code error "Unable to read $rmsPV value: $rmsValue"
    }
    array set rmsData $rmsValue
    set pk($supply) $rmsData(mean)
}


proc CheckBControlStatus {args} {
    set supply ""
    APSParseArguments {supply}
    global apsScriptHost apsScriptCommand apsScriptUser
    
    #check if bcontrol is aborted or suspended
    set bcontrolstate 0
    set runControlPV B:$supply:AutoCorrectionControlRC
    set suspended 0
    if [catch {PingRunControl -runControlPV $runControlPV} result] {
        return -code error "Error of PingRunControl in CheckBControlStatus before checking Bcontrol status: $result"
    }
    while {!$bcontrolstate} {
        if [catch {APScavget -list=B:${supply}bcontrollawRC.RUN -pend=20 -printErrors} bcontrolstate] {
            return -code error "Unable to read value of B:${supply}bcontrollawRC.RUN : $bcontrolstate"
        }
	if [catch {APScavget -list=$runControlPV.SUSP -num -pend=20 -printErrors} suspended] {
	    return -code error "Unable to read value of $runControlPV.RUN : $suspended."
	}
        if [catch {PingRunControl -runControlPV $runControlPV} result] {
            return -code error "Error of PingRunControl in CheckBControlStatus after reading Bcontrol pv :$result"
        }
        if {$bcontrolstate} {
            break
        } else {
            if {!$suspended} {
                SetStatus "Bcontrol is not running, waiting for Bcontrol to start..."
		if [catch {exec logMessage -sourceId=${supply}AutoCorrection -tag=applicationName $apsScriptCommand \
			       -tag=user $apsScriptUser -tag=host "$apsScriptHost" -tag=execution AutoCorrection -tag=action Suspended \
			       -tag=description "Suspending $supply auto-correction because Bcontrol is not running."} result] {
		   # return -code error "logMessage error4: $result"
		}
                if [catch {PingRunControl -runControlPV $runControlPV} result] {
                    return -code error "Error of PingRunControl in before setting glitch pvs: $result"
                }
                if [catch {APScavput -list=B:${supply}:Ramp:AutoCorrGlitchBO=1 -pend=20} result] {
                    return -code error "Error in setting $supply glitch pv: $result"
                }
                if [catch {PingRunControl -runControlPV $runControlPV} result] {
                    return -code error "Error of PingRunControl after setting glitch pvs: $result"
                }
                after 1000
                if [catch {APScavput -list=B:${supply}:Ramp:AutoCorrGlitchBO=0 -pend=20} result] {
                    return -code error "Error in setting $supply glitch pv: $result"
                }
	    }
            if [catch {PingRunControl -runControlPV $runControlPV} result] {
                return -code error "Error of PingRunControl in CheckBControlStatus during suspending auto-correction: $result"
            }
            after 1000
        }
    }
    if [catch {PingRunControl -runControlPV $runControlPV} result] {
        return -code error "Error of PingRunControl in CheckBControlStatus after checking Bcontrol status: $result"
    }
    if [catch {CheckSlopeAndZeroStatus -supply $supply} result] {
        return -code error $result
    }
}

proc GetBControlSupplyValues {args} {
    set supply ""
    set triggerType ""
    APSParseArguments {supply triggerType}
    global apsScriptHost apsScriptCommand apsScriptUser count IRamp
    set runControlPV B:$supply:AutoCorrectionControlRC
    global pk slopeError zeroError
    switch $triggerType {
        peak {
            set type pk
        }
        rms {
            set type rms
        }
    }
    set runControlPV B:$supply:AutoCorrectionControlRC
    set firstTime 1
    set timeout [expr [clock seconds]+10]
    while {[clock seconds]<$timeout} {
        if [catch {PingRunControl -runControlPV $runControlPV} result] {
            return -code error "Error of PingRunControl in GetBControlSupplyValues before reading values: $result"
        }
	if {$supply=="BM" || $supply=="SF"} {
	    if [catch {APScavget  -list=It:Ddg4chan0.GATE -printErrors -pend=10 -num} rampState] {
	          SetStatus "$supply rms reaches the stop-correction limit, stop correction."
	          ShutdownSystem -runControlPV $runControlPV -errorMessage "Error reading BM ramp status: $rampState"
	    }
	    if {!$rampState && $count} {
	      SetStatus "reset auto-correction count to 0 when BM ramp is off."
	      set count 0
	   }
	}
        
        while {1} {
	    if {$supply=="BM" || $supply=="SF"} {
		if [catch {APScavget  -list=It:Ddg4chan0.GATE -printErrors -pend=10 -num} rampState] {
		   SetStatus "$supply rms reaches the stop-correction limit, stop correction."
		   ShutdownSystem -runControlPV $runControlPV -errorMessage "Error reading BM ramp status: $rampState"
		}
		if {!$rampState && $count} {
		    SetStatus "reset auto-correction count to 0 when BM ramp is off."
		    set count 0
		}
	    }
            if [catch {APScavget  -list=B:${supply}: \
                         -list=DeltaI${type}AO,RampSlopeErrCALC,ZeroErrCALC \
                         -statistics=number=4,pause=0.5,format=tagvalue } rmsValue] {
                return -code error "Unable to read B:${supply}:DeltaI${type}AO: $rmsValue"
            }
            update
            set delta [lrange $rmsValue 0 15]
            set slope [lrange $rmsValue 16 31]
            set zero [lrange $rmsValue 32 47]
            array set deltaData $delta
            array set slopeData $slope
            array set zeroData $zero
            break
            #do not check the spread anymore, 9/27/2013 CYao.
            if {$deltaData(spread)>=0.02} {
                SetStatus "The value range of B:${supply}:DeltaI${type}AO is greater than 0.02 (The maximum is $deltaData(max) and the min value is $deltaData(min)). It is probably a spike, ignore this data!"
            } else {
                break
            }
            if [catch {PingRunControl -runControlPV $runControlPV} result] {
                return -code error "Error of PingRunControl in GetBControlSupplyValues before reading values: $result"
            }
            after 1000
        }
        if [catch {PingRunControl -runControlPV $runControlPV} result] {
            return -code error "Error of PingRunControl in GetBControlSupplyValues after reading values:$result"
        }
        set pk($supply) $deltaData(mean)
        set slopeError($supply) $slopeData(mean)
        set zeroError($supply) $zeroData(mean)
        
        if {$pk($supply)<=0 || $pk($supply)>=0.30} {
            if $firstTime {
                SetStatus "$supply rms dI/I out of range(0-0.30), loading safety..."
                if [catch { exec logMessage -sourceId=${supply}AutoCorrection -tag=applicationName $apsScriptCommand \
                              -tag=user $apsScriptUser -tag=host "$apsScriptHost" -tag=execution GetBControlSupplyValues -tag=action Error \
                              -tag=description "$supply rms dI\/I out of range(0-0.30), waiting for it to come back to normal..." } result] {
                    # return -code error "logMessage error5: $result"
                }
                if [catch {APSBoosterLoadSafetyRamp -$supply 1 -IRamp $IRamp \
                             -description "loading $desc safety ramp for $supply after $count ramp correction attempts." } result] {
                    SetStatus "$result"
                    catch {ArchiveWaveformData -start 0 -dataFileLabel $dataFileLabel -supply $supply }
                    ShutdownSystem -runControlPV $runControlPV -errorMessage "Error(loadSafetyRamps): $result"
                }
                set firstTime 0
            }
        } else {
            if !$firstTime {
                SetStatus "$supply came back to normal, resuming auto-correction...."
                if [catch {exec logMessage -sourceId=${supply}AutoCorrection -tag=applicationName $apsScriptCommand \
                             -tag=user $apsScriptUser -tag=host "$apsScriptHost" -tag=execution GetBControlSupplyValues \
                             -tag=action Normal -tag=description "$supply came back to normal, resuming auto-correction..." } result] {
                    #   return -code error "logMessage error6: $result"
                }
            }
            break
        }
        if [catch {PingRunControl -runControlPV $runControlPV} result] {
            return -code error "Error of PingRunControl in GetBControlSupplyValues during suspending auto-correction: $result"
        }
        after 1000
    }
}

# Booster Ramp Correction Procedure.
proc VcorrectAndCheck {args} {
    set supply ""
    APSParseArguments {supply}
    global apsScriptHost apsScriptCommand apsScriptUser IRamp
   
    set runControlPV B:$supply:AutoCorrectionControlRC
    if [catch {PingRunControl -runControlPV $runControlPV} result] {
        return -code error "Error of PingRunControl in VcorrectAndCheck before starting: $result"
    }
    if $IRamp {
        if [catch {BoosterRampVCurrentCorrectAndCheck -supply $supply -runControlPV $runControlPV \
                     -user $apsScriptUser -host $apsScriptHost -application $apsScriptCommand } result] {
            return -code error "VCorrectAndCheck: $result"
        }
    } else {
        if [catch {BoosterRampVCorrectAndCheck -supply $supply -runControlPV $runControlPV \
                     -user $apsScriptUser -host $apsScriptHost -application $apsScriptCommand } result] {
            return -code error "VCorrectAndCheck: $result"
        }
    }
    if $IRamp {
        if [catch {ReadRMSValues -supply $supply } result] {
            return -code error "VcorrectAndCheck3: $result"
        }
    } else {
        if [catch {CheckSlopeAndZeroStatus -supply $supply } result] {
            return -code error "VcorrectAndCheck3: $result"
        }
    }
    if [catch {PingRunControl -runControlPV $runControlPV} result] {
        return -code error "Error of PingRunControl in VcorrectAndCheck after CheckSlopeAndZeroStatus: $result"
    }
    return 0
}

proc CheckSlopeAndZeroStatus {args} {
    set supply ""
    APSParseArguments {supply} 
    #decide to no check the status
    return
    global apsScriptHost apsScriptCommand apsScriptUser
    set pvList [list B:$supply:SlopeStatMBBO B:$supply:ZeroStatMBBO]
    set putList [list B:$supply:SlopePushMBBO B:$supply:ZeroPushMBBO]
    set runControlPV B:$supply:AutoCorrectionControlRC
    if [catch {PingRunControl -runControlPV $runControlPV} result] {
        return -code error "Error of PingRunControl in CheckSlopeAndZeroStatus before starting: $result"
    }
    set setted 0
    while {1} {
        set ok 1
        if [catch {APScavget -list=[join $pvList ,] -pend=20 -numerical} statusList] {
            return -code error $statusList
        }
        if [catch {PingRunControl -runControlPV $runControlPV} result] {
            return -code error "Error of PingRunControl in CheckSlopeAndZeroStatus after reading values: $result"
        }
        foreach pv $pvList status $statusList setPV $putList {
            if {$status=="?"} {
                return -code error "Unable to read value of $pv!"
            }
        }
        foreach pv $pvList status $statusList setPV $putList {
            if !$status {
                set ok 0
                if {!$setted} {
                    SetStatus "Enable the slope/zero state ($setPV)."
                    if [catch {exec logMessage -sourceId=${supply}AutoCorrection -tag=applicationName $apsScriptCommand \
				   -tag=user $apsScriptUser -tag=host "$apsScriptHost" -tag=execution SlopeErrorState \
				   -tag=action Enable -tag=description "Enable $setPV"} result] {
                       # return -code error "logMessage error10: $result"
                    }
                    if [catch {APScavput -list=$setPV=1 -pend=20} result] {
                        return -code error $result
                    }
                    if [catch {PingRunControl -runControlPV $runControlPV} result] {
                        return -code error "Error of PingRunControl in CheckSlopeAndZeroStatus after enabling $setPV: $result"
                    }
                }
            }
        }
        set setted 1
        if {$ok} {
            break
        }
        if [catch {PingRunControl -runControlPV $runControlPV} result] {
            return -code error "Error of PingRunControl in CheckSlopeAndZeroStatus during waiting for slope or errorstate to become enabled: $result"
        }
        after 1000
    }
    if [catch {PingRunControl -runControlPV $runControlPV} result] {
        return -code error "Error of PingRunControl in CheckSlopeAndZeroStatus after checking: $result"
    }
}

proc CheckTopUp {args} {
    global runControlPV supply
    global apsScriptHost apsScriptCommand apsScriptUser

    if [catch {PingRunControl -runControlPV $runControlPV} result] {
        return -code error "Error of PingRunControl in CheckTopUp before starting: $result"
    }
    if [catch {APScavget -list=Mt:TopUpAutoEnableC.VAL -numerical -pend=20} topup] {
        return -code error $topup
    }
    if [catch {PingRunControl -runControlPV $runControlPV} result] {
        return -code error "Error of PingRunControl in CheckTopUp after reading value of Mt:TopUpAutoEnableC.VAL: $result"
    }
    if {$topup=="?"} {
        return -code error "Can not read value of Mt:TopUpAutoEnableC.VAL"
    }
    set suspended 0
    if $topup {
        while {1} {
            if [catch {APScavget -list=Mt:TopUpTime2Warn.VAL -pend=20} warningtime] {
                return -code error $warningtime
            }
            if [catch {PingRunControl -runControlPV $runControlPV} result] {
                return -code error "Error of PingRunControl in CheckTopUp after reading value of Mt:TopUpTime2Warn.VAL: $result"
            }
            if {$warningtime=="?"} {
                return -code error "can not read value of Mt:TopUpTime2Warn.VAL"
            }
            if {$warningtime<20} {
                if {!$suspended} {
                    SetStatus "Too close to topup to correct ramp, waiting for topup pulse to be injected."
                    if [catch {exec logMessage -sourceId=${supply}AutoCorrection -tag=applicationName $apsScriptCommand -tag=user $apsScriptUser \
				   -tag=host "$apsScriptHost" -tag=execution AutoCorrection -tag=action Suspended \
				   -tag=description "Suspend auto-correction until after the topup injection." } result] {
                       # return -code error "logMessage error11: $result"
                    }
                    if [catch {PingRunControl -runControlPV $runControlPV} result] {
                        return -code error "Error of PingRunControl before seting glitch pv: $result"
                    }
                    if [catch {APScavput -list=B:${supply}:Ramp:AutoCorrGlitchBO=1 -pend=20} result] {
                        return -code error "Error in setting $supply glitch pv: $result"
                    }
                    if [catch {PingRunControl -runControlPV $runControlPV} result] {
                        return -code error "Error of PingRunControl after setting glitch pvs: $result"
                    }
                    set suspended 1
                }
                if {$suspended} {
		    after 1000
                    if [catch {APScavput -list=B:${supply}:Ramp:AutoCorrGlitchBO=0 -pend=20} result] {
                        return -code error "Error in setting $supply glitch pv: $result"
                    }
                }
                if [catch {PingRunControl -runControlPV $runControlPV} result] {
                    return -code error "Error of PingRunControl in CheckTopUp during suspending auto-correction: $result"
                }
                after 1000
            } else {
                if {$suspended} {
                    SetStatus "Resuming auto-correction ..."
                    if [catch {exec logMessage -sourceId=${supply}AutoCorrection -tag=applicationName $apsScriptCommand \
				   -tag=user $apsScriptUser -tag=host "$apsScriptHost" -tag=execution AutoCorrection \
				   -tag=action Resumed -tag=description "Topup injection complete, resuming auto-correction." } result] {
                      #  return -code error "logMessage error12: $result"
                    }
                }
                if [catch {PingRunControl -runControlPV $runControlPV} result] {
                    return -code error "Error of PingRunControl in CheckTopUp after resuming auto-correction: $result"
                }
                break
            }
        }
    } 
}

set lastPing 0

proc PingRunControl {args} {
    global lastPing
    set sec [clock seconds]
    if {[expr $lastPing + 2] > $sec} {
        return
    } else {
        set lastPing $sec
    }
    
    set runControlPV ""
    APSParseArguments {runControlPV}

    catch {APSRunControlPing} status
    switch $status {
        RUNCONTROL_OK {}
        RUNCONTROL_ABORT {
            return -code error "Auto-correction was aborted."
        }
        RUNCONTROL_TIMEOUT -
        RUNCONTROL_ERROR {
            return -code error "Unable to ping runcontrol record of $runControlPV: $status."
        }
    }
}

proc ShutdownSystem {args} {
    set runControlPV ""
    set errorMessage ""
    APSStrictParseArguments {runControlPV errorMessage}
    global apsScriptHost apsScriptCommand apsScriptUser supply
    
    if [catch {exec logMessage -sourceId=${supply}AutoCorrection -tag=applicationName $apsScriptCommand -tag=user $apsScriptUser \
		   -tag=host "$apsScriptHost" -tag=execution AutoCorrection -tag=action Abort \
		   -tag=description "Attemping to shut down auto-correction because: $errorMessage." } result] {
        SetStatus "logMessage error15: $result"
       # exit
    }
    catch {APSRunControlExit}
    if [catch {APScavput -list=$runControlPV.ABRT=1 -pend=20} result] {
        SetStatus $result
        if [catch {exec logMessage -sourceId=${supply}AutoCorrection -tag=applicationName $apsScriptCommand \
		       -tag=user $apsScriptUser -tag=host "$apsScriptHost" -tag=execution AutoCorrection -tag=action Abort \
		       -tag=description "Shutdown failed: $result." } result] {
            SetStatus "logMessage error16: $result"
	  #  exit
        }
    }
    exec cawait -waitFor=$runControlPV.RUN,equal=0
    catch {exec cavput -list=$runControlPV.CLR=1 -pend=20}
    if [catch {exec logMessage -sourceId=${supply}AutoCorrection -tag=applicationName $apsScriptCommand \
		   -tag=user $apsScriptUser -tag=host "$apsScriptHost" -tag=execution AutoCorrection -tag=action Abort \
		   -tag=description "Shutdown succeeded. Auto-correction was aborted."} result] {
	SetStatus "logMessage error17: $result"
    }
    after 2000
    exit
}

proc StartAutoCorrection {args} {
    set runControlPV ""
    set supply ""
    set triggerType ""
    set pingTimeout 60
    APSParseArguments {runControlPV supply triggerType pingTimeout}
    
    #check runcontrol
    SetStatus "checking runcontrol $runControlPV .."
    if [catch {APScavget -list=$runControlPV.RUN -pend=20} running] {
        SetStatus "Can not read value of $runControlPV.RUN: $running"
        exit
    }
    if {$running=="?"} {
        SetStatus "Can not read value of $runControlPV.RUN."
        exit
    }
  
    if $running {
        if [catch {APScavget -list=$runControlPV.HOST -pend=20} host] {
            SetStatus $result
            exit
        }
        SetStatus "$supply ramp auto correction is already running on $host!"
        exit
    }
    #initialize new runcontrol
    #clear runcontrol record
    if [catch {APScavput -list=$runControlPV.CLR=1 -pend=20} result] {
        SetStatus $result
        exit
    }
    global IRamp
    if $IRamp {
        set desc IRamp
    } else {
        set desc VRamp
    }
    if [catch {APSRunControlInit -pv $runControlPV \
                 -description "$supply $desc Auto-correction" \
                 -timeout [expr $pingTimeout * 1000] } result] {
        SetStatus "Unable to initialize runcontrol for $supply auto-correction, the runcontrol record may not be cleared, press the clear button on the medm screen to clear the record and restart: $result"
        exit
    }
    APSRunControlLogMessage -message "Running" -severity 0
    if [catch {PingRunControl -runControlPV $runControlPV} result] {
        return -code error $result
    }
    if [catch {CheckBControlStatus -supply $supply} result] {
        return -code error $result
    }
    SetStatus "Reading $supply dI/I $triggerType values..."
    if !$IRamp {
        if [catch {GetBControlSupplyValues -supply "$supply" -triggerType "$triggerType"} result] {
            return -code error $result
        }
    } else {
        if [catch {ReadRMSValues -supply "$supply"} result] {
            return -code error $result
        }
    }
}

proc GetBoosterAFGGain {args} {
    set supply ""
    APSParseArguments {supply}
    global L92 L109 L132
    if [catch {APScavget -list=BOO:LatticeCALC -pend=20} lattice] {
        return -code error $lattice
    }
    if {$lattice !=92 && $lattice !=109 && $lattice !=132} {
        return -code error "Booster lattice is unknown!"
    }
    return [set L${lattice}($supply)]
}

proc CheckPTBToBTSEfficiency {args} {
    set supply ""
    APSParseArguments {supply}
    set runControlPV B:$supply:AutoCorrectionControlRC
    if [catch {APScavget -list=Mt:TopUpAutoEnableC.VAL -pend=30 -numeric} topup] {
        return -code error "CheckPTBToBTSEfficiency: $topup"
    }
    if {!$topup} {
        return 0
    } else {
        #read the efficiency after topup shots
        while {1} {
            if [catch {PingRunControl -runControlPV $runControlPV} result] {
                return -code error "Error of PingRunControl in CheckPTBToBTSEfficiency: $result"
            }
            if [catch {APScavget -list=Mt:TopUpTime2Inject.VAL -pend=30} injection] {
                return -code error "CheckPTBToBTSEfficiency: $injection"
            }
            update
            if {$injection==0} {
                break
            }
            after 500
        }
        after 2000
        if [catch {APScavget -list=topupPTB2BTSEfficiencyM.VAL -pend=30 } efficiency] {
            return -code error "CheckPTBToBTSEfficiency: $efficiency"
        }
        update
        if {$efficiency<75} {
            SetStatus "The PTB to BTS efficiency is $efficiency (<75%)."
            return 0
        } else {
            return 1
        }
    }
}

proc ArchiveWaveformData {args} {
    set start 1
    set dataFileLabel ""
    set supply ""
    APSStrictParseArguments {start dataFileLabel supply}
    global IRamp
    
    set date [clock format [clock seconds] -format %Y-%m%d]
    if $IRamp {
        set archiveDirectory /home/helios/oagData/booster/rampLogFiles/IRamp/rampCorrectionLogFiles/$date
    } else {
        set archiveDirectory /home/helios/oagData/booster/rampLogFiles/VRamp/rampCorrectionLogFiles/$date
    }
    if ![file exist $archiveDirectory] {
        exec mkdir -p $archiveDirectory
    }
    if $start {
        set suffix _Start
    } else {
        set suffix _Finish
    }
    if ![string length $dataFileLabel] {
        set dataFileLabel [APSOffsetDateInfo -today 1 -dateFormat Y-M-D]_[lindex [exec date] 3]
    }
    
    set filename ${supply}${dataFileLabel}${suffix}.sdds
    if $IRamp {
        if [catch {exec BIRampWaveformMon -filename $archiveDirectory/$filename} result] {
            return -code error $result
        }
    } else {
        if [catch {exec BRampWaveformMon -filename $archiveDirectory/$filename} result] {
            return -code error $result
        }
    }
    if [catch {exec sddsprocess ${archiveDirectory}/$filename -nowarnings \
                   -redefine=param,ArchiveData,1,type=long} result] {
        return -code error $result
    }
    if [catch {exec gzip $archiveDirectory/$filename} result] {
        return -code error $result
    }
    if [catch {exec rm $archiveDirectory/${filename}~} result] {
        return -code error $result
    }
}

proc CheckSFBMStatus {args} {
    set supply ""
    APSParseArguments {supply}
    global firstBmOn count
    #modify to skip correction for all magnets when BM is off. 7//29/2014 H. Shang
    
    ### old comments: dipole ramp on/off affects SF, turn off SF auto correction if dipole ramp is off
    if [catch {APScavget -list=It:Ddg4chan0.GATE -num -pend=10} bmOn] {
        SetStatus "Unable to read dipole ramp state: $bmOn"
        ShutdownSystem -runControlPV $runControlPV -errorMessage "Error(bmOn read): $bmOn"
    }
    if !$bmOn {
        if $firstBmOn {
            SetStatus "skip $supply auto-correction when BM ramp is off."
            set firstBmOn 0
        }
        set count 0
        return 0
    }
    set firstBmOn 1
    return 1
}

#execution starts here
if [catch {CheckArguments -supply "$supply" -triggerType "$triggerType"} result] {
    puts stderr $result
    exit
}
if [catch {ReadAFGGainLimit} result] {
    puts stderr $result
    exit
}

set runControlPV B:$supply:AutoCorrectionControlRC
SetStatus "Starting $supply auto-correction ..."

if [catch {exec logMessage -sourceId=${supply}AutoCorrection -tag=applicationName $apsScriptCommand -tag=user $apsScriptUser \
	       -tag=host "$apsScriptHost" -tag=execution AutoCorrection -tag=action Start \
	       -tag=description "Starting $supply auto-correction..." } result] {
    SetStatus "logMessage error18: $result"
   # exit
}

if [catch {StartAutoCorrection -runControlPV $runControlPV -supply $supply \
             -triggerType $triggerType -pingTimeout $pingTimeout} result] {
    SetStatus $result
    ShutdownSystem -runControlPV $runControlPV -errorMessage "Error(StartAutoCorrection): $result"
}
SetStatus "$supply auto-correction started..."
#set the slope and error gain
if [catch {APScavput -list=B:BconZeroGainAO=0.25,B:BconSlopeGainAO=$BControlSlopeGain -pend=20} result] {
    SetStatus $result
    ShutdownSystem -runControlPV $runControlPV -errorMessage "$result" 
}
#set the glitch pv to zero
if [catch {APScavput -list=B:${supply}:Ramp:AutoCorrGlitchBO=0 -pend=20} result] {
    SetStatus "Error in setting $supply glitch pv: $result"
    ShutdownSystem -runControlPV $runControlPV -errorMessage "$result" 
}
if [catch {PingRunControl -runControlPV $runControlPV} result] {
    SetStatus $result
    ShutdownSystem -runControlPV $runControlPV -errorMessage "Error(PingRunControl): $result"
}
set dataFileLabel ""
set firstBmOn 1
if {$supply=="SF"} {
    set zeroErrorLimit $SFzeroErrorLimit
}

set startedCorrection 0

while {1} {
    set count 0
    set safetyLoad 0
    set checktimes 0
    #ping runcontrol
    
    
    if [catch {PingRunControl -runControlPV $runControlPV} result] {
        SetStatus "Error of PingRunControl before checking BM ramp on/off status: $result"
        ShutdownSystem -runControlPV $runControlPV -errorMessage "$result" 
    }
    if ![CheckSFBMStatus -supply $supply] {
        after 2000
	continue
    }   
    if {$supply=="BM"} {
        #check if SR BM is conditioning
        set firstConditioning 1
        while {1} {
            #if [catch {APScavget -list=S:BM:StandardizeSUB.PROC -printErrors -pend=30} conditioning] {
             #   SetStatus "Error in checking SR BM conditioning: $conditioning"
              #  ShutdownSystem -runControlPV $runControlPV -errorMessage "$conditioning" 
		  # }
	    set conditioning 0
            if [catch {PingRunControl -runControlPV $runControlPV} result] {
                SetStatus "Error of PingRunControl after check SR BM conditioning: $result"
                ShutdownSystem -runControlPV $runControlPV -errorMessage "$result" 
            }
            if $conditioning {
                if $firstConditioning {
                    SetStatus "Skip BM auto correction when SR BM is conditioning..."
                }
                set firstConditioning 0
                after 1000
                continue
            } else {
                break
            }
        }
    }
    #set the glitch pv to zero
    if [catch {APScavput -list=B:${supply}:Ramp:AutoCorrGlitchBO=0 -pend=20} result] {
        SetStatus "Error in setting $supply glitch pv: $result"
        ShutdownSystem -runControlPV $runControlPV -errorMessage "$result" 
    }
    if !$IRamp {
        if [catch {CheckBControlStatus -supply $supply} result] {
            SetStatus $result
            ShutdownSystem -runControlPV $runControlPV -errorMessage "Error(CheckBControlStatus): $result"
        }
    }
    if [catch {PVTests} result] {
        SetStatus $result
        ShutdownSystem -runControlPV $runControlPV -errorMessage "Error(PVTests): $result"
    }
    if [catch {PingRunControl -runControlPV $runControlPV} result] {
        SetStatus "Error of PingRunControl before checking BM ramp on/off status: $result"
        ShutdownSystem -runControlPV $runControlPV -errorMessage "$result" 
    }
    #if [catch {GetBControlSupplyValues -supply "$supply" -triggerType "$triggerType" } result] {
    #    SetStatus $result
    #    ShutdownSystem -runControlPV $runControlPV -errorMessage "Error(GetBControlSupplyValues): $result"
    #    exit  
    #}
    if [catch {ReadRMSValues -supply "$supply" } result] {
        SetStatus $result
        ShutdownSystem -runControlPV $runControlPV -errorMessage "Error(GetBControlSupplyValues): $result"
        exit  
    }
    set startedCorrection 0
    if [pv getw $limitVarList] {
        puts stderr "Error reading limit pvs: $errorCode"
        exit 1
    }
    while {abs($pk($supply)) > $rmsStartLimit || ($startedCorrection && abs($pk($supply)) > $rmsStopLimit) } {
        if {$supply=="BM"} {
            set firstConditioning 1
            while {1} {
                #if [catch {APScavget -list=S:BM:StandardizeSUB.PROC -printErrors -pend=30} conditioning] {
                 #   SetStatus "Error in checking SR BM conditioning: $conditioning"
                  #  ShutdownSystem -runControlPV $runControlPV -errorMessage "$conditioning" 
                   # exit
		      # }
		set conditioning 0
                if [catch {PingRunControl -runControlPV $runControlPV} result] {
                    SetStatus "Error of PingRunControl after check SR BM conditioning: $result"
                    ShutdownSystem -runControlPV $runControlPV -errorMessage "$result" 
                    exit
                }
                if $conditioning {
                    if $firstConditioning {
                        SetStatus "Skip BM auto correction when SR BM is conditioning..."
                    }
                    set firstConditioning 0
                    after 1000
                    continue
                } else {
                    break
                }
            }
        }
        if !$IRamp {
            if [catch {CheckBControlStatus -supply $supply} result] {
                SetStatus $result
                ShutdownSystem -runControlPV $runControlPV -errorMessage "Error(CheckBControLStatus): $result"
                exit
            }
        }
        SetStatus "$supply : $triggerType dI/I above limit; waiting 2 seconds..."
        set errorCount 0
        set timeout [expr [clock seconds]+2]
        while {[clock seconds]<$timeout} {
            if [catch {PingRunControl -runControlPV $runControlPV} result] {
                SetStatus $result
                ShutdownSystem -runControlPV $runControlPV -errorMessage "Error(PingRunControl): $result"
                exit
            }
            after 500
        }
        if !$IRamp {
            if [catch {GetBControlSupplyValues -supply "$supply" -triggerType "$triggerType"} result] {
                SetStatus $result
                ShutdownSystem -runControlPV $runControlPV \
                  -errorMessage "Error(GetBControlSupplyValues): $result"
                exit
            }
        } else {
            if [catch {ReadRMSValues -supply "$supply"} result] {
                SetStatus $result
                ShutdownSystem -runControlPV $runControlPV \
                  -errorMessage "Error(GetBControlSupplyValues): $result"
                exit
            }
        }
        if ![CheckSFBMStatus -supply $supply] {
	    break
	}
        if !$IRamp {
            while {[expr {abs($slopeError($supply))}] > $slopeErrorLimit || [expr {abs($zeroError($supply))}] > $zeroErrorLimit} {
                if [catch {CheckBControlStatus -supply $supply} result] {
                    SetStatus $result
                    ShutdownSystem -runControlPV $runControlPV \
                      -errorMessage "Error(CheckBControlStatus): $result"
                    exit
                }
                SetStatus "$supply : slope and/or zero too far from zero to proceed.  Waiting 2 seconds..."
                set timeout [expr [clock seconds]+2]
                while {[clock seconds]<$timeout} {
                    if [catch {PingRunControl -runControlPV $runControlPV} result] {
                        SetStatus $result
                        ShutdownSystem -runControlPV $runControlPV \
                          -errorMessage "Error(PingRunControl): $result"
                        exit
                    }
                    after 500
                }
                if [catch {GetBControlSupplyValues -supply "$supply" -triggerType "$triggerType"} result] {
                    SetStatus $result
                    ShutdownSystem -runControlPV $runControlPV \
                      -errorMessage "Error(GetBControlSupplyValues): $result"
                    exit
                }
                if ![CheckSFBMStatus] {
                    break
                }
                incr errorCount
                if {$errorCount>50} {
                    SetStatus "The slope and zero Error of $supply exceeds the limits after 50 seconds, please check the supply and restart auto-correction."
                    ShutdownSystem -runControlPV $runControlPV -errorMessage "The slope and zero Error of $supply exceeds the limits after 50 seconds, please check the supply and restart auto-correction."
                    exit
                }
            }
            SetStatus "$supply : slope and/or zero error close enough to zero to proceed correction..." 
        }
	if ![CheckSFBMStatus -supply $supply] {
	    break
	}
        incr count
        SetStatus "archive waveform data..."
        set dataFileLabel [APSOffsetDateInfo -today 1 -dateFormat Y-M-D]_[lindex [exec date] 3]
        catch {ArchiveWaveformData -start 1 -dataFileLabel $dataFileLabel -supply $supply} result
        
        if ![CheckSFBMStatus -supply $supply] {
	    break
	}
        SetStatus "start correction..."
        if {$supply=="BM"} {
            set firstConditioning 1
            while {1} {
               # if [catch {APScavget -list=S:BM:StandardizeSUB.PROC -printErrors -pend=30} conditioning] {
                #    SetStatus "Error in checking SR BM conditioning: $conditioning"
                 #   ShutdownSystem -runControlPV $runControlPV -errorMessage "$conditioning" 
                 #   exit
                #}
		set conditioning 0
                if [catch {PingRunControl -runControlPV $runControlPV} result] {
                    SetStatus "Error of PingRunControl after check SR BM conditioning: $result"
                    ShutdownSystem -runControlPV $runControlPV -errorMessage "$result" 
                    exit
                }
                if $conditioning {
                    if $firstConditioning {
                        SetStatus "Skip BM auto correction when SR BM is conditioning..."
                    }
                    set firstConditioning 0
                    after 1000
                    continue
                } else {
                    break
                }
            }
        }
        if [catch {VcorrectAndCheck -supply $supply} result] {
            SetStatus "$result"
            SetStatus "Attempt to correct $supply ramp failed.  \nCorrection is too different from the safety ramp."
            SetStatus "Loading safety ramp..."
            if [catch {APSBoosterLoadSafetyRamp -$supply 1 -IRamp $IRamp \
			   -description "$result, Attempt to correct $supply ramp failed, loading $desc safety ramp" } result] {
                SetStatus "$result"
                catch {ArchiveWaveformData -start 0 -dataFileLabel $dataFileLabel -supply $supply}
                ShutdownSystem -runControlPV $runControlPV -errorMessage "Error(loadSafetyRamps): $result"
            }
            set count 0
        }
        SetStatus "archive waveform data..."
        set dataFileLabel [APSOffsetDateInfo -today 1 -dateFormat Y-M-D]_[lindex [exec date] 3]
        catch {ArchiveWaveformData -start 0 -dataFileLabel $dataFileLabel -supply $supply} result
        set startedCorrection 1
        SetStatus "$supply : ramp corrected for $count times. waiting $waitTime  seconds ..."
        set timeout [expr [clock seconds]+ $waitTime]
        while {[clock seconds]<$timeout} {
            if [catch {PingRunControl -runControlPV $runControlPV} result] {
                SetStatus $result
                catch {ArchiveWaveformData -start 0 -dataFileLabel $dataFileLabel -supply $supply}
                ShutdownSystem -runControlPV $runControlPV -errorMessage "Error(PingRunControl): $result"
            }
            after 500
        }
        if !$IRamp {
            if [catch {GetBControlSupplyValues -supply "$supply" -triggerType "$triggerType"} result] {
                SetStatus "$result"
                catch {ArchiveWaveformData -start 0 -dataFileLabel $dataFileLabel -supply $supply }
                ShutdownSystem -runControlPV $runControlPV -errorMessage "Error(GetBControlSupplyValues): $result"
            }
        } else {
            if [catch {ReadRMSValues -supply "$supply"} result] {
                SetStatus "$result"
                catch {ArchiveWaveformData -start 0 -dataFileLabel $dataFileLabel -supply $supply }
                ShutdownSystem -runControlPV $runControlPV -errorMessage "Error(GetBControlSupplyValues): $result"
            }
        }
        if ![CheckSFBMStatus -supply $supply] {
            break
        }
        if {abs($pk($supply)) <= $rmsStopLimit} {
            SetStatus "$supply rms reaches the stop-correction limit, stop correction after correction for $count times."
	    if [catch {exec logMessage -sourceId=${supply}AutoCorrection -tag=applicationName BRampAutoCorr \
			   -tag=user "$apsScriptUser" -tag=host "$apsScriptHost" -tag=execution VCorrectAndCheck \
			   -tag=action VcorrectCompleted \
			   -tag=description "Auto-correction was completed after $count times correction, the $triggerType dI\/I is within spec now."} result] {
		SetStatus "logMessage error19: $result"
		# ShutdownSystem -runControlPV $runControlPV -errorMessage "logMessage error19: $result"
	    }
            break
        }
        if {$count>=50} {
            #load safety ramp
	    if [catch {exec logMessage -sourceId=${supply}AutoCorrection -tag=applicationName BRampAutoCorr \
			   -tag=user "$apsScriptUser" -tag=host "$apsScriptHost" -tag=execution VCorrectAndCheck \
			   -tag=action Failed \
			   -tag=description "Auto-correction failed after 50 corrections, loading safety"} result] {
		SetStatus "logMessage error19: $result"
		# ShutdownSystem -runControlPV $runControlPV -errorMessage "logMessage error19: $result"
	    }
            SetStatus "load safety ramp for $supply after $count ramp correction attempts."
            if [catch {APSBoosterLoadSafetyRamp -$supply 1 -IRamp $IRamp \
                         -description "loading $desc safety ramp for $supply after $count ramp correction attempts." } result] {
                SetStatus "$result"
                catch {ArchiveWaveformData -start 0 -dataFileLabel $dataFileLabel -supply $supply }
                ShutdownSystem -runControlPV $runControlPV -errorMessage "Error(loadSafetyRamps): $result"
            }
            incr safetyLoad
            set count 0
        }
        
        if {$safetyLoad > 5} {
            SetStatus "Automatic ramp corrector for $supply corrupted!"
            catch {ArchiveWaveformData -start 0 -dataFileLabel $dataFileLabel -supply $supply}
            ShutdownSystem -runControlPV $runControlPV -errorMessage "Automatic ramp corrector for $supply was corrupted!"
            exit
        }
        
        set withincount 0
        while {abs($pk($supply)) < $rmsStopLimit} {
            if [catch {CheckBControlStatus -supply $supply} result] {
                SetStatus $result
                ShutdownSystem -runControlPV $runControlPV -errorMessage "Error(CheckBControlStatus): $result"
                exit
            }
            if [catch {PVTests} result] {
                SetStatus $result
                ShutdownSystem -runControlPV $runControlPV -errorMessage "Error(PVTests): $result"
            }
            if !$withincount {
                catch {ArchiveWaveformData -start 0 -dataFileLabel $dataFileLabel -supply $supply}
                SetStatus "$supply : ramp $triggerType dI/I is within spec for now..."
                if [catch {exec logMessage -sourceId=${supply}AutoCorrection -tag=applicationName BRampAutoCorr \
			       -tag=user "$apsScriptUser" -tag=host "$apsScriptHost" -tag=execution VCorrectAndCheck \
			       -tag=action VcorrectCompleted \
			       -tag=description "Auto-correction was completed\, the $triggerType dI\/I is within spec now."} result] {
                    SetStatus "logMessage error19: $result"
                   # ShutdownSystem -runControlPV $runControlPV -errorMessage "logMessage error19: $result"
                }
            }
            set withincount 1
            if [catch {PingRunControl -runControlPV $runControlPV} result] {
                SetStatus $result
                ShutdownSystem -runControlPV $runControlPV -errorMessage "Error(PingRunControl): $result"
            }
            if [catch {GetBControlSupplyValues -supply "$supply" -triggerType "$triggerType" } result] {
                SetStatus $result
                ShutdownSystem -runControlPV $runControlPV -errorMessage "Error(GetBControlSupplyValues): $result"
            }
            set count 0
            set safetyLoad 0
            after 1000
        }
        if $withincount {
            SetStatus "\n Auto-correction started again..."
        }
        if [pv getw $limitVarList] {
            puts stderr "Error reading limit pvs: $errorCode"
            exit 1
        }
    }
    if [catch {PingRunControl -runControlPV $runControlPV} result] {
        SetStatus $result
        ShutdownSystem -runControlPV $runControlPV -errorMessage "Error(PingRunControl): $result"
    }
    APSRunControlLogMessage -message "Running" -severity 0
    after 1000
}
exit
