
proc APSMpRestoreScalarCorrectorsInfo {} {
    return "This procedure restores corrector setpoints from the UBOP or the injection reference file. It is useful for restoring normal orbit after the beam was dumped by correctors \"gone wild\" (or other reasons) in vector mode. The correctors remain in scalar mode at the end of the procedure."
}

#This procedure has been placed in the attic
proc APSMpRestoreScalarCorrectors {args} {
    #following steps are used for restoring orbit
    #a) make sure there is no stored beam.
    #b) Open RTFB loops. Set BPM setpoints to zero.
    #c) Set all correctors to scalar mode.
    #d) Ramp SCR SteeringPS from UBOP. (20 steps is ok).
    set referenceFile /home/helios/oagData/SCR/snapshots/SR/SR-UserBeamPreferred.gz
    set paramFile /home/helios/oagData/sr/rtfeedback/parameterFiles/srfb-default.param

    set plane both
    set statusVar ""
    APSMpStep init -promptDialog APSMpRestoreScalarCorrectorsInitDialog \
      -vars {plane referenceFile} -proc APSMpRestoreScalarCorrectors
    if ![string length $plane] {
        APSStrictParseArguments {plane statusVar}
        if ![string length $plane] {
            APSMpReturn error "Plane is not chosen"
        }
    }
    if [string length $statusVar] {
        APSSetVarAndUpdate $statusVar "Restoring scalar correctors in $plane plane ..."
    }
    if [string length $statusVar] {
        APSSetVarAndUpdate $statusVar "1. Loading Parameters ..."
    }
    APSMpStep "Load Parameters"
    if [catch {APSReadExecuteParamFile -filename $paramFile -readonly 1} result] {
        APSMpReturn error "APSMpRestoreScalarCorrectors: $result"
    }
    if [string length $statusVar] {
        APSSetVarAndUpdate $statusVar "2. Check if there is stored beam.."
    }
    APSMpStep "check if there is stored beam"
    if [catch {exec cavget -list=S-DCCT:CurrentM \
             } current] {
        APSMpReturn error "APSMpRestoreScalarCorrectors: $current"
    }
    if [expr abs($current) > 0.1] {
        if {[tk_dialog2 .warningDialog "Warning Message" \
               "Stored beam exists, are you sure to continue?" \
               warning -1 Continue Cancel] == 1} {
            APSMpReturn error "APSMpRestoreScalarCorrectors: stored beam exists."
        }
    }

    APSMpStep "Open RTFB loops"
    if [string length $statusVar] {
        APSSetVarAndUpdate $statusVar "3. Open RTFB loops.."
    }
    if [catch {APSOpenRTFBLoops } result] {
        APSMpReturn error "APSMpSRRestoreScalarCorrectors: $result"
    }
    APSMpStep "Set BPM setpoints to zero."
    if [string length $statusVar] {
        APSSetVarAndUpdate $statusVar "4. Set BPM setpoints to zero.."
    }
    if [catch {APSZeroRTBPMSetpoints -plane $plane} result] {
        APSMpReturn error "APSMpSRRestoreScalarCorrectors: $result"
    }
    APSMpStep "Set correctors to scalar mode."
    if [string length $statusVar] {
        APSSetVarAndUpdate $statusVar "5. Set correctors to scalar mode.."
    }
    if [catch {APSSetCorrMode -corrMode scalar -plane $plane} result] {
        APSMpReturn error "APSMpSRRestoreScalarCorrectors: $result"
    }
    APSMpStep "Ramp SCR SteeringPS from reference file. (20 steps is ok)"
    if [string length $statusVar] {
        APSSetVarAndUpdate $statusVar "6. Ramp SCR SteeringPS from reference file (20 steps is ok).."
    }
    set tmpfile /tmp/[APSTmpString]
    APSAddToTmpFileList -ID 1 -fileList $tmpfile
    switch $plane {
        h -
        v {
            set Plane [string toupper $plane]
            if [catch {eval exec sddsprocess $referenceFile \
                         {"-match=column,ValueString=,!"} \
                         -match=col,ControlName=SFB*CurrentAO \
                         {"-match=column,ControlName=*${Plane}*"} \
                         -match=col,Category=SteeringPS $tmpfile -noWarn} result] {
                APSMpReturn error "APSMpRestoreSteeringPS1: $result"
            }
        }
        both {
            if [catch {eval exec sddsprocess $referenceFile \
                         {"-match=column,ValueString=,!"} \
                         -match=col,ControlName=SFB*CurrentAO \
                         -match=col,Category=SteeringPS $tmpfile -noWarn} result] {
                APSMpReturn error "APSMpRestoreSteeringPS1: $result"
            }
        }
        default {
            APSMpReturn error "APSMpSRRestoreScalarCorrectors: Invalid plane given"
        }
    }
    set logFile /tmp/SRLog[APSTmpString]
    APSAddToTmpFileList -ID 1 -fileList $logFile
    if [catch {APSRampToSnapshot -initDialog 1 -steps 20 \
                 -logFile $logFile -fileName $tmpfile } result] {
        if {[tk_dialog2 .warningDialog "Warning Message" \
               "$result\n\nProblem with ramping $tmpfile setting\n\nNote that the restoration of configuration may be incomplete." \
               warning -1 Continue Abort] == 1} {
            APSMpReturn error "APSMpSRRestoreScalarCorrectors: $result"
        }
    } 
    if [string length $statusVar] {
        APSSetVarAndUpdate $statusVar "Restore scalar corrector in $plane plane done."
    }
    APSMpReturn ok
}

