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

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)]

# $Log: not supported by cvs2svn $
# Revision 1.23  2006/01/25 21:08:07  shang
# replaced LSFlag by Flag in processing orbit controllaw config files, since LSFlag column
# does not exist in config file.
#
# Revision 1.22  2003/02/04 03:46:21  emery
# Added -noWarning to sddsselect prevent tcl error.
#
# Revision 1.21  2002/10/15 03:33:32  emery
# Corrected the labels in the tab widgets.
#
# Revision 1.20  2002/10/14 04:06:18  emery
# Changed order of tab widgets (H ID done before V BM).
#
# Revision 1.19  2002/07/09 16:15:05  emery
# Added a -noWarning to the sddsselect for creating a non-LS bpm
# file.
#
# Revision 1.18  2002/05/27 20:03:59  emery
# Added invert option to RestoreTransferBPMs. Fixed status message
# for the transfer buttons.
#
# Revision 1.17  2002/05/27 18:56:47  emery
# Replaced a "ID" with the variable "sourceType". This corrects
# a bug when the non-BM bpms are transfered.
#
# Revision 1.16  2002/04/23 17:13:22  emery
# Replaced the argument h with argument $plane in start orbit correction.
#
# Revision 1.15  2002/03/12 21:47:53  emery
# Removed SCR file selecting procedures that were already available
# as library procedures.
#
# Revision 1.14  2002/03/12 18:50:17  emery
# Made tab widget for SCR file selection and ID and BM steering
# in h and v planes.
#
# Revision 1.13  2002/01/29 16:25:40  borland
# Embedded old SCR procedures to fix incompatibility with new ones.
#
# Revision 1.12  2002/01/22 22:45:46  emery
# Added Despike column with zero values to config file.
#
# Revision 1.11  2002/01/22 21:20:54  emery
# Improved some context help.
#
# Revision 1.10  2002/01/22 20:17:11  emery
# Correct a context help for new button.
#
# Revision 1.9  2002/01/22 20:14:40  emery
# SPlit function of restore/transfer into two buttons.
#
# Revision 1.8  2002/01/22 18:54:44  emery
# Fixed missing searchString in entry box by making the variable global.
# Added more context help on the regenerate button.
#
# Revision 1.7  2002/01/19 09:54:57  emery
# Polluted file for h is now created after code was found outside of {h v} loop
#
# Revision 1.6  2002/01/19 08:33:44  emery
# Added generatePolluted procedure, which select polluted bpms
# to be simply all bpms minus those of light source points
# and those to be locked down at the other ligth source type.
# Removed sdds file writing of old polluted bpm files.
#
# Revision 1.5  2001/12/11 18:31:17  emery
# Fixed name of column LSFlag in procedure generateLSFlags.
#
# Revision 1.4  2001/12/11 18:27:03  emery
# Changed sddsprocess argument -def to -redef for LSFlags.
#
# Revision 1.3  2001/12/11 18:24:26  emery
# Added buttons to generate LSFlags column in config files
# that were generated elsewhere.
#
# Revision 1.2  2001/12/11 15:08:59  emery
# Split the orbit correction buttons into x and y corrections.
#
# Revision 1.1  2001/12/05 08:52:43  emery
# First installation. Tested, but some physics issues left
# from a x-plane BM steering divergence problem.
#

set CVSRevisionAuthor "\$Revision: 1.24 $ \$Author: emery $"

APSApplication . -name SRRestoreSteering \
  -overview "SRRestoreSteering restores the steering in the SR, say, after a lattice change. Need to define the two valid configurations in each plane before starting in a plane."


