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

# $Log: not supported by cvs2svn $
# Revision 1.36  2010/01/29 15:56:28  shang
# increased the bpm sector selection window size so that all items can be shown and the buttons are lined up correctly.
#
# Revision 1.35  2010/01/27 16:28:49  shang
# modified to get the monopulse bpm ioc list from APSGetMonopulseBPMIOCList proc to automatically exclude the FPGA bpm iocs.
#
# Revision 1.34  2009/12/16 20:06:49  shang
# fixed the bugs of read configuration buttons which complained that the corrector related variables did not exist.
#
# Revision 1.33  2009/01/22 22:52:54  shang
# added S38 back to the memory scanner
#
# Revision 1.32  2009/01/21 23:41:53  shang
# removed FPGA bpms from setting SCDU, MemoryScanner and History, and removed sector 38 from Mombo history since the corresponding PVs no longer exist.
#
# Revision 1.31  2006/03/30 20:12:14  shang
# increased the tab frame height so that it can display all elements on linux workstations.
#
# Revision 1.30  2004/02/10 15:30:28  shang
# added transfer ID xray bpm blades and separates previous transfer widget into
# transfers and zerovalues.
#
# Revision 1.29  2003/11/19 02:02:16  emery
# Expanded wildcard matching for rf related bpms from [45] to [12345]
#
# Revision 1.28  2003/11/11 18:00:20  borland
# SCDU and History operations are now sensitive to the ElectronicsType in the
# BPM status file.  In particular, these operations are only executed for
# ElectronicsType=Monopulse.
#
# Revision 1.27  2003/09/28 06:12:05  emery
# MAde sure that all cavget has 120 seconds pending time
#
# Revision 1.26  2003/05/26 04:49:54  emery
# Added C:P0 to list of P0s
#
# Revision 1.25  2003/04/21 17:07:06  shang
# increased the height of tabwidget to display all info
#
# Revision 1.24  2002/10/07 17:03:44  soliday
# Restored the auto_path to the correct value.
#
# Revision 1.23  2002/09/17 21:11:55  shang
# added setting bpm timing mode (Default/Cog) feature to sector option.
#
# Revision 1.22  2002/08/07 14:53:58  shang
# enable existing dipole bpm (in y plane) buttons
#
# Revision 1.21  2002/08/06 20:54:42  shang
# changed widgets to make it look better and easier to operate
#
# Revision 1.20  2002/05/24 07:57:15  emery
# Added check of sector variable list for ChangeSectorMemScan
#
# Revision 1.19  2001/09/24 17:01:56  borland
# Fixed enable/disable mixup for InUse PVs.
#
# Revision 1.18  2001/09/24 16:58:16  borland
# Now allow changing InUse fields for individual BPMs.
# Also, added Query function for individual BPM operations.
#
# Revision 1.17  2001/08/28 23:15:14  emery
# Changed list of ms types for trasnfering RfSetpoints to a reduced set of
# :ms: for setting and :mswAve for reading.
#
# Revision 1.16  2001/08/16 16:53:30  emery
# Added number to average for xray bpms and P0 bpms
# into the sector-wide number-to-average command.
#
# Revision 1.15  2001/08/13 20:51:14  emery
# Added transfers for x-ray bpms. Added filters for
# bpms for various command. This prevents sending a value
# to a PV that doesn't exist. Iin the scase of BM x-ray
# bpms added code which would filter out the x-plane
# command as these bpms only readback in y plane.
#
# Revision 1.14  2001/05/09 13:43:35  emery
# Added RF setpoint transfers
#
# Revision 1.13  2001/04/19 17:11:22  emery
# Updated the tab frames for the new timing system PVs.
#
# Revision 1.12  2001/02/06 17:05:26  emery
# Added SCDU operation OffsetP (self-test offset).
# Replaced swap frame with tab widget.
#
# Revision 1.11  1999/10/06 15:52:27  emery
# Added excludeP0s argument to IndividualBPMsSelected so that
# P0 could get excluded in some of the PV operations.
#
# Revision 1.10  1999/05/20 21:33:39  borland
# Changed labels for transfer buttons to indicate more clearly what they
# do.   Added P0 BPMs plus a way to determine which ones are actually
# there (using the SCR request file for SR)
#
# Revision 1.9  1999/04/27 20:08:16  borland
# Fixed transfer feature.  Now delta-transfers the ErrorCC to SetpointAO or
# OffsetAO.
#
# Revision 1.8  1999/04/27 18:51:51  borland
# Added individual bpm transfer operations for setpoints and offsets.
#
# Revision 1.7  1998/03/05 22:57:40  borland
# Allows controlling number-to-average and filter coefficient for IOC
# averaging.
#
# Revision 1.6  1998/03/05 22:25:45  borland
# Added memory scanner control with BPM averaging enable/disable.
#
# Revision 1.5  1997/05/30 20:00:23  borland
# Added ability to change waveform readout enable/disable for
# normal histories and mombos.
#
# Revision 1.4  1997/01/14 14:48:10  borland
# Increased pend time from 60s to 120s.
#
# Revision 1.3  1996/09/19 21:51:17  borland
# Changed from using "exec wish" to "exec oagwish".
#
# Revision 1.2  1996/07/05 23:08:27  borland
# Added -pend=60 option to all cavputs to avoid timeouts.
#
# Revision 1.1  1996/06/14  23:07:23  borland
# 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 CVSRevisionAuthor "\$Revision: 1.37 $ \$Author: shang $"

APSApplication . -name SRbpmConfig -version $CVSRevisionAuthor \
  -overview "Storage ring bpm configuration tool."

set bpmList {AP0 AP1 AP2 AP3 AP4 BP5 BP4 BP3 BP2 BP1 BP0 CP0 D1 D2 I1 I2}
set bpmListColon {A:P0 A:P1 A:P2 A:P3 A:P4 B:P5 B:P4 B:P3 B:P2 B:P1 B:P0 C:P0 BM:P1 BM:P2 ID:P1 ID:P2}

proc MakeCheckButtonListFrame {widget args} {
    set parent ""
    set label ""
    set labelList ""
    set state0List ""
    set state1List ""
    set value0List ""
    set value1List ""
    set command ""
    set commandArgumentList ""
    set frameWidth 500
    set frameHeight 500
    set addQuery 0
    if [APSStrictParseArguments \
          {parent labelList state0List state1List command commandArgumentList label frameWidth frameHeight value0List value1List addQuery}]==-1 {
              return
          } 
    set width [expr [APSMaxStringLength $labelList]+1]
    APSFrame $widget -parent $parent -label "" -noPack 0 -width $frameWidth -height $frameHeight
    $parent$widget.frame configure -relief flat
    set w0 $parent$widget.frame
    pack propagate $w0 0
    set index 0
    foreach label $labelList state0 $state0List state1 $state1List argument $commandArgumentList {
        set value0 0
        set value1 1
        if [llength $value0List] {
            set value0 [lindex $value0List $index]
        } 
        if [llength $value1List] {
            set value1 [lindex $value1List $index]
        } 
        if [string match $state0 $state1] {
            APSFrame .a$index -parent $w0 -label $label -orientation horizontal  \
              -packOption "-side top -fill x"
            APSButton .b0 -parent $w0.a$index.frame -text $state1 \
              -command "$command $argument $value1" -size small
        } else {
            APSFrame .a$index -parent $w0 -label $label -orientation horizontal \
              -packOption "-side top -fill x"
            APSButton .b0 -parent $w0.a$index.frame -text $state0 \
              -command "$command $argument $value0" -size small
            APSButton .b1 -parent $w0.a$index.frame -text $state1 \
              -command "$command $argument $value1" -size small
        }
        $w0.a$index.label configure -width $width
        if $addQuery {
            APSButton .b2 -parent $w0.a$index.frame -text "Query" \
            -command "$command $argument __query__" -size small
        }
        incr index
    }
}

