
proc APSMpRTFBRebootInfo {args} {
    return "This procedure runs automatic steps before and after a manual RTFB reboot. The user will be prompted to execute the actual reboot at the appropriate time."
}

#This procedure has been placed in the attic
proc APSMpRTFBReboot {args} {
    APSMpStep init -promptDialog "APSMpPromptInitDialog"
    APSMpStep "Aborting top-up..."
    if [catch {exec cavput -list=Mt:TopUpAutoEnableC.VAL=0} result] {
        APSMpReturn error "Unable to disable top up: $result"
    }
    if [catch {exec cavput -list=S:TopupBucketAssignmentRC.ABRT=1 } result] {
        APSMpReturn error "Unable to abort topup controllaw: $result"
    }
    APSMpStep "Suspend rf frequency controllaw and circumference controllaw."
    if [catch  {exec cavput -list=S:rfFreqControlLawRC.SUSP=1,S:circumferenceChangeRC.SUSP=1 } result] {
        APSMpReturn error "Unable to suspend rf frequency controllaw and circumference controllaw: $result"
    }
    APSMpStep "Starting pre-boot procedures..."
    APSMpRTFBPreReboot
    APSMpStep "Starting boot and post-boot procedures..."
    APSMpRTFBPostReboot
   
    APSMpStep "Resume rf frequency controllaw and circumference controllaw."
    if [catch  {exec cavput -list=S:rfFreqControlLawRC.SUSP=0,S:circumferenceChangeRC.SUSP=0 } result] {
        APSMpReturn error "Unable to suspend rf frequency controllaw and circumference controllaw: $result"
    }
    
    APSMpStep "Starting top-up ..."
    set answer [tk_dialog2 .warning "Warning Message" \
                  "Manually start top-up, press \"continue\" if done or \"Abort\" to abort" \
                  warning -1 Continue Abort]
    if $answer==1 {
        APSMpReturn error "RTFB post-reboot was aborted!"
    }
    #if [catch {exec cavput -list=Mt:TopUpAutoEnableC.VAL=1} result] {
    #    APSMpReturn error "Unable to enable top up: $result"
    #}
    #if [catch {exec cavput -list=S:TopupBucketAssignmentRC.RUN=1 } result] {
    #    APSMpReturn error "Unable to start topup controllaw: $result"
    #}
   
    APSMpReturn ok
}


proc APSMpRTFBPreRebootInfo {args} {
    return "This procedure helps to prepare for rebooting RTFB."
}

proc APSMpRTFBPreReboot {args} {
    global apshpFilterCutoffVert apshpFilterCutoffHoriz apshpFilterInitialVert apshpFilterInitialHoriz 
    global apshpFilterRampPoints apshpFilterRampInterval
    
    APSMpSetRTFBGlobalParameters -readonly 1
    
    APSMpStep "Inform the floor coordinator ..."
    set answer [tk_dialog2 .warning "Warning Message" \
                  " Please inform the floor coodinator that you are preparing for rebooting RTFB system, press \"continue\" to start or \"Abort\" to abort" \
                  warning -1 Continue Abort]
    if $answer==1 {
        APSMpReturn error "RTFB pre-reboot was aborted!"
    }
    #test if the injector is available
    APSMpStep "Check if the injector is available..."
    if [catch {WaitForTaskToFinish -cavget "APScavget -list=BTS:CM:q -pend=10 -label" \
                 -waitLimit 2 \
                 -updateInterval 1 \
                 -checkExpression {$value < 0.5} } results] {
        if {[APSPEMTKDialog .warningDialog -text "APSMpRTFBPreReboot: Problem occurred while waiting for the injector charge to be greater than 0.5 nC\n$results"] == 1} {
            APSMpReturn error "APSMpRTFBPreReboot: $results"
        }
    }

    APSMpStep "Abort both horizontal and vertical orbit controllaw"
    if [catch {APSMpAbortSRControllaw} result] {
        APSMpReturn error "APSMpRTFBPreReboot1: $result"
    }
   
    APSMpStep "Suspend dp offset transfer..."
    if [catch {exec cavput -list=SR:CorrectorFFTransferRC.SUSP=1 } result] {
	APSMpReturn error "Unable to suspend dp offset transfer: $result"
    }
    APSMpStep "Disable DC corrector vectors"
    if [catch {APSSetCorrMode -plane both -corrMode scalar} result] {
        APSMpReturn error "APSMpRTFBPreReboot2: $result"
    }

    APSMpStep "Reset/Open All RTFB Loops"
    if [catch {APSMpRTFBResetOpenLoops -hpFilterInitialVert $apshpFilterInitialVert \
                 -hpFilterInitialHoriz $apshpFilterInitialHoriz } result] {
        APSMpReturn error "APSMpRTFBPreReboot3: $result"
    }
    APSMpStep "Set RTFB corrector to Maintenance Mode ..."
    if [catch {APSSetRTFBCorrectorMode -all 0 -mode Maintenance} result] {
        APSMpReturn error "APSMpRTFBPreReboot4: $result"
    }
   
    APSMpStep "Verify all RTFB correctors are in maintenance mode..."
    set corrList [APSGetRTFBCorrectorList -all 0 -plane both]
    if [catch {WaitForTaskToFinish -cavget "APScavget -list=[join $corrList ,] -list=:ControlSrcBO -pend=30 -label" \
                 -waitLimit 1 \
                 -updateInterval 1  \
                 -checkExpression {$value != "Maintenance" } } results] {
        if {[APSPEMTKDialog .warningDialog -text "APSMpRTFBPreReboot: Problem occurred while waiting for setting the RTFB corrector to maintenance mode\n$results"] == 1} {
            APSMpReturn error "APSMpRTFBPreReboot: $results"
        }
    }
    APSMpStep "Set all other correctors to maintenance mode"
    if [catch {APSSetCorrMode -plane both -sourceMode Maintenance} result] {
        APSMpReturn error "APSMpRTFBPreReboot: $result"
    }
    if [catch {WaitForTaskToFinish -cavget "APScavget -list=S -range=beg=1,end=40 -list=A:H1,A:H2,A:H4,A:V1,A:V2,A:V4,B:H4,B:H3,B:H2,B:H1,B:V4,B:V3,B:V2,B:V1 -list=:ControlSrcBO -pend=30 -label" \
                 -waitLimit 1 \
                 -updateInterval 1  \
                 -checkExpression {$value != "Maintenance" } } results] {
        if {[APSPEMTKDialog .warningDialog -text "APSMpRTFBPreReboot: Problem occurred while waiting for setting the DC correctors to Maintenace mode\n$results"] == 1} {
            APSMpReturn error "APSMpRTFBPreReboot6: $results"
        }
    }
    APSMpReturn ok
}

proc APSMpRTFBPostRebootInfo {args} {
    return "This procedure helps to let all channel accesses to reconnect after RTFB is rebooted."
}

