#!/bin/sh  
# \
exec oagwish "$0" "$@"
#
# $Log: not supported by cvs2svn $
# Revision 1.2  2006/09/21 20:39:58  soliday
# Updated because of PV name changes.
#
# Revision 1.1  2000/04/26 18:22:21  soliday
# First version.
#
#

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

set args $argv
set initialConfig "h.default"
APSStrictParseArguments {initialConfig}
if [info exists env(PRINTER)] {
  set printerName $env(PRINTER)
} else {
  set printerName mcr1
}

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



proc Print {} {
    global printerName apsScriptUser
    APSSetVarAndUpdate sconfigConfigStatus Printing
    set output "Printed by $apsScriptUser on [clock format [clock seconds]]\n\n"
    set letterList "A A A A B B B B B C"
    set numberList "1 2 3 4 5 4 3 2 1 0"
    set output2    "                     1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3 3 3 3 3 3 3 3 3 4 l\n"
    append output2 "   1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 l"
    append output [format "%48s\n%84s\n%s" Monitors A $output2]
    append output [CheckboxHor -letterList $letterList -numberList $numberList -plane P]
    foreach plane "H" {
	append output [format "\n\n%50s\n%84s\n%s" "$plane Correctors" A $output2]
	append output [CheckboxHor -letterList "A A A A B B B B" -numberList "1 2 3 4 4 3 2 1" -plane $plane]
    }
    global sconfigReadDescription sconfigReadFile
    append output [format "\n\n%-15s%s" Config: $sconfigReadFile]
    append output [format "\n%-15s%s" Description: $sconfigReadDescription]
    set fileName /tmp/[APSTmpString]
    APSAddToTempFileList $fileName
    set fileId [open $fileName w 0600]
    puts $fileId $output
    close $fileId
    exec cat $fileName | lpr -P$printerName
    APSSetVarAndUpdate sconfigConfigStatus Done
}

proc CheckboxHor {args} {
    set output ""
    set itemList ""
    APSStrictParseArguments {letterList numberList plane itemList}
    foreach letter $letterList number $numberList itemName $itemList {
        set item ${letter}${number}
        append output [format "\n%2s " $item]
        set item ${letter}:${plane}${number}
        if {[llength $itemName]} {
            set item $itemName
        }
        for {set checkBoxColumn 1} {$checkBoxColumn<41} {incr checkBoxColumn} {
            set checkVar sconfigS$checkBoxColumn$item
            global $checkVar
            if {[set $checkVar]==1} {
                append output "x "
            } else {
                append output [format "%c " 183]
            }
        }
        set checkVar sconfigS${item}
        global $checkVar
        if {[set $checkVar]==1} {
            append output "x "
        } else {
            append output [format "%c " 183]
        }
    }
    return $output
}

proc printDialog {} {
    set printDialog [APSUniqueName .]
    toplevel $printDialog
    wm title $printDialog "Print Dialog"
    global printerName
    APSLabeledEntry .enterPrinter -parent $printDialog -label Printer -textVariable printerName
    APSButton .startPrinting -parent $printDialog -text Print -command "Print;destroy $printDialog"
    APSButton .cancelPrinting -parent $printDialog -text Cancel -command "destroy $printDialog"
}

.menu.file.menu insert 1 command -label "Print..." -command "printDialog"


set rootname sconfig