proc APSOpenRTFBLoops {args} {
    global hpFilterInitialVert hpFilterInitialHoriz 
    set plane ""
    APSStrictParseArguments {plane}
    switch $plane {
        h {
            if [catch {exec cavput -pend=10 -list=SRFB:MPS:resetBO=1; \
                         exec cavput -pend=10 -list=SRFB:GBLM:DSPLoadParamsBO=1; \
                         exec cavput -pend=10 -list=SRFB:GBL:Hor:CloseLoopBO=1,SRFB:GBL:Vert:CloseLoopBO=1; \
                         exec cavput -pend=10 -list=SRFB:GBL:Hor:CloseLoopBO=0,SRFB:GBL:Vert:CloseLoopBO=0; } error] {
                APSMpReturn error "APSMpSROpenRTFPLoops: $error"
            }
            if [catch {exec cavput -pend=15 -list=SRFB:fhSlAO=$hpFilterInitialHoriz; \
                         exec cavput -pend=15 -list=SRFB:GBL:loadBO=1} error] {
                APSMpReturn error "APSMpSROpenRTFPLoops: $error"
            } 
        }
        v {
            if [catch {exec cavput -pend=15 -list=SRFB:GBL:Hor:CloseLoopBO=0,SRFB:GBL:Vert:CloseLoopBO=0; \
                         exec cavput -pend=10 -list=SRFB:GBLM:Hor:CloseLoopBO=1,SRFB:GBLM:Vert:CloseLoopBO=1; \
                         exec cavput -pend=10 -list=SRFB:GBLM:Hor:CloseLoopBO=1,SRFB:GBLM:Vert:CloseLoopBO=1; \
                         exec cavput -pend=10 -list=SRFB:MPS:resetBO=1; \
                         exec cavput -pend=10 -list=SRFB:GBLM:DSPLoadParamsBO=1; } error] {
                APSMpReturn error "APSMpSROpenRTFPLoops: $error"
            }
            if [catch {exec cavput -pend=15 -list=SRFB:fhAO=$hpFilterInitialVert; \
                         exec cavput -pend=15 -list=SRFB:GBL:loadBO=1} error] {
                APSMpReturn error "APSMpSROpenRTFPLoops: $error"
            }
        }
        both {
            if [catch {exec cavput -pend=15 -list=SRFB:GBL:Hor:CloseLoopBO=0,SRFB:GBL:Vert:CloseLoopBO=0; \
                         exec cavput -pend=10 -list=SRFB:GBLM:Hor:CloseLoopBO=1,SRFB:GBLM:Vert:CloseLoopBO=1; \
                         exec cavput -pend=10 -list=SRFB:GBLM:Hor:CloseLoopBO=1,SRFB:GBLM:Vert:CloseLoopBO=1; \
                         exec cavput -pend=10 -list=SRFB:MPS:resetBO=1; \
                         exec cavput -pend=10 -list=SRFB:GBLM:DSPLoadParamsBO=1; \
                         exec cavput -pend=10 -list=SRFB:GBL:Hor:CloseLoopBO=1,SRFB:GBL:Vert:CloseLoopBO=1; \
                         exec cavput -pend=10 -list=SRFB:GBL:Hor:CloseLoopBO=0,SRFB:GBL:Vert:CloseLoopBO=0; } error] {
                APSMpReturn error "APSMpSROpenRTFPLoops: $error"
            }
            if [catch {exec cavput -pend=15 -list=SRFB:fhAO=$hpFilterInitialVert,SRFB:fhSlAO=$hpFilterInitialHoriz; \
                         exec cavput -pend=15 -list=SRFB:GBL:loadBO=1} error] {
                APSMpReturn error "APSMpSROpenRTFPLoops: $error"
            }
        }
    }
    APSMpReturn ok
}