proc APSMpRTFBPostReboot {args} {
    global apshpFilterCutoffVert apshpFilterCutoffHoriz apshpFilterInitialVert apshpFilterInitialHoriz
    global apshpFilterRampPoints apshpFilterRampInterval
    
    APSMpSetRTFBGlobalParameters -readonly 1
    
    APSMpStep "Wait for manually reboot RTFB ioc..."
    set answer [tk_dialog2 .warning "Warning Message" \
                  "Manually reboot RTFB ioc., press \"continue\" if done or \"Abort\" to abort" \
                  warning -1 Continue Abort]
    if $answer==1 {
        APSMpReturn error "RTFB post-reboot was aborted!"
    }
    APSMpStep "Restore the SR BPM setpoints and offsets from reference file ..."
    if [catch {APSMpRestoreSRBPMOffsetsAndSetpoints -datapool 1} result] {
        APSMpReturn error "APSMpRTFBPostReboot1: $result"
    }
    APSMpStep "Restore the SRXrayBPM system..."
    if [catch {exec sddsprocess /home/helios/oagData/SCR/snapshots/SRXrayBPM/SRXrayBPM-UserBeamPreferred.gz -pipe=out \
                 "-match=col,IsReadOnly=n" \
                 | sddscasr -pipe=in -pend=60 -restore } result] {
        APSMpReturn error "APSMpRTFBPostReboot2a -- error restoring SRXrayBPM: $result"
    }
    APSMpStep "Restore the SRXrayBPMWaveform system..."
    set filename [file readlink /home/helios/oagData/SCR/snapshots/SRXrayBPMWaveform/SRXrayBPMWaveform-UserBeamPreferred.gz]
    set waveformFile [file root $filename].waveform.gz
    if ![file exist $waveformFile] {
        APSMpReturn error "APSMpRTFBPostReboot2b -- error $waveformFile for SRXrayBPMWavefor user operation does not exist!"
    }
    if [catch {exec sddswput $waveformFile -pend=60} result] {
        APSMpReturn error "APSMpRTFBPostReboot2c -- error restoring SRXrayBPM user operation: $result"
    }
    APSMpStep "Initialize RTFB ..."
    if [catch {APSMpInitializeRTFBSystem} result] {
        APSMpReturn error "APSMpRTFBPostReboot2: $result"
    }
   
    APSMpStep "Set RTFB to operation mode"
    if [catch {APSSetRTFBCorrectorMode -mode Operation -all 0} result] {
        APSMpReturn error "APSMpRTFBPostReboot2a: $result"
    }
    APSMpStep "Check and clear any fault on RTFB main screens, such as reflect memory fault, stopped dsp ect."
    tk_dialog2 .warning "Warning Message" "Please check and clear any fault on RTFB main screens, such as reflective memory fault, stopped dsp ect. Press \"OK\" to continue" warning -1 OK
    
    APSMpStep "Reset/Open all RTFB loops (close any tripped local loops)..."
    if [catch {APSMpRTFBResetOpenLoops -hpFilterInitialVert $apshpFilterInitialVert \
                 -hpFilterInitialHoriz $apshpFilterInitialHoriz } result] {
        APSMpReturn error "APSMpRTFBPostReboot4: $result"
    }
    
    APSMpStep "Set all DC correctors to Operation mode..."
    if [catch {APSSetCorrMode -plane both -sourceMode Operation} result] {
        APSMpReturn error "APSMpRTFBPostReboot5: $result"
    }
    
    APSMpStep "Check if all DC correctors are in Operation mode ..."
    
    if [catch {WaitForTaskToFinish -cavget "APScavget -list=S -range=beg=1,end=40 -list=A:H1,A:H2,A:H4,A:V1,A:V2,A:V4,B:H4,B:H3,B:H2,B:H1,B:V4,B:V3,B:V2,B:V1 -list=:ControlSrcBO -pend=30 -label" \
                 -waitLimit 1 \
                 -updateInterval 1  \
                 -checkExpression {$value != "Operation" } } results] {
        if {[APSPEMTKDialog .warningDialog -text "APSMpRTFBPreReboot: Problem occurred while waiting for setting the DC correctors to Operation mode\n$results"] == 1} {
            APSMpReturn error "APSMpRTFBPostReboot6: $results"
        }
    }
    
    APSMpStep "resum dp offset transfer..."
    if [catch {exec cavput -list=SR:CorrectorFFTransferRC.SUSP=0 } result] {
	APSMpReturn error "Unable to resume dp offset transfer: $result"
    }
    APSMpStep "Restart orbit controllaw..."
    tk_dialog2 .warning "Warning Message:" \
      "Restart orbit controllaw by press \"Start\" button in SROrbitControllaw program and wait for the orbit to converge. Press \"Continue\" to continue" \
      warning -1 Continue
    APSMpStep "Reset/Open RTFB loops..."
    if [catch {APSMpRTFBResetOpenLoops -hpFilterInitialVert $apshpFilterInitialVert \
                 -hpFilterInitialHoriz $apshpFilterInitialHoriz} result] {
        APSMpReturn error "APSMpRTFBPostReboot7: $result"
    }
    APSMpStep "Close RTFB loops..."
    if [catch {APSMpRTFBCloseLoops -hpFilterCutoffVert $apshpFilterCutoffVert \
                 -hpFilterCutoffHoriz $apshpFilterCutoffHoriz \
                 -hpFilterInitialVert $apshpFilterInitialVert \
                 -hpFilterInitialHoriz $apshpFilterInitialHoriz \
                 -hpFilterRampPoints $apshpFilterRampPoints \
                 -hpFilterRampInterval $apshpFilterRampInterval } result] {
        APSMpReturn error "APSMpRTFBPostReboot8: $result"
    }
    APSMpStep "Make SR routine save..."
    set result ""
    set retry 1
    while {$retry} {
        if [catch {APSSaveMachine -machine SR \
                     -description "Routine save: Save after RTFB reboot"} result] {
            APSMpReturn error "APSMpRTFBPostReboot: $result"
        }
        set retry 0
        set snapshot [lindex $result 0]
        if {[llength $result] > 1 } {
            APSFileDisplayWindow [APSUniqueName .burtlog] -fileName [lindex $result 1] \
              -comment "Burt log file returned when attempting to save correctors." \
              -width 80 \
              -contextHelp "Burt log file returned when attempting to save correctors."
            # query for retry, quit or blunder ahead
            switch [APSMultipleChoice [APSUniqueName .] -modal 1 -question "An error has been detected during the initial SR save. The most convenient thing to do is to retry a save.  If after several retries the problem still occurs, you should investigate possible IOC problems." -labelList {"Retry save" "Quit" "Blunder ahead"} -returnList {retry quit blunderAhead} -name "Retry save operation or quit steering?"] {
                retry {
                    set retry 1
                }
                quit {
                    set retry 0
                    APSMpReturn error "APSMpRTFBPostReboot: See info in [lindex $result 1]"
                }
                blunderAhead {
                    set retry 0
                }
            }
        }
    }
   APSMpReturn ok
}


proc APSMpAbortSRControllaw {args} {
    global orbitCorrectionWasRunning dpOrbitCorrectionWasRunning
    set orbitCorrectionWasRunning 0
    set dpOrbitCorrectionWasRunning 0
    foreach coord {X Y} {
        if [catch {exec cavget -list=S:RC:OrbitControlLaw${coord}C.RUN -pend=10} wasRunning1] {
            return -code error $wasRunning1
        }
        if {$wasRunning1=="?"} {
            return -code error "Unable to get value of S:RC:OrbitControlLaw${coord}C.RUN!"
        }
        if $wasRunning1 {
            set orbitCorrectionwasRunning 1
        }
        if [catch {exec cavget -list=DP:S:OrbitControlLaw${coord}SDDS.RUN -pend=10} wasRunning2] {
            return -code error $wasRunning2
        }
        if {$wasRunning2=="?"} {
            return -code error "Unable to get value of DP:S:OrbitControlLaw${coord}SDDS.RUN!"
        }
        if $wasRunning2 {
            set dpOrbitCorrectionWasRunning 1
        }
    }
    if $orbitCorrectionWasRunning {
        if [catch {exec cavput -list=S:RC:OrbitControlLawXC,S:RC:OrbitControlLawYC,S:rfFreqControlLawRC -list=.ABRT=1} result] {
            return -code error "Problem aborting controllaw: $result"
        }
    }
    if $dpOrbitCorrectionWasRunning {
        #turn off DP orbit correction
        if [catch {exec cavput -list=DP:S: \
                     -list=OrbitControlLawX,OrbitControlLawY \
                     -list=SDDS.ABRT=1} result] {
            return -code error "Problem aborting DP controllaw: $result"
        }
    }
}