proc MakeSCRSelectionFrame {widget args} {
    global initialSCRSystem system oagDataDir searchString
    set daysPast 7
# SCRFiles is an array, but the variable SCRFile will be
# a regular variable for the procedure KnLValues
    set arrayName SCRFiles
    set searchString *

    set parent ""

    APSStrictParseArguments {parent}

    APSFrame $widget -parent $parent -label "Input parameters"
    set w $parent$widget.frame

    APSFrame .file  -parent $w -label "Choose SCR File for BPM setpoints"
    set w $parent$widget.frame.file.frame

    global $arrayName
    global apsSCRConfigStartYear apsSCRConfigStartMonth apsSCRConfigStartDay
    global apsSCRConfigEndYear apsSCRConfigEndMonth apsSCRConfigEndDay 
    APSSCRDateTimeEntryWidget .dtew -parent $w 
    APSSCRDefineVariables
    set system $initialSCRSystem
    APSDateBreakDown -dayVariable apsSCRConfigStartDay \
        -yearVariable apsSCRConfigStartYear -monthVariable apsSCRConfigStartMonth \
        -twoDigitYear 0 -leadingZeros 0
    APSDateBreakDown -dayVariable apsSCRConfigEndDay \
        -yearVariable apsSCRConfigEndYear -monthVariable apsSCRConfigEndMonth \
        -twoDigitYear 0 -leadingZeros 0
    if $daysPast {
        APSIncrementDateVariables -offset [expr -1*abs($daysPast)] -unit day \
          -dayVariable apsSCRConfigStartDay -yearVariable apsSCRConfigStartYear \
          -monthVariable apsSCRConfigStartMonth 
    }
    APSLabeledEntry .descript -parent $w.dtew.frame \
      -label "Description search string: " \
      -textVariable searchString  -packOption "-side top" -width 40 \
      -contextHelp "Enter a string to use in searching for files by matching the description given by the operator who saved the snapshot."
    APSFrame .choice -parent $w -label "Snapshot choice" 
    set w1 $w.choice.frame
    set ${arrayName}(ShortFilename) ""
    set ${arrayName}(Description) ""
    APSLabeledOutput .filename -parent $w1 -label "Filename" \
      -textVariable ${arrayName}(ShortFilename) -width 100
    APSLabeledOutput .description -parent $w1 -label "Description" \
      -textVariable ${arrayName}(Description) -width 100

    APSButton .refresh -parent $w -text Refresh \
      -command \
      "APSListSCRMatchSetArray -machine \$system -height 8 \
      -startYear \$apsSCRConfigStartYear -startMonth \$apsSCRConfigStartMonth \
      -startDay \$apsSCRConfigStartDay \
      -endYear \$apsSCRConfigEndYear -endMonth \$apsSCRConfigEndMonth \
      -endDay \$apsSCRConfigEndDay \
      -descriptionFragment \$searchString -parent $w \
      -statusCallback SetStatus \
      -callback APSAddSCRDialogCallback \
      -arrayName $arrayName -routine 0"
    APSListSCRMatchSetArray -machine $system -height 8 \
      -startYear $apsSCRConfigStartYear -startMonth $apsSCRConfigStartMonth \
      -startDay $apsSCRConfigStartDay \
      -endYear $apsSCRConfigEndYear -endMonth $apsSCRConfigEndMonth \
      -endDay $apsSCRConfigEndDay \
      -descriptionFragment $searchString -parent $w  \
      -statusCallback SetStatus \
      -callback APSAddSCRDialogCallback \
      -arrayName $arrayName -routine 0

    set w $parent$widget.frame

}


