#!/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)]
APSDebugPath
wm geometry . +10+10

set args $argv
set buttonOrientation horizontal
set fontSize regular
set includeP0s 1
set includeIDs 1
set includeBMs 1

proc APSReadUnifiedSteeringConfig {args} {
    set rootname ""
    set filename ""
    set logic replace
    set includeP0s 0
    set includeIDs 0
    set includeBMs 0
    set sectorCount 40
    set nameTypeList {Corrector Monitor}
    set application DCOrbitCorrection
    set RTFBrootname ""
    set lattice ""
    APSStrictParseArguments {rootname filename lattice includeP0s includeIDs includeBMs \
                               sectorCount nameTypeList RTFBrootname}
    global ${rootname}BadBPMList 
    if {![info exists ${rootname}BadBPMList]} {
        set ${rootname}BadBPMList ""
    }
    set BPMList [list A:P1 A:P2 A:P3 A:P4 B:P5 B:P4 B:P3 B:P2 B:P1]
    if $includeP0s {
        set BPMList [concat A:P0 $BPMList B:P0 C:P0]
    }
    if $includeIDs {
        set BPMList [concat $BPMList ID:P1 ID:P2]
    }
    if $includeBMs {
        set BPMList [concat $BPMList BM:P1 BM:P2]
    }
    switch -regexp $rootname {
        h {
            set BPMMissingList [APSGetMissingBPMList -plane h]
            set missingList "S1A:H3 S39B:H1 S40A:H3 $BPMMissingList [set ${rootname}BadBPMList]"
            set corList "A:H1 A:H2 A:H3 A:H4 B:H4 B:H3 B:H2 B:H1 C:H1"
        }
        v {
            set BPMMissingList [APSGetMissingBPMList -plane v]
            set missingList "S1A:V3 S39B:V1 S40A:V3 $BPMMissingList [set ${rootname}BadBPMList]"
            set corList "A:V1 A:V2 A:V3 A:V4 B:V4 B:V3 B:V2 B:V1 C:V1"
        }
    }
    set sectorList ""
    set suffixList [concat $BPMList $corList]
    global ${RTFBrootname}MainDir ${RTFBrootname}LatSubDir ${RTFBrootname}Lattice ${RTFBrootname}ReadFile
    set ${RTFBrootname}Lattice $lattice
    set pars [exec sddsquery -par $filename]
    set tmpRoot /tmp/[APSTmpString]
    if [lsearch $pars "RTFBConfig"]>=0 {
        set rtfbFile [lindex [exec sdds2stream -par=RTFBConfig $filename] 0]
        set ${RTFBrootname}ReadFile [file tail $rtfbFile]
        set ${RTFBrootname}Lattice [file tail [file dir $rtfbFile]]
        set ${RTFBrootname}LatSubDir [file tail [file dir [file dir $rtfbFile]]]
        set ${RTFBrootname}MainDir [file dir [file dir [file dir $rtfbFile]]]
    }
   
    set tmpRoot /tmp/[APSTmpString]
    set dir [file dir $filename]
    
    if [catch {exec sddsprocess $filename $tmpRoot.bpm -nowarning \
                 -match=parameter,NameType=MonitorNames \
                 "-test=parameter,n_rows 0 >" \
                 -filter=column,Flag,1,1 
        exec sddsprocess $filename $tmpRoot.corr -nowarning \
                 -match=parameter,NameType=CorrectorNames \
                 "-test=parameter,n_rows 0 >" \
                 -filter=column,Flag,1,1 } result] {
        return -code error "Problem making list of included $nameType items: $result"
    }
    
    global ${rootname}Plane

    APSRescanBadOrbitDevices -rootname $rootname -plane [set ${rootname}Plane] -application DCOrbitCorrection
    
    if [catch {eval exec sddscombine $tmpRoot.bpm $tmpRoot.corr -merge -pipe=out \
                 | tee $tmpRoot.selections \
                 | sdds2stream -pipe=in -column=Name} onNameList] {
        return -code error "Problem getting name list: $onNameList"
    }
    if [catch {eval exec sdds2stream $filename -parameter=Description | tail -1} readDescription] {
        set readDescription ""
    }
    global ${rootname}ConfigStatus ${rootname}CBWidget
    set ${rootname}ConfigStatus "Read configuration from $filename"
    update
    
    if [lsearch -exact [APSGetSDDSNames -class column -fileName $tmpRoot.selections] Weight]!=-1 {
        if [catch {APSGetSDDSColumns -fileName $tmpRoot.selections \
                     -columnList Weight -variableList WeightList} result] {
            return -code error "Problem getting weight data: $result"
        }
    } else {
        set WeightList [APSReplicateItem -number [llength $onNameList] -item 1.0]
    }
    if [lsearch -exact [APSGetSDDSNames -class column -fileName $tmpRoot.selections] Despike]!=-1 {
        if [catch {APSGetSDDSColumns -fileName $tmpRoot.selections \
                     -columnList Despike -variableList DespikeList} result] {
            return -code error "Problem getting despike data: $result"
        }
    } else {
        set DespikeList ""
        foreach item $onNameList {
            if [regexp {(BM)|(ID)} $item] {
                lappend DespikeList 0
            } else {
                lappend DespikeList 1
            }
        }            
    }
    
    set dir [file dir $filename]
    if ![file exist $dir/irm] {
        set ${rootname}ConfigStatus "Warning: the irm of [file tail $dir] does not exist!"
    } else {
        if [catch {exec sdds2stream -par=ConditionNumber $dir/irm} result] {
            set ${rootname}ConfigStatus "$result!"
        } else {
            set ${rootname}ConfigStatus "The condition number is $result"
        }
        if [catch {exec sdds2stream -par=NumberOfSingularValuesUsed $dir/irm} singular] {
            set ${rootname}ConfigStatus "$singular!"
        } else {
            set ${rootname}ConfigStatus "The number of singular values is $singular."
        }
    }
    update
    
    APSSetSRSectorButtons -mode all-off -rootname ${rootname} -sectorList $sectorList \
      -sectorCount $sectorCount -itemList $suffixList
   
    foreach item $onNameList weight $WeightList despike $DespikeList {
        set nameFlag ${rootname}${item} 
        set weightVar ${rootname}${item}Weight
        set despikeVar ${rootname}${item}Despike
        global $nameFlag ${rootname}${item}Weight ${rootname}${item}Despike
        #set $nameFlag 1
        [set ${rootname}CBWidget($item)] invoke
        set ${rootname}${item}Weight $weight
        set ${rootname}${item}Despike $despike
    }
    global ${rootname}ReadDescription
    set ${rootname}ReadDescription $readDescription
    
    #read RTFB config
    APSReadOrbitCorrectionConfig -rootname $RTFBrootname -filename [set ${RTFBrootname}MainDir]/[set ${RTFBrootname}LatSubDir]/[set ${RTFBrootname}Lattice]/[set ${RTFBrootname}ReadFile]/config -logic replace -includeP0s $includeP0s -includeIDs $includeIDs -includeBMs $includeBMs  -application RTFeedback
    
}