proc APSMpSetRTFBGlobalParameters {args} {
    set filename /home/helios/oagData/sr/rtfeedback/parameterFiles/srfb-default.param
    set readonly 0
    global status
    set statusCallback ""
    APSStrictParseArguments {filename readonly statusCallback}
    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] == ""} {
                        if [string length $statusCallback] {
                            eval $statusCallback {"unrecognized procedure $procName"}
                        }
                    } else {
                        $procName $ValueString
                    }
                }
            }
            set {
                global aps$ControlName
                set aps$ControlName $ValueString
            }
            default {
                #set status "Unrecognized Parameter File ControlType: $ControlType"
            }
        }
    }
}

proc APSMpRTFBResetOpenLoops {args} {
    #global apshpFilterInitialVert apshpFilterInitialHoriz
    #global apshpFilterCutoffVert apshpFilterCutoffHoriz apshpFilterInitialVert apshpFilterInitialHoriz
    #global apshpFilterRampPoints apshpFilterRampInterval
    set hpFilterInitialVert ""
    set hpFilterInitialHoriz ""
    set runHloop 1
    set runVloop 1
    APSStrictParseArguments {hpFilterInitialVert hpFilterInitialHoriz runHloop runVloop}

    if {![string length $hpFilterInitialVert] || ![string length $hpFilterInitialHoriz] } {
        return -code error "hpFilterInitialVert or hpFilterInitialHoriz is not given"
    }
    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=${runHloop},SRFB:GBL:Vert:CloseLoopBO=${runVloop}
        exec cavput -pend=10 -list=SRFB:GBL:Hor:CloseLoopBO=0,SRFB:GBL:Vert:CloseLoopBO=0 \
             } error] {
        return -code error "APSMpRTFBResetOpenLoops: $error"
    }
    # Resetting filter parameters...
    if [catch {exec cavput -pend=15 \
                 -list=SRFB:fhAO=$hpFilterInitialVert,SRFB:fhSlAO=$hpFilterInitialHoriz
        exec cavput -pend=15 -list=SRFB:GBL:loadBO=1} error] {
        return -code error "APSMpRTFBResetOpenLoops: $error"
    }
}


proc APSMpRestoreSRBPMOffsetsAndSetpoints {args} {
    set waveformFileDir /home/helios/oagData/sr/orbitControllaw/waveforms
    set setpointReferenceFile /home/helios/oagData/SCR/snapshots/SR/SR-UserBeamPreferred.gz
    set offsetReferenceFile /home/helios/oagData/SCR/snapshots/SR/SR-BPMOffsetReference.gz
    set plane both
    set datapool 0
    APSStrictParseArguments {plane datapool offsetReferenceFile setpointReferenceFile}
    
    set plane [string tolower $plane]
    switch $plane {
        h {
            set coords x
        }
        v {
            set coords y
        }
        both {
            set coords {x y}
        }
        default {
            return -code error "APSRestoreSRBPMOffsetsAndSetpoints1: Invalid plane given: $plane"
        }
    }
    set tmpRoot /tmp/[APSTmpString]
    APSAddToTmpFileList -ID RestoreDPOffsets -fileList "$tmpRoot.ref1 $tmpRoot.ref2"
    if [catch {APSSCRLogAction -file $setpointReferenceFile -action restore-start} result] {
	puts stderr "$result"
    }
    if [catch {APSSCRLogAction -file $offsetReferenceFile -action restore-start} result] {
	puts stderr "$result"
    }
    foreach coord $coords {
        if [catch {exec sddsprocess $offsetReferenceFile $tmpRoot.ref1 \
                     -match=col,ControlName=*:${coord}:OffsetAO \
                     -edit=col,DeviceName,ControlName,%/:ms:${coord}:OffsetAO// \
                     -scan=col,Offset,ValueString,%lf 
            exec sddsprocess $setpointReferenceFile $tmpRoot.ref2 \
                     -match=col,ControlName=*:${coord}:SetpointAO \
                     -edit=col,DeviceName,ControlName,%/:ms:${coord}:SetpointAO// \
                     -scan=col,Setpoint,ValueString,%lf
            exec sddscombine $tmpRoot.ref1 $tmpRoot.ref2 \
                     -merge $tmpRoot.snap.$coord -overwrite} result] {
            APSDeleteTmpFileList -ID RestoreDPOffsets
            return -code error "APSRestoreSRBPMOffsetsAndSetpoints2:: $result"
        }
        APSAddToTmpFileList -ID RestoreDPOffsets -fileList "$tmpRoot.adjust $tmpRoot.$coord"
        if $datapool {
            set waveformFile ${waveformFileDir}/adjust[string toupper $coord]BpmInfo.sdds
            if [catch {exec sddsxref $tmpRoot.ref1 $tmpRoot.ref2 -pipe=out \
                         -match=DeviceName -take=Setpoint -nowarnings \
                         | sddsprocess -pipe=in "-define=col,Waveform,Offset Setpoint +" $tmpRoot.adjust
                exec sddsxref $waveformFile $tmpRoot.adjust -match=DeviceName -take=Waveform -fillIn \
                         -reuse -nowarnings $tmpRoot.$coord 
                exec sddswput $tmpRoot.$coord} result] {
                return -code error "APSRestoreSRBPMOffsetsAndSetpoints3:: $result"
            }
        }
        if [catch {exec sddscasr -restore $tmpRoot.snap.$coord -pend=70 } result] {
            return -code error "APSRestoreSRBPMOffsetsAndSetpoints(sddscasr): $result"
        }
    }
    #restore xray bpm blads offset and rateP
    if [catch {exec sddsprocess $setpointReferenceFile $tmpRoot.xray \
		   "-match=col,ControlName=*OffsetP,ControlName=*RateP,|" } result] {
	return -code error "APSRestoreSRBPMOffsetsAndSetpoints4: $result"
    }
    APSAddToTmpFileList -ID RestoreDPOffsets -fileList $tmpRoot.xray
    if [catch {exec sddscasr -restore $tmpRoot.xray -pend=80} result] {
	return -code error "APSRestoreSRBPMOffsetsAndSetpoints5 -error in restoring Xray bpm blades offset and rateP: $result"
    }
    if [catch {APSSCRLogAction -file $setpointReferenceFile -action restore-end} result] {
	puts "$result"
    }
    if [catch {APSSCRLogAction -file $offsetReferenceFile -action restore-end} result] {
	puts "$result"
    }
}