proc MakeActionWidget {widget args} {
    set parent ""
    APSParseArguments {parent plane sourceType}
    
    APSFrame $widget -parent $parent -label "Ordered Sequence of Actions" \
      -packOption "-side top" \
      -contextHelp "Actions to execute in order."
    set w $parent$widget.frame

    APSButton .createConfig -parent $w -text "Create $sourceType Configuration" \
      -packOption "-side top" \
      -command "createConfiguration -plane $plane -sourceType $sourceType" \
      -contextHelp "Creates configuration $plane.${sourceType}Steering for steering $sourceType light sources."

    set w0 $w
    set rootname $plane$sourceType
    global ${rootname}MainDir ${rootname}Lattice 
    set ${rootname}MainDir /home/helios/oagData/sr/orbitControllaw/lattices
    set ${rootname}Lattice default
    global ${rootname}Plane ${rootname}ReadFile ${rootname}ReadDescription
    global ${rootname}FilterEnd1 
    set ${rootname}Plane $plane
    set ${rootname}ReadFile $plane.${sourceType}Steering
    set ${rootname}ReadDescription ""
    set ${rootname}FilterEnd1 .*
    APSFileSelectWidget .file -parent $w0 -variable ${rootname}ReadFile -label "Config: " \
      -pathVariableList [list ${rootname}MainDir ${rootname}Lattice] \
      -mode directory -filterVariableList \
      [list ${rootname}Plane ${rootname}FilterEnd1] -width 60 \
      -incrementButtons 1 -contextHelp \
      "Enter the name of the configuration file to read."

    APSLabeledOutput .descrip -parent $w0 -label "Description: " -width 80 -packOption "-side top -anchor w" \
      -textVariable ${rootname}ReadDescription -contextHelp \
      "Shows the description of the last-read configuration file."
    
    APSButton .readDesc -parent $w -text "Read description of config" \
      -packOption "-side top" \
      -command "ReadDescription  -plane $plane -sourceType $sourceType" \
      -contextHelp "Reads the description of the configuration."

    APSButton .generateLSFlags -parent $w -text "Regenerate LS flags" \
      -packOption "-side top" \
      -command "generateLSFlags -plane $plane -sourceType $sourceType" \
      -contextHelp "Generates LS flags for steering $sourceType light sources. LS flags are additional flags associated with the bpms to distinguish light source bpms and other bpms that are supposed to be unsteered. Used only when config was written by another application."

    APSButton .restore -parent $w -text "Restore $sourceType bpms" \
      -packOption "-side top" \
      -command "RestoreTransferBPMs -sourceType $sourceType -restore 1 -transfer 0 -plane $plane" \
      -contextHelp "Restores bpms for $sourceType in $plane plane."

    APSButton .transfer -parent $w -text "Transfer non-$sourceType bpms" \
      -packOption "-side top" \
      -command "RestoreTransferBPMs -sourceType $sourceType -restore 0 -transfer 1 -plane $plane -invert 1" \
      -contextHelp "Transfer bpms from inverse set of bpms for $sourceType in $plane plane."

    APSButton .correct -parent $w \
      -packOption "-side top" \
      -text "Run $plane-orbit correction for $sourceType sources" \
      -command "CorrectOrbit -sourceType $sourceType -plane $plane" \
      -contextHelp "Correct the orbit for bpms for all $sourceType light sources while keeping the other light source fixed."

    APSButton .transferP -parent $w \
      -packOption "-side top" \
      -text "Transfer Polluted bpms for $sourceType steering" \
      -command "TransferPollutedBPMs -sourceType $sourceType -plane $plane" \
      -contextHelp "Transfer polluted bpms for $sourceType steering in $plane plane."

    switch $sourceType {
        ID {
            set otherType BM
        }
        BM {
            set otherType ID
        }
    }
    APSButton .restoreOther -parent $w -text "Restore $otherType bpms" \
      -packOption "-side top" \
      -command "RestoreTransferBPMs -sourceType $otherType -restore 1 -transfer 0 -plane $plane" \
      -contextHelp "Restores bpms for $otherType in $plane plane."

    return
}