proc APSZeroRTBPMSetpoints {args} {
    set plane both
    APSStrictParseArguments {plane}
    if [catch {exec cavget  -pend=15 -list=SRFB:GBL:Hor:CloseLoopBO} hloop] {
        return -code error "ZeroRTBPMSetpoints: Error reading hloop: $hloop"
    }
    if [catch {exec cavget  -pend=15 -list=SRFB:GBL:Vert:CloseLoopBO} vloop] {
        return -code error "ZeroRTBPMSetpoints: Error reading vloop: $vloop"
    }

    if {[string match $hloop "Close"] || [string match $vloop "Close"]} {
        return -code error "Can't set bpm setpoints to zero when at least one loop is closed."
    }
    for {set i 1} {$i<41} {incr i} {
        set ioc [expr ($i - 1) / 2 * 2 + 1]
        lappend listArguments S${ioc}FB:GB${i}
    }
    switch $plane {
        both {
            exec cavput -list=[join $listArguments ,] -list=:bpm -list=1,2,3,4 \
              -list=:x,:y -list=:RefAO=0
        }
        h {
            exec cavput -list=[join $listArguments ,] -list=:bpm -list=1,2,3,4 \
              -list=:x:RefAO=0
        }
        v {
            exec cavput -list=[join $listArguments ,] -list=:bpm -list=1,2,3,4 \
              -list=:y:RefAO=0
        }
    }
    return ok
}

proc APSReadExecuteParamFile {args} {
    set readonly 0

    APSStrictParseArguments {filename readonly}
    set ControlNames [APSGetSDDSColumn -fileName $filename -column ControlName]
    set ControlTypes [APSGetSDDSColumn -fileName $filename -column ControlType]
    set ValueStrings [APSGetSDDSColumn -fileName $filename -column ValueString]

    foreach ControlName $ControlNames ControlType $ControlTypes ValueString $ValueStrings {
        switch $ControlType {
            pv {
                if !$readonly {
                    if [catch {exec cavput -pend=15 \
                                 -list=$ControlName=$ValueString \
                             } error]  {
                        return -code error $error
                    }
                }
            }
            pvList {
                if !$readonly {
                    if [catch {eval exec cavput -pend=15 -list=$ControlName  $ValueString \
                             } error] {
                        return -code error $error
                    }
                }
            }
            proc {
                if !$readonly {
                    # check the given command exists
                    set procName $ControlName
                    if {[info proc $procName] == ""} {
                        return -code error "Unrecognized procedure $procName"
                    } else {
                        $procName $ValueString
                    }
                }
            }
            set {
                global $ControlName
                set $ControlName $ValueString
            }
            default {
                return -code error "Unrecognized Parameter File ControlType: $ControlType"
            }
        }
    }
}

proc APSMpRestoreScalarCorrectorsInitDialog {frame} {
    global APSMpRestoreScalarCorrectors
    set APSMpRestoreScalarCorrectors(plane) both
    
    pack [frame $frame.f1]    
    APSRadioButtonFrame .plane -parent $frame.f1 -variable APSMpRestoreScalarCorrectors(Plane) \
      -buttonList {Horizontal Vertical Both} -valueList {h v both} \
      -label "Plane for restoring scalar correctors:   " -orientation horizontal \
      -contextHelp "Choose plane to restore scalar correctors"  
    APSRadioButtonFrame .referenceFile -parent $frame.f1 -variable APSMpRestoreScalarCorrectors(referenceFile) \
      -buttonList {"UBOP (gaps closed)" "Injection (gaps open)"} -valueList {/home/helios/oagData/SCR/snapshots/SR/SR-UserBeamPreferred.gz /home/helios/oagData/SCR/snapshots/SR/SR-InjectionOpenGaps.gz} \
      -label "Plane for restoring scalar correctors:   " -orientation horizontal \
      -contextHelp "Choose reference file from which to restore scalar correctors"  
    APSMpReturn ok
}