proc APSMpInitializeRTFBSystem {args} {
    set paramDir /home/helios/oagData/sr/rtfeedback/parameterFiles
    set paramFile srfb-default.param
    set xconfigDir h.default
    set yconfigDir v.default
    set baseDir /home/helios/oagData/sr/rtfeedback/lattices/default
    set statusCallback ""
    global status
    APSStrictParseArguments {paramDir paramFile xconfigDir yconfigDir statusCallback}
    
    set filename $paramDir/$paramFile
    APSMpStep "read parameters"
    if [catch {APSMpSetRTFBGlobalParameters -filename $filename} result] {
        return -code error "APSMpInitializeRTFBSystem(read parameters): $result"
    }
    if [catch {exec cavput -pend=15 -list=SRFB:GBL:loadBO=1} error] {
        return -code error "APSMpInitializeRTFBSystem: unable to set SRFB:GBL:loadBO to 1: $result"
    }

    # Does this step with rmInitFile<n> do anything useful?
    if [string length $statusCallback] {
        eval $statusCallback {"Resetting response matrix elements..."}
    }
    #    loadRespMat $rmInitDir $rmInitFile1
    #    loadRespMat $rmInitDir $rmInitFile2
    # converted the old rmInitFile[12] to <plane>.<bpm> configurations
    set planeList [list h v h v h v]
    set configDirList [list h.ap1 v.ap1 h.bp1 v.bp1 $xconfigDir $yconfigDir]
    APSMpStep "load matrix..."
    foreach plane $planeList configDir $configDirList {
        set file $baseDir/$configDir/irm
        set config $baseDir/$configDir/config
        if [file exists $file] {
            if [catch {exec srfbNewLoadMatrix -l -$plane $file $config} error]  {
                return -code error "Error loading response matrix for plane $plane: $error"
            }
        } else {
            return -code error "APSMpInitializeRTFBSystem: $file does not exist!"
        }
        set dateString [exec date]
        if [catch {exec cavput -pend=15 \
                     -list=SRFB:GBL:HresMDateSI=${dateString},SRFB:GBL:VresMDateSI=${dateString} } error]  {
            return -code error "Error while setting date for response matrix loading: $error"
        }
    }

    APSMpStep "Re-applying corrector setpoints in order to process SetAI PVs once..."
    if [catch {exec cavput -list=SFB:S -range=beg=1,end=40 \
                 -list=A:,B: -list=H,V -list=1,2,3,4 \
                 -list=:CurrentAO=0 -delta -pend=15 \
             } result] {
        return -code error "APSMpInitializeRTFBSystem: $result"
    }
    APSMpStep "Enable feedforward..."
    if [catch {APSMpEnableFeedForward} result] {
        return -code error "APSMpInitializeRTFBSystem: $result"
    }
    APSMpStep "Set P0/P1 Enables ..."
    if [catch {APSMpSetP1Enables} result] {
        return -code error "APSMpInitializeRTFBSystem: $result"
    }
    APSMpStep "Zero RTFB bpm setpoints .."
    if [catch {APSMpZeroRTBPMSetpoints} result] {
        return -code error "InitializeSystem: $result"
    }
    if [string length $statusCallback] {
        eval $statusCallback {"Set corrector InUse to RTFB..."}
    }
    APSMpStep "Set corrector in Use to RTFB"
    if [catch {APSSetCorrectorInUse -configRTFB $xconfigDir} result] {
        return -code error "InitializeSystem: $result"
    }
    if [catch {APSSetCorrectorInUse -configRTFB $yconfigDir} result] {
        return -code error "InitializeSystem: $result"
    }
    if [string length $statusCallback] {
        eval $statusCallback {"Done."}
    }
    #update FFwaveform file for SRIDSteering, SRCUSteering, SRBMSteering
    set waveformDir /home/helios/oagData/sr/orbitControllaw/waveforms
    foreach plane {h v} coord {x y} {
	#RTFBXbpmInfo.sdds one page of FF bpms, update the FF bpm names
        if [catch {exec sddsprocess $waveformDir/RTFB[string toupper $coord]bpmInfo.sdds \
                     -edit=col,ControlName,DeviceName,ei/:${coord}:SelectedMI/ -pipe=out \
                     | sddscasr -save -pipe \
                     | sddsconvert -pipe=in $waveformDir/FFwaveform.$plane -rename=col,ValueString=BPMName } result] {
            return -code error $result
        }
	#create FFwaveform.h.transfer -- one page
        if [catch {exec sddsconvert $waveformDir/FFwaveform.$plane -pipe=out \
                     -rename=par,WaveformPV=FFDeltaWaveformPV,FFSetWaveformPV=WaveformPV \
                     -rename=col,DeviceName=OldDeviceName,BPMName=DeviceName \
                     | sddsprocess -pipe=in $waveformDir/FFwaveform.$plane.transfer -redefine=par,IsSum,0 -reprint=par,Prefix, \
                     -reprint=par,Suffix,:ms:$coord:SetpointAO -reprint=par,Suffix1, } result] {
            return -code error $result
        }
	#create FFwaveform.h.delta - one page
        if [catch {exec sddsconvert $waveformDir/FFwaveform.$plane -pipe=out \
                     -rename=col,DeviceName=OldDeviceName,BPMName=DeviceName \
                     | sddsconvert -pipe=in -retain=par,*Waveform* -retain=col,DeviceName,ControlName \
                     $waveformDir/FFwaveform.$plane.delta } result] {
            return -code error $result
        }
	# contains corrector waveform, nonFF waveform
	if [catch {exec sddsprocess $waveformDir/${plane}corrInfo.sdds $waveformDir/${plane}corrInfo.sdds.delta \
		       -reprint=par,Suffix,:CurrentAO -reprint=par,Prefix,SFB: -reprint=par,WaveformPV,%s,DeltaWaveformPV
	    exec sddsprocess $waveformDir/adjust[string toupper $coord]BpmInfo.sdds $waveformDir/adjust[string toupper $coord]BpmInfo.sdds.delta \
		       -reprint=par,WaveformPV,%s,DeltaWaveformPV \
		       -reprint=par,Suffix,:ms:${coord}:SetpointAO -reprint=par,Suffix1,:ms:${coord}:OffsetAO 
	    exec sddscombine $waveformDir/${plane}corrInfo.sdds.delta $waveformDir/adjust[string toupper $coord]BpmInfo.sdds.delta -pipe=out \
		       | sddsconvert -pipe=in -retain=col,DeviceName,ControlName \
		       $waveformDir/deltaWaveform.$plane.nonFF } result] {
	    return -code error "Error creating deltaWaveform.$plane.nonFF : $result"
	}
	if [catch {exec sddscombine $waveformDir/deltaWaveform.$plane.nonFF $waveformDir/FFwaveform.$plane.delta \
                     $waveformDir/deltaWaveform.$plane -overwrite } result] {
            return -code error $result
	}
    }
    if [catch {exec sddscombine  $waveformDir/transferWaveform.sdds.nonFF $waveformDir/FFwaveform.h.transfer $waveformDir/FFwaveform.v.transfer \
                 $waveformDir/transferWaveformOneTime.sdds -overwrite } result] {
        return -code error "Error creating transferWaveform.sdds: $result"
    }
    return 0
}

proc APSMpEnableFeedForward {args} {
    set ffWaveFile /home/helios/oagData/sr/RTFB/FFwaveforms/lattices/default/Septum
    set upstreamName "S37FB:S38A:H3"
    set downstreamName "S39FB:S39A:H3"
    set statusCallback ""
    global status
    APSStrictParseArguments {ffWaveFile upstreamName downstreamName statusCallback}
    
    # download waveforms to corrector channels
    if [string length $statusCallback] {
        eval $statusCallback {"Loading feedforward waveforms..."}
    }
    if [catch {exec sddswput $ffWaveFile} result] {
        return -code error "APSMpEnableFeedForward: Error putting to waveform records: $result"
    }

    # enable channels and push 'load'
    if [string length $statusCallback] {
        eval $statusCallback {"Enabling feedforward channels..."}
    }
    if [catch {exec cavput -pend=15 -list=SRFB:accessControlMBBO.VAL=0
        exec cavput -pend=15 -list=$upstreamName,$downstreamName \
                 -list=:feedForwardEnC=1
        exec cavput -pend=10 -list=SRFB:accessControlMBBO.VAL=3 \
             } error ] {
        return -code error "APSMpEnableFeedForward: $error"
    }
    if [catch {exec cavput -pend=15 -list=SRFB:GBL:loadBO=1,SRFB:GBLM:DSPLoadParamsBO=1} error] {
        return -code error "APSMpEnableFeedForward: $error"
    }
    if [string length $statusCallback] {
        eval $statusCallback {"Done."}
    }
}