proc MakeAPSButtonListFrame {widget args} {
    set parent ""
    set label ""
    set labelList ""
    set command ""
    set commandArgumentList ""
    set frameWidth 500
    set frameHeight 500
    if [APSStrictParseArguments \
          {parent labelList command commandArgumentList label frameWidth frameHeight}]==-1 {
              return
          } 
    set width [expr [APSMaxStringLength $labelList]+1]

    APSFrame $widget -parent $parent -label "" -noPack 0 -width $frameWidth -height $frameHeight
    $parent$widget.frame configure -relief flat
    set w0 $parent$widget.frame
    pack propagate $w0 0
    foreach label $labelList commandArg $commandArgumentList {
        set w [APSUniqueName .]
        APSButton $w -parent $w0 -text $label \
          -command "$command $commandArg" -packOption "-side top" -size small
    }
}

proc MakeIndividualOpsWidget {widget args} {
    set parent ""
    if [APSStrictParseArguments {parent}]==-1 {
        return
    } 
    set frameWidth 430
    set frameHeight 350
    APSFrame $widget -parent $parent -label "" 
    $parent$widget.frame configure -relief flat
    set w $parent$widget.frame
    set widgetList [APSTabFrame .controls -parent $parent$widget.frame \
                      -label "Individual BPM Operations" \
                      -labelList "SCDU MemScan Transfers ZeroValues" \
                      -width $frameWidth -height $frameHeight ]
    pack $parent$widget.frame.controls
    $parent$widget.frame.controls.frame.tn select 0
    set windex 0

    set tabwidget [lindex $widgetList $windex]
    incr windex
    MakeCheckButtonListFrame .scdu -parent $tabwidget -label SCDU \
      -labelList {xEnable yEnable sumEnable backupTrig testMode forceFreeRun lockState gainLevel resyncMode} \
      -state0List {Enable Enable Enable Off Off Off Unlocked LoGain Enable} \
      -state1List {Disable Disable Disable On On On Locked HiGain Inhibit} \
      -command ChangeSCDU -addQuery 1 \
      -commandArgumentList {disablex_bo disabley_bo disablesum_bo backuptrig_bo test_bo ffreerun_bo lock_bo normal_bo resync_bo} \
      -frameHeight $frameHeight -frameWidth $frameWidth 

    set tabwidget [lindex $widgetList $windex]
    incr windex
    MakeCheckButtonListFrame .mscan -parent $tabwidget -label "Memory Scanner" \
      -labelList {AveOn xInUse yInUse} \
      -state0List {Enable Disable Disable} \
      -state1List {Disable Enable Enable} \
      -command ChangeMemScan -addQuery 1 \
      -commandArgumentList {msAve:AveEnbBO ms:x:InUseBO ms:y:InUseBO} \
      -frameHeight $frameHeight -frameWidth $frameWidth 

    #    set tabwidget [lindex $widgetList $windex]
    #    incr windex
    #    No more indiviudal timing PV controls with the new timing system
    #    MakeCheckButtonListFrame .timing -parent $tabwidget -label "Timing" \
      -labelList {timingEnable bankSelect} \
      -state0List {Yes Ram0} \
      -state1List {No Ram1} \
      -command ChangeIndivTiming \
      -commandArgumentList {time.DBD time.BSD} \
      -frameHeight $frameHeight -frameWidth $frameWidth 
    if {0} {
    #history no long needed, H. Shang 8/20/2015
    set tabwidget [lindex $widgetList $windex]
    incr windex
    MakeCheckButtonListFrame .beamHistory -parent $tabwidget -label "Beam History" \
      -labelList {fillMode readState readMode singleShot resyncState wformDisplay} \
      -state0List {Continuous Disable SingleShot Disable Disable Disable} \
      -state1List {StopOnFull Enable Continuous Enable Enable Enable} \
      -command ChangeIndivHistory -addQuery 1 \
      -commandArgumentList {bh.FIM0 bh.BRDE bh.BRDM bh.SSEN bh.FIR0 bh:wfDisable_bo.VAL} \
      -frameHeight $frameHeight -frameWidth $frameWidth 
   }

    set tabwidget [lindex $widgetList $windex]
    incr windex
    MakeAPSButtonListFrame .transfers -parent $tabwidget -label "Operations" \
      -command TransferOrbit \
      -labelList {"x Setpoint += ErrorCC" "x RF Setpoint += RfErrorM" \
                    "y Setpoint += ErrorCC" "x/y Setpoint += ErrorCC" \
                    "x Offset += ErrorCC" "y Offset += ErrorCC" "x/y Offset += ErrorCC" \
                    "ID Xbpm blades xfer" \
      } \
      -commandArgumentList \
      { "-plane x -mode setpointXfer" "-plane x -mode RFsetpointXfer" \
          "-plane y -mode setpointXfer" "-plane both -mode setpointXfer" \
          "-plane x -mode offsetXfer" "-plane y -mode offsetXfer" "-plane both -mode offsetXfer" \
          "-mode IDbladesXfer"
      }
    
    set tabwidget [lindex $widgetList $windex]
    incr windex
    MakeAPSButtonListFrame .zero -parent $tabwidget -label "Operations" \
      -command TransferOrbit \
      -labelList {"0 -> x setpoint" "0 -> x RF setpoint" "0 -> y setpoint" \
                    "0 -> x/y setpoint" "0 -> x offset" "0 -> y offset" "0 -> x/y offset" \
                } \
      -commandArgumentList \
      {"-plane x -mode setpointZero" "-plane x -mode RFsetpointZero" \
         "-plane y -mode setpointZero" "-plane both -mode setpointZero" \
         "-plane x -mode offsetZero" "-plane y -mode offsetZero" "-plane both -mode offsetZero" \
     }
    
}