proc createConfiguration {args} {
    set sourceType ID
    APSParseArguments {sourceType plane}
# creates files:
# config with additional column LSflag
# polluted
# If config has already been created by another application,
# then we need to add the proper LSflag using a seperate procedure.
# We also need to create file polluted when file config already exists.
# That's more complicated.
    switch $sourceType {
        ID {
            set configName IDSteering
        }
        BM {
            set configName BMSteering
        }
        default {
            return -code error "createConfiguration(0): Invalid sourceType argument."
        }
    }
    SetStatus "Creating configurations $plane.${sourceType}Steering..."
    set tmpfile /tmp/[APSTmpString]
    set date [clock format [clock seconds] -format "%D-%T"]
    switch $plane {
        h {
            if [catch {open $tmpfile.hcorrectors w} fidhc] {
                return -code error "createConfiguration(0): $fidhc"
            }
            puts $fidhc SDDS1
            puts $fidhc "&parameter name=Description, type=string, &end"
            puts $fidhc "&parameter name=NameType, type=string, &end"
            puts $fidhc "&parameter name=PVType, type=string, &end"
            puts $fidhc "&column name=Name, type=string,  &end"
            puts $fidhc "&data mode=ascii, no_row_counts=1 &end"
            puts $fidhc "Configuration for $sourceType steering restoration $date"
            puts $fidhc "CorrectorNames"
            puts $fidhc "plain"

            if [catch {open $tmpfile.hbpms w} fidhb] {
                return -code error "createConfiguration(1): $fidhb"
            }
            puts $fidhb SDDS1
            puts $fidhb "&parameter name=Description, type=string, &end"
            puts $fidhb "&parameter name=NameType, type=string, &end"
            puts $fidhb "&parameter name=PVType, type=string, &end"
            puts $fidhb "&column name=Name, type=string,  &end"
            puts $fidhb "&column name=LSFlag, type=short,  &end"
            puts $fidhb "&data mode=ascii, no_row_counts=1 &end"
            puts $fidhb "Configuration for $sourceType steering restoration $date"
            puts $fidhb "MonitorNames"
            puts $fidhb "plain"
            
        }
        v {
            if [catch {open $tmpfile.vcorrectors w} fidvc] {
                return -code error "createConfiguration(0): $fidvc"
            }
            puts $fidvc SDDS1
            puts $fidvc "&parameter name=Description, type=string, &end"
            puts $fidvc "&parameter name=NameType, type=string, &end"
            puts $fidvc "&parameter name=PVType, type=string, &end"
            puts $fidvc "&column name=Name, type=string,  &end"
            puts $fidvc "&data mode=ascii, no_row_counts=1 &end"
            puts $fidvc "Configuration for $sourceType steering restoration $date"
            puts $fidvc "CorrectorNames"
            puts $fidvc "plain"

            if [catch {open $tmpfile.vbpms w} fidvb] {
                return -code error "createConfiguration(1): $fidvb"
            }
            puts $fidvb SDDS1
            puts $fidvb "&parameter name=Description, type=string, &end"
            puts $fidvb "&parameter name=NameType, type=string, &end"
            puts $fidvb "&parameter name=PVType, type=string, &end"
            puts $fidvb "&column name=Name, type=string,  &end"
            puts $fidvb "&column name=LSFlag, type=short,  &end"
            puts $fidvb "&data mode=ascii, no_row_counts=1 &end"
            puts $fidvb "Configuration for ${sourceType} steering restoration $date"
            puts $fidvb "MonitorNames"
            puts $fidvb "plain"
            
        }
    }
    # select P0/P1 bpms from list of good bpms.
    # need to know these even when we are doing BM steering.
    if [catch {APSSRGetWorkingP0SectorsList} P0List] {
        SetStatus "createConfiguration (2): Problem getting working P0s: $P0List"
        return
    }
    set LSsectors [exec sdds2stream /home/helios/oagData/sr/${sourceType}s/sectors.sdds  -col=Sector]
    # use BM Xray bpm in y plane wherever they are vailable.
    set BMXlist [APSGetBMXRayBPMList -plane V -okForDCOrbitCorrection 1]
    for {set i 1} {$i < 41} {incr i} {
        set i1 [expr $i + 1]
        if [expr $i1 == 41] {
            set i1 1
        }
        # the LS flags can be generated by proc generateLSFlags as well.
        switch $sourceType {
            ID {
                if [string match $plane h] {
                    puts $fidhb "S${i}B:P4 0"
                    puts $fidhb "S${i}B:P3 0"
                } else {
                    if {[lsearch -exact $BMXlist S${i}BM:P1] > -1 &&
                        [lsearch -exact $BMXlist S${i}BM:P2] > -1 } {
                        # both are available
                        puts $fidvb "S${i}BM:P1 0"
                        puts $fidvb "S${i}BM:P2 0"
                    } elseif {[lsearch -exact $BMXlist S${i}BM:P1] > -1 } {
                        # one is available
                        puts $fidvb "S${i}BM:P1 0"
                        puts $fidvb "S${i}B:P5 0"
                    } elseif {[lsearch -exact $BMXlist S${i}BM:P2] > -1 } {
                        # other is available
                        puts $fidvb "S${i}BM:P2 0"
                        puts $fidvb "S${i}B:P5 0"
                    } else {
                        # none are available
                        puts $fidvb "S${i}B:P5 0"
                        puts $fidvb "S${i}B:P3 0"
                    }
                }
            }
            BM {
                if [string match $plane h] {
                    puts $fidhb "S${i}B:P3 1"
                    puts $fidhb "S${i}B:P4 1"
                } else {
                    if {[lsearch -exact $BMXlist S${i}BM:P1] > -1 &&
                        [lsearch -exact $BMXlist S${i}BM:P2] > -1 } {
                        # both are available
                        puts $fidvb "S${i}BM:P1 1"
                        puts $fidvb "S${i}BM:P2 1"
                    } elseif {[lsearch -exact $BMXlist S${i}BM:P1] > -1 } {
                        # one is available
                        puts $fidvb "S${i}BM:P1 1"
                        puts $fidvb "S${i}B:P5 1"
                    } elseif {[lsearch -exact $BMXlist S${i}BM:P2] > -1 } {
                        # other is available
                        puts $fidvb "S${i}BM:P2 1"
                        puts $fidvb "S${i}B:P5 1"
                    } else {
                        # none are available
                        if {$i == 35} {
                            # sector 35 is a special case where we need to use
                            # the bpms to steer vertically.
                            puts $fidvb "S${i}B:P3 1"
                            puts $fidvb "S${i}B:P4 1"
                        } else {
                            puts $fidvb "S${i}B:P5 0"
                        }
                    }
                }
            }
        }
        if {[lsearch -exact $P0List $i] > -1} {
            # need two bpms that are outside the bump. These bpms 
            # will be held fixed by OC.
            set LSflag [string match ID $sourceType]
            if [string match $plane h] {
                puts $fidhb "S${i}B:P0 $LSflag"
                puts $fidhb "S${i1}A:P0 $LSflag"
            } else {
                puts $fidvb "S${i}B:P0 $LSflag"
                puts $fidvb "S${i1}A:P0 $LSflag"
            }
        } else {
            # P1 are to be used. 
            # P1's are selected for non-light source sectors too.
            set LSflag [string match ID $sourceType]
            if [string match $plane h] {
                puts $fidhb "S${i}B:P1 $LSflag"
                puts $fidhb "S${i1}A:P1 $LSflag"
            } else {
                puts $fidvb "S${i}B:P1 $LSflag"
                puts $fidvb "S${i1}A:P1 $LSflag"
            }
        }
        switch $sourceType {
            ID {
                if [string match $plane h] {
                    puts $fidhc S${i}B:H2
                    puts $fidhc S${i1}A:H2
                    if {[lsearch -exact $LSsectors $i] > -1 } {
                        puts $fidhc S${i}B:H3
                        puts $fidhc S${i1}A:H3
                    }
                } else {
                    puts $fidvc S${i}B:V2
                    puts $fidvc S${i1}A:V2
                    if {[lsearch -exact $LSsectors $i] > -1 } {
                        puts $fidvc S${i}B:V3
                        puts $fidvc S${i1}A:V3
                    }
                }
            }
            BM {
                if [string match $plane h] {
                    puts $fidhc S${i}A:H2
                    puts $fidhc S${i}B:H2
                    if {[lsearch -exact $LSsectors $i] > -1 } {
                        puts $fidhc S${i}B:H4
                        puts $fidhc S${i}B:H3
                    }
                } else {
                    puts $fidvc S${i}A:V2
                    puts $fidvc S${i1}B:V3
                    if {[lsearch -exact $LSsectors $i] > -1 } {
                        puts $fidvc S${i}B:V4
                        puts $fidvc S${i}B:V2
                    }
                }
            }
        }
    }
    if [string match $plane h] {
        close $fidhb
        close $fidhc
    } else {
        close $fidvb
        close $fidvc
    }
    set baseDir /home/helios/oagData/sr/orbitControllaw
    set configDir $baseDir/lattices/default/${plane}.$configName
    catch {exec mkdir -p $configDir}
    exec sddscombine $tmpfile.${plane}bpms $tmpfile.${plane}correctors \
      -pipe=out \
      | sddsprocess -pipe=in $configDir/config \
      -def=col,Flag,1,type=short \
      -def=col,Despike,0,type=long

    catch {exec sddscollapse $filename $filename.collapsed}
    APSSRGenerateOrbCorrFiles -rootname S -generate 1 \
      -configFile $configDir/config \
      -plane $plane \
      -referenceMatrix $baseDir/lattices/default/refMatrices/$plane.default \
      -outputRoot $configDir/ \
      -singularValues 400 \
      -removeVectors 0
    
    if [catch {generatePolluted -sourceType $sourceType -plane $plane \
             } results] {
        return -code error $results
    }
    set config $plane.${sourceType}Steering
    SetStatus "Config $config created or overwritten."
    return
}