proc APSMpDisableFeedForward {args} {
    set ffWaveFile /home/helios/oagData/sr/RTFB/FFwaveforms/lattices/default/Septum
    set upstreamName "S37FB:S38A:H3"
    set downstreamName "S39FB:S39A:H3"
    set statusCallback ""
    global status
    APSStrictParseArguments {ffWaveFile upstreamName downstreamName statusCallback}

    set upstreamEN "$upstreamName:feedForwardEnC"
    set downstreamEN "$downstreamName:feedForwardEnC"
    
    # enable channels and push 'load'
    if [string length $statusCallback] {
        eval $statusCallback {"Disabling feedforward channels..."}
    }
    if [catch {exec cavput -pend=15 -list=SRFB:accessControlMBBO.VAL=0
        exec cavput -pend=15 -list=$upstreamName,$downstreamName \
                 -list=:feedForwardEnC=0
        exec cavput -pend=10 -list=SRFB:accessControlMBBO.VAL=3 \
             } error ] {
        return -code error "APSMpDisableFeedForward: $error"
    }
    if [catch {exec cavput -pend=15 -list=SRFB:GBL:loadBO=1,SRFB:GBLM:DSPLoadParamsBO=1} error] {
        return -code error "APSMpDisableFeedForward: $error"
    }
    if [string length $statusCallback] {
        eval $statusCallback {"Done."}
    }
}

# This will now set the P0s and P1s
proc APSMpSetP1Enables {args} {
    set statusCallback ""
    global status
    APSStrictParseArguments {statusCallback}
    set file /home/helios/oagData/sr/BPMStatus/config.sdds
    # need to remove the P0/P1 bpms inside the septum correction bump S38A:H3 to 
    # injection straight section
    
    set columns [exec sddsquery -col $file]
    foreach Plane {H V} coord {x y} {
        if [lsearch $columns OkForRMSCalculation$Plane]<0 {
            if [catch {exec sddsprocess $file -pipe=out \
                           -match=col,DeviceName=S*\[AB\]:P0 \
                           -match=col,DeviceName=S38B:P0,DeviceName=S39A:P0,|,DeviceName=S39B:P0,|,! \
                           -filter=col,Nonexistent${Plane},0,0 \
                           -filter=col,OkForRTFeedback${Plane},1,1 \
                           | sdds2stream -pipe=in -col=DeviceName \
                       } selectedP0 ] {
                return -code error "APSMpSetP1Enables: $selectedP0"
            } 
            if [catch {exec sddsprocess $file -pipe=out \
                           -match=col,DeviceName=S*\[AB\]:P1 \
                           -match=col,DeviceName=S38B:P1,DeviceName=S39A:P1,|,DeviceName=S39B:P1,|,! \
                           -filter=col,Nonexistent${Plane},0,0 \
                           -filter=col,OkForRTFeedback${Plane},1,1 \
                           | sdds2stream -pipe=in -col=DeviceName \
                       } selectedP1 ] {
                return -code error "APSMpSetP1Enables: $selectedP1"
            }
            if [catch {exec sddsprocess $file -pipe=out \
                           -match=col,DeviceName=S*\[AB\]:P2 \
                           -match=col,DeviceName=S38B:P2,DeviceName=S39A:P2,|,DeviceName=S39B:P2,|,! \
                           -filter=col,Nonexistent${Plane},0,0 \
                           -filter=col,OkForRTFeedback${Plane},1,1 \
                           | sdds2stream -pipe=in -col=DeviceName \
                       } selectedP2 ] {
                return -code error "APSMpSetP1Enables: $selectedP2"
            }
        } else {
            if [catch {exec sddsprocess $file -pipe=out \
                           -match=col,DeviceName=S*\[AB\]:P0 \
                           -filter=col,Nonexistent${Plane},0,0 \
                           -filter=col,OkForRMSCalculation${Plane},1,1 \
                           | sdds2stream -pipe=in -col=DeviceName \
                       } selectedP0 ] {
                return -code error "APSMpSetP1Enables: $selectedP0"
            }
            if [catch {exec sddsprocess $file -pipe=out \
                           -match=col,DeviceName=S*\[AB\]:P1 \
                           -filter=col,Nonexistent${Plane},0,0 \
                           -filter=col,OkForRMSCalculation${Plane},1,1 \
                           | sdds2stream -pipe=in -col=DeviceName \
                       } selectedP1 ] {
                return -code error "APSMpSetP1Enables: $selectedP2"
            }
            if [catch {exec sddsprocess $file -pipe=out \
                           -match=col,DeviceName=S*\[AB\]:P2 \
                           -filter=col,Nonexistent${Plane},0,0 \
                           -filter=col,OkForRMSCalculation${Plane},1,1 \
                           | sdds2stream -pipe=in -col=DeviceName \
                       } selectedP2 ] {
                return -code error "APSMpSetP1Enables: $selectedP2"
            }
        }
        if [catch {exec cavput -list=SRFB:S -range=beg=1,end=40 \
                       -list=A:P0,B:P0,A:P1,B:P1,A:P2,B:P2 -list=:${coord}:IncludeInRmsC=0 \
                   } result ] {
            return -code error "APSMpSetP1Enables: $result"
        }
        if [string length $statusCallback] {
            eval $statusCallback {"Setting status for bpms [join $selectedP0 \ ]..."}
        }
        if [catch {exec cavput -list=SRFB: -list=[join $selectedP0 ,] \
                       -list=:${coord}:IncludeInRmsC=1 \
                   } result ] {
            return -code error "APSMpSetP1Enables:  $result"
        }
        if [string length $statusCallback] {
            eval $statusCallback {"Setting status for bpms [join $selectedP1 \ ]..."}
        }
        if [catch {exec cavput -list=SRFB: -list=[join $selectedP1 ,] \
                       -list=:${coord}:IncludeInRmsC=1 \
                   } result ] {
            return -code error "APSMpSetP1Enables:  $result"
        }
        if [string length $statusCallback] {
            eval $statusCallback {"Setting status for bpms [join $selectedP2 \ ]..."}
        }
        if [catch {exec cavput -list=SRFB: -list=[join $selectedP2 ,] \
                       -list=:${coord}:IncludeInRmsC=1 \
                   } result ] {
            return -code error "APSMpSetP1Enables:  $result"
        }
    }
    if [catch {exec cavput -list=SRFB:dsp2:loadC=1 \
               } result ] {
        return -code error "APSMpSetP1Enables: $result"
    }
    if [string length $statusCallback] {
        eval $statusCallback {"Done."}
    }
}