proc MakeSectorOpsWidget {widget args} {
    set parent ""
    if [APSStrictParseArguments {parent}]==-1 {
        return
    } 
    set frameWidth 430
    set frameHeight 350

    APSFrame $widget -parent $parent -label "" 
    $parent$widget.frame configure -relief flat
    set w $parent$widget.frame
    set widgetList [APSTabFrame .controls -parent $parent$widget.frame \
                      -label "Sector Operations" \
                      -labelList "Timing \"Bunch Clock\" MemScan" \
                      -width $frameWidth -height $frameHeight ]
    pack $parent$widget.frame.controls
    $parent$widget.frame.controls.frame.tn select 0
    set windex 0

    set tabwidget [lindex $widgetList $windex]
    incr windex
    MakeCheckButtonListFrame .timing -parent $tabwidget -label "Timing" \
      -labelList {"Pattern Enable" "100ns Delay" Force Init "Trigger Inhibit" \
                    "Soft Init" "Clock Detect Reset" "Lost P0 Detect Reset" "Init Rcvd Reset" \
                "bpm timing mode"} \
      -state0List {Enable In Enable Enable Enable \
                     Reset Reset Reset Reset Default} \
      -state1List {Disable Out Disable Disable Disable \
                     Reset Reset Reset Reset Cog} \
      -command ChangeSectorTiming \
      -commandArgumentList {disablePatternBO disableBCGdlyBO disableForceBO disableInitBO disableInhibitBO \
                              softInitBO lostClkRstBO lostP0RstBO initRcvdRstBO TimingModeMO} \
      -frameHeight $frameHeight -frameWidth $frameWidth 
    
    set tabwidget [lindex $widgetList $windex]
    incr windex
    MakeCheckButtonListFrame .timing -parent $tabwidget -label "Bunch Clock" \
      -labelList {"Bunch Clock Generator"} \
      -state0List {Enable} \
      -state1List {Disable} \
      -command ChangeSectorBunchClock \
      -commandArgumentList {DisableBO} \
      -frameHeight $frameHeight -frameWidth $frameWidth 
    
    set tabwidget [lindex $widgetList $windex]
    incr windex
    MakeCheckButtonListFrame .memscan -parent $tabwidget \
      -label "Memory Scanner" \
      -labelList {Num2Ave AveCoeff} \
      -state0List {10 0.1} \
      -state1List {128 1.0} \
      -value0List {10 0.1} \
      -value1List {128 1.0} \
      -command ChangeSectorMemScan \
      -commandArgumentList {msAve:Num2AveAO mswAve:CoeffAO} \
      -frameHeight $frameHeight -frameWidth $frameWidth 

    if {0} {
     #history and mobo history become obsolete now, H. Shang 8/20/2015
    set tabwidget [lindex $widgetList $windex]
    incr windex
    MakeCheckButtonListFrame .history -parent $tabwidget -label "History" \
      -labelList {allFifoReset allFifoResetEnable ring P0CountEnable TurnsCountEnable TurnsCountReset \
                    allFifoResynchEnable allFifoResynch} \
      -state0List {Yes No  Booster No No Yes No Yes } \
      -state1List {Yes Yes SR Yes Yes Yes Yes Yes } \
      -command ChangeSectorHistory \
      -commandArgumentList {beamH.FIRA beamHfifoResetBo beamH.RING beamH.P0CM beamH.TCNM beamH.FMR3 \
                              beamH.FRRA beamH.FRR5 } \
      -frameHeight $frameHeight -frameWidth $frameWidth 

    set tabwidget [lindex $widgetList $windex]
    incr windex
    MakeCheckButtonListFrame .mombo -parent $tabwidget -label "Mombo History" \
      -labelList {fifoFillMode fifoReset ResyncEnable fifoReadEnable fifoReadMode fifoSingShotMode wformDisplay} \
      -state0List {Continuous Yes Disable Disable SingleShot Disable Disable} \
      -state1List {StopOnFull Yes Enable  Enable Continuous Enable Enable} \
      -command ChangeMomboHistory \
      -commandArgumentList {bh.FIM0 bh.FRST bh.FIR0 bh.BRDE bh.BRDM bh.SSEN bh:wfDisable_bo.VAL} \
      -frameHeight $frameHeight -frameWidth $frameWidth 
     }
}

set ValidBPMList {}
proc IndividualBPMsSelected {args} {
    global bpmList bpmListColon ValidBPMList FPGAbpmList
    set excludeP0s 0
    set excludeXray 0
    set excludeBMXray 0
    set useWildcard ""
    set excludeFPGA 0
    APSParseArguments {excludeP0s excludeXray useWildcard excludeBMXray excludeFPGA}
    set selectedList ""
    if [llength $ValidBPMList]<2 {
        if [catch {exec sddsprocess /home/helios/oagData/sr/BPMStatus/config.sdds -pipe=out \
                     -filter=column,NonexistentH,0,0,NonexistentV,0,0,| \
                     | sdds2stream -pipe -column=DeviceName} ValidBPMList] {
            SetMainStatus "Unable to get list of valid BPMs: $ValidBPMList"
            set ValidBPMList {}
        }
    }
    if $excludeFPGA {
        if ![info exist FPGAbpmList] {
            if [catch {exec sddsprocess /home/helios/oagData/sr/BPMStatus/config.sdds -pipe=out \
                         -match=column,ElectronicsType=FPGA \
                         | sdds2stream -pipe -column=DeviceName} FPGAbpmList] {
                SetMainStatus "Unable to get list of valid BPMs: $FPGAbpmList"
                set FPGAbpmList ""
            }
        }
    }
    set index 0
    foreach bpm $bpmList {
        if {$excludeXray} {
            if {[string match D? $bpm] || [string match I? $bpm]} {
                incr index
                continue
            }
        }
        if {$excludeBMXray} {
            if {[string match D? $bpm]} {
                incr index
                continue
            }
        }
        if {$excludeP0s} {
            if [regexp P0 $bpm] {
                incr index
                continue 
            }
        }
        if {$useWildcard != "" && ![string match $useWildcard $bpm]} {
            incr index
            continue
        }
        for {set sector 1} {$sector<41} {incr sector} {
            global S${sector}$bpm
            if {[set S${sector}$bpm]} {
                set bpmName $sector[lindex $bpmListColon $index]
                if [lsearch -exact $ValidBPMList S$bpmName]>-1 {
                    if {$excludeFPGA} {
                        if {[lsearch -exact $FPGAbpmList S$bpmName]<0} {
                            lappend selectedList $bpmName
                        }
                    } else {
                        lappend selectedList $bpmName
                    }
                }
            }
        }
        incr index
    }
   # puts $selectedList
    return $selectedList
}