proc APSSRConfigRFFreqCorrection {widget args} {
    set parent ""
    set rootname sconfig
    set fileFrame 1
    APSStrictParseArguments {parent rootname fileFrame}

    set BPMSuffixList [list A:P0 A:P1 A:P2 A:P3 A:P4 B:P5 B:P4 B:P3 B:P2 B:P1 B:P0 C:P0]
    set BPMMissingList [APSGetMissingBPMList -plane H]

    # Make a frame grid with three vertical areas.  "top" will contain the
    # checkbutton grids, and bot will contain the controls (read, write, etc.)
    APSFrameGrid $widget -parent $parent -yList {status top bot}

    # Make a dedicated scrolled status area for this configuration.
    global ${rootname}ConfigStatus
    set ${rootname}ConfigStatus ""
    APSScrolledStatus .scrolled -parent $parent$widget.status -textVariable ${rootname}ConfigStatus \
      -width 110 -height 3 -lineLimit 1000 -label ""
    APSFrame .but -parent $parent$widget.top

    # Make the checkbutton grids
    set w $parent$widget.top.but.frame
    set pOption "-side top"
    APSSRFRFreqMonitorCheckButtons .smbut -parent $w -rootname $rootname -packOption $pOption

    if $fileFrame {
        # Make frames for read, write, etc. controls.  Will go into a 
        # widget swap frame.
        set frameHeight 125
        set frameWidth 900
        set w $parent$widget.bot.fileops.frame
        APSWidgetSwapFrame .fileops -parent $parent$widget.bot -label "" \
          -contextHelp "File operations frame for rf freq correction configuration" \
          -widgetList "$w.lattice $w.read $w.good $w.write $w.refmat $w.matrix"  \
          -labelList [list Lattice... Read... Good... Write... {Reference matrices...} {Generate controllaw files...}] \
          -commandList [list {} {} {} "APSSetVarAndUpdate ${rootname}WriteDir \"\"" {} {}] \
          -height $frameHeight -width $frameWidth \
          -buttonSize small -buttonPosition 0
        pack propagate $parent$widget.bot.fileops.frame 0
        pack $parent$widget.bot.fileops -side top

        # Make lattice selection frame.
        global ${rootname}Lattice ${rootname}MainDir ${rootname}LatSubDir
        set ${rootname}Lattice default
        set ${rootname}MainDir /home/helios/oagData/sr/rfOrbitControllaw
        set ${rootname}LatSubDir lattices
        APSFrame .lattice -parent $w -label "Lattice" -noPack 1 \
          -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 $w.lattice.frame
        APSLabeledEntry .maindir -parent $w0 -label "Main directory: " \
          -textVariable ${rootname}MainDir -width 80 -contextHelp \
          "Enter the name of the main directory for the rf freq correction system."
        APSFileSelectWidget .lattice -parent $w0 -label "Lattice: " \
          -pathVariableList [list ${rootname}MainDir ${rootname}LatSubDir] -mode directory -width 76 \
          -variable ${rootname}Lattice -incrementButtons 0 -contextHelp \
          "Enter the name of the lattice with which to work."
        APSButton .default -parent $w0.lattice -text D -size small \
          -contextHelp "Makes the named file into the default lattice." \
          -command "APSMakeLink -confirm 1 -confirmMessage {Change default lattice? Are you sure?} -local 1 -log 1 -chmod a+wr -filename \[subst \$${rootname}MainDir/\$${rootname}LatSubDir/\$${rootname}Lattice\] -linkname \[subst \$${rootname}MainDir/\$${rootname}LatSubDir/default\]; set ${rootname}Lattice default"

        # Make configuration-read frame.
        global ${rootname}ReadFile ${rootname}ReadDescription ${rootname}Plane
        global ${rootname}FilterEnd1
        set ${rootname}Plane h
        set ${rootname}ReadFile h.default
        set ${rootname}ReadDescription ""
        set ${rootname}FilterEnd1 .*
        APSFrame .read -parent $w -label "Read configuration" -noPack 1 \
          -width $frameWidth -height $frameHeight -contextHelp \
          "Use this frame to read combined monitor and corrector configurations."
        set w0 $w.read.frame
        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 76 \
          -incrementButtons 1 -contextHelp \
          "Enter the name of the configuration file to read."
        APSLabeledOutput .descrip -parent $w0 -label "Description: " -width 76 \
          -textVariable ${rootname}ReadDescription -contextHelp \
          "Shows the description of the last-read configuration file."
        APSRadioButtonFrame .rb1 -parent $w0 -packOption "-side left" -label "Plane: " \
          -variable ${rootname}Plane -buttonList {H} -valueList {h} \
          -orientation horizontal -contextHelp \
          "Choose plane with which you are dealing.  Determines what configurations are viewable and what configuration names are generated."
        APSButton .io0 -parent $w0 -text Read(replace) -size small -command \
          "APSReadRFFreqCorrectionConfig -rootname $rootname -filename \$${rootname}MainDir/\$${rootname}LatSubDir/\$${rootname}Lattice/\$${rootname}ReadFile/config -logic replace" \
          -contextHelp "Press to read data to replace the existing configuration, using the named configuration file."
        APSButton .io1 -parent $w0 -text Read(or) -size small -command \
          "APSReadRFFreqCorrectionConfig -rootname $rootname -filename \$${rootname}MainDir/\$${rootname}LatSubDir/\$${rootname}Lattice/\$${rootname}ReadFile/config -logic" \
          -contextHelp "Press to read data to or with the existing configuration, using the named configuration file."
        APSButton .io2 -parent $w0 -text Read(and) -size small -command \
          "APSReadRFFreqCorrectionConfig -rootname $rootname -filename \$${rootname}MainDir/\$${rootname}LatSubDir/\$${rootname}Lattice/\$${rootname}ReadFile/config -logic and" \
          -contextHelp "Press to read data to and with the existing configuration, using the named configuration file."
        APSButton .io3 -parent $w0 -text Read(not) -size small -command \
          "APSReadRFFreqCorrectionConfig -rootname $rootname -filename \$${rootname}MainDir/\$${rootname}LatSubDir/\$${rootname}Lattice/\$${rootname}ReadFile/config -logic not" \
          -contextHelp "Press to read data specifying elements to turn off, using the named configuration file."

        # Make the write-configuration frame
        global ${rootname}WriteDir 
        APSFrame .write -parent $w -label "Write configuration" -noPack 1 \
          -width $frameWidth -height $frameHeight -contextHelp \
          "Use this frame to write combined monitor and corrector configurations."
        set w0 $w.write.frame
        set ${rootname}WriteDir h.[clock format [clock seconds] -format %Y-%m%d].00
        APSFileSelectWidget .file -parent $w0 -variable ${rootname}WriteDir \
          -pathVariableList [list ${rootname}MainDir ${rootname}LatSubDir ${rootname}Lattice] \
          -label "Config: " -noSelect 0 -mode directory -incrementButtons 1 -width 76 -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 76 \
          -textVariable ${rootname}WriteDescription -contextHelp \
          "Use to enter a description for the configuration to be written."
        APSRadioButtonFrame .rb1 -parent $w0 -packOption "-side left" -label "Plane: " \
          -variable ${rootname}Plane -buttonList {H} -valueList {h} \
          -orientation horizontal -contextHelp \
          "Choose plane with which you are dealing.  Determines what configurations are viewable and what configuration names are generated."
        APSButton .io -parent $w0 -text Write -size small -command \
          "APSSRWriteRFFreqCorrectionConfig -rootname $rootname -filename \$${rootname}MainDir/\$${rootname}LatSubDir/\$${rootname}Lattice/\$${rootname}WriteDir/config -description \$${rootname}WriteDescription -configName \$${rootname}WriteDir" \
          -contextHelp "Press to write data, using the named configuration file."

        # Make frame for read/write/apply of "good" component files
        global ${rootname}GoodHMonFile ${rootname}GoodVMonFile ${rootname}GoodHCorrFile ${rootname}GoodVCorrFile ${rootname}GoodDir
        APSFrame .good -parent $w -label "Good component files" -noPack 1 \
          -width $frameWidth -height $frameHeight -contextHelp \
          "Use this frame to mask the configuration using files that give lists of good monitors, horizontal correctors, and vertical correctors.  These files can be created using the read and write operations of this screen."
        set w0 $w.good.frame 
        set ${rootname}GoodDir goodComponents
        set ${rootname}GoodHMonFile hmon.default
        set ${rootname}GoodVMonFile vmon.default
        set ${rootname}GoodHCorrFile hc.default
        set ${rootname}GoodVCorrFile vc.default
        foreach Plane {H} plane {h} {
            APSFileSelectWidget .${plane}mon -parent $w0 -variable ${rootname}Good${Plane}MonFile \
              -pathVariableList [list ${rootname}MainDir ${rootname}GoodDir] \
              -label "${Plane}. Mon.:" -mode file -width 72 -incrementButtons 1 \
              -filter "${plane}mon.*" 
            APSButton .apply -parent $w0.${plane}mon -text A -size small \
              -contextHelp "Applies the file to the present configuration.  Beware of applying a file in the wrong slot---e.g., a monitor file in a corrector slot or vice-versa." \
              -command "APSReadSRConfig -rootname $rootname -filename \[subst \$${rootname}MainDir/\$${rootname}GoodDir/\$${rootname}Good${Plane}MonFile\] -logic and -nameTypeList Monitor -knownSuffixes \{$BPMSuffixList\} -missingList \{$BPMMissingList\}"
            APSButton .write -parent $w0.${plane}mon -text W -size small \
              -contextHelp "Writes the present $Plane monitor configuration to the named file." \
              -command "APSWriteSRFRFreqConfig -interactive 1 -rootname $rootname -filename \[subst \$${rootname}MainDir/\$${rootname}GoodDir/\$${rootname}Good${Plane}MonFile\] -nameTypeList Monitor -suffixLists \{\{$BPMSuffixList\}\}"
            APSButton .default -parent $w0.${plane}mon -text D -size small \
              -contextHelp "Makes the named file into the default good ${Plane} monitor list." \
              -command "APSMakeLink -confirm 1 -confirmMessage {Change default good ${Plane} monitor list? Are you sure?} -local 1 -log 1 -chmod a+wr -filename \[subst \$${rootname}MainDir/\$${rootname}GoodDir/\$${rootname}Good${Plane}MonFile\] -linkname \[subst \$${rootname}MainDir/\$${rootname}GoodDir/${plane}mon.default\]; set ${rootname}Good${Plane}MonFile ${plane}mon.default"
            APSButton .genname -parent $w0.${plane}mon -text G -size small -command \
              "set ${rootname}Good${Plane}MonFile \[APSNextGenerationedName -directory \$${rootname}MainDir/\$${rootname}GoodDir -name ${plane}mon.\[clock format \[clock seconds\] -format %Y-%m%d\].00 -newFile 1 -separator .\]" \
              -contextHelp "Generates a unique, unused name for the good ${Plane} monitor list."
        }


        # Make the reference matrix selection frame
        global ${rootname}RefMatrix 
        set ${rootname}RefMatrix(h) h.default
        set ${rootname}RefMatrix(v) v.default
        APSFrame .refmat -parent $w -label "Reference matrices" -noPack 1 \
          -width $frameWidth -height $frameHeight -contextHelp \
          "Use this frame to select the names of the reference matrix files.  These are used together with configuration files to generate the inverse matrices for rf freq correction."
        set w0 $w.refmat.frame
        global ${rootname}refMatrices
        set ${rootname}refMatrices refMatrices
        foreach plane {h} {
            APSFileSelectWidget .${plane}ref -parent $w0 -mode file \
              -label "[string toupper $plane] plane: " -width 76 \
              -variable ${rootname}RefMatrix($plane) \
              -pathVariableList [list ${rootname}MainDir ${rootname}LatSubDir ${rootname}Lattice ${rootname}refMatrices] \
              -contextHelp \
              "Enter the name of the reference response matrix file for the $plane plane."
            APSButton .default -parent $w0.${plane}ref -text D -size small \
              -contextHelp "Makes the named file into the default $plane-plane reference matrix." \
              -command "APSMakeLink -confirm 1 -confirmMessage {Change reference matrix? Are you sure?} -local 1 -log 1 -chmod a+wr -filename \[subst \$${rootname}MainDir/\$${rootname}LatSubDir/\$${rootname}Lattice/\$${rootname}refMatrices/\$${rootname}RefMatrix($plane)\] -linkname \[subst \$${rootname}MainDir/\$${rootname}LatSubDir/\$${rootname}Lattice/\$${rootname}refMatrices/$plane.default\]; set ${rootname}RefMatrix($plane) $plane.default"
        }

        # Make the frame for computing the matrix and installing it.
        global ${rootname}Plane ${rootname}SingValues ${rootname}RemoveVectors ${rootname}SetupOutputDir 
        APSFrame .matrix -parent $w -label "Compute matrix" -noPack 1 \
          -width $frameWidth -height $frameHeight -contextHelp \
          "Use this frame to generate the matrix for rf freq correction from an existing configuration."
        set w0 $w.matrix.frame
        set ${rootname}SingValues 320
        set ${rootname}RemoveVectors 0
        APSFileSelectWidget .file -parent $w0 -variable ${rootname}WriteDir \
          -pathVariableList [list ${rootname}MainDir ${rootname}LatSubDir ${rootname}Lattice] -filter "h.* v.*" \
          -label "Config: " -noSelect 0 -mode directory -incrementButtons 1 -width 76 -contextHelp \
          "Enter the name of the configuration to use." \
          -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 .\]"

        frame $w0.f1 
        pack $w0.f1 -fill x
        APSLabeledEntry .le1 -parent $w0.f1 -packOption "-side left" -textVariable ${rootname}SingValues \
          -label "Number of singular values: " -width 8 -contextHelp \
          "Enter the number of singular values to keep."
        APSRadioButtonFrame .rb1 -parent $w0.f1 -packOption "-side left" -label "Plane: " \
          -variable ${rootname}Plane -buttonList {H} -valueList {h} \
          -orientation horizontal -contextHelp \
          "Choose plane for which to compute the matrix."
        APSRadioButtonFrame .rb2 -parent $w0.f1 -packOption "-side left" -label "Remove DC vectors: " \
          -variable ${rootname}RemoveVectors -buttonList {N Y} -valueList {0 1} \
          -orientation horizontal -contextHelp \
          "Removes DC vectors from singular values decomposition. May help in horizontal plane convergence. Not recommended for vertical plane."
        APSButton .gen -parent $w0.f1 -text Compute -size small -packOption "-side left" -command \
          "APSSRFRFreqGenerateOrbCorrFiles -rootname $rootname -generate 1 -chmod a+rw -configFile \$${rootname}MainDir/\$${rootname}LatSubDir/\$${rootname}Lattice/\$${rootname}WriteDir/config -plane \$${rootname}Plane -referenceMatrix \$${rootname}MainDir/\$${rootname}LatSubDir/\$${rootname}Lattice/refMatrices/\$${rootname}RefMatrix(\$${rootname}Plane) -outputRoot \$${rootname}MainDir/\$${rootname}LatSubDir/\$${rootname}Lattice/\$${rootname}WriteDir/ -singularValues \$${rootname}SingValues -removeVectors \$${rootname}RemoveVectors"
        APSButton .vdefault -parent $w0.f1 -text "Make Default" -size small -packOption "-side left" \
          -contextHelp "Makes the named configuration into the default corrector configuration for chosen plane." \
          -command "APSSRFRFreqInstallOrbCorrFiles -rootname $rootname"
    }
    APSSwapInWidget $widget.bot.fileops -parent $parent -swapIn $w.read
}