proc APSWriteUFSteeringConfig {args} {
    set rootname ""
    set filename ""
    set plane h
    set description ""
    set interactive 0
    set includeP0s 0
    set includeIDs 0
    set includeBMs 0
    set configName ""
    set sectorCount 40
    set sectorList ""
    set rampTimeRange ""
    #booster=1 for writing booster configuration
    set RTFBrootname ""
    APSStrictParseArguments {rootname filename description interactive includeP0s \
                               includeIDs includeBMs configName rampTimeRange \
                               plane sectorCount sectorList RTFBrootname}
    if [lsearch -exact [list h v] [set plane [string tolower $plane]]]==-1 {
        return -code error "APSSRWriteYSSteerubgConfig: invalid plane: $plane"
    }
    if [lsearch -exact [list h v] [set plane [string tolower $plane]]]==-1 {
        return -code error "APSSRWriteYSSteerubgConfig: invalid plane: $plane"
    }
    global ${rootname}ConfigStatus ${rootname}CBWidget ${rootname}RefMatrix ${rootname}SingValues ${RTFBrootname}SingValues
    global ${rootname}BPMPVType ${rootname}CorrectorPVType
    global ${RTFBrootname}WriteDir ${RTFBrootname}Lattice ${RTFBrootname}RefMatrix
    global ${RTFBrootname}MainDir ${RTFBrootname}LatSubDir
    global ${rootname}MainDir ${rootname}LatSubDir ${rootname}Lattice ${rootname}WriteDir
    global ${RTFBrootname}WriteDescription ${rootname}WriteDescription 
    set UFdir [set ${rootname}MainDir]/[set ${rootname}LatSubDir]
    set rtfbdir [set ${RTFBrootname}MainDir]/[set ${RTFBrootname}LatSubDir]
    set UFlattice [set ${rootname}Lattice]
    set rtfblattice [set ${RTFBrootname}Lattice]
    set ${rootname}BPMPVType DP
    set ${rootname}CorrectorPVType DP

    if {$rtfblattice=="default"} {
        cd $rtfbdir
        set dir [file readlink default]
        set ${RTFBrootname}Lattice $dir
        set $rtfblattice $dir
    }

    if {$UFlattice=="default"} {
        cd $UFdir
        set dir [file readlink default]
        set ${rootname}Lattice $dir
        set UFlattice $dir
    }
    
    if [string compare $UFlattice $rtfblattice]!=0 {
        return -code error "UF lattice and RTFB lattice have to be the same."
    }
    
    if ![string length [set ${rootname}WriteDir]] {
        set ${rootname}WriteDir [APSNextGenerationedName -directory $UFdir/$UFlattice \
                                   -name $plane.[clock format [clock seconds] -format %Y-%m%d].00 -newFile 1 -separator .]
    }
    set writeRTFB 0
    if {![string length [set ${RTFBrootname}WriteDir]]} {
        set ${RTFBrootname}WriteDir [APSNextGenerationedName -directory $rtfbdir/$rtfblattice \
                                       -name $plane.[clock format [clock seconds] -format %Y-%m%d].00 -newFile 1 -separator .]
        set writeRTFB 1
    }
    
    set UFconfig [set ${rootname}MainDir]/[set ${rootname}LatSubDir]/[set ${rootname}Lattice]/[set ${rootname}WriteDir]
    set rtfbconfig [set ${RTFBrootname}MainDir]/[set ${RTFBrootname}LatSubDir]/[set ${rootname}Lattice]/[set ${RTFBrootname}WriteDir]
    if {![file exist $rtfbconfig/config] || ![file exist $rtfbconfig/rm] || ![file exist $rtfbconfig/irm]} {
        set writeRTFB 1
    }
    
    set ${rootname}ConfigStatus "Writing UF config ..."
    update
    if [catch {APSSRWritePlaneOrbitCorrectionConfig -interactive 1 -rootname $rootname -plane $plane \
                 -filename $UFconfig/config -description [set ${rootname}WriteDescription] -includeP0s $includeP0s \
                 -includeIDs $includeIDs -includeBMs $includeBMs -configName [set ${rootname}WriteDir] } result] {
        return -code error "Error writing UF config: $result"
    }
   
    if $writeRTFB {
         set ${rootname}ConfigStatus "Writing RTFB config ..."
        update
        if [catch {APSSRWritePlaneOrbitCorrectionConfig -interactive 1 -rootname $RTFBrootname -plane $plane \
                     -filename $rtfbconfig/config -description [set ${rootname}WriteDescription] \
                     -includeP0s $includeP0s -includeIDs $includeIDs -includeBMs $includeBMs -configName [set ${RTFBrootname}WriteDir] } result] {
            return -code error "Error writing RTFB config: $result"
        }
    }
    if [catch {exec sddsprocess -nowarnings $UFconfig/config -reprint=par,RTFBConfig,$rtfbconfig } result] {
        return -code error "Error define parameter RTFBConfig: $result"
    }
    set ${rootname}ConfigStatus "$UFconfig config generated."
}