proc TransferOrbit {args} {
    set plane ""
    set mode ""
    APSStrictParseArguments {plane mode}
    #set BPMsToChange [IndividualBPMsSelected]
    #run SelectedBPMList to get the selected bpms in x and y plane
    set BPMsToChange [SelectedBPMList]
    set count [llength $BPMsToChange]
    if {$count==0} {
        SetMainStatus "No BPMs selected---no transfers done."
        return
    }
    set zero 0
    switch $mode {
        setpointXfer {
            set readFrom ErrorCC
            set xferTo SetpointAO
        }
        RFsetpointXfer {
            set readFrom RfErrorM
            set xferTo RfSetpointP
        }
        offsetXfer {
            set readFrom ErrorCC
            set xferTo OffsetAO
        }
        setpointZero {
            set zero 1
            set xferTo SetpointAO
        }
        RFsetpointZero {
            set zero 1
            set xferTo RfSetpointP
        }
        offsetZero {
            set zero 1
            set xferTo OffsetAO
        }
        IDbladesXfer {
            set IDsectors ""
            foreach bpm $BPMsToChange {
                if ![string match *ID* $bpm] {continue}
                if ![scan $bpm %ld sector] {continue}
                if [lsearch $IDsectors $sector]<0 {
                    lappend IDsectors $sector
                }
            }
            if ![llength $IDsectors] {
                SetMainStatus "No IDs were selected for ID blades transfer."
                return
            }
        }
        default {
            SetMainStatus "Invalid mode: $mode"
            return
        }
    }
    if {$mode=="IDbladesXfer"} {
        SetMainStatus "Transfer ID blades for [llength $IDsectors] sectors...[exec date +%H:%M:%S]"
    } else { 
        switch $plane {
            x -
            y {
            }
            both {
                set plane [list x y]
            }
            default {
                SetMainStatus "Invalid plane: $plane"
                return
            }
        }
        if !$zero {
            SetMainStatus "Transferring $plane orbit(s) to ${mode}s for $count BPMs...[exec date +%H:%M:%S]"
        } else {
            SetMainStatus "Setting $plane ${mode}s to 0 for $count BPMs...[exec date +%H:%M:%S]"
        }
    }
    switch $mode {
        IDbladesXfer {
            if [catch {exec cavput -list=S -list=[join $IDsectors ,] \
                         -list=ID:XferBladeOffsetC.PROC=1 -pend=30} result ] {
                SetMainStatus "Unable to transfer ID blades: $result"
            }
            SetMainStatus "Done."
            return
        }
        RFsetpointXfer -
        RFsetpointZero 
        {
            # include only bpms that have RF-related setpoints: [AB]:P[12345]
            #changesmadehere
            #set BPMsToChange [IndividualBPMsSelected -excludeXray 1 -useWildcard {[AB]P[12345]}]
	    # Actually not all P0s have a RfErrorM PV, so selecting P0s
	    # will make a cavget hang up. LEm 7/4/13
            set BPMsToChange [SelectedBPMList -excludeIDXray 1 -excludeBMXray 1 ]
            #                    -useWildcard {[AB]:P[12345]}]
            if ![llength $BPMsToChange] {
                SetMainStatus "No bpm selected matched the list of RF-related bpms."
                return
            }
            if [catch {exec cavget -pend=120 -list=S -list=[join $BPMsToChange ,] \
                         -list=:ms: -list=[join $plane ,] -list=:$xferTo -dry} pvList] {
                SetMainStatus "$pvList"
                return
            }
            # include only bpms that have RF-related setpoints: [AB]:P[12345]
            if !$zero {
                if [catch {exec cavget -pend=120 -list=S -list=[join $BPMsToChange ,] \
                             -list=:mswAve: -list=[join $plane ,] -list=:${readFrom}} dataList] {
                    SetMainStatus "$dataList"
                    return
                }
            } else {
                set dataList [APSReplicateItem -item 0.0 -number [llength $pvList]]
            }
        }
        default {
            # other transfers
            switch $plane {
                x -
                y {
                    set BPMsToChange [getnonBpm $BPMsToChange $plane]
                    if ![llength $BPMsToChange] {
                        SetMainStatus "Bpms selected do not work in plane $plane."
                        set pvList ""
                        if !$zero {
                            set dataList ""
                        }
                    } else {
                        if [catch {exec cavget -pend=120 -list=S -list=[join $BPMsToChange ,] \
                                 -list=:ms: -list=[join $plane ,] -list=:$xferTo -dry} pvList] {
                            SetMainStatus "$pvList"
                            return
                        }
                        if !$zero {
                            if [catch {exec cavget -pend=120 -list=S -list=[join $BPMsToChange ,] \
                                     -list=:mswAve: -list=[join $plane ,] -list=:${readFrom}} dataList] {
                                SetMainStatus "$dataList"
                                return
                            }
                        } else {
                            set dataList [APSReplicateItem -item 0.0 -number [llength $pvList]]
                        }
                    }
                }
                default {
                    # default is the {x y} list
                    set xList [getnonBpm $BPMsToChange x]
                    if [llength $xList] {
                        if [catch {exec cavget -pend=120 -list=S -list=[join $xList ,] \
                                     -list=:ms:x -list=:$xferTo -dry} pvXList] {
                            SetMainStatus "$pvXList"
                            return
                        }
                        if !$zero {
                            if [catch {exec cavget -pend=120 -list=S -list=[join $xList ,] \
                                         -list=:mswAve:x -list=:${readFrom} } dataXList] {
                                SetMainStatus "$dataXList"
                                return
                            }
                        } else {
                            set dataXList [APSReplicateItem -item 0.0 -number [llength $pvXList]]
                        }
                    } else {
                        SetMainStatus "Bpms selected work do not work in plane x."
                        set pvXList ""
                        set dataXList ""
                    }
                    set yList [getnonBpm $BPMsToChange y]
                    if [llength $yList] {
                        if [catch {exec cavget -pend=120 -list=S -list=[join $yList ,] \
                                     -list=:ms:y -list=:$xferTo -dry } pvYList] {
                            SetMainStatus "$pvYList"
                            return
                        }
                        if !$zero {
                            if [catch {exec cavget -pend=120 -list=S -list=[join $yList ,] \
                                         -list=:mswAve:y -list=:${readFrom}} dataYList] {
                                SetMainStatus "$dataYList"
                                return
                            }
                        } else {
                            set dataYList [APSReplicateItem -item 0.0 -number [llength $pvYList]]
                        }
                    } else {
                        SetMainStatus "Bpms selected work do not work in plane y."
                        set pvYList ""
                        set dataYList ""
                    }
                    # combine the two lists
                    set pvList $pvXList
                    set dataList $dataXList
                    foreach pv $pvYList {
                        lappend pvList $pv
                    }
                    foreach bp $dataYList {
                        lappend dataList $bp
                    }
                }
            }
        }
    }
    if ![llength $pvList] {
        SetMainStatus "No transfers done."
        return
    }
    foreach pv $pvList datum $dataList {
        lappend commandOptList $pv=$datum
    }
   
    if $zero {
        # Just send zeros to all the items on the list
        if [catch {exec cavput -pend=120 -list=[join $commandOptList ,]} result] {
            SetMainStatus "$result"
        }
    } else {
        # Add the ErrorCC to the setpoints or offsets
        if [catch {exec cavput -pend=120 -list=[join $commandOptList ,] -deltaMode} result] {
            SetMainStatus "$result"
        }
    }
    SetMainStatus "Done."
}

proc ChangeSCDU {suffix state} {
    #set BPMsToChange [IndividualBPMsSelected -excludeP0s 1 -excludeXray 1\
     #                   -useWildcard {[AB]P[12345]}]
    set BPMsToChange [SelectedBPMList -excludeP0s 1 -excludeIDXray 1 -excludeFPGA 1 \
                        -excludeBMXray 1 -electronicsType Monopulse]  
   
    set count [llength $BPMsToChange] 
    if {$count==0} {
        SetMainStatus "No valid BPMs selected---SCDU settings not changed/queried."
        return
    }
    
    if [string compare $state __query__]!=0 {
        SetMainStatus "Changing $count BPMs...[exec date +%H:%M:%S]"
        exec cavput -list=S=$state -list=[join $BPMsToChange ,] -list=:$suffix \
          -pend=120
    } else {
        SetMainStatus "Querying $count BPMs...[exec date +%H:%M:%S]"
        set query [exec cavget -list=S -list=[join $BPMsToChange ,] -list=:$suffix \
                     -pend=120 -label]
        SetMainStatus "$query"
    }
    SetMainStatus "Done."
}