proc APSSRFRFreqInstallOrbCorrFiles {args} {
    set rootname ""
    APSStrictParseArguments {rootname}
    global ${rootname}MainDir ${rootname}LatSubDir ${rootname}Lattice
    global ${rootname}WriteDir ${rootname}Plane ${rootname}ConfigStatus
    if {![APSMultipleChoice [APSUniqueName .] \
            -question "Change default orbit correction files? Are you sure?" -returnList {1 0} \
            -labelList {Yes No}]} {
        return
    }
    APSMakeLink -local 1 -log 1 -chmod a+wr \
      -filename [subst \$${rootname}MainDir/\$${rootname}LatSubDir/\$${rootname}Lattice/\$${rootname}WriteDir] \
      -linkname [subst \$${rootname}MainDir/\$${rootname}LatSubDir/\$${rootname}Lattice/\$${rootname}Plane.default]
    APSSetVarAndUpdate ${rootname}ConfigStatus "[subst \$${rootname}WriteDir] installed as [subst \$${rootname}Plane] default."
    set ${rootname}WriteDir [subst \$${rootname}Plane.default]
    set matrixFile /home/helios/oagData/controllaw/SRorbit/hp8657/rfFreq.matrix
    set matrixTestsFile /home/helios/oagData/controllaw/SRorbit/hp8657/rfFreq.tests
    if {![file exists $matrixFile]} {
	APSSetVarAndUpdate sconfigConfigStatus "$matrixFile is not a link, new matrix file not copied"
	bell
	return
    }
    if {![file exists $matrixTestsFile]} {
	APSSetVarAndUpdate sconfigConfigStatus "$matrixTestsFile is not a link, new matrix file not copied"
	bell
	return
    }
    if {[string compare [file type $matrixFile] link] != 0} {
	APSSetVarAndUpdate sconfigConfigStatus "$matrixFile is not a link, new matrix file not copied"
	bell
	return
    }
    if {[string compare [file type $matrixTestsFile] link] != 0} {
	APSSetVarAndUpdate sconfigConfigStatus "$matrixTestsFile is not a link, new matrix file not copied"
	bell
	return
    }
    set linkFile [file readlink $matrixFile]
    set directory [file dirname $matrixFile]
    set name [file tail $linkFile]

    if {[string last . $name] > [string last - $name]} {
	set separator "."
    } else {
	set separator "-"
    }
    if [catch {APSNextGenerationedName -name $name -separator $separator \
	-newFile 1 -directory $directory} genName] {
	APSSetVarAndUpdate sconfigConfigStatus "$genName"
	APSSetVarAndUpdate sconfigConfigStatus "\nFile not saved."
	bell
	return
    }
    set matrixFileNew $directory/$genName

    set linkFile [file readlink $matrixTestsFile]
    set directory [file dirname $matrixTestsFile]
    set name [file tail $linkFile]

    if {[string last . $name] > [string last - $name]} {
	set separator "."
    } else {
	set separator "-"
    }
    if [catch {APSNextGenerationedName -name $name -separator $separator \
	-newFile 1 -directory $directory} genName] {
	APSSetVarAndUpdate sconfigConfigStatus "$genName"
	APSSetVarAndUpdate sconfigConfigStatus "\nFile not saved."
	bell
	return
    }
    set matrixTestsFileNew $directory/$genName
    

    file copy -force [file join [subst \$${rootname}MainDir/\$${rootname}LatSubDir/\$${rootname}Lattice/\$${rootname}Plane.default] irm] $matrixFileNew
    file copy -force [file join [subst \$${rootname}MainDir/\$${rootname}LatSubDir/\$${rootname}Lattice/\$${rootname}Plane.default] tests] $matrixTestsFileNew
    catch {exec chmod go-w $matrixFileNew}
    catch {exec chmod go-w $matrixTestsFileNew}
    file delete -force $matrixFile $matrixTestsFile
    set oldDirectory [pwd]
    cd $directory
    exec ln -s [file tail $matrixFileNew] [file tail $matrixFile]
    exec ln -s [file tail $matrixTestsFileNew] [file tail $matrixTestsFile]
    cd $oldDirectory
    APSSetVarAndUpdate sconfigConfigStatus "The new generationed file \
	$matrixFileNew was created."

}