proc APSMpZeroRTBPMSetpoints {args} {
    global status
    set statusCallback ""
    set plane both
    APSStrictParseArguments {plane statusCallback}
    
    if [string length $statusCallback] {
        eval $statusCallback {"Setting $plane plane RTFB bpm setpoints to zero..."}
    }
    for {set i 1} {$i<41} {incr i} {
        set ioc [expr ($i - 1) / 2 * 2 + 1]
        lappend listArguments S${ioc}FB:GB${i}
    }
    if [catch {exec cavget  -pend=15 -list=SRFB:GBL:Hor:CloseLoopBO} hloop] {
        return -code error "APSMpZeroRTBPMSetpoints: Error reading hloop: $hloop"
    }
    if [catch {exec cavget  -pend=15 -list=SRFB:GBL:Vert:CloseLoopBO} vloop] {
        return -code error "APSMpZeroRTBPMSetpoints: Error reading vloop: $vloop"
    }
    
    switch $plane {
        both {
            if {[string match $hloop "Close"] || [string match $vloop "Close"]} {
                if [string length $statusCallback] {
                    eval $statusCallback {"Can't set all bpm setpoints to zero when either loop is closed."}
                }
                return -code error "APSMpZeroRTBPMSetpoints: Can't set all bpm setpoints to zero when either loop is closed."
            }
            exec cavput -list=[join $listArguments ,] -list=:bpm -list=1,2,3,4 \
              -list=:x,:y -list=:RefAO=0
        }
        h {
            if [string match $hloop "Close"]  {
                if [string length $statusCallback] {
                    eval $statusCallback {"Can't set bpm setpoints to zero when H loop is closed."}
                }
                return -code error "APSMpZeroRTBPMSetpoints: Can't set bpm setpoints to zero when H loop is closed."
            }
            exec cavput -list=[join $listArguments ,] -list=:bpm -list=1,2,3,4 \
              -list=:x:RefAO=0
        }
        v {
            if [string match $vloop "Close"]  {
                if [string length $statusCallback] {
                    eval  $statusCallback {"Can't set bpm setpoints to zero when V loop is closed."}
                }
                return -code error "APSMpZeroRTBPMSetpoints: Can't set bpm setpoints to zero when V loop is closed."
            }
            exec cavput -list=[join $listArguments ,] -list=:bpm -list=1,2,3,4 \
              -list=:y:RefAO=0
        }
    }
    if [string length $statusCallback] {
        eval $statusCallback {"Done."}
    }
}

proc APSMpCheckCorrectorMode {args} {
    set mode Operation
    set plane both
    set all 1
    APSStrictParseArguments {mode plane all}

    set badcorrectors ""
    set corrList [APSGetRTFBCorrectorList -all $all -plane $plane]
    if [catch {exec cavget -list=[join $corrList ,] \
                 -list=:ControlSrcBO -pend=30 } valList] {
        return -code error $result
    }
    foreach corr $corrList val $valList {
        if {[string compare $val $mode]!=0} {
            lappend badcorrectors $corr
        }
    }
    return $badcorrectors
}


proc APSSetRTFBCorrectorMode {args} {
    set all 0
    set plane both
    set mode ""
    set pscuTolerance 1.0
    set readbackTolerance 1.0
    set checkStatus 1
    APSStrictParseArguments {all plane mode pscuTolerance readbackTolerance checkStatus}
    
    if ![string length $mode] {
        return -code error "Corrector mode is not provided!"
    }
    if {$mode!="Maintenance" && $mode!="Operation"} {
        return -code error "Invalid corrector mode given: $mode"
    }
    set corrList [APSGetRTFBCorrectorList -all $all -plane $plane]
    if {$mode=="Operation" && $checkStatus} {
        set badStatus [APSCheckCorrectorStatus -corrList $corrList]
        if {[llength $badStatus] > 0} {
            if ![APSQueryToProceed -message "Warning: the following correctors appear to be off: [join $badStatus ,]. \n\nARE YOU SURE YOU WANT TO CONTINUE WITH GRABBING THE CORRECTORS?"] {
                return -code error "Set RTFB corrector to Operation mode was Aborted"
            }
        }
            set badReadbacks [APSCheckCorrsPassive -tolerance $readbackTolerance -corrList $corrList]
        if {[llength $badReadbacks] > 0} {
            if ![APSQueryToProceed -message "Warning: the following correctors have setpoint/readback deltas > ${readbackTolerance}A: [join $badReadbacks ,].\n\nARE YOU SURE YOU WANT TO CONTINUE WITH GRABBING THE CORRECTORS?"] {
                return -code error "Set RTFB corrector to Operation mode was Aborted"
            }
        }
    }
    if [catch {exec cavput -pend=15 -list=SRFB:accessControlMBBO.VAL=0
        exec cavput -pend=10 -blunder -list=[join $corrList ,] -list=:ControlSrcBO=$mode 
        exec cavput -pend=10 -blunder -list=SRFB:GBLM:DSPCtrlBO=$mode
        exec cavput -pend=10 -blunder -list=SRFB:accessControlMBBO.VAL=3 \
             } error] {
        return -code error "Failed to release correctors properly: $error"
    }
    #set status "Setting corrector alarm limit to +/-${pscuTolerance}A"; update
    if [catch {exec cavput -pend=10 -blunder -list=[join $corrList ,] \
                 -list=:ToleranceCALC.C=$pscuTolerance} error ] {
        return -code error "Failed to set alarm limits properly: $error"
    }
}

proc APSGetRTFBCorrectorList {args} {
    set all 0
    set plane both
    APSStrictParseArguments {all plane}
    set plane [string toupper $plane]
    switch $plane {
        H -
        V {
            set planes $plane
        }
        BOTH {
            set planes {H V}
        }
        default {
            return -code error "invalid plane given:$plane"
        }
    }
    set corrList ""
    if $all {
        foreach pl $planes {
            # Here, all means from sector 2 to 39
            catch {exec cavget -list=S -range=begin=2,end=39 -list=A:${pl}3 -dryRun} corr1
            set corrList [concat $corrList $corr1]
        }
    } else {
        foreach pl $planes {
            set config /home/helios/oagData/sr/${pl}CorrectorStatus/config.sdds
            set corr1 [exec sddsprocess $config -pipe=out -match=col,DeviceName=S*A:${pl}3 \
                         -filter=col,Nonexistent,0,0 \
                         -filter=col,OkForRTFeedback,0.5,1.5 -nowarnings \
                         | sdds2stream -pipe -col=DeviceName]
            set corrList [concat $corrList $corr1]
        }
    }
    return $corrList
}

proc APSCheckCorrectorStatus {args} {

    APSStrictParseArguments {corrList}

    if [catch {exec cavget -pend=30 -label -embrace \
                 -list=[join $corrList ,] -list=:StatusCALC} result] {
        return -code error $result
    }

    set badCorrs ""
    foreach corrector $result {
        if {[lindex [split $corrector] 1] > 1 } {
            lappend badCorrs [string trimright  [lindex [split $corrector] 0] ":StatusCALC"]
        }
    }
    return $badCorrs
}