proc ChangeMemScan {suffix state} {
    set excludeBMXray 0
    set xSuffixList [list ms:x:InUseBO]
    if [lsearch -exact $xSuffixList $suffix]!=-1 {
        set excludeBMXray 1
    }
    
    #set BPMsToChange [IndividualBPMsSelected -excludeP0s 0 -excludeXray 0 \
     #                   -excludeBMXray $excludeBMXray]
    set BPMsToChange [SelectedBPMList -excludeP0s 0 -excludeIDXray 0 -excludeBMXray $excludeBMXray -excludeFPGA 0]
    
    set count [llength $BPMsToChange] 
    if {$count==0} {
        SetMainStatus "No BPMs selected---memory scanner settings not changed/queried."
        return
    }
    if [string compare $state "__query__"]!=0 {
        SetMainStatus "Changing $count BPMs...[exec date +%H:%M:%S]"
        exec cavput -list=S=$state -list=[join $BPMsToChange ,] -list=:$suffix \
          -pend=120
    } else {
        SetMainStatus "Querying $count BPMs...[exec date +%H:%M:%S]"
        set query [exec cavget -list=S -list=[join $BPMsToChange ,] -list=:$suffix \
                     -pend=120 -label]
        SetMainStatus "$query"
    }
    SetMainStatus "Done."
}

proc ChangeIndivHistory {suffix state} {
    #set BPMsToChange [IndividualBPMsSelected -excludeP0s 1]
    #set BPMsToChange [IndividualBPMsSelected -excludeP0s 1 -excludeXray 1 \
                                        #  -useWildcard {[AB]P[12345]}]
    set BPMsToChange [SelectedBPMList -excludeP0s 1 -excludeIDXray 1 -excludeBMXray 1 \
                        -electronicsType Monopulse -excludeFPGA 1]
    set count [llength $BPMsToChange] 
    if {$count==0} {
        SetMainStatus "No valid BPMs selected---history settings not changed/queried."
        return
    }
    if [string compare $state __query__]!=0 {
        SetMainStatus "Changing $count BPMs...[exec date +%H:%M:%S]"
        exec cavput -list=S=$state -list=[join $BPMsToChange ,] -list=:$suffix \
          -pend=120
    } else {
        SetMainStatus "Querying $count BPMs...[exec date +%H:%M:%S]"
        set query [exec cavget -list=S -list=[join $BPMsToChange ,] -list=:$suffix \
                     -pend=120 -label]
        SetMainStatus "$query"
    }
    SetMainStatus "Done."
}


proc ChangeIndivTiming {suffix state} {
    global bpmList
    set selectedList ""
    
    set count 0
    for {set sector 1} {$sector<41} {incr sector} {
       # if {$sector==38} {
       #     continue
       # }
        set index 0
        foreach bpm $bpmList {
            #select only [AB]P[12345]
            if {![string match {*P[12345]} $bpm]} {
                continue
            }
            global S${sector}$bpm
            if [subst \$S${sector}$bpm] {
                lappend selectedList ${sector}:${suffix}${index}
                incr count
            }
            incr index
        }
    }
   
    SetMainStatus "Changing $count BPMs...[exec date +%H:%M:%S]"
    exec cavput -list=S:bpm=$state -list=[join $selectedList ,] \
      -pend=120
    SetMainStatus "Done."
}

proc SectorsSelected {args} {
    set excludeS38 0
    APSParseArguments {excludeS38}
    set selectedList ""
    for {set sector 1} {$sector<41} {incr sector} {
        if {$excludeS38 && $sector==38} {
            continue
        }
        global sectorsS${sector}Sector
        set name sectorsS${sector}Sector 
        if [set $name] {
            lappend selectedList ${sector}
        }
    }
    #puts $selectedList
    return $selectedList
}

proc ChangeSectorTiming {suffix state} {
    set selectedList [SectorsSelected]
    set count [llength $selectedList]
    set allowedList {1 3 5 7 9 11 13 15 17 19 21 23 25 27 \
                       29 31 33 35 36 37 38 39 40} 
    if {$count==0} {
        SetMainStatus "No sectors selected---timing not changed."
        return
    }
    SetMainStatus "Changing $count sectors...[exec date +%H:%M:%S]"
    if [string compare $suffix TimingModeMO]==0 {
        set selectedList1 ""
        foreach item $selectedList {
            if [lsearch -exact $allowedList $item]!=-1 {
                lappend selectedList1 $item
            }
        }
        set selectedList $selectedList1
        set count [llength $selectedList]
        if {$count==0} {
            SetMainStatus "No sectors selected---timing not changed."
            return
        }
        exec cavput -list=S=$state -list=[join $selectedList ,] -list=Bpm -list=:$suffix -pend=100
    } else {
        exec cavput -list=S=$state -list=[join $selectedList ,] -list=BpmTime -list=:$suffix \
          -pend=120
    }
    SetMainStatus "Done."
}

proc ChangeSectorBunchClock {suffix state} {
    set selectedList [SectorsSelected]
    set allowedList {1 3 5 7 9 11 13 15 17 19 21 23 25 27 \
                       29 31 33 35 36 37 38 39 40} 
    set selectedList1 ""
    foreach item $selectedList {
        if [lsearch -exact $allowedList $item]!=-1 {
            lappend selectedList1 $item
        }
    }
    set selectedList $selectedList1
    set count [llength $selectedList]
    if {$count==0} {
        SetMainStatus "No sectors selected---timing not changed."
        return
    }
    SetMainStatus "Changing $count sectors...[exec date +%H:%M:%S]"
    exec cavput -list=S=$state -list=[join $selectedList ,] -list=BpmBnchClkGen -list=$suffix \
      -pend=120
    SetMainStatus "Done."
}

proc ChangeSectorMemScan {suffix state} {
    set selectedList [SectorsSelected]
    if [lsearch -exact [list msAve:Num2AveAO mswAve:CoeffAO] $suffix]!=-1 {
       # set allowedList {1 3 5 7 9 11 13 15 17 19 21 23 25 27 \
                           29 31 33 35 36 37 39 40} 
        set allowedList [APSGetMonopulseBPMIOCList]
        set selectedList1 ""
        foreach item $selectedList {
            if [lsearch -exact $allowedList $item]!=-1 {
                lappend selectedList1 $item
            }
        }
        set selectedList $selectedList1
    }
    set count [llength $selectedList]
    if {$count==0} {
        SetMainStatus "No sectors selected---memory scanner not changed."
        return
    }
    SetMainStatus "Changing $count sectors to $state...[exec date +%H:%M:%S]"
    exec cavput -list=S:bpm=$state -list=[join $selectedList ,] -list=:$suffix -pend=120
    
    # do P0 iocs
    set allowedList {1 3 5 7 9 11 13 15 17 19 21 23 \
                       31 33 35} 
    set selectedList1 ""
    foreach item $selectedList {
        if [lsearch -exact $allowedList $item]!=-1 {
            lappend selectedList1 $item
        }
    }
    set selectedList $selectedList1
    if [llength $selectedList] {
        exec cavput -list=S:bpm=$state -list=[join $selectedList ,] -list=P0:$suffix -pend=120
    }
    # do Xray iocs
    set allowedList {1 3 5 7 9 11 13 15 17 19 21 \
                       33 35} 
    set selectedList1 ""
    foreach item $selectedList {
        if [lsearch -exact $allowedList $item]!=-1 {
            lappend selectedList1 $item
        }
    }
    set selectedList $selectedList1
    if [llength $selectedList] {
        exec cavput -list=S:bpm=$state -list=[join $selectedList ,] -list=Xray:$suffix -pend=120
    }
    SetMainStatus "Done."
}