proc APSComputeUFSteeringMatrix {args} {
    set rootname ""
    set filename ""
    set plane h
    set description ""
    set interactive 0
    set includeP0s 0
    set includeIDs 0
    set includeBMs 0
    set configName ""
    set sectorCount 40
    set sectorList ""
    set rampTimeRange ""
    #booster=1 for writing booster configuration
    set RTFBrootname ""
    set SVDanalysis 0
    set deleteVectors ""
    APSStrictParseArguments {rootname filename description interactive includeP0s \
                               includeIDs includeBMs configName rampTimeRange \
                               plane sectorCount sectorList RTFBrootname SVDanalysis deleteVectors}
    if [lsearch -exact [list h v] [set plane [string tolower $plane]]]==-1 {
        return -code error "APSSRWriteYSSteerubgConfig: invalid plane: $plane"
    }
    global ${rootname}ConfigStatus ${rootname}CBWidget ${rootname}RefMatrix ${rootname}SingValues ${RTFBrootname}SingValues
    global ${RTFBrootname}WriteDir ${RTFBrootname}Lattice ${RTFBrootname}RefMatrix
    global ${RTFBrootname}MainDir ${RTFBrootname}LatSubDir
    global ${rootname}MainDir ${rootname}LatSubDir ${rootname}Lattice ${rootname}WriteDir
    global ${RTFBrootname}WriteDescription ${rootname}WriteDescription 
    set UFdir [set ${rootname}MainDir]/[set ${rootname}LatSubDir]
    set rtfbdir [set ${RTFBrootname}MainDir]/[set ${RTFBrootname}LatSubDir]
    set UFlattice [set ${rootname}Lattice]
    set rtfblattice [set ${RTFBrootname}Lattice]
    
    if ![string length [set ${rootname}WriteDir]] {
        return -code error "Write directory is empty."
    }
    set UFconfig [set ${rootname}MainDir]/[set ${rootname}LatSubDir]/[set ${rootname}Lattice]/[set ${rootname}WriteDir]
    if {![file exist $UFconfig] || ![file exist $UFconfig/config]} {
        return -code error "Write config $UFconfig not generated yet!"
    }
    set rtfbconfig [lindex [exec sdds2stream -par=RTFBConfig $UFconfig/config] 0]
    if {![file exist $rtfbconfig] || ![file exist $rtfbconfig/config]} {
        return -code error "RTFB config $rtfbconfig does not exist! Have to rewrite UF config!"
    }
    
    set ${rootname}ConfigStatus "computing slow correction matrices ..."
    update
    set dirRefMatFile $UFdir/[set ${rootname}Lattice]/refMatrices/[set ${rootname}RefMatrix]
    set dirRefMatFile /home/helios/oagData/sr/orbitControllaw/lattices/[set ${rootname}Lattice]/refMatrices/[set ${rootname}RefMatrix]

    if [catch {APSSRGenerateOrbCorrFiles -rootname $rootname -generate 1 \
                 -configFile $UFconfig/config -plane $plane \
                 -referenceMatrix $dirRefMatFile \
                 -outputRoot $UFconfig -singularValues [set ${rootname}SingValues] -SVDanalysis 0 } result] {
        return -code error "Error in computing irm for slow system -- $UFconfig : $result"
    }
    
    exec mv $UFconfig/rm $UFconfig/rm_slow
    exec mv $UFconfig/irm $UFconfig/irm_slow
    set computeRTFB 1
    if {[file exist $rtfbconfig/irm] && [file exist $rtfbconfig/rm]} {
        if ![APSYesNoPopUp "Recompute RTFB matrix?"] {
            set computeRTFB 0
        }
    }
    if $computeRTFB {
        set ${rootname}ConfigStatus "computing rm and irm for RTFB config -- [set ${RTFBrootname}WriteDir] ...."
        update
        if [catch {APSSRGenerateOrbCorrFiles -rootname $RTFBrootname -generate 1 \
                     -configFile $rtfbconfig/config -plane $plane \
                     -referenceMatrix $rtfbdir/[set ${RTFBrootname}Lattice]/refMatrices/[set ${RTFBrootname}RefMatrix] \
                     -outputRoot $rtfbconfig -singularValues [set ${RTFBrootname}SingValues] -SVDanalysis 0 } result] {
            return -code error "Error in computing irm for RTFB (fast) system : $result"
        }
    }
    set ${rootname}ConfigStatus "computing UF matrices -- [set ${rootname}WriteDir] ...."
    update
    cd $UFconfig
  
    set slowCorrList [exec sddsprocess $UFconfig/config -pipe=out -match=par,NameType=CorrectorNames \
                        | sdds2stream -pipe=in -col=Name]
    set slowBPMList [exec sddsprocess $UFconfig/config -pipe=out -match=par,NameType=MonitorNames \
                        | sdds2stream -pipe=in -col=Name]
    set fastCorrList [exec sddsprocess $rtfbconfig/config  -pipe=out -match=par,NameType=CorrectorNames \
                        | sdds2stream -pipe=in -col=Name]
    set fastBPMList [exec sddsprocess $rtfbconfig/config  -pipe=out -match=par,NameType=MonitorNames \
                       | sdds2stream -pipe=in -col=Name]
    #consider xray bpms
    set slowIDBPM ""
    set slowBMBPM ""
    set fastIDBPM ""
    set fastBMBPM ""
    set slowEquationCmd ""
    set fastEquationCmd ""

    foreach bpm $slowBPMList {
        switch -regexp $bpm {
            ID {
                lappend slowIDBPM $bpm
            }
            BM {
                lappend slowBMBPM $bpm
            }
        }
    }
    foreach bpm $fastBPMList {
        switch -regexp $bpm {
            ID {
                lappend fastIDBPM $bpm
            }
            BM {
                lappend fastBMBPM $bpm
            }
        }
    }
    set IDBPMsKnownList [APSGetIDXRayBPMList -plane $plane]
    set IDBPMEqnList    [APSGetIDXRayEqnList -plane $plane]
    set BMBPMsKnownList [APSGetBMXRayBPMList -plane $plane]
    set BMBPMEqnList    [APSGetBMXRayEqnList -plane $plane]
    foreach type {slow fast} {
        set IDs [set ${type}IDBPM]
        set BMs [set ${type}BMBPM]
        if [llength $IDs] {
            if ![llength [set ${type}EquationCmd]] {
                lappend ${type}EquationCmd sddsprocess -pipe
            }
            foreach item $IDs {
                set index [lsearch -exact $IDBPMsKnownList $item]
                if $index==-1 {
                    return -code error "APSSRGenerateOrbCorrFiles(7): no information on $item"
                }
                set equation [lindex $IDBPMEqnList $index]
                if ![string length $equation] {
                    return -code error "APSSRGenerateOrbCorrFiles(8): no equation defined for $item."
                }
                lappend  ${type}EquationCmd "-define=column,$item,$equation"
            }
        }
        if [llength $BMs] {
            foreach item $BMs {
                if ![llength [set ${type}EquationCmd]] {
                    lappend ${type}EquationCmd sddsprocess -pipe
                }
                set index [lsearch -exact $BMBPMsKnownList $item]
                if $index==-1 {
                    return -code error "APSSRGenerateOrbCorrFiles(9): no information on $item"
                }
                set equation [lindex $BMBPMEqnList $index]
                if ![string length $equation] {
                    return -code error "APSSRGenerateOrbCorrFiles(10): no equation defined for $item."
                }
                lappend ${type}EquationCmd "-define=column,$item,$equation"
            }   
        }
    }
    
    if [string length $slowEquationCmd] {
        if [catch {eval exec sddsconvert ${dirRefMatFile} -delete=col,s -pipe=out \
                     | sddstranspose -pipe \
                     | $slowEquationCmd \
                     | sddstranspose -pipe -newColumnNames=OldColumnNames -oldColumnNames=BPMName \
                     | sddsselect -pipe $UFconfig/rm_slow -match=BPMName \
                     | sddsconvert -pipe=in rmSF -retain=col,[join $fastCorrList ,] } result] {
            return -code error "Error in generating matrices1a: $result"
        }
        if [catch { eval exec sddsconvert ${dirRefMatFile} -delete=col,s -pipe=out \
                      | sddstranspose -pipe \
                      | $slowEquationCmd \
                      | sddstranspose -pipe -newColumnNames=OldColumnNames -oldColumnNames=BPMName \
                      | sddsselect -pipe $UFconfig/rm_slow -match=BPMName \
                      | sddsconvert -pipe=in rmSS -retain=col,[join $slowCorrList ,] } result] {
            return -code error "Error in generating matrices1b: $result"
        }
    } else {
        if [catch {eval exec sddsconvert ${dirRefMatFile} -delete=col,s -pipe=out \
                     | sddstranspose -pipe \
                     | sddstranspose -pipe -newColumnNames=OldColumnNames -oldColumnNames=BPMName \
                     | sddsselect -pipe $UFconfig/rm_slow -match=BPMName \
                     | sddsconvert -pipe=in rmSF -retain=col,[join $fastCorrList ,] } result] {
            return -code error "Error in generating matrices1a: $result"
        }
        if [catch { eval exec sddsconvert ${dirRefMatFile} -delete=col,s -pipe=out \
                      | sddstranspose -pipe \
                      | sddstranspose -pipe -newColumnNames=OldColumnNames -oldColumnNames=BPMName \
                      | sddsselect -pipe $UFconfig/rm_slow -match=BPMName \
                      | sddsconvert -pipe=in rmSS -retain=col,[join $slowCorrList ,] } result] {
            return -code error "Error in generating matrices1b: $result"
        }
    }
    if [string length $fastEquationCmd] {
        if [catch {eval exec sddsconvert -pipe=out ${dirRefMatFile} -delete=col,s \
                     | sddstranspose -pipe \
                     | $fastEquationCmd \
                     | sddstranspose -pipe -newColumnNames=OldColumnNames -oldColumnNames=BPMName \
                     | sddsselect -pipe ${rtfbconfig}/rm -match=BPMName=BPMName \
                     | sddsconvert -pipe=in rmFS -delete=col,* -retain=col,[join $slowCorrList ,] } result] {
            return -code error "Error in generating matrices1c: $result"
        }
        if [catch {eval exec sddsconvert -pipe=out ${dirRefMatFile} -delete=col,s \
                     | sddstranspose -pipe \
                     | $fastEquationCmd \
                     | sddstranspose -pipe -newColumnNames=OldColumnNames -oldColumnNames=BPMName \
                     | sddsselect -pipe ${rtfbconfig}/rm -match=BPMName=BPMName \
                     | sddsconvert -pipe=in rmFF -delete=col,* -retain=col,[join $fastCorrList ,] } result] {
            return -code error "Error in generating matrices1d: $result"
        }
    } else {
        if [catch {eval exec sddsconvert -pipe=out ${dirRefMatFile} -delete=col,s \
                     | sddstranspose -pipe \
                     | sddstranspose -pipe -newColumnNames=OldColumnNames -oldColumnNames=BPMName \
                     | sddsselect -pipe ${rtfbconfig}/rm -match=BPMName=BPMName \
                     | sddsconvert -pipe=in rmFS -delete=col,* -retain=col,[join $slowCorrList ,] } result] {
            return -code error "Error in generating matrices1c: $result"
        }
        if [catch {eval exec sddsconvert -pipe=out ${dirRefMatFile} -delete=col,s \
                     | sddstranspose -pipe \
                     | sddstranspose -pipe -newColumnNames=OldColumnNames -oldColumnNames=BPMName \
                     | sddsselect -pipe ${rtfbconfig}/rm -match=BPMName=BPMName \
                     | sddsconvert -pipe=in rmFF -delete=col,* -retain=col,[join $fastCorrList ,] } result] {
            return -code error "Error in generating matrices1d: $result"
        }
    }
    
    
    if [catch {exec  sddspseudoinverse ./rmFF ./irmFF -minimum=0.0 -largestSingularValues=[set ${RTFBrootname}SingValues]\
                 -sFile=./rmFF.s -uMatrix=./rmFF.u -vMatrix=./rmFF.v 
        eval exec sddspseudoinverse ./rmSS ./irmSS -minimum=0.0 -largestSingularValues=[set ${rootname}SingValues]  } result] {
        return -code error "Error in computing inverse for rmFF and rmSS: $result"
    }
    set num1 [exec sdds2stream -par=ConditionNumber irmFF]
    set num2 [exec sdds2stream -par=ConditionNumber irmSS]
    set ${rootname}ConfigStatus "irmFF condition number is $num1; if it is too big, you need to reduce the singular values of RTFB."
    set ${rootname}ConfigStatus "irmSS condition number is $num2; if it is too big, you need to reduce the singular values of UF."
    update
    if [catch {exec sddsmatrixop rmSF rmDP -push=./irmFF -multiply \
                 -push=./rmFS -multiply -push=./rmSS -swap -subtract } result] {
        return -code error "Error in compute UF rm: $result"
    }
    if [catch {exec sddstranspose -pipe=out rmDP \
                 | sddsxref -pipe irm_slow -take=ControlName  \
                 | sddstranspose -pipe -newColumnNames=ControlName \
                 | sddsconvert -pipe -del=col,OldColumnNames \
                 | sddsxref -pipe=in rm_slow rm -take=BPMName } result] {
        return -code error "Error in putting bpm and corrector names to rmDP: $result"
    }
    
    set singularValues [set ${rootname}SingValues]
    
    if $SVDanalysis {
        set tmpRoot /tmp/[APSTmpString]
        if [catch {exec sddspseudoinverse rm $tmpRoot.irm -minimum=0.0 -largestSingularValues=[set ${rootname}SingValues] \
                     -sFile=s -vMatrix=v -uMatrix=u } result] {
            return -code error "Error in svd analysis of rmSS 1 : $result"
        }
        set convertOption -retain=col,OldColumnNames
        for {set i 0} {$i<$singularValues} {incr i} {
            append convertOption ,SV[format %03d $i]
        }
        if [catch {exec sddsconvert v $tmpRoot.v $convertOption} result] {
             return -code error "Error in svd analysis of rmSS 2(svd): $result:`"
        }
        # execution is blocked until the user makes the choice of
        # vectors in tksddsplot and quits.
        set returnList [exec tksddsplot $tmpRoot.v -col=OldColumnNames,SV* -sep \
                          -enum=interval=20 -selectFrames]
        set deleteVectors ""
        set index 0
        foreach selected $returnList {
            if {!$selected} {
                lappend deleteVectors $index
            }
            incr index
        }
        global ${rootname}DeleteModes
        set ${rootname}DeleteModes $deleteVectors
        APSSetVarAndUpdate ${rootname}ConfigStatus "SVD analysis done."
       # return
    }
    set inverseOptions ""
    global ${rootname}DeleteModes
    if ![string length $deleteVectors] {
        if {[info exists ${rootname}DeleteModes] && 
            [llength [set ${rootname}DeleteModes]]} {
                set deleteVectors [set ${rootname}DeleteModes]
        }
    }
    # When the procedure is called from pem, say, there may
    # be no request to delete modes, and the variable
    # ${rootname}DeleteModes may not even be defined.
    # This variable is defined and set in the GUI.
    # Perhaps the variable should be in the arguments list
    # instead of a global.
    if [llength $deleteVectors] {
        lappend inverseOptions -deleteVectors=[join $deleteVectors ,]
    }

    if [catch {eval exec sddspseudoinverse rm -pipe=out -minimum=0.0 -largest=[set ${rootname}SingValues] \
                 $inverseOptions \
                 | sddsconvert -pipe=in irm -rename=column,OldColumnNames=ControlName } result] {
        return -code error "Error in compute UF irm: $result"
    }
    set num [exec sdds2stream -par=ConditionNumber irm]
    set ${rootname}ConfigStatus "done. Condition number is $num; if it is too big, you need to reduce the singular values of UF."
    update
}