proc APSCheckCorrsPassive {args} {

    APSStrictParseArguments {tolerance corrList}

    set currentAO [split [exec cavget -pend=10 "-delim= " -errorValue=-999 \
                            -list=[join $corrList ,] -list=:CurrentAO]]
    set currentAI [split [exec cavget -pend=10 "-delim= " -errorValue=999 \
                            -list=[join $corrList ,] -list=:CurrentAI]]
    set dacAI     [split [exec cavget -pend=10 "-delim= " -errorValue=999 \
                            -list=[join $corrList ,] -list=:DacAI]]
    # compute list of errors
    set badReadbackList ""
    for {set i 0} {$i < [llength $corrList]} {incr i} {
        # check that all readbacks are floating-point numbers
        if {([regexp {^\-?[0-9]+\.?[0-9]*(e\-?[0-9][0-9])?$} [lindex $currentAO $i]] == 0) || \
              ([regexp {^\-?[0-9]+\.?[0-9]*(e\-?[0-9][0-9])?$} [lindex $currentAI $i]] == 0) || \
              ([regexp {^\-?[0-9]+\.?[0-9]*(e\-?[0-9][0-9])?$} [lindex $dacAI $i]] == 0) } {
            lappend badReadbackList [lindex $corrList $i]
        } else {
            set delta [expr [lindex $currentAI $i] - [lindex $currentAO $i]]
            if {[expr abs($delta)] > $tolerance} {
                lappend badReadbackList [lindex $corrList $i]
            } else {
                set delta [expr [lindex $dacAI $i] - [lindex $currentAO $i]]
                if {[expr abs($delta)] > $tolerance} {
                    lappend badReadbackList [lindex $corrList $i]
                } 
            }
        }
    }
    return $badReadbackList
}

proc APSMpRTFBCloseLoops {args} {
    #global apshpFilterInitialVert apshpFilterInitialHoriz
    #global apshpFilterCutoffVert apshpFilterCutoffHoriz apshpFilterInitialVert apshpFilterInitialHoriz
    #global apshpFilterRampPoints apshpFilterRampInterval
    global status
    set statusCallback ""
    set hpFilterCutoffVert ""
    set hpFilterCutoffHoriz ""
    set hpFilterInitialVert ""
    set hpFilterInitialHoriz ""
    set hpFilterRampPoints ""
    set hpFilterRampInterval ""
    APSStrictParseArguments {statusCallback hpFilterCutoffVert hpFilterCutoffHoriz \
                               hpFilterInitialVert  hpFilterInitialHoriz hpFilterRampPoints \
                               hpFilterRampInterval}
  
    if {![string length $hpFilterCutoffVert] || ![string length $hpFilterCutoffHoriz] || \
          ![string length $hpFilterInitialVert] || ![string length $hpFilterInitialHoriz] || \
          ![string length $hpFilterRampPoints] || ![string length $hpFilterRampInterval] } {
        return -code error "Some filter parameters are missing!"
    }

    if [string length $statusCallback] {
        eval $statusCallback {"Checking that correctors are in Operation mode..."}
    }

    # Check if there are any actual bad correctors (that we would have
    # set to Maintenance mode) that still have (incorrectly) the flag
    # OKForRTFB in the corrector database. The correctors is
    # presumably absent from the matrix we loaded, so we don't check
    # the matrix here.  Search good list of correctors in database
    # that are in Maintenance mode.
    #                                 allowed values
    # Maintenance     NotOKforRTFB    n
    # Maintenance     OKforRTFB       0        list badcorrectors. check that this is zero length
    # Maintenance                     n        
    # Operation       NotOKforRTFB    0
    # Operation       OKforRTFB       N - n
    # Operation                       N - n
    # N is 38 now but could increase when BH4 and BV4 are implemented.

    if [catch {APSMpCheckCorrectorMode -mode Operation -all 0} badcorrectors] {
        return -code error "APSMpRTFBCloseLoops: $badcorrectors"
    }
    if {[llength $badcorrectors]} {
        return -code error "These correctors are in Maintenance mode and declared as usable in the status management utility: [join $badcorrectors ,]"
    }
    if [string length $statusCallback] {
        eval $statusCallback {"Setting initial highpass filter values..."}
    }
    APSMpStep "Setting initial highpass filter values..."
    if [catch {exec cavput -pend=15 -list=SRFB:fhAO=$hpFilterInitialVert,SRFB:fhSlAO=$hpFilterInitialHoriz; \
                 exec cavput -pend=15 -list=SRFB:GBL:loadBO=1} error] {
       return -code error "APSMpRTFBCloseLoops: $error"
    }
    if [string length $statusCallback] {
        eval $statusCallback {"Disabling AC voltmeter..."}
    }
    APSMpStep "Disabling AC voltmeter..."
    if [catch {exec cavput -pend=15 -list=SRFB:D85:ACV:EnableBO=Disable \
             } error] {
        return -code error "APSMpRTFBCloseLoops: $error"
    }

    if [string length $statusCallback] {
        eval $statusCallback {"Closing feedback loops..."}
    }
    APSMpStep "Closing feedback loops..."
    if [catch {exec cavput -pend=15 \
                 -list=SRFB:GBL:Hor:CloseLoopBO=1,SRFB:GBL:Vert:CloseLoopBO=1} error] {
        return -code error "APSMpRTFBCloseLoops: $error"
    }
    APSMpStep "wait [expr 2*$hpFilterRampInterval] seconds to ensure system does not trip." 
    # wait to ensure system does not trip
    after [expr $hpFilterRampInterval*1000]
    after [expr $hpFilterRampInterval*1000]
    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 {$hloop == "Close" || $vloop == "Close" } {
        if [string length $statusCallback] {
            eval $statusCallback {"Ramping high pass filter..."}
        }
        APSMpStep "Ramping high pass filter..."
        set index 0
        while {($index < $hpFilterRampPoints)} {
            if { $hloop == "Close" } {
                set value [exec rpnl "$hpFilterInitialHoriz $hpFilterCutoffHoriz / log \
             $hpFilterRampPoints 1 - / $index * $hpFilterInitialHoriz log - -1 * 10 swap pow"]
                if [string length $statusCallback] {
                    eval $statusCallback {"Setting horizontal highpass to [format %4.3gHz $value]"}
                }
                APSMpStep "Setting horizontal highpass to [format %4.3gHz $value]"
                if [catch {exec cavput -pend=15 -list=SRFB:fhSlAO=$value; \
                             exec cavput -pend=15 -list=SRFB:GBL:loadBO=1} error] {
                    return -code error "Error setting horizontal regulator: $error"
                }
            }
            if { $vloop == "Close" } {
                set value [exec rpnl "$hpFilterInitialVert $hpFilterCutoffVert / log \
             $hpFilterRampPoints 1 - / $index * $hpFilterInitialVert log - -1 * 10 swap pow"]
                if [string length $statusCallback] {
                    eval $statusCallback {"Setting vertical highpass to [format %4.3gHz $value]"}
                }
                APSMpStep "Setting vertical  highpass to [format %4.3gHz $value]"
                if [catch {exec cavput -pend=15 -list=SRFB:fhAO=$value; \
                             exec cavput -pend=15 -list=SRFB:GBL:loadBO=1} error] {
                    return -code error "Error setting vertical regulator: $error"
                }
            }
            APSWaitWithUpdate -waitSeconds $hpFilterRampInterval -updateInterval 1
            incr index
        }
    } else {
        return -code error "Error: loops tripped or failed to close"
    }
}