proc APSSRFRFreqGenerateOrbCorrFiles {args} {
    set configFile ""
    set outputRoot ""
    set referenceMatrix ""
    set plane h
    set generate 0
    set install 0
    set rootname ""
    set singularValues 320
    set removeVectors 0
    set chmod ""
    APSStrictParseArguments {configFile plane outputRoot referenceMatrix generate install rootname singularValues removeVectors chmod}
    
    if {!$generate && !$install} return
    if ![string length $rootname] {
        return -code error "APSSRFRFreqGenerateOrbCorrFiles: programming error: no variable rootname"
    }

    if {![string length $configFile] || ![file exists $configFile]} {
        return -code error "APSSRFRFreqGenerateOrbCorrFiles: supply a configuration file, or one that exists ($configFile was given)."
    }
    set configFile [APSResolveLink $configFile]

    if {![string length $referenceMatrix] || ![file exists $referenceMatrix]} {
        return -code error "APSSRFRFreqGenerateOrbCorrFiles: supply a reference matrix file, or one that exists ($referenceMatrix was given)."
    }
    set referenceMatrix [APSResolveLink $referenceMatrix]
    set origRefMatrix $referenceMatrix

    if ![string length $outputRoot] {
        return -code error "APSSRFRFreqGenerateOrbCorrFiles: supply an output rootname."
    }

    global ${rootname}ConfigStatus
    set ${rootname}ConfigStatus "Working..."
    update
    set correctorNames A014-IETS:BTC:SRSetFreqM
    set tmpRoot /tmp/[APSTmpString]
    APSAddToTempFileList $tmpRoot.monFlags 
    if [catch {exec sddsprocess $configFile -pipe=out \
                 -match=parameter,NameType=MonitorNames \
                 -filter=column,Flag,1,1 \
                 | sddscombine -pipe -merge \
                 | tee $tmpRoot.monFlags \
                 | sdds2stream -pipe -column=Name} monitorNames] {
        return -code error "APSSRFRFreqGenerateOrbCorrFiles: $monitorNames"
    }
    set monitorNameMatchOption ""
    set IDBPMList ""
    foreach item $monitorNames {
        if [string match *ID* $item]!=0 {
            lappend IDBPMList $item
        }
        if [string length $monitorNameMatchOption] {
            set monitorNameMatchOption "$monitorNameMatchOption,BPMName=$item,|"
        } else {
            set monitorNameMatchOption "-match=column,BPMName=$item"
        }
    }
    set BMBPMList ""
    foreach item $monitorNames {
        if [string match *BM* $item]!=0 {
            lappend BMBPMList $item
        }
        if [string length $monitorNameMatchOption] {
            set monitorNameMatchOption "$monitorNameMatchOption,BPMName=$item,|"
        } else {
            set monitorNameMatchOption "-match=column,BPMName=$item"
        }
    }
    if [llength $IDBPMList] {
        set IDBPMsKnownList [APSGetIDXRayBPMList]
        set IDBPMEqnList   [APSGetIDXRayEqnList]
        lappend equationCmd sddsprocess -pipe
        foreach item $IDBPMList {
            set index [lsearch -exact $IDBPMsKnownList $item]
            if $index==-1 {
                return -code error "APSSRFRFreqGenerateOrbCorrFiles: no information on $item"
            }
            lappend equationCmd "-define=column,$item,[lindex $IDBPMEqnList $index]"
        }
    }
    if [llength $BMBPMList] {
        set BMBPMsKnownList [APSGetBMXRayBPMList]
        set BMBPMEqnList   [APSGetBMXRayEqnList]
        lappend equationCmd sddsprocess -pipe
        foreach item $BMBPMList {
            set index [lsearch -exact $BMBPMsKnownList $item]
            if $index==-1 {
                return -code error "APSSRFRFreqGenerateOrbCorrFiles: no information on $item"
            }
            lappend equationCmd "-define=column,$item,[lindex $BMBPMEqnList $index]"
        }
    }
    if { [llength $IDBPMList] || [llength $BMBPMList] } {
        set tmpMatrix /tmp/[APSTmpString]
        if [catch {eval exec sddstranspose $referenceMatrix -pipe=out  \
                     | $equationCmd \
                     | sddstranspose -pipe=in $tmpMatrix \
                     -newColumnNames=OldColumnNames -oldColumnNames=BPMName} result] {
            return -code error "APSSRFRFreqGenerateOrbCorrFiles: $result"
        }
        set referenceMatrix $tmpMatrix
    }
    if $removeVectors {
        set inverseOptions "-largestSingularValues=$singularValues -removeDCVectors"
    } else {
        set inverseOptions "-largestSingularValues=$singularValues"
    }
    if [lsearch -exact [APSGetSDDSNames -fileName $tmpRoot.monFlags -class column] Weight]!=-1 {
        lappend inverseOptions "-weights=$tmpRoot.monFlags,name=Name,value=Weight"
    }
    if [catch {exec rm -f $outputRoot/irm
        eval exec sddsconvert $referenceMatrix -pipe=out \
                 -retain=column,BPMName,[join $correctorNames ,] \
                 | sddsprocess -pipe $monitorNameMatchOption \
                 | sddspseudoinverse -pipe $inverseOptions \
                 | sddsconvert -pipe -rename=column,OldColumnNames=Actuators \
                 | sddsprocess -pipe \
                 -print=parameter,ConfigurationFile,$configFile \
                 -print=parameter,ReferenceMatrix,$origRefMatrix \
		 | sddsconvert -pipe=in $outputRoot/irm \
		 {-editnames=column,S*,ei\\:mswAve:x:AdjustedCC\\}} result] {
        return -code error "APSSRFRFreqGenerateOrbCorrFiles: $result"
    }
    if {[string length $chmod] && [catch {eval exec chmod $chmod $outputRoot/irm} result]} {
        return -code error "APSSRFRFreqGenerateOrbCorrFiles: error doing chmod $chmod on $outputRoot/irm"
    }
    if [catch {exec sdds2stream -param=ConditionNumber $outputRoot/irm} condNumber] {
        return -code error "APSSRFRFreqGenerateOrbCorrFiles: error getting condition number"
    }

    set testFile(ColumnNames) "ControlName MinimumValue MaximumValue SleepTime"
    set testFile(ColumnInfo.MinimumValue) "type SDDS_DOUBLE"
    set testFile(ColumnInfo.MaximumValue) "type SDDS_DOUBLE"
    set testFile(ColumnInfo.SleepTime) "type SDDS_DOUBLE"
    lappend testFile(Column.ControlName) S:InjectingStatusMBBI S-DCCT:CurrentM A014-IETS:BTC:SRSetFreqM
    lappend testFile(Column.MinimumValue) -0.5 1.5 351926661.5
    lappend testFile(Column.MaximumValue) 0.5 105.0 351927661.5
    lappend testFile(Column.SleepTime) 3.0 3.0 3.0
    foreach item $monitorNames {
	lappend testFile(Column.ControlName) ${item}:mswAve:x:ErrorCC
	lappend testFile(Column.MinimumValue) -1.5
	lappend testFile(Column.MaximumValue) 1.5
	lappend testFile(Column.SleepTime) 3.0
    }
    foreach item $monitorNames {
	lappend testFile(Column.ControlName) ${item}:ms.XAVS
	lappend testFile(Column.MinimumValue) -0.5
	lappend testFile(Column.MaximumValue) 1.5
	lappend testFile(Column.SleepTime) 3.0
    }
    set testFile(Column.ControlName) [list $testFile(Column.ControlName)]
    set testFile(Column.MinimumValue) [list $testFile(Column.MinimumValue)]
    set testFile(Column.MaximumValue) [list $testFile(Column.MaximumValue)]
    set testFile(Column.SleepTime) [list $testFile(Column.SleepTime)]
    if {[catch {sdds save $outputRoot/tests testFile} result]} {
	set ${rootname}ConfigStatus "Error: $result"
	bell
	return
    }
    if {[string length $chmod] && [catch {eval exec chmod $chmod $outputRoot/tests} result]} {
        return -code error "APSSRFRFreqGenerateOrbCorrFiles: error doing chmod $chmod on $outputRoot/tests"
    }

    set ${rootname}ConfigStatus "Done.  Condition number is $condNumber ."
    update
}