proc ReadDescription {args} {
    set sourceType ""
    set plane ""
    APSParseArguments {sourceType plane}

    set rootname $plane$sourceType
    global ${rootname}ReadFile ${rootname}ReadDescription
    set config [subst \$${rootname}ReadFile]

    SetStatus "Reading description of $config..."
    set tmpfile /tmp/[APSTmpString]
    
    # read the configuration
    set baseDir /home/helios/oagData/sr/orbitControllaw
    switch $plane {
        h {set coord x}
        v {set coord y}
    }
    set configDir $baseDir/lattices/default/$config
    if ![file exists $configDir/config] {
        SetStatus "Can't find config file for $configName."
        return
    }
    set ${rootname}ReadDescription [lindex [exec sdds2stream $configDir/config -para=Description] 0]
    SetStatus "Done."
    return
}

proc generateLSFlags {args} {
    set sourceType ""
    set plane ""
    APSParseArguments {sourceType plane}

    set rootname $plane$sourceType
    global ${rootname}ReadFile ${rootname}ReadDescription
    set config [subst \$${rootname}ReadFile]

    SetStatus "Adding column LSflag to $config..."
    set tmpfile /tmp/[APSTmpString]
    
    # read the configuration
    set baseDir /home/helios/oagData/sr/orbitControllaw
    switch $plane {
        h {set coord x}
        v {set coord y}
    }
    set configDir $baseDir/lattices/default/$config
    if ![file exists $configDir/config] {
        SetStatus "Can't find config file for $configName."
        return
    }
    exec sddsprocess $configDir/config $configDir/config.bpm -noWarning \
      -match=para,NameType=MonitorNames
    exec sddsprocess $configDir/config $configDir/config.corr -noWarning \
      -match=para,NameType=CorrectorNames
    # create LS and nonLS files.
    switch $plane$sourceType {
        hBM {
            exec sddsprocess $configDir/config.bpm $configDir/LS -noWarning \
              -match=col,Name=*P\[34\] \
              -redef=col,LSFlag,1,type=long
        }
        vBM {
            exec sddsprocess $configDir/config.bpm $configDir/LS -noWarning \
              -match=col,Name=*P\[34\],Name=*BM:P?,| \
              -redef=col,LSFlag,1,type=long
        }
        hID {
            exec sddsprocess $configDir/config.bpm $configDir/LS -noWarning \
              -match=col,Name=*P\[345\],! \
              -redef=col,LSFlag,1,type=long
        }
        vID {
            exec sddsprocess $configDir/config.bpm $configDir/LS -noWarning \
              -match=col,Name=*P\[345\],Name=*BM:P?,|,! \
              -redef=col,LSFlag,1,type=long
        }
    }
    exec sddsselect $configDir/config.bpm $configDir/LS -pipe=out \
      -invert -match=Name -nowarnings \
      | sddsprocess -pipe=in $configDir/nonLS -noWarning \
      -redef=col,LSFlag,0,type=long
    exec sddscombine $configDir/LS $configDir/nonLS \
      -merge $configDir/config.bpm -overWrite
    exec sddscombine $configDir/config.bpm $configDir/config.corr \
      $configDir/config -overWrite
    
    if [catch {generatePolluted -sourceType $sourceType -plane $plane \
             } results] {
        return -code error $results
    }
    SetStatus "LS flags generated."
}