#from checkCorrReadbacks in SRFBControl
proc APSMpRTFBCheckCorrReadbacks {args} {
    global status readbackTolerance
    set readbackTolerance 1.0
    set statusCallback ""
    APSStrictParseArguments {readbackTolerance statusCallback}
    
    if [string length $statusCallback] {
        eval $statusCallback {"Checking required correctors are switched on..."}
    }
    set badStatus [APSCheckCorrectorStatus -all 0]
    
    if {[llength $badStatus] > 0} {
        if [string length $statusCallback] {
            eval $statusCallback {"The following correctors appear to be off: [join $badStatus ,]"}
        } else {
            return -code error "The following correctors appear to be off: [join $badStatus ,]"
        }
    } else {
        if [string length $statusCallback] {
            eval $statusCallback {"All required correctors are switched on."}
        }
    }
    if [string length $statusCallback] {
        eval $statusCallback {"Checking corrector readbacks..."}
    }
    set badReadbacks [APSCheckCorrsPassive -tolerance $readbackTolerance -all 0]
    if {[llength $badReadbacks] > 0} {
        if [string length $statusCallback] {
            eval $statusCallback {"The following correctors have  setpoint/readback errors greater than ${readbackTolerance}A: [join $badReadbacks ,]"}
        } else {
            return -code error "The following correctors have  setpoint/readback errors greater than ${readbackTolerance}A: [join $badReadbacks ,]"
        }
    } else {
        if [string length $statusCallback] {
            eval $statusCallback {"All correctors read within ${readbackTolerance}A of setpoint."}
        } else {
            return "All correctors read within ${readbackTolerance}A of setpoint."
        }
    }
}

proc APSMpRTFBLoadResponseMatrix {args} {
    set hconfig h.default
    set vconfig v.default
    set baseDir /home/helios/oagData/sr/rtfeedback/lattices/default
    APSStrictParseArguments {hconfig vconfig baseDir}
    set tmpfile /tmp/[APSTmpString]
    foreach plane {h v} {
        APSMpStep "Loading $plane response matrix ..."
        set configDir [set ${plane}config]
        set file ${baseDir}/$configDir/irm
        set config ${baseDir}/${configDir}/config
        if [file exists $file] {
            if [catch {exec srfbNewLoadMatrix -l -$plane $file $config} error]  {
                APSMpReturn error "APSMpRTFBLoadResponseMatrix: error loading response matrix for plane $plane: $error"
            }
        } else {
            APSMpReturn error "APSMpRTFBLoadResponseMatrix: cannot find file $file"
        }
        set dateString [exec date]
        if [catch {exec cavput -pend=15 -list=SRFB:GBL:HresMDateSI=${dateString},SRFB:GBL:VresMDateSI=${dateString} } error]  {
            APSMpReturn error "APSMpRTFBLoadResponseMatrix: error while setting date for response matrix loading: $error"
        }       
    }
    APSMpReturn ok
}

proc APSCheckRTFBbpmSetpoints {args} {
    set plane ""
    set bpmLimit 10
    APSStrictParseArguments {plane bpmLimit}
    if ![string length $plane] {
        return -code error "APSCheckRTFBbpmSetpoints(1a): plane (h or v) is not provided."
    }
    set plane [string tolower $plane]
    switch $plane {
        h -
        x {
            set plane h
            set coord x
        }
        v -
        y {
            set plane v
            set coord y
        }
        default {
            return -code error "APSCheckRTFBbpmSetpoints(1): Invalid plane - $plane provided, should be h or v."
        }
    }
    if [catch {APSSRCheckCorrectorMode -plane $plane} corrMode] {
        return -code error "APSCheckRTFBbpmSetpoints(2): $corrMode"
    }
    set tmpRoot /tmp/[APSTmpString]
    APSAddToTmpFileList -ID bpmlimit -fileList $tmpRoot.bpm
    switch $corrMode {
        scalar {
            if [catch {exec sddsprocess /home/helios/oagData/sr/orbitControllaw/waveforms/DP:[string toupper $coord]bpmSetPt:WF-zero \
                         -pipe=out -edit=col,ControlName,DeviceName,ei/:${coord}:RefAO \
                         | sddscasr -pipe -save \
                         | sddsprocess -pipe -scan=col,Value,ValueString,%lf \
                         | sddsprocess -pipe=in $tmpRoot.bpm -nowarnings "-test=col,Value -$bpmLimit < Value $bpmLimit > ||" } result] {
                return -code error "APSCheckRTFBbpmSetpoints(3): $result"
            }
        } 
        vector {
            APSSToTmpFileList -ID bpmlimit -fileList $tmpRoot.bpm.1
            if [catch {exec sddswget  /home/helios/oagData/sr/orbitControllaw/waveforms/DP:[string toupper $coord]bpmSetPt:WF-zero \
                         $tmpRoot.bpm.1 } result] {
                return -code error "APSCheckRTFBbpmSetpoints(4): $result"
            }
            if [catch {exec sddsprocess $tmpRoot.bpm.1 $tmpRoot.bpm \
                         -redefine=col,Value,Waveform \
                         -nowarnings "-test=col,Waveform -$bpmLimit < Waveform $bpmLimit > ||" } result] {
                return -code error "APSCheckRTFBbpmSetpoints(5): $result"
            }
        }
    }
    set rows [exec sdds2stream -rows=bar $tmpRoot.bpm]
    if !$rows {
        return
    }
    if [catch {exec sddsprintout $tmpRoot.bpm "-title=folloing RTFB bpm setpoint are out of range (exceed 10mm)" \
                 -nolabel \
                 -col=DeviceName -col=Value,format=%.2f } printOut] {
        return -code error  "APSCheckRTFBbpmSetpoints(6): $printOut"
    }
    return $printOut
}

proc APSFixRTFBbpmSetpoints {args} {
    set plane ""
    set bpmLimit 10
    set statusCallback ""
    APSStrictParseArguments {plane bpmLimit statusCallback}
    if ![string length $plane] {
        APSMpReturn error "APSFixRTFBbpmSetpoints(1a): plane (h or v) is not provided."
    }
    set plane [string tolower $plane]
    switch $plane {
        h -
        x {
            set plane h
            set coord x
        }
        v -
        y {
            set plane v
            set coord y
        }
        default {
            APSMpReturn error "APSFixRTFBbpmSetpoints(1): Invalid plane - $plane provided, should be h or v."
        }
    }
    APSMpStep "Check corrector mode..."
    if [string length $statusCallback] {
        eval $statusCallback {"Check corrector mode..."}
    }
    if [catch {APSSRCheckCorrectorMode -plane $plane} corrMode] {
        APSMpReturn error "APSFixRTFBbpmSetpoints(2): $corrMode"
    }
    if {$corrMode=="vector"} {
        APSAlertBox .warning -type warning -errorMessage "Now please open the RTFB loops, press OK when it is done."
    }
    if ![APSYesNoPopUp "To fix the RTFB bpm setpoints, first set the RTFB bpm setpoints to zero, would like you to do so now?"] {
        APSMpReturn error "APSFixRTFBbpmSetpoints(3): fix RTFB bpm setpoints was cancel."
    }
    APSMpStep "Set RTFB bpm setpoints to zero."
    if [string length $statusCallback] {
        eval $statusCallback {"Set RTFB bpm setpoints to zero."}
    }
    switch $corrMode {
        scalar {
            if [catch {exec sddsprocess /home/helios/oagData/sr/orbitControllaw/waveforms/DP:[string toupper $coord]bpmSetPt:WF-zero \
                         -pipe=out -edit=col,ControlName,DeviceName,ei/:${coord}:RefAO -reprint=col,ValueString,0 \
                         | sddscasr -pipe=in -restore } result] {
                APSMpReturn error "APSFixRTFBbpmSetpoints(3): $result"
            }
        } 
        vector {
            if [catch {exec sddswput /home/helios/oagData/sr/orbitControllaw/waveforms/DP:[string toupper $coord]bpmSetPt:WF-zero } result] {
                APSMpReturn error "APSFixRTFBbpmSetpoints(4): $result"
            }
        }
    }
    APSAlertBox .warning -type warning -errorMessage "Now please start the orbit controllaw, press OK after controllaw is running."
    
    APSMpReturn ok
}