proc ChangeSectorHistory {suffix state} {
    set selectedList [SectorsSelected -excludeS38 1]
    set count [llength $selectedList]
    if {$count==0} {
        SetMainStatus "No sectors selected---history not changed."
        return
    }
    SetMainStatus "Changing $count sectors...[exec date +%H:%M:%S]"
    exec cavput -list=S:bh=$state -list=[join $selectedList ,] -list=:$suffix \
      -pend=120 
    SetMainStatus "Done."
}

proc ChangeMomboHistory {suffix state} {
    set selectedList [SectorsSelected -excludeS38 1]
    set count [llength $selectedList]
    if {$count==0} {
        SetMainStatus "No sectors selected---MOMBO not changed."
        return
    }
    SetMainStatus "Changing $count sectors...[exec date +%H:%M:%S]"
    exec cavput -list=S:bpm=$state -list=[join $selectedList ,] -list=:$suffix \
      -pend=120 
    SetMainStatus "Done."
}

proc MakeBPMSelectionWidget {widget args} {
    set parent ""
    if [APSStrictParseArguments {parent}]==-1 {
        return
    }
    APSFrame $widget -parent $parent -label "BPM Selection" \
      -contextHelp "BPM Selection Frame.  Press individual check buttons to select and deselect individual BPMs.  Use the 1/0/T buttons to control a sectors worth of BPMs together or to control all BPMs in a given position together.  The 1 button selects, the 0 button deselects, and the T button toggles."

    set w $parent$widget.frame
    APSFrame .f1 -parent $w -packOption "-side top"
    APSFrame .f2 -parent $w -packOption "-side top"

    set xList {}
    for {set sector 1} {$sector<41} {incr sector} {
        lappend xList s$sector
    }
    lappend xList all0 all1 all2
    global bpmList

    APSFrameGrid .fg -parent $w.f1.frame -xList $xList 
    set w $w.f1.frame.fg

    # make labels for columns (including sectors)
    for {set sector 1} {$sector<41} {incr sector} {
        APSLabel .legend -parent $w.s$sector \
          -text [format %02ld $sector] -packOption "-side top"
        $w.s$sector.legend.label configure \
          -font -adobe-courier-medium-r-normal-*-*-120-*-*-*-*-*-*
    }
    for {set all 0} {$all<3} {incr all} {
        APSLabel .label -parent $w.all$all -text "all"  -packOption "-side top" \
          -width 4
        $w.all$all.label.label configure \
          -font -adobe-courier-medium-r-normal-*-*-120-*-*-*-*-*-*
    }

    # make rows of check buttons, one row per BPM position
    set cbn 0
    set bpmNum 0 
    foreach bpm $bpmList {
        incr bpmNum
        for {set sector 1} {$sector<41} {incr sector} {
            # make individual button for this sector and BPM position
            global S${sector}$bpm
            set S${sector}$bpm 0
            APSStateButton .b$bpm -parent $w.s${sector} \
              -packOption "-side top" -text $bpm \
              -size small -variable S${sector}$bpm \
              -contextHelp "Selects/deselects operations for bpm $bpm of sector $sector."
            $w.s${sector}.b$bpm configure -bd 0
            $w.s${sector}.b$bpm.button configure -padx 0 
            if $bpmNum==[llength $bpmList] {
                # make buttons for sector-wide items
                APSStateButton .bGlobal -parent $w.s$sector \
                  -packOption "-side top" -text S \
                  -size small -variable S${sector}Global \
                  -contextHelp "Selects/deselects whole-sector operations for sector $sector."
                $w.s$sector.bGlobal configure -bd 0
                $w.s$sector.bGlobal.button configure -padx 0
                # make ganged buttons for the column (sector)
                APSButton .gang1 -parent $w.s$sector -text 1 -size small \
                  -command "SetBPMSector $w $sector 1" -packOption "-side top" \
                  -contextHelp "Selects all BPMs in sector $sector."
                APSButton .gang0 -parent $w.s$sector -text 0 -size small \
                  -command "SetBPMSector $w $sector 0" -packOption "-side top" \
                  -contextHelp "Deselects all BPMs in sector $sector."
                APSButton .gangt -parent $w.s$sector -text T -size small\
                  -command "ToggleBPMSector $w $sector" -packOption "-side top" \
                  -contextHelp "Toggles selection state for all BPMs in sector $sector."
                $w.s$sector.gang1 configure -bd 0
                $w.s$sector.gang0 configure -bd 0
                $w.s$sector.gangt configure -bd 0
            }
        }

        # make ganged buttons for the row (i.e., the BPM position)
        APSButton .set$bpmNum -parent $w.all0 -text 1 \
          -command "SetBPMPosition $w $bpm 1" -size small  -packOption "-side top" \
          -contextHelp "Selects all $bpm BPMs."
        APSButton .unset$bpmNum -parent $w.all1 -text 0 \
          -command "SetBPMPosition $w $bpm 0" -size small  -packOption "-side top" \
          -contextHelp "Deselects all $bpm BPMs."
        APSButton .toggle$bpmNum -parent $w.all2 -text T \
          -command "ToggleBPMPosition $w $bpm" -size small -packOption "-side top" \
          -contextHelp "Toggles selection state for all $bpm BPMs."
        $w.all0.set$bpmNum configure -bd 0
        $w.all1.unset$bpmNum configure -bd 0
        $w.all2.toggle$bpmNum configure -bd 0
    }

    # make ganged buttons for the row of global selection buttons
    APSButton .setGlobal -parent $w.all0 -text 1 \
      -command "SetGlobalSector $w 1" -size small -packOption "-side top" \
      -contextHelp "Sets all whole-sector selections."
    APSButton .unsetGlobal -parent $w.all1 -text 0 \
      -command "SetGlobalSector $w 0" -size small -packOption "-side top" \
      -contextHelp "Unsets all whole-sector selections."
    APSButton .toggleGlobal -parent $w.all2 -text T \
      -command "ToggleGlobalSector $w" -size small -packOption "-side top" \
      -contextHelp "Toggles  all whole-sector selections."
    $w.all0.setGlobal configure -bd 0
    $w.all1.unsetGlobal configure -bd 0
    $w.all2.toggleGlobal configure -bd 0

    set w0 $parent$widget.frame.f2.frame
    APSButton .all -parent $w0 -text "Select all" \
      -command "SetAllBPMSelects $w 1" 
    APSButton .none -parent $w0 -text "Deselect all" \
      -command "SetAllBPMSelects $w 0" 
    APSButton .toggle -parent $w0 -text "Toggle all" \
      -command "ToggleAllBPMSelects $w"
}