proc APSMpCloseRTFBLoops {args} {
    
    global abort
    global hpFilterCutoffVert hpFilterCutoffHoriz hpFilterInitialVert hpFilterInitialHoriz
    global hpFilterRampPoints hpFilterRampInterval
    
    set abort 0
    set plane ""
    APSStrictParseArguments {plane}
    switch $plane {
        h {
            set runHloop 1
            set runVloop 0
        }
        v {
            set runHloop 0
            set runVloop 1
        }
        both {
            set runHloop 1
            set runVloop 1
        }
        default {
            return -code error "Invalid plane given (should be h, v or both)"
        }
    }
    
    if {[APSVerifyCorrectorModeSwitches -wrongMode Maintenance -plane $plane] == -1} {
        return -code error "Wrong modes found!"
    }
    
    #set status "Setting initial highpass filter values..."; update
    if $runHloop {
	if [catch {exec cavput -pend=15 -list=SRFB:fhSlAO=$hpFilterInitialHoriz; \
		       exec cavput -pend=15 -list=SRFB:GBL:loadBO=1} error] {
	    return -code error $error
	}
    }
    if $runVloop {
	if [catch {exec cavput -pend=15 -list=SRFB:fhAO=$hpFilterInitialVert; \
		       exec cavput -pend=15 -list=SRFB:GBL:loadBO=1} error] {
	    return -code error $error
	}
    }
    #set status "Disabling AC voltmeter..."; update
    if [catch {exec cavput -pend=15 -list=SRFB:D85:ACV:EnableBO=Disable \
	       } error] {
        return -code error $error
    }
    
    #set status "Closing feedback loops..."; update
    if $runHloop {
	if [catch {exec cavput -pend=15 \
		       -list=SRFB:GBL:Hor:CloseLoopBO=${runHloop}} error] {
	    return -code error $result
	}
    }
    if $runVloop {
	if [catch {exec cavput -pend=15 \
		       -list=SRFB:GBL:Vert:CloseLoopBO=${runVloop}} error] {
	    return -code error $result
	}
    }
    # wait to ensure system does not trip
    exec sleep $hpFilterRampInterval
    exec sleep $hpFilterRampInterval
    if [catch {exec cavget  -pend=15 -list=SRFB:GBL:Hor:CloseLoopBO} hloop] {
       return -code error "Error reading hloop: $hloop"
    }
    if [catch {exec cavget  -pend=15 -list=SRFB:GBL:Vert:CloseLoopBO} vloop] {
        return -code error "Error reading vloop: $vloop"
    }

    if {(($runHloop && ($hloop == "Close")) || ($runVloop && ($vloop == "Close"))) } {
        set status "Ramping high pass filter..."; update
        set index 0
        while {($index < $hpFilterRampPoints) && ($abort == 0)} {
            if { $runHloop && ($hloop == "Close") } {
                set value [exec rpnl "$hpFilterInitialHoriz $hpFilterCutoffHoriz / log \
             $hpFilterRampPoints 1 - / $index * $hpFilterInitialHoriz log - -1 * 10 swap pow"]
               # set status [format "Setting horizontal highpass to %4.3gHz" $value]; update

                if [catch {exec cavput -pend=15 -list=SRFB:fhSlAO=$value; \
                             exec cavput -pend=15 -list=SRFB:GBL:loadBO=1} error] {
                    #set status "Error setting horizontal regulator: $error"; update
                    return -code error "Error setting horizontal regulator: $error"
                }
            }
            if { $runVloop && ($vloop == "Close") } {
                set value [exec rpnl "$hpFilterInitialVert $hpFilterCutoffVert / log \
             $hpFilterRampPoints 1 - / $index * $hpFilterInitialVert log - -1 * 10 swap pow"]
               # set status [format "Setting vertical   highpass to %4.3gHz" $value]; update

                if [catch {exec cavput -pend=15 -list=SRFB:fhAO=$value; \
                             exec cavput -pend=15 -list=SRFB:GBL:loadBO=1} error] {
                   # set status "Error setting vertical regulator: $error"; update
                    return -code error "Error setting vertical regulator: $error"
                }
            }
            APSWaitWithUpdate -waitSeconds $hpFilterRampInterval -updateInterval 1
            incr index
        }
        if $abort {
          #  set status "Aborted"; update
            return "Aborted"
        } else {
          #  set status "Done."; update
            return "Done"
        }
    } else {
        set status "Error: loops tripped or failed to close"
    }
}

proc APSVerifyCorrectorModeSwitches {args} {
    set plane ""
    set wrongMode ""
    APSStrictParseArguments {wrongMode plane}
    
    switch $plane {
        h -
        v {
            set planes [string toupper $plane]
        }
        both {
            set planes {H V}
        }
    }
    set corrList ""
    foreach pl $planes {
        if [catch {exec cavget -list=S -range=beg=1,end=40 \
                     -list=A:${plane}1,A:${pl}2,A:${pl}4,B:${pl}4,B:${pl}3,B:${pl}2,B:${pl}1 \
                     -list=:ControlSrcBO -dry} dryList] {
            return -code error "$dryList"
        }
        set corrList [concat $corrList $dryList]
    }
    if [catch {exec cavget -list=[join $corrList ,] -pend=10 -label -embrace } modes] {
        return -code error "$modes"
    }
    set bad ""
    foreach item $modes {
        if {[lsearch $item $wrongMode] != -1} {
            lappend bad [string trimright [lindex $item 0] :ControlSrcBO]
        }
    }
    if {[llength $bad] != 0} {
        if ![APSQueryToProceed -message "Warning: the following correctors are in $wrongMode mode [join $bad ,] \
          Are you sure you want to continue?"] {
              return -1
          }
    }
    return 1
}