proc generatePolluted {args} {
    set sourceType ""
    set plane ""
    APSParseArguments {sourceType plane}
    
    set rootname $plane$sourceType
    global ${rootname}Plane ${rootname}ReadFile ${rootname}ReadDescription
    set config [subst \$${rootname}ReadFile]

    SetStatus "Generating file of polluted bpms for $config..."
    set tmpfile /tmp/[APSTmpString]

    # read the configuration
    set baseDir /home/helios/oagData/sr/orbitControllaw
    switch $plane {
        h {set coord x}
        v {set coord y}
    }
    set configDir $baseDir/lattices/default/$config

    if ![file exists $configDir/config] {
        SetStatus "Can't find config file for $configName."
        return
    }
    # Polluted bpms are all bpms minus bpms in config.
    set statusDir /home/helios/oagData/sr/BPMStatus
    set tmpfile /tmp/[APSTmpString]
    exec sddsprocess $configDir/config $tmpfile.bpmConfig \
      -match=para,NameType=MonitorNames
    exec sddsprocess $statusDir/config.sdds -pipe=out \
      -filter=col,Nonexistent[string toupper $plane],0,0 \
      -match=col,DeviceName=*ID*,! \
      -filter=col,OkForDCOrbitCorrection[string toupper $plane],1,1 \
      | sddsconvert -pipe=in $tmpfile.allBpms \
      -rename=col,DeviceName=Name -retain=col,DeviceName
    exec sddsselect $tmpfile.allBpms $tmpfile.bpmConfig $configDir/polluted \
      -match=Name -invert
    SetStatus "Polluted bpm file generated for $config."
}