proc SetGlobalSector {widget value} {
    for {set sector 1} {$sector<41} {incr sector} {
        global S${sector}Global 
        set S${sector}Global $value
        if $value {
            $widget.s$sector.bGlobal.button configure -relief sunken
        } else {
            $widget.s$sector.bGlobal.button configure -relief raised
        }
    }
}

proc ToggleGlobalSector {widget} {
    for {set sector 1} {$sector<41} {incr sector} {
        global S${sector}Global 
        set value [expr ![subst \$S${sector}Global]]
        set S${sector}Global $value
        if $value {
            $widget.s$sector.bGlobal.button configure -relief sunken
        } else {
            $widget.s$sector.bGlobal.button configure -relief raised
        }
    }
}

proc SetAllBPMSelects {widgetRoot value} {
    for {set sector 1} {$sector<41} {incr sector} {
        SetBPMSector $widgetRoot $sector $value
    }
}

proc ToggleAllBPMSelects {widgetRoot} {
    for {set sector 1} {$sector<41} {incr sector} {
        ToggleBPMSector $widgetRoot $sector
    }
}


# Toggles settings of BPM selection for a sector
proc ToggleBPMSector {widgetRoot sector} {
    global bpmList
    foreach bpm $bpmList {
        global S${sector}$bpm
        set S${sector}$bpm [expr ![subst \$S${sector}$bpm]]
        set widget $widgetRoot.s$sector.b$bpm
        if  [subst \$S${sector}$bpm] {
            $widget.button configure -relief sunken
        } else {
            $widget.button configure -relief raised
        }
    }
}

# Changes settings of BPM selection for a sector
proc SetBPMSector {widgetRoot sector value} {
    global bpmList
    foreach bpm $bpmList {
        global S${sector}$bpm
        set S${sector}$bpm $value
        set widget $widgetRoot.s$sector.b$bpm
        if  [subst \$S${sector}$bpm] {
            $widget.button configure -relief sunken
        } else {
            $widget.button configure -relief raised
        }
    }
}

# Toggles settings of BPM selection for a position
proc ToggleBPMPosition {widgetRoot bpm} {
    for {set sector 1} {$sector<41} {incr sector} {
        global S${sector}$bpm 
        set S${sector}$bpm [expr ![subst \$S${sector}$bpm]]
        set widget $widgetRoot.s$sector.b$bpm
        if [subst \$S${sector}$bpm] {
            $widget.button configure -relief sunken
        } else {
            $widget.button configure -relief raised
        }
    }
}

# Changes settings of BPM selection for a position
proc SetBPMPosition {widgetRoot bpm value} {
    for {set sector 1} {$sector<41} {incr sector} {
        global S${sector}$bpm 
        set S${sector}$bpm $value
        set widget $widgetRoot.s$sector.b$bpm
        if $value {
            $widget.button configure -relief sunken
        } else {
            $widget.button configure -relief raised
        }
    }
}

proc SetMainStatus {text} {
    global mainStatus
    set mainStatus "$text"
    update
}


proc nonBpmfilter {plane} {
    set filename "/home/helios/oagData/sr/BPMStatus/config.sdds"
    if ![file exists $filename] {
        SetMainStatus "$filename for bmp's x or y plane's existence does not exist"
        return
    }
    if {![APSCheckSDDSFile -fileName $filename]} {
        SetMainStatus "$filename is not an SDDS file."
        return
    }
    set bpms [APSGetSDDSColumn -fileName $filename -column DeviceName]
    set noX [APSGetSDDSColumn -fileName $filename -column NonexistentH]
    set noY [APSGetSDDSColumn -fileName $filename -column NonexistentV]
    set xList ""
    set yList ""
    set total [llength $bpms]
    
    for {set i 0} {$i<$total} {incr i} {
        if ![lindex $noX $i] {
            lappend xList [lindex $bpms $i]
        }
        if ![lindex $noY $i] {
            lappend yList [lindex $bpms $i]
        }
    }
    switch $plane {
        x {
            return $xList
        }
        y {
            return $yList
        }
        default {
            return
        }
    }
}

proc getnonBpm {olist plane} {
    set list [nonBpmfilter $plane]
    set validList ""
    foreach bpm $olist {
        if [string match *$bpm* $list] {
            lappend validList $bpm
        }
    }
    return $validList
}

proc MakeBPMSelectionFrame {widget args} {
    set parent ""
    global plane
    APSStrictParseArguments {parent}
    global rootname
    set rootname ""
    switch $plane {
        h {
            set rootname hconfig
        }
        v {
            set rootname vconfig
        }
        default {
            return -code error "The plane has to be h or v"
        }
    }
    set rootname vconfig
    if [winfo exist $parent$widget] {
        destroy $parent$widget
    }
    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 ID:P1 ID:P2 BM:P1 BM:P2]
    
    set BPMMissingList [APSGetMissingBPMList -plane $plane]
    set includeP0s 1
    set includeIDs 1
    set includeBMs 1
    
    pack [frame $parent$widget]
    APSFrame .up -parent $parent$widget
    APSRadioButtonFrame .choosePlane -variable plane -valueList {h v} -buttonList {h v} \
	-parent $parent$widget.up.frame -orientation vertical -packOption "-side left" -label "Plane" \
	-commandList {"setbpmPlane h" "setbpmPlane v"}
    
    #make file frame 
    APSFrame .read -parent $parent$widget.up.frame \
      -contextHelp "Use this frame to read combine bpms."
    set w0 $parent$widget.up.frame.read.frame
    global ${rootname}ReadFile ${rootname}ReadDescription ${rootname}Plane
    global ${rootname}FilterEnd1 ${rootname}MainDir ${rootname}LatSubDir ${rootname}Lattice
    set ${rootname}Plane $plane
    set ${rootname}ReadFile ${plane}.default
    set ${rootname}ReadDescription ""
    set ${rootname}FilterEnd1 .*
    set ${rootname}MainDir /home/helios/oagData/sr/orbitControllaw
    set ${rootname}LatSubDir lattices
    set ${rootname}Lattice default
    APSFrameGrid .grid -parent $w0 -xList {x1 x2}
    set w1 $w0.grid.x1
    set w2 $w0.grid.x2
    APSLabeledEntry .maindir -parent $w1 -label "Main directory: " \
      -textVariable ${rootname}MainDir -width 50 -contextHelp \
      "Enter the name of the main directory for the orbit correction system."
    APSFileSelectWidget .lattice -parent $w1 -label "Lattice: " \
      -pathVariableList [list ${rootname}MainDir ${rootname}LatSubDir] -mode directory -width 50 \
      -variable ${rootname}Lattice -incrementButtons 0 -contextHelp \
      "Enter the name of the lattice with which to work."
    APSFileSelectWidget .file -parent $w1 -variable ${rootname}ReadFile -label "Config: " \
      -pathVariableList [list ${rootname}MainDir ${rootname}LatSubDir ${rootname}Lattice] \
      -mode directory -filterVariableList \
      [list ${rootname}Plane ${rootname}FilterEnd1] -width 50 \
      -incrementButtons 1 -contextHelp \
      "Enter the name of the configuration file to read."
    
    APSButton .io0 -parent $w2 -text Read(replace) -size small -packOption "-side top" -command \
	"APSReadOrbitCorrectionConfig -rootname $rootname -filename \$${rootname}MainDir/\$${rootname}LatSubDir/\$${rootname}Lattice/\$${rootname}ReadFile/config -logic replace -includeP0s $includeP0s -includeIDs $includeIDs -includeBMs $includeBMs -nameTypeList Monitor" \
	-contextHelp "Press to read data to replace the existing configuration, using the named configuration file."
    APSButton .io1 -parent $w2  -text Read(or) -size small -packOption "-side top" -command \
	"APSReadOrbitCorrectionConfig -rootname $rootname -filename \$${rootname}MainDir/\$${rootname}LatSubDir/\$${rootname}Lattice/\$${rootname}ReadFile/config -logic or -includeP0s $includeP0s -includeIDs $includeIDs -includeBMs $includeBMs -nameTypeList Monitor" \
	-contextHelp "Press to read data to or with the existing configuration, using the named configuration file."
    APSButton .io2 -parent $w2 -text Read(and) -size small -packOption "-side top" -command \
	"APSReadOrbitCorrectionConfig -rootname $rootname -filename \$${rootname}MainDir/\$${rootname}LatSubDir/\$${rootname}Lattice/\$${rootname}ReadFile/config -logic and -includeP0s $includeP0s -includeIDs $includeIDs -includeBMs $includeBMs -nameTypeList Monitor" \
	-contextHelp "Press to read data to and with the existing configuration, using the named configuration file." 
    APSButton .io3 -parent $w2 -text Read(not) -size small -packOption "-side top"  -command \
	"APSReadOrbitCorrectionConfig -rootname $rootname -filename \$${rootname}MainDir/\$${rootname}LatSubDir/\$${rootname}Lattice/\$${rootname}ReadFile/config -logic not -includeP0s $includeP0s -includeIDs $includeIDs -includeBMs $includeBMs -nameTypeList Monitor" \
	-contextHelp "Press to read data specifying elements to turn off, using the named configuration file."
    #make cheack button frame
    APSFrame .but -parent $parent$widget 
    set w2 $parent$widget.but.frame
    
    APSSRMonitorCheckButtons .smbut -parent $w2 -rootname $rootname -noLabel 1 -sectorControl 1 \
      -orientation horizontal -packOption "-side left" -includeP0s 1 -includeIDs 1 -includeBMs 1 
}