set createNewRTFBConfig 0
proc MakeUFWidgets {widget args} {
    set parent ""
    set plane ""
    set rootname ""
    set includeP0s 0
    set includeIDs 0
    set includeBMs 0
    set buttonOrientation vertical
    set RTFBrootname ""
    APSParseArguments {parent plane rootname includeP0s includeIDs includeBMs buttonOrientation RTFBrootname}

    global ${rootname}ConfigStatus createNewRTFBConfig ${rootname}RefMatrix
    
    set ${rootname}ConfigStatus ""

    APSFrame $widget -parent $parent -label "" -packOption "-expand true -fill both"
    APSScrolledStatus .scrolled -parent $parent$widget.frame \
      -textVariable ${rootname}ConfigStatus \
      -width 85 -height 6 -lineLimit 1000 -label ""
    
    set widgetList [APSTabFrame .devtab -parent $parent$widget.frame -label "" \
                      -labelList "Monitors Correctors" -width 1050 -height 440 \
                      -packOption "-expand true -fill both" ]
   
    set missingBPMList \
      [APSSRGetBadOrbitDevices -plane $plane -device BPM -application RTFeedback]
    
    global ${rootname}BadBPMList 
    set ${rootname}BadBPMList $missingBPMList
    
    switch $plane {
        h {
            set suffixList {A:H1 A:H2 A:H3 A:H4 B:H4 B:H3 B:H2 B:H1 C:H1}
        }
        v {
            set suffixList {A:V1 A:V2 A:V3 A:V4 B:V4 B:V3 B:V2 B:V1 C:V1}
        }
    }
    APSSRMonitorCheckButtons .smbut -parent [lindex $widgetList 0] -rootname $rootname \
      -orientation $buttonOrientation -BP5Only 0 \
      -includeP0s $includeP0s -includeIDs $includeIDs -includeBMs $includeBMs \
      -missingListVar ${rootname}BadBPMList \
      -noLabel 1 -packOption "-side top"
    APSSRCorrectorCheckButtons .shbut -parent [lindex $widgetList 1] -rootname $rootname \
      -plane [string toupper $plane] -orientation $buttonOrientation \
      -packOption  "-side top"
    
    APSSetSRSectorButtons -mode all-off -rootname ${rootname} \
      -sectorCount 40 -itemList $suffixList
    
    set frameWidth 800
    set frameHeight 450
    set labelList [list Config... Read... Write-Compute... ]
    set commandList [list {} {} \
                       "APSSetVarAndUpdate ${rootname}WriteDir \"\"" ]
    
    
    set widgetList [APSTabFrame .fileops -parent $parent$widget.frame -label "" \
                      -labelList $labelList \
                      -commandList $commandList \
                      -height $frameHeight -width $frameWidth]
    
    pack $parent$widget.frame.fileops -side top
    $parent$widget.frame.fileops.frame.tn select 1
    set windex 0
    
    #config tab
    global ${rootname}Lattice ${rootname}MainDir ${rootname}LatSubDir ${rootname}refMatrices ${rootname}RefLatticeDir ${rootname}RefMatrix
   
    set ${rootname}Lattice default
    set ${rootname}MainDir /home/helios/oagData/sr/unifiedSteering
    set ${rootname}LatSubDir lattices
    set ${rootname}RefLatticeDir /home/helios/oagData/sr/orbitControllaw/lattices
    set ${rootname}refMatrices refMatrices
    set ${rootname}RefMatrix $plane.default
    cd [set ${rootname}MainDir]/[set ${rootname}LatSubDir]
    set ${rootname}Lattice [file readlink default]
    
    set widget [lindex $widgetList $windex]
    incr windex
    APSFrame .lattice -parent $widget  -label "Lattice" \
      -width $frameWidth -height $frameHeight -contextHelp \
      "Use this frame to specify the lattice directory name and main directory area.  You may also change the default lattice from here."
    set w0 $widget.lattice.frame
    APSLabeledEntry .maindir -parent $w0 -label "Main directory: " \
      -textVariable ${rootname}MainDir -width 60 -contextHelp \
      "Enter the name of the main directory for the orbit correction system."
    APSFileSelectWidget .config -parent $w0 -label "Lattice: " \
      -pathVariableList [list ${rootname}MainDir ${rootname}LatSubDir] -mode directory -width 60 \
      -variable ${rootname}Lattice -incrementButtons 0 -contextHelp \
      "Enter the name of the lattice with which to work."
    APSFileSelectWidget .reflattice -parent $w0 -label "Reference matrix:" -width 60\
      -pathVariableList [list ${rootname}RefLatticeDir ${rootname}Lattice ${rootname}refMatrices] \
      -variable ${rootname}RefMatrix  -mode file -incrementButtons 0 -contextHelp \
      "Enter the name of the reference response matrix file for the $plane plane."
    
    
    #read tab
    
    global ${rootname}ReadFile ${rootname}ReadDescription ${rootname}Plane
    global ${rootname}FilterEnd1
    set ${rootname}Plane $plane
    set ${rootname}ReadFile $plane.defaultXRDP
    set ${rootname}ReadDescription ""
    set ${rootname}FilterEnd1 .*
    set widget [lindex $widgetList $windex]
    
    incr windex
    APSFrame .read -parent $widget -label "Read configuration" \
      -width $frameWidth -height $frameHeight -contextHelp \
      "Use this frame to read combined monitor and corrector configurations."
    set w0 $widget.read.frame
    APSLabeledOutput .lattice -parent $w0 -label "Lattice: " -width 60 \
      -textVariable ${rootname}Lattice -contextHelp \
      "Shows the lattice of the configuration for which this read widget applies."
    APSFileSelectWidget .file -parent $w0 -variable ${rootname}ReadFile -label "Config: " \
      -pathVariableList [list ${rootname}MainDir ${rootname}LatSubDir ${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."
    APSFrame .bf -parent $w0 -relief flat -label "" -packOption "-side top -anchor w"
    set w1 $w0.bf.frame
    APSButton .io0 -parent $w1 -text Read(replace) -packOption "-side left -anchor n" -size small -command \
      "APSReadUnifiedSteeringConfig -rootname $rootname -filename \$${rootname}MainDir/\$${rootname}LatSubDir/\$${rootname}Lattice/\$${rootname}ReadFile/config -lattice \$${rootname}Lattice -includeP0s $includeP0s -includeIDs $includeIDs -includeBMs $includeBMs   -RTFBrootname $RTFBrootname" \
      -contextHelp "Press to read data to replace the existing configuration, using the named configuration file."
    
    #write tab
    global ${rootname}WriteDir  createNewRTFBConfig
   
    set widget [lindex $widgetList $windex]
    incr windex
    APSFrame .write -parent $widget -label "Write configuration" \
      -width $frameWidth -height $frameHeight -contextHelp \
      "Use this frame to write combined monitor and corrector configurations."
    set w0 $widget.write.frame
    APSLabeledOutput .lattice -parent $w0 -label "Lattice: " -width 60 \
      -textVariable ${rootname}Lattice -contextHelp \
      "Shows the lattice of the configuration for which this write widget applies."
    #set ${rootname}WriteDir h.[clock format [clock seconds] -format %Y-%m%d].00
    set ${rootname}WriteDir ""
    APSFileSelectWidget .file -parent $w0 -variable ${rootname}WriteDir \
      -pathVariableList [list ${rootname}MainDir ${rootname}LatSubDir ${rootname}Lattice] \
      -label "Config: " -noSelect 0 -mode directory -incrementButtons 1 -width 60 -contextHelp \
      "Enter the name of the configuration to write." \
      -filterVariableList [list ${rootname}Plane ${rootname}FilterEnd1]
    APSButton .genname -parent $w0.file -text G -size small -command \
      "set ${rootname}WriteDir \[APSNextGenerationedName -directory \$${rootname}MainDir/\$${rootname}LatSubDir/\$${rootname}Lattice -name \$${rootname}Plane.\[clock format \[clock seconds\] -format %Y-%m%d\].00 -newFile 1 -separator .\]"
    APSLabeledEntry .descrip -parent $w0 -label "Description: " -width 60 \
      -textVariable ${rootname}WriteDescription -contextHelp \
      "Use to enter a description for the configuration to be written."
    global ${rootname}SingValues ${rootname}DeleteModes
    set ${rootname}SingValues 320
    set ${rootname}DeleteModes ""
    
    APSLabeledEntry .sing -parent $w0 -label "Number of singular values:" -width 80 -textVariable ${rootname}SingValues
    APSLabeledEntry .mode -parent $w0 -label "Mode to delete:" -width 80 -textVariable ${rootname}DeleteModes

    APSButton .write -parent $w0 -text "Write" -size small -command \
        "APSWriteUFSteeringConfig -rootname $rootname -interactive 1 -filename \$${rootname}MainDir/\$${rootname}LatSubDir/\$${rootname}Lattice/\$${rootname}WriteDir/config -description \$${rootname}WriteDescription -includeP0s $includeP0s -includeIDs $includeIDs -includeBMs $includeBMs  -configName \$${rootname}WriteDir -plane $plane  -RTFBrootname $RTFBrootname"
    
    APSButton .svd -parent $w0 -text "SVD analysis" -size small  -command "APSComputeUFSteeringMatrix -rootname $rootname -interactive 1 -filename \$${rootname}MainDir/\$${rootname}LatSubDir/\$${rootname}Lattice/\$${rootname}WriteDir/config -description \$${rootname}WriteDescription -includeP0s $includeP0s -includeIDs $includeIDs -includeBMs $includeBMs  -configName \$${rootname}WriteDir -plane $plane  -RTFBrootname $RTFBrootname -SVDanalysis 1" \
      -contextHelp "does svd analysis."
    
    APSButton .io -parent $w0 -text Compute -size small -command \
      "APSComputeUFSteeringMatrix -rootname $rootname -interactive 1 -filename \$${rootname}MainDir/\$${rootname}LatSubDir/\$${rootname}Lattice/\$${rootname}WriteDir/config -description \$${rootname}WriteDescription -includeP0s $includeP0s -includeIDs $includeIDs -includeBMs $includeBMs  -configName \$${rootname}WriteDir -plane $plane  -RTFBrootname $RTFBrootname" \
      -contextHelp "Press to write data, using the named configuration file."
}


proc CreateUFWidget {args} {
    set plane ""
    set parent ""
    APSParseArguments {plane parent}

}
set ufLatticeDir /home/helios/oagData/sr/unifiedSteering/lattices
set refMatrixDir /home/helios/oagData/sr/unifiedSteering/lattices/refMatrices
set dpLatticeDir /home/helios/oagData/sr/orbitControllaw/lattices
set refMatrixDir  /home/helios/oagData/sr/orbitControllaw/refMatrices
set rtfbLatticeDir /home/helios/oagData/sr/rtfeedback/lattices



APSApplication . -name SRUnifiedSteeringConfig -version 1 \
  -overview {This application allows configuration of SR $application.  You may choose the lattice, which monitors and correctors to use, and restrict your choices to only good components.}

package require iwidgets
set win .userFrame

set wList [APSTabFrame .top -parent $win -width 1100 -height 850 \
             -labelList [list "Horizontal UF" "Vertical UF"] -label "" -tabPosition n]
set wx [lindex $wList 0]
set wy [lindex $wList 1]

set xList [APSTabFrame .hor -parent $wx -width 1100 -height 850 \
             -labelList [list "Horizontal RTFB" "Horizontal UFDP"] -label ""]
set yList [APSTabFrame .ver -parent $wy -width 1100 -height 850 \
             -labelList [list "Vertical RTFB" "Vertical UFDP"] -label ""]

#horizontal
set x1 [lindex $xList 0]
set x2 [lindex $xList 1]

set hRTFBrootname hfbconfig

APSSRConfigPlaneOrbitCorrection .hfbconfig -parent $x1 \
      -rootname hfbconfig \
      -fileFrame 1 -buttonOrientation $buttonOrientation -includeP0s 1 \
      -includeIDs 1 -includeBMs 1 -plane h \
      -application RTFeedback
MakeUFWidgets .hufconfig -parent $x2 -rootname hufsteering -plane h \
  -includeP0s 1 -includeIDs 1 -includeBMs 1 -buttonOrientation $buttonOrientation \
  -RTFBrootname hfbconfig

$wx.hor.frame.tn select 1


#vertical
set y1 [lindex $yList 0]
set y2 [lindex $yList 1]

APSSRConfigPlaneOrbitCorrection .vfbconfig -parent $y1 \
      -rootname vfbconfig \
      -fileFrame 1 -buttonOrientation $buttonOrientation -includeP0s 1 \
      -includeIDs 1 -includeBMs 1 -plane v \
      -application RTFeedback

MakeUFWidgets .hufconfig -parent $y2 -rootname vufsteering -plane v \
  -includeP0s 1 -includeIDs 1 -includeBMs 1 -buttonOrientation $buttonOrientation \
  -RTFBrootname vfbconfig

$wy.ver.frame.tn select 1