proc RestoreTransferBPMs {args} {
    global SCRFiles
    set sourceType ID
    set transfer 1
    set restore 0
    set invert 0
    set plane ""
    APSParseArguments {plane sourceType transfer restore invert}
    if ![string length $SCRFiles(Filename)] {
        SetStatus "No SCR file selected."
        return
    }
    if {$restore && $transfer} {
        SetStatus "RestoreTransferBPMs: can't set both restore and transfer to 1."
        return
    }
    set rootname $plane$sourceType
    global ${rootname}Plane ${rootname}ReadFile ${rootname}ReadDescription
    set config [subst \$${rootname}ReadFile]

    set qualifier ""
    if $invert {
        set qualifier "non-"
    }
    if $restore {
        SetStatus "Restoring $plane-plane bpms for $qualifier$sourceType source from file $SCRFiles(Filename)..."
    }
    if $transfer {
        SetStatus "Transfering $plane-plane bpms for $qualifier$sourceType source..."
    }
    # 
    set tmpfile /tmp/[APSTmpString]
    exec sddsprocess $SCRFiles(Filename) $tmpfile.setpoints \
      -match=col,Beamline=SR,Category=BPM,& \
      -match=col,ControlName=S*SetpointAO \

    exec sddsprocess $tmpfile.setpoints $tmpfile.xsetpoints \
      -match=col,ControlName=S*x* \
      -def=col,Flag,1 \
      -print=para,NameType,MonitorNames \
      -edit=col,Name,ControlName,%/:ms:x:SetpointAO//
    exec sddsprocess $tmpfile.setpoints $tmpfile.ysetpoints \
      -match=col,ControlName=S*y* \
      -def=col,Flag,1 \
      -print=para,NameType,MonitorNames \
      -edit=col,Name,ControlName,%/:ms:y:SetpointAO//

    set baseDir /home/helios/oagData/sr/orbitControllaw
    switch $plane {
        h {set coord x}
        v {set coord y}
    }
    set configDir $baseDir/lattices/default/$config

    exec sddsprocess $configDir/config $tmpfile.${plane}config \
      -match=para,NameType=MonitorNames \
      -filter=col,Flag,1,1
    exec sddsselect $tmpfile.${coord}setpoints $tmpfile.${plane}config \
      $tmpfile.${coord}setpoint.used \
      -match=Name
    if $restore {
        if [catch {exec sddscasr -restore $tmpfile.${coord}setpoint.used } result ] {
            SetStatus "RestoreBPMs: $result"
        }
        SetStatus "Bpm setpoints in ${plane}-plane restored."
        update
    }
    if $transfer {
        if !$invert {
            set bpmList [exec sdds2stream $tmpfile.${coord}setpoint.used -col=Name ]
            if [catch {APSSRTransferBPMList -msType mswAve \
                         -plane $coord -list $bpmList \
                     } result ] {
                SetStatus "$sourceType bpms in ${plane}-plane transfered."
                update
            }
        } else {
            # transfer all bpms except the light source bpms.
            if [catch {APSSRTransferBPMAdjustedValues -msType mswAve \
                         -plane $coord \
                         -excludeConfigFileList $tmpfile.${coord}setpoint.used \
                     } result ] {
                SetStatus "RestoreBPMs: $result"
            }
            SetStatus "Non-$sourceType bpms in ${plane}-plane transfered."
            update
        }
    }
    return
}