#note this Plane is only for configuration files 

proc SelectedBPMList {args} {
    global Plane
    global rootname
    set sectorCount 40
    set excludeP0s 0
    set excludeIDXray 0
    set excludeBMXray 0
    set excludeFPGA 0
    set electronicsType *
    set useWildcard ""
    APSParseArguments {excludeP0s excludeIDXray useWildcard excludeBMXray electronicsType excludeFPGA}
    set BPMSuffixList [list A:P1 A:P2 A:P3 A:P4 B:P5 B:P4 B:P3 B:P2 B:P1]
    set excludeSuffix ""
    if !$excludeP0s {
        set BPMSuffixList [concat A:P0 $BPMSuffixList B:P0 C:P0]
    } else {
        lappend excludeSuffix A:P0 B:P0 C:P0
    }
    if !$excludeIDXray {
        set BPMSuffixList [concat $BPMSuffixList ID:P1 ID:P2]
    } else {
        lappend excludeSuffix ID:P1 ID:P2
    }
    if !$excludeBMXray {
        set BPMSuffixList [concat $BPMSuffixList BM:P1 BM:P2]
    } else {
        lappend excludeSuffix BM:P1 BM:P2
    }
    set AllowedByElectronicsList ""
    if [string compare $electronicsType *]!=0 {
        if [catch {exec sddsprocess /home/helios/oagData/sr/BPMStatus/config.sdds -pipe=out \
                     -match=column,ElectronicsType=$electronicsType \
                     | sdds2stream -pipe -column=DeviceName} AllowedByElectronicsList] {
            SetMainStatus "Unable to get list of BPMs with electronics $electronicsType"
            return ""
        }
    }
    if $excludeFPGA {
        global FPGAbpmList
        if ![info exist FPGAbpmList] {
            if [catch {exec sddsprocess /home/helios/oagData/sr/BPMStatus/config.sdds -pipe=out \
                         -match=column,ElectronicsType=FPGA \
                         | sdds2stream -pipe -column=DeviceName} FPGAbpmList] {
                SetMainStatus "Unable to get list of BPMs with electronics FPGA"
                return ""
            }
        }
    }
    set names ""
    for {set sector 1} {$sector<=$sectorCount} {incr sector} {
        foreach exSuffix $excludeSuffix {
            set nameFlagx1 ${rootname}S${sector}$exSuffix
            global $nameFlagx1
          #  set $nameFlagx1 0
        }
        foreach suffix $BPMSuffixList {
            set nameFlagx ${rootname}S${sector}${suffix}
            global $nameFlagx 
            if {$useWildcard != "" && ![string match $useWildcard $suffix]} {
              #  set $nameFlagx 0
                continue
            }           
            if [set $nameFlagx] {
                if {![llength $AllowedByElectronicsList] || \
                      [lsearch -exact $AllowedByElectronicsList S${sector}${suffix}]!=-1} {
                    if $excludeFPGA {
                        if [lsearch -exact $FPGAbpmList S${sector}${suffix}]<0 {
                            lappend names ${sector}$suffix
                        }
                    } else {
                        lappend names ${sector}$suffix
                    }
                }
            }
        }
    }
    #puts $names
    return $names
}

proc setbpmPlane {value} {
    global plane rootname
    global ${rootname}ReadFile ${rootname}ReadDescription ${rootname}Plane
    global ${rootname}FilterEnd1 ${rootname}MainDir ${rootname}LatSubDir ${rootname}Lattice
    
    switch $value {
	h {
	    set plane h
	}
	v {
	    set plane v
	}
    }
    set ${rootname}Plane $plane
    set ${rootname}ReadFile ${plane}.default
    set ${rootname}ReadDescription ""
    set ${rootname}FilterEnd1 .*
    return
}

proc MakeSectorSelectionFrame {widget args} {
    set parent ""
    #the variable name is sectorsS${sector}Sector
    APSStrictParseArguments {parent}
    pack [frame $parent$widget]
    APSSRSectorButtons .sectorButtons -parent $parent$widget -rootname sectors \
	-orientation horizontal \
	-label "" -description "Sector selections" \
	-itemList Sector -packOption "-side top" \
	-itemLabelList Sector 
}

set mainStatus "Working..."
APSScrolledStatus .status -parent .userFrame -textVariable mainStatus -width 80 \
  -height 4
update

set tableList [list bpmSelection sectorSelection]
set widgetList [APSTabFrame .controls -parent .userFrame -labelList $tableList -width 1110 -height 540]
set frame1 [lindex $widgetList 0]
set frame2 [lindex $widgetList 1]
set plane v
MakeBPMSelectionFrame .bpm -parent $frame1 
MakeSectorSelectionFrame .sector -parent $frame2
update
APSFrameGrid .opsfg -parent .userFrame -packOption "-side top" \
  -xList {left right}
MakeIndividualOpsWidget .indivOps -parent .userFrame.opsfg.left
update
MakeSectorOpsWidget .sectorOps -parent .userFrame.opsfg.right
update

SetMainStatus "Ready."