proc APSSRWriteRFFreqCorrectionConfig {args} {
    set rootname ""
    set filename ""
    set description ""
    set interactive 1
    set configName ""
    APSStrictParseArguments {rootname filename description interactive configName}

    if ![string length [string trim $configName]] {
        return -code error "APSSRWriteRFFreqCorrectionConfig: supply a configuration name"
    }

    set path [file dirname $filename]
    set pathPart [file tail $path]

#    APSSRSectorUnsetMissing -rootname $rootname -missingList {S1A:H3 S39B:H1 S40A:H3}
#    APSSRSectorUnsetMissing -rootname $rootname -missingList {S1A:V3 S39B:V1 S40A:V3}
#    set BPMList [list A:P1 A:P2 A:P3 A:P4 B:P5 B:P4 B:P3 B:P2 B:P1]
    set BPMList [list B:P5]
    set confirm 0
    if $interactive {
        if [APSCountSRConfig -rootname $rootname -itemList $BPMList]==0 {
            set confirm 1
            append confirmQuery "\nNo monitors chosen."
        }
        if {$confirm &&
            [APSMultipleChoice [APSUniqueName .] -question "Possible problem: $confirmQuery" \
               -labelList {Continue Cancel} -returnList {1 0}]==0} {
            return
        }
    }
    if ![file exists $path] {
        exec mkdir -p $path
        exec chmod a+wx $path
    } else {
        if {$interactive && \
              [APSMultipleChoice [APSUniqueName .] -question "That configuration exists.  Overwrite?" \
                 -labelList {Yes No} -returnList {1 0}]==0} {
            return
        }
        if [catch {eval exec rm -f [glob $path/*]} result] {
            return -code error "APSSRWriteRFFreqCorrectionConfig: $result"
        }
    }
    APSWriteSRFRFreqConfig -rootname $rootname -filename $filename \
      -nameTypeList {Monitor} -interactive $interactive \
      -suffixLists $BPMList  \
      -description $description
    catch {exec sddscollapse $filename $filename.collapsed}
}

proc APSWriteSRFRFreqConfig {args} {
    set rootname ""
    set filename ""
    set nameTypeList ""
    set suffixLists ""
    set description ""
    set interactive 0
    set chmod ""
    APSStrictParseArguments {rootname filename nameTypeList suffixLists description interactive chmod}

    if ![string length $filename] {
        return -code error "APSWriteSRFRFreqConfig: No filename specified for rf freq configuration"
    }
    if {$interactive && [file exists $filename] && \
          [APSMultipleChoice [APSUniqueName .] -question "$filename exists.  Overwrite?" \
             -labelList {Yes No} -returnList {1 0}]==0} {
        return 
    }
    if [catch {sdds open $filename w} fid] {
        return -code error "APSWriteSRFRFreqConfig: Unable to open file $filename: $fid"
    }
    if [catch {sdds defineColumn $fid Name -type SDDS_STRING
        sdds defineColumn $fid Flag -type SDDS_SHORT 
        sdds defineColumn $fid Weight -type SDDS_DOUBLE
        sdds defineColumn $fid Despike -type SDDS_LONG
        sdds defineParameter $fid Description -type SDDS_STRING
        sdds defineParameter $fid NameType -type SDDS_STRING
        sdds writeLayout $fid} result] {
        catch {sdds close $fid}
        return -code error "APSWriteSRFRFreqConfig: problem defining SDDS elements: $result"
    }
    set nameTypeIndex -1
    global ${rootname}ConfigStatus
    foreach nameType $nameTypeList {
        incr nameTypeIndex
        set flags ""
        set names ""
        set weights ""
        set despikeFlags ""
        for {set sector 1} {$sector<41} {incr sector} {
            foreach suffix [lindex $suffixLists $nameTypeIndex] {
                set nameFlag ${rootname}S${sector}$suffix
                set weightVar ${rootname}S${sector}${suffix}Weight
                set despikeVar ${rootname}S${sector}${suffix}Despike
                global $nameFlag $weightVar $despikeVar
                if [set $nameFlag] {
                    lappend flags 1
                    lappend names S${sector}$suffix
                    if [info exists $weightVar] {
                        lappend weights [set $weightVar]
                    } else {
                        lappend weights 1.0
                    }
                    if [info exists $despikeVar] {
                        lappend despikeFlags [set $despikeVar]
                    } else {
                        lappend despikeFlags 1
                    }
                }
            }
        }
        if [llength $flags]==0 continue
        APSSetVarAndUpdate ${rootname}ConfigStatus "[llength $flags] $nameType"
        if [catch {sdds startPage $fid [expr 360*20] 
            sdds setParameter $fid Description $description
            sdds setParameter $fid NameType ${nameType}Names} result] {
            catch {sdds close $fid}
            return -code error "APSWriteSRFRFreqConfig: SDDS problem: $result"
        }
        foreach column {names flags weights} {
            APSSetVarAndUpdate ${rootname}ConfigStatus [llength $column]
        }
        if [catch {eval sdds setColumn $fid Name $names
            eval sdds setColumn $fid Flag $flags 
            eval sdds setColumn $fid Weight $weights
            eval sdds setColumn $fid Despike $despikeFlags
            sdds writePage $fid} result] {
            catch {sdds close $fid}
            return -code error "APSWriteSRFRFreqConfig: SDDS problem: $result"
        }
    }
    if [catch {sdds close $fid} result] {
        return -code error "APSWriteSRFRFreqConfig: SDDS problem: $result"
    }
    if {[string length $chmod] && [catch {eval exec chmod $chmod $filename} result]} {
        return -code error "APSWriteSRFRFreqConfig:  error doing chmod $chmod on $filename"
    }
    global ${rootname}ConfigStatus
    set ${rootname}ConfigStatus "Wrote configuration to $filename"
    update
}

proc APSReadRFFreqCorrectionConfig {args} {
    set rootname ""
    set filename ""
    set logic replace
    APSStrictParseArguments {rootname filename logic}
#    set BPMList [list A:P1 A:P2 A:P3 A:P4 B:P5 B:P4 B:P3 B:P2 B:P1]
    set BPMList [list B:P5]
    set suffixList $BPMList
    if [catch {APSReadSRConfig -rootname $rootname -filename $filename -logic $logic \
                 -nameTypeList {Monitor} \
                 -knownSuffixes $suffixList} description] {
        return -code error $description
    }
    global ${rootname}ReadDescription
    set ${rootname}ReadDescription $description
}

proc APSSRFRFreqMonitorCheckButtons {widget args} {
    set rootname ""
    set parent ""
    set packOption "-side left"
    APSStrictParseArguments {rootname parent packOption}

    set itemList [list A:P0 A:P1 A:P2 A:P3 A:P4 B:P5 B:P4 B:P3 B:P2 B:P1 B:P0 C:P0]
    set itemLabelList [list A0 A1 A2 A3 A4 B5 B4 B3 B2 B1 B0 C0]
    set missingList [APSGetMissingBPMList -plane H]
    APSSRFRFreqSectorButtons .sbbut -parent $parent -rootname ${rootname} \
      -label "Monitors" -description "monitors" \
      -itemList $itemList -itemLabelList $itemLabelList \
      -packOption $packOption -missingList $missingList \
      -command ""
}


proc APSSRFRFreqSectorButtons {widget args} {
    set parent "" 
    set rootname ""
    set label "Unknown selections"
    set description "No description"
    set itemList ""
    set command ""
    set missingList ""
    set packOption "-side left"
    set itemLabelList ""
    APSStrictParseArguments {parent rootname label description itemList command \
                               missingList packOption itemLabelList}

    APSFrame $widget -parent $parent -label $label \
      -packOption $packOption

    set f1 $parent$widget.frame.f1
    set command1 ""
    frame $parent$widget.frame.f1
    eval pack $parent$widget.frame.f1 -side left
    if [llength $itemLabelList] {
	# make vertical column for labels using item names
	frame $f1.labels
	pack $f1.labels -side left -fill y -expand 1
	set f2 $f1.labels
	# labels for items
	for {set index [llength $itemLabelList]} {$index>0} {} {
	    incr index -1
	    label $f2.item$index -text [lindex $itemLabelList $index] \
		-borderwidth 1 -padx 0 -pady 0 -highlightthickness 0
	    pack $f2.item$index -side bottom 
	}
	# make vertical columns for checkbuttons vs sector number
	for {set n 1} {$n<=40} {incr n} {
	    # column for checkbuttons
	    frame $f1.sector$n
	    pack $f1.sector$n -side left
	    set f2 $f1.sector$n
	    for {set index [llength $itemList]} {$index>0} {} {
		incr index -1
		set item [lindex $itemList $index]
		set name S${n}$item
		set nameFlag ${rootname}$name
		global $nameFlag
		if {![info exists $nameFlag]} {
		    set $nameFlag 1
		}
		if [string length $command] {
		    set command1 "$command -sector $n -item $item -nameFlag $nameFlag"
		}
		checkbutton $f2.item$index -text "" -variable $nameFlag \
		    -borderwidth 1 -padx 0 -pady 0 -highlightthickness 0 \
		    -command "$command1"
		if {[llength $missingList] && [lsearch $missingList $name]!=-1} {
		    $f2.item$index configure -state disabled
		}
		pack $f2.item$index -side bottom
		set apsContextHelp($f2.item$index) $name
	    }
	    if $n>9 {
		label $f2.label -text \
		    [format "\n%1d\n%1d" [expr int($n/10)] [expr $n-int($n/10)*10]] \
		    -borderwidth 0 -padx 0 -pady 0 -highlightthickness 0
	    } else {
		label $f2.label -text \
		    [format "\n\n%1d" $n] \
		    -borderwidth 0 -padx 0 -pady 0 -highlightthickness 0
	    }
	    pack $f2.label -side bottom
	}
    }

    # Position toggle buttons
    APSSRFRFreqSectorPositionButtons .frametog -parent $parent$widget.frame -rootname $rootname \
      -description $description -itemList $itemList -missingList $missingList
    # Global buttons
    APSSRFRFreqSectorGlobalButtons .frameButtonsSB -parent $parent$widget.frame -rootname $rootname \
      -description $description -itemList $itemList -missingList $missingList
    APSSRSectorUnsetMissing -rootname $rootname -missingList $missingList
}

proc APSSRFRFreqSectorPositionButtons {widget args} {
    set parent ""
    set description ""
    set itemList ""
    set rootname ""
    set missingList ""
    APSStrictParseArguments {parent description itemList rootname missingList}

    set f2 $parent$widget
    frame $f2
    set side1 left
    set side2 top
    pack $f2 -side $side1

    label $f2.label -text "A\nl\nl" \
	-borderwidth 1 -padx 0 -pady 0 -highlightthickness 0
    pack $f2.label -side $side2

    foreach item $itemList {
        set togVar ${rootname}S${item}
        global $togVar
        if {![info exists $togVar]} {
            set $togVar 1
        }
        set w $f2.$togVar
        checkbutton $f2.$togVar -text "" -variable $togVar \
          -command "APSSRSectorTogglePosition -rootname $rootname -item $item -missingList [list $missingList] -toggleVar $togVar" \
          -borderwidth 1 -padx 0 -pady 0 -highlightthickness 0
        pack $f2.$togVar -in $f2 -side $side2
        set apsContextHelp($f2.$togVar) \
          "Toggles all $description in this position in the sector\
               on or off."
    }
}

proc APSSRFRFreqSectorGlobalButtons {widget args} {
    set parent ""
    set rootname ""
    set description ""
    set itemList ""
    set missingList ""
    APSStrictParseArguments {parent rootname description itemList missingList}

    set f2 $parent$widget
    frame $f2
    set side1 left
    set side2 top
    pack $f2 -side $side1
    APSButton .allon -parent $f2 -text "+All" \
      -command "APSSetSRSectorButtons -mode all-on -rootname $rootname -itemList [list $itemList] -missingList [list $missingList]" \
      -size small -packOption "-side $side2" -contextHelp \
      "Sets all $description buttons on."
    APSButton .alloff -parent $f2 -text "-All" \
      -command "APSSetSRSectorButtons -mode all-off -rootname $rootname -itemList [list $itemList] -missingList [list $missingList]" \
      -size small -packOption "-side $side2" -contextHelp \
      "Sets all $description buttons off."
    APSButton .count -parent $f2 -text "Count" -size small -packOption "-side $side2" -command \
      "set ${rootname}ConfigStatus \"$description count is \[APSCountSRConfig -rootname $rootname -itemList [list $itemList] -missingList [list $missingList] \]\"" \
      -contextHelp "Counts the number of $description buttons that are on."
}

APSSRConfigRFFreqCorrection .config \
    -parent .userFrame \
    -rootname $rootname \
    -fileFrame 1

if [string length $initialConfig] {
    set ${rootname}ReadFile $initialConfig
    eval APSReadRFFreqCorrectionConfig -rootname $rootname -filename \$${rootname}MainDir/\$${rootname}LatSubDir/\$${rootname}Lattice/\$${rootname}ReadFile/config -logic replace
    }