proc CorrectOrbit {args} {
    set sourceType ID
    set plane ""
    APSParseArguments {sourceType plane}

    set rootname $plane$sourceType
    global ${rootname}Plane ${rootname}ReadFile ${rootname}ReadDescription
    set config [subst \$${rootname}ReadFile]

    set options "-steps=60 -interval=0.5 -gain=0.2 -verb -deltaLimit=value=0.5"

    set Plane [string toupper $plane]
    set baseDir /home/helios/oagData/sr/orbitControllaw
    set configDir $baseDir/lattices/default/$config
    if ![file exists $configDir/tests] {
        SetStatus "Can't find tests file for $config. Please run SRorbitControllaw and press Generate." 
        return
    }
    APSExecLog .sr${Plane}OrbitControllaw \
      -lineLimit 2048 -width 100 \
      -name "SR ${Plane}-orbit Correction from restore steering application" \
      -unixCommand "sddscontrollaw $configDir/irm -testValues=$configDir/tests \
             -controlQuantityDefinitions=$configDir/definitions.msAve \
             -actuator=ControlName $options"
    SetStatus "Orbit controllaw in $plane-plane started with $config..."
    return
}

proc TransferPollutedBPMs {args} {
    set sourceType ID
    set plane ""
    APSParseArguments {plane sourceType}

    set rootname $plane$sourceType
    global ${rootname}Plane ${rootname}ReadFile ${rootname}ReadDescription
    set config [subst \$${rootname}ReadFile]

    set baseDir /home/helios/oagData/sr/orbitControllaw
    switch $plane {
        h {set coord x}
        v {set coord y}
    }
    set configDir $baseDir/lattices/default/$config

    SetStatus "Transfering polluted bpms for $config..."
    # use file polluted in steering configuration directory
    set bpmList [exec sdds2stream -col=Name $configDir/polluted]
    if [catch {exec cavget -pend=20 -list=[join $bpmList ,] \
                 -list=:mswAve:$coord -list=:AdjustedCC} valueList] {
        SetStatus "$valueList"
        return
    }
    if [catch {exec cavget -pend=20 -list=[join $bpmList ,] \
                 -list=:ms:$coord -list=:SetpointAO -dry} pvList] {
        SetStatus "$pvList"
        return
    } 
    foreach pv $pvList value $valueList {
        lappend commandOptList $pv=$value
    }
    if [catch {exec cavput -pend=30 -list=[join $commandOptList ,]} result] {
        SetStatus "$result"
        result
    }
    SetStatus "Polluted bpms for $config transfered."
    return
}


proc SetStatus {text} {
    global status
    set status $text
}


set status "Working."
APSScrolledStatus .status -parent .userFrame -textVariable status -width 90

set widgetList [APSTabFrame .tabs -parent .userFrame -label "" \
                  -labelList {"Setpoint File" "BM H Steering" "ID H Steering" "BM V Steering" "ID V Steering"} \
                  -width 1000 -height 500]

set initialSCRSystem SR
MakeSCRSelectionFrame .select -parent [lindex $widgetList 0]
MakeActionWidget .action -parent [lindex $widgetList 1] -plane h -sourceType BM
MakeActionWidget .action -parent [lindex $widgetList 2] -plane h -sourceType ID
MakeActionWidget .action -parent [lindex $widgetList 3] -plane v -sourceType BM
MakeActionWidget .action -parent [lindex $widgetList 4] -plane v -sourceType ID
set status "Ready."
update
