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

#
# $Log: not supported by cvs2svn $
# Revision 1.46  2008/07/22 15:57:55  shang
# added "Toggle BPM Permission" button to reset the access mode so that qualified users can have write permission to BPLD pvs (the write permission was disabled after ioc reboots)
#
# Revision 1.45  2005/10/26 04:01:41  emery
# Removed Shang's tcl library in auto_path.
#
# Revision 1.44  2003/12/17 19:12:37  shang
# the calibration factor is replaced the real value of gain PVs obtained from
# UBOP reference file and the color of the readback or setpoint and download entry
# to red together with the apply button if the difference between readback (or setpoint)
# and download is greater than the tolerance.
#
# Revision 1.43  2003/10/29 21:57:48  shang
# fixed the problem that the "apply" button became red only the difference of
# all four limits exceeded the tolerance, now it is read if at least one of them exceeds
# the tolerance.
#
# Revision 1.42  2003/10/02 16:30:10  shang
# changed the default tolerance from 0.03 to 0.1
#
# Revision 1.41  2003/09/16 19:29:05  emery
# Fixed the applying of setpoints to DBPLD limits with P1s.
# Use arrays firstChannelBPM and secondChannelBPM in
# ApplySetpoints.
#
# Revision 1.40  2003/09/15 18:30:00  emery
# Use global variables firstChannelBPM secondChannelBPM in procedure to
# create pv links. Since variable digitalPVs is no longer needed,
# it was deleted.
#
# Revision 1.39  2003/09/15 17:07:07  emery
# Initial some lists to "" before lappend loop in CheckLockStatus
# to prevent errors when not all pv channels are available.
#
# Revision 1.38  2003/08/07 15:17:09  shang
# the digital pv now is obtained from config file; added Brief view which only
# displays the difference between setpoint and download values
#
# Revision 1.37  2003/07/24 22:32:54  emery
# Replaced hard-coded P0 string in PV names with variable
# bpmType. This will have to be changed next shutdown when
# P1's will be nbBPMs and be connected to digital BPLDs.
#
# Revision 1.36  2002/08/20 18:41:36  emery
# Added some bells to alert when bpld is unlocked.
#
# Revision 1.35  2001/12/04 20:42:35  emery
# Changed the umon of the lock status PVs to a polling of these PVs.
# Aplication no longer locks up.
#
# Revision 1.34  2001/07/30 08:00:01  emery
# Fixed a problem in proc CheckLockStatus where the
# array variable had the element sector instead of $sector.
#
# Revision 1.33  2001/07/26 22:02:59  emery
# Added umons for digital bpld readbacks.
#
# Revision 1.32  2001/05/15 15:59:39  emery
# Fixed checking lock status of dbpld.
#
# Revision 1.31  2001/05/04 18:45:54  emery
# Added DBPLD setpoints readbacks.
#
# Revision 1.30  2001/02/26 19:49:13  emery
# Introduced a tolerance variable for checking readbacks versus setpoints.
#
# Revision 1.29  2000/07/19 21:21:20  emery
# Added digital BPLDs. Configuration taken from
# new column IsDigital of file sectors.sdds.
# The BPLD is either digital or not. FO rthe digital
# BPLD there are two rows per sector, and the readback
# of the limits are absent because they don't exist.
# Reworked the widget for the P0, P1, P2 bpm
# default limits to use label entry frames so that
# H and V plane values are side by side.
#
# Revision 1.28  2000/06/06 10:40:42  emery
# Added entries to modify the default limits for P1 and P2 bpms.
# Added command to change the DRVH and DRVL limits.
#
# Revision 1.27  1999/07/25 15:44:02  emery
# changed limits to ID4 to reflect the internal bump angles.
#
# Revision 1.26  1999/07/01 23:03:53  emery
# Use multiple-list foreach statement for assigned values to
# firstChannelBPM and secondChannelBPM.
#
# Revision 1.25  1999/05/17 19:12:56  emery
# Chaged the list of sectors that uses P1s to 32, 33, and 35.
#
# Revision 1.24  1999/04/19 18:44:05  emery
# Improved error message for ca connection error for BPLD PVs.
#
# Revision 1.23  1999/02/03 20:53:47  emery
# Changed background color to labeled entries
# of the four middle columns of table to make
# it easier to compare values between readbacks and setpoints.
#
# Revision 1.22  1999/02/03 02:05:19  emery
# Added sector 34 as a sector using P1 bpms.
#
# Revision 1.21  1999/01/22 16:14:10  emery
# Highlight for APPLY button is now done correctly
# when a second file is read.
#
# Revision 1.20  1999/01/19 16:57:57  borland
# Now highlights the apply button if the setpoint or readback is different from
# the computation by 0.01mm
#
# Revision 1.19  1999/01/19 12:09:54  emery
# Made fancy scroll window for entering different real orbit limits
# for each ID. Moved read offset button to a separate action frame.
#
# Revision 1.18  1999/01/19 10:30:25  emery
# Removed the last modifications for the ID33 and ID35 limits special cases,
# and added different modifications for the ID33 and ID35 special cases
# that take into account that offset avlues for ID33 and ID35
# must be taken from from P1 bpms.
#
# Revision 1.16  1998/01/10 10:56:23  emery
# Replaced name BPMOffsetBeamReference with BPMOffsetReference
#
# Revision 1.15  1998/01/10 10:44:02  emery
# Changed the default reference file
# to BPMOffsetBeamReference
#
# Revision 1.14  1997/05/29 17:02:26  emery
# Fixed the order of table labels.
#
# Revision 1.13  1997/05/23 11:32:34  emery
# Removed dialog windows in favor of large table
# of BPLD trip limit data. Apply button
# is highlighted in red when the present trip limits differ from
# values to download.
# The default offset file is read in and processed immediately
# before the trip limit table is created.
#
# Revision 1.12  1997/01/15 16:26:31  emery
# Removed the ApplySetpoint procedure from the
# CheckLockStatus procedure. This removes nested
# ca callback routines which caused us problems.
#
# Revision 1.11  1996/12/11 22:54:18  borland
# Changed SR-Reference to SR-UserBeamReference, since the latter is not a valid
# reference file anymore!
#
# Revision 1.10  1996/10/17 19:43:56  borland
# Fixed some erroneous labels.
#
# Revision 1.9  1996/10/08 17:27:37  borland
# Added proper CVS header.
#
#

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.47 $ \$Author: shang $"


APSApplication . -name "SRBPLDLimitsLoading" -version $CVSRevisionAuthor \
        -overview "SRBPLDLimitsLoading calculates the BPLD trip limits from a file of offsets and downloads the limits.\n\nP2 bpms are used for BPLDs."

set SRBPLDLoadingStatus "Initializing ..."
APSScrolledStatus .status -parent .userFrame -width 60 \
        -textVariable SRBPLDLoadingStatus

proc SetSRBPLDLoadingStatus {text} {
    global SRBPLDLoadingStatus
    set SRBPLDLoadingStatus $text
    update
    bell
}

proc MakeOptionFrame {widget args} {
    global snapFile
    global BPLDList xLimit yLimit xLimitMax yLimitMax 
    APSParseArguments {parent}

    set w $parent$widget
    APSFrame $widget -parent $parent -label "" \
      -contextHelp "Frame to specify options for automatically downloading adjusted BPLD trip limits."
    $w.frame  configure -relief flat -bd 0
    APSFrame .options -parent $w.frame -label "Options" \
      -packOption "-side left" \
      -contextHelp "Frame to specify options for automatically downloading adjusted BPLD trip limits."
    APSFrame .limits -parent $w.frame -label "Real Orbit Limits" \
      -contextHelp "Frame to view or enter real orbit limits. After making a change to a value, press the READ OFFSET button for a re-calculation."

    set w $parent$widget.frame.options
    APSLabeledEntry .snapFile -parent $w.frame -label "SR snap file" \
      -textVariable snapFile -width 30 \
      -contextHelp "Enter the file from which the BPM offsets are taken."
#    APSButton .readOffsets -parent $w.frame.snapFile -text "READ OFFSETS" \
      -command {ReadOffsets} -contextHelp \
      "Reads the bpm offsets from the SR snap file selected, and determines the values of the trip limits for the BPLDs."


    set labelWidth 40
    APSLabeledEntryFrame .limitMax -parent $w.frame \
      -label [format %-${labelWidth}s "BPM digitizer H/V maximums for BPLD (mm)"] \
      -variableList {xLimitMax yLimitMax} -width 10 -orientation horizontal \
      -contextHelp "Enter the maximum allowed value for the BPLD limit for the horizontal and vertical planes. This is due to the digitizing limit of the bpm system."

    foreach bpm {P0 P1 P2} {
        APSLabeledEntryFrame .limit$bpm -parent $w.frame \
          -label [format %-${labelWidth}s "BPLD H/V ranges for $bpm (mm)"] \
          -variableList "xLimitNormal($bpm) yLimitNormal($bpm)" -width 10 -orientation horizontal \
          -contextHelp "Enter the maximum allowed value for the $bpm BPLD limit."
    }
    APSLabeledEntry .page -parent $w.frame -label "pager numbers (space-separated)" \
      -textVariable pagerNumbers -width 30 \
      -contextHelp "Enter a list of email pager numbers to be notified when settings are changed.  Used to inform operators when to move to another location." 
    APSLabeledEntry .tol -parent $w.frame -label "tolerance" \
      -textVariable tolerance -width 30 \
      -contextHelp "the warning threshold of the difference between setpoint and download values, the apply becomes read if the difference is bigger than the tolerance"
    set w $parent$widget.frame.limits
    label $w.frame.label  -text "  x (mm)  y (mm)"
    pack $w.frame.label  -side top
    set wscroll [APSScroll .scroll -parent $w.frame \
                   -contextHelp "Real orbit limits for each sector"]
    foreach sector $BPLDList {
        set sectorWidget $wscroll.s$sector.frame
        APSFrame .s$sector -parent $wscroll -height 20 \
          -packOption "-side top"
        $sectorWidget configure -relief flat -bd 0
        label $sectorWidget.label -text "$sector" -width 2 -pady 2
        pack  $sectorWidget.label -side left -fill x
        APSLabeledEntry .xLimit -parent $sectorWidget \
          -label ""  -width 6 \
          -packOption {-padx 0 -pady 0 -side left} \
          -textVariable xLimit($sector)
        APSLabeledEntry .yLimit -parent $sectorWidget \
          -label ""  -width 6 \
          -packOption {-padx 0 -pady 0 -side left} \
          -textVariable yLimit($sector)
#        $sectorWidget.xLimit.entry configure -relief flat -bd 0
#        $sectorWidget.yLimit.entry configure -relief flat -bd 0
        set lastWidget $sectorWidget
    }
    tkwait visibility $lastWidget 
    APSScrollAdjust $w.frame.scroll -numVisible 6
 
    return 0
}

proc MakeSectorsTable {widget args} {
    global BPLDList firstChannelBPM secondChannelBPM IsDigitalList 
    global OffsetRead
    global xHiAO xLoAO yHiAO yLoAO xHiAI xLoAI yHiAI yLoAI
    global xHiDownload xLoDownload yHiDownload yLoDownload applyButtonWidget
    global LockStatus errorCode brief
    
    set switch 0
    set parent ""
    APSParseArguments {parent switch}
    
   
    after 1000 "CheckLockStatus"
    foreach sector $BPLDList isDigital $IsDigitalList {
        if {!$isDigital} {
            if {[pv linkw \
                   [list xHiAO($sector) xLoAO($sector) yHiAO($sector) yLoAO($sector) \
                      xHiAI($sector) xLoAI($sector) yHiAI($sector) yLoAI($sector) \
                      LockStatus($sector)] \
                   [list S${sector}BPLD:xUpTripLimitAO S${sector}BPLD:xLowTripLimitAO \
                      S${sector}BPLD:yUpTripLimitAO S${sector}BPLD:yLowTripLimitAO \
                      S${sector}BPLD:xUpTripLimitAI S${sector}BPLD:xLowTripLimitAI \
                      S${sector}BPLD:yUpTripLimitAI S${sector}BPLD:yLowTripLimitAI \
                      S${sector}BPLD:limitsLockBI]] != 0} {
                APSAlertBox .alert -errorMessage "Problem with connecting with \
                  S${sector}BPLD:xUpTripLimitAO S${sector}BPLD:xLowTripLimitAO \
                  S${sector}BPLD:yUpTripLimitAO S${sector}BPLD:yLowTripLimitAO \
                  S${sector}BPLD:xUpTripLimitAI S${sector}BPLD:xLowTripLimitAI \
                  S${sector}BPLD:yUpTripLimitAI S${sector}BPLD:yLowTripLimitAI or\
                  S${sector}BPLD:limitsLockBI:$errorCode"
                return 1
            }
        } else {
            # if digital then bpms can be named P0 or P1.
            set sector1 [expr $sector + 1]
            set Bbpm $firstChannelBPM($sector)
            set Abpm $secondChannelBPM($sector)
            if {[pv linkw \
                   [list xHiAO(${sector}u) xLoAO(${sector}u) yHiAO(${sector}u) yLoAO(${sector}u) \
                      xHiAI(${sector}u) xLoAI(${sector}u) yHiAI(${sector}u) yLoAI(${sector}u) \
                      LockStatus(${sector}u) \
                      xHiAO(${sector}d) xLoAO(${sector}d) yHiAO(${sector}d) yLoAO(${sector}d) \
                      xHiAI(${sector}d) xLoAI(${sector}d) yHiAI(${sector}d) yLoAI(${sector}d) \
                      LockStatus(${sector}d)] \
                   [list ${Bbpm}:dbpld:xhiAO ${Bbpm}:dbpld:xloAO \
                      ${Bbpm}:dbpld:yhiAO ${Bbpm}:dbpld:yloAO \
                      ${Bbpm}:dbpld:xhiAI ${Bbpm}:dbpld:xloAI \
                      ${Bbpm}:dbpld:yhiAI ${Bbpm}:dbpld:yloAI \
                      ${Bbpm}:dbpld:xlockBI \
                      ${Abpm}:dbpld:xhiAO ${Abpm}:dbpld:xloAO \
                      ${Abpm}:dbpld:yhiAO ${Abpm}:dbpld:yloAO \
                      ${Abpm}:dbpld:xhiAI ${Abpm}:dbpld:xloAI \
                      ${Abpm}:dbpld:yhiAI ${Abpm}:dbpld:yloAI \
                      ${Abpm}:dbpld:xlockBI ]] != 0} {
                APSAlertBox .alert -errorMessage "Problem with connecting with \
                  ${Bbpm}:dbpld:xhiAO ${Bbpm}:dbpld:xloAO \
                  ${Bbpm}:dbpld:yhiAO ${Bbpm}:dbpld:yloAO \
                  ${Bbpm}:dbpld:xlockBI \
                  ${Abpm}:dbpld:xhiAO ${Abpm}:dbpld:xloAO \
                  ${Abpm}:dbpld:yhiAO ${Abpm}:dbpld:yloAO \
                  ${Abpm}:dbpld:xlockBI:$errorCode"
                return 1
            }
        }

        if {!$isDigital} {
#            if {[pv umon LockStatus($sector) "CheckLockStatus -sector $sector" ] != 0} {
#                APSAlertBox .alert -errorMessage "$errorCode"
#                return 1
#            }
            if {[pv umon xHiAO($sector)] != 0} {
                APSAlertBox .alert -errorMessage "$errorCode"
                return 1
            }
            if {[pv umon xLoAO($sector)] != 0} {
                APSAlertBox .alert -errorMessage "$errorCode"
                return 1
            }
            if {[pv umon yHiAO($sector)] != 0} {
                APSAlertBox .alert -errorMessage "$errorCode"
                return 1
            }
            if {[pv umon yLoAO($sector)] != 0} {
                APSAlertBox .alert -errorMessage "$errorCode"
                return 1
            }
            if {[pv umon xHiAI($sector)] != 0} {
                APSAlertBox .alert -errorMessage "$errorCode"
                return 1
            }
            if {[pv umon xLoAI($sector)] != 0} {
                APSAlertBox .alert -errorMessage "$errorCode"
                return 1
            }
            if {[pv umon yHiAI($sector)] != 0} {
                APSAlertBox .alert -errorMessage "$errorCode"
                return 1
            }
            if {[pv umon yLoAI($sector)] != 0} {
                APSAlertBox .alert -errorMessage "$errorCode"
                return 1
            }
            set rowLabel($sector) $sector
        } else {
            foreach channel {u d} {
#                if {[pv umon LockStatus($sector$channel) "CheckLockStatus -sector $sector$channel" ] != 0} {
#                    APSAlertBox .alert -errorMessage "$errorCode"
#                    return 1
#                }
                if {[pv umon xHiAO($sector$channel)] != 0} {
                    APSAlertBox .alert -errorMessage "$errorCode"
                    return 1
                }
                if {[pv umon xLoAO($sector$channel)] != 0} {
                    APSAlertBox .alert -errorMessage "$errorCode"
                    return 1
                }
                if {[pv umon yHiAO($sector$channel)] != 0} {
                    APSAlertBox .alert -errorMessage "$errorCode"
                    return 1
                }
                if {[pv umon yLoAO($sector$channel)] != 0} {
                    APSAlertBox .alert -errorMessage "$errorCode"
                    return 1
                }
                if {[pv umon xHiAI($sector$channel)] != 0} {
                    APSAlertBox .alert -errorMessage "$errorCode"
                    return 1
                }
                if {[pv umon xLoAI($sector$channel)] != 0} {
                    APSAlertBox .alert -errorMessage "$errorCode"
                    return 1
                }
                if {[pv umon yHiAI($sector$channel)] != 0} {
                    APSAlertBox .alert -errorMessage "$errorCode"
                    return 1
                }
                if {[pv umon yLoAI($sector$channel)] != 0} {
                    APSAlertBox .alert -errorMessage "$errorCode"
                    return 1
                }
                set rowLabel($sector$channel) $sector$channel
            }
        }
    }
    
    APSFrame $widget -parent $parent -packOption "-expand 1 -fill both" \
      -label ""  -contextHelp {Table of BPLD data.}
    set tabWidget [APSTabFrame .views -parent $parent$widget.frame -label "" \
                     -labelList "Brief Full" -width 1000 -height 300 \
                    -packOption "-fill y -expand true" ]
    pack $parent$widget.frame.views -side top
    set w1 [lindex $tabWidget 0]
    set w2 [lindex $tabWidget 1]
    $parent$widget.frame.views.frame.tn select 0
    MakeSectorsView -parent $w1 -brief 1
    $parent$widget.frame.views.frame.tn select 1
    MakeSectorsView -parent $w2 -brief 0
}

proc MakeSectorsView {args} {
    global BPLDList IsDigitalList
    global OffsetRead
    global xHiAO xLoAO yHiAO yLoAO xHiAI xLoAI yHiAI yLoAI
    global xHiDownload xLoDownload yHiDownload yLoDownload applyButtonWidget
    global LockStatus errorCode brief

    set parent ""
    set brief 0
    
    APSParseArguments {parent brief}
    
    # Create labels for data table
    set prefixes {xLo xHi yLo yHi}
    set prefixHelp(xLo) "Lower horizontal limit"
    set prefixHelp(yLo) "Lower vertical limit"
    set prefixHelp(xHi) "Upper horizontal limit"
    set prefixHelp(yHi) "Upper vertical limit"
    set suffixes {AO AI Download}
    set suffixHelp(AO) " EPICS setpoint"
    set suffixHelp(AI) " EPICS readback"
    set suffixHelp(Download) " to download"
    set columns ""
    foreach suffix $suffixes {
        if ![string compare $suffix AI] {
            set backgroundColor grey95
        } else {
            set backgroundColor white
        }
        foreach prefix $prefixes {
            set columns [lappend columns $prefix$suffix]
            set color($prefix$suffix) $backgroundColor
            set contextHelpCol($prefix$suffix) "$prefixHelp($prefix)$suffixHelp($suffix)"
        }
    }
    foreach prefix $prefixes {
        set color(${prefix}Diff) white
        set contextHelpCol(${prefix}Diff) "$prefixHelp($prefix) difference)"
    }
    
    APSFrame .colLabel1 -parent $parent -packOption "-side top -fill x"
    $parent.colLabel1.frame configure -relief flat -bd 0
    label $parent.colLabel1.frame.blank1 -text "" -width 3
    pack $parent.colLabel1.frame.blank1 -side left
    if !$brief {
        label $parent.colLabel1.frame.labelAO -text "EPICS setpoints" 
        label $parent.colLabel1.frame.labelAI -text "EPICS readbacks"
        label $parent.colLabel1.frame.labelDown -text "Values to download" 
        pack $parent.colLabel1.frame.labelAO \
          $parent.colLabel1.frame.labelAI \
          $parent.colLabel1.frame.labelDown \
          -side left -expand true
        set wid1 4
    } else {
        label $parent.colLabel1.frame.labelDiff -text "Difference between setpoint and download value" 
        pack $parent.colLabel1.frame.labelDiff -side left 
        set wid1 5
    }
    label $parent.colLabel1.frame.blank2 -text "" -width 12 
    pack $parent.colLabel1.frame.blank2 -side left

    APSFrame .colLabel2 -parent $parent -packOption "-side top -fill x"
    $parent.colLabel2.frame configure -relief flat -bd 0
    label $parent.colLabel2.frame.blank -text "" -width $wid1 
    pack $parent.colLabel2.frame.blank -side left
    set colLabel "x Lo   x Up   y Lo   y Up"
    label $parent.colLabel2.frame.label1 -text $colLabel 
    if !$brief {
        label $parent.colLabel2.frame.label2 -text $colLabel 
        label $parent.colLabel2.frame.label3 -text "$colLabel     "
        pack $parent.colLabel2.frame.label1 $parent.colLabel2.frame.label2 \
          $parent.colLabel2.frame.label3  -side left -expand true
        
    } else {
        pack $parent.colLabel2.frame.label1  -side left 
    }
    label $parent.colLabel2.frame.blank2 -text "" -width 10
    pack $parent.colLabel2.frame.blank2 -side left
    label $parent.colLabel2.frame.blank3 -text "" -width 5
    pack $parent.colLabel2.frame.blank3 -side left
    
    # rows of sector widgets
    global wscrollFull wscrollBrief
    set wscroll [APSScroll .scroll -parent $parent -packOption "-expand 1 -fill both" \
                   -contextHelp "View sectors orbit scan results"]
    if $brief {
        set wscrollBrief $wscroll
    } else {
        set wscrollFull $wscroll
    }
    if $brief {
        set columns ""
        foreach prefix $prefixes {
            lappend columns ${prefix}Diff
        }
        set ext brief
    } else {
        set ext full
    }
    foreach sector $BPLDList isDigital $IsDigitalList {
        if {!$isDigital} {
            set sectorWidget $wscroll.s$sector.frame
            APSFrame .s$sector -parent $wscroll -height 20 \
              -packOption "-side top"
            $sectorWidget configure -relief flat -bd 0
            label $sectorWidget.label -text "$sector" -width 2 -pady 2
            pack  $sectorWidget.label -side left -fill x 
            
            foreach col $columns {
                APSLabeledOutput .$col -parent $sectorWidget \
                  -label ""  -width 6 \
                  -packOption {-padx 0 -pady 0 -side left} \
                  -textVariable ${col}($sector) 
                $sectorWidget.$col.entry configure -relief flat -bd 0 -bg $color($col)
            }
            APSLabeledOutput .lock -parent $sectorWidget \
              -label "" -width 8 \
              -packOption {-padx 0 -pady 0 -side left} \
              -textVariable LockStatus($sector) \
              -contextHelp "Lock state of BPLDs."
            $sectorWidget.lock.entry configure -relief flat -bd 0
            APSButton .apply -parent $sectorWidget -text "APPLY" -size small\
              -highlightColor red -highlight 1 -packOption {-pady 1 -side left} \
              -command "ApplySetpoints -sector $sector" \
              -contextHelp "Download trip limits to setpoints for sector $sector BPLD. This button is enabled only when the BPLD state is unlocked.\n\nA highlighted button means that the values to download are different from the setpoint. The BPLD should be unlocked and the APPLY should be pressed."
            set applyButtonWidget($sector$ext) $sectorWidget.apply.button
            CheckBPLDSetpoints -sector $sector -extensions $ext
            set lastWidget $sectorWidget
        } else {
            foreach channel {u d} {
                set sectorWidget $wscroll.s$sector$channel.frame
                APSFrame .s$sector$channel -parent $wscroll -height 20 \
                  -packOption "-side top"
                $sectorWidget configure -relief flat -bd 0
                label $sectorWidget.label -text "$sector$channel" -width 3 -pady 2
                pack  $sectorWidget.label -side left -fill x
               
                foreach col $columns {
                    APSLabeledOutput .$col -parent $sectorWidget \
                      -label ""  -width 6 \
                      -packOption {-padx 0 -pady 0 -side left} \
                      -textVariable ${col}($sector$channel)
                    $sectorWidget.$col.entry configure -relief flat -bd 0 -bg $color($col)
                }
                APSLabeledOutput .lock -parent $sectorWidget \
                  -label "" -width 8 \
                  -packOption {-padx 0 -pady 0 -side left} \
                  -textVariable LockStatus($sector$channel) \
                  -contextHelp "Lock state of BPLDs."
                $sectorWidget.lock.entry configure -relief flat -bd 0
                APSButton .apply -parent $sectorWidget -text "APPLY" -size small\
                  -highlightColor red -highlight 1 -packOption {-pady 1 -side left} \
                  -command "ApplySetpoints -sector $sector$channel" \
                  -contextHelp "Download trip limits to setpoints for sector $sector BPLD. This button is enabled only when the BPLD state is unlocked.\n\nA highlighted button means that the values to download are different from the setpoint. The BPLD should be unlocked and the APPLY should be pressed."
                set applyButtonWidget($sector$channel$ext) $sectorWidget.apply.button
                CheckBPLDSetpoints -sector $sector$channel -extensions $ext
                set lastWidget $sectorWidget
            }
        }
    }
    tkwait visibility $lastWidget 
    APSScrollAdjust $parent.scroll -numVisible 6
}

proc CheckBPLDSetpoints {args} {
    global xHiDownload xLoDownload yHiDownload yLoDownload
    global xHiAO xLoAO yHiAO yLoAO
    global xHiAI xLoAI yHiAI yLoAI
    global applyButtonWidget   pagerNumbers
    global OffsetRead tolerance
    global xLoDiff xHiDiff yLoDiff yHiDiff wscrollFull wscrollBrief
    
    set sector ""
    set extensions brief
    APSParseArguments {sector extensions}
    if ![string length $sector] {
        return -code error "No value given for sector"
    }
   # set tolerance 0.030
    
    if !$OffsetRead {
        foreach ext $extensions {
            APSChangeButtonHighlight $applyButtonWidget($sector$ext) -highlight 0
        }
        return 0
    }
    set highlight 0
    foreach limit {xHi xLo yLo yHi} {
        set setpoint [subst \$${limit}AO($sector)]
        set toDownload [subst \$${limit}Download($sector)]
        set ${limit}Diff($sector) [format %.7f [expr $setpoint - $toDownload]]
        if [info exists ${limit}AI($sector)] {
            set readback [subst \$${limit}AI($sector)]
            if {[expr abs( $readback - $toDownload) > $tolerance] } {
                set highlight 1
                $wscrollFull.s$sector.frame.${limit}AI.entry configure -fg red
                $wscrollFull.s$sector.frame.${limit}Download.entry configure -fg red
            } else {
                $wscrollFull.s$sector.frame.${limit}AI.entry configure -fg black
                $wscrollFull.s$sector.frame.${limit}Download.entry configure -fg black
            }
        } 
        if {[expr abs( $setpoint - $toDownload ) > $tolerance] } {
            set highlight 1
            $wscrollBrief.s$sector.frame.${limit}Diff.entry configure -fg red
            $wscrollFull.s$sector.frame.${limit}AO.entry configure -fg red
            $wscrollFull.s$sector.frame.${limit}Download.entry configure -fg red
        } else {
            $wscrollBrief.s$sector.frame.${limit}Diff.entry configure -fg black
            $wscrollFull.s$sector.frame.${limit}AO.entry configure -fg black
            $wscrollFull.s$sector.frame.${limit}Download.entry configure -fg black
        }
    }
    if $highlight {
        foreach ext $extensions {
            APSChangeButtonHighlight $applyButtonWidget($sector$ext) -highlight 1 \
              -highlightColor red
        }
    } else {
        foreach ext $extensions {
            APSChangeButtonHighlight $applyButtonWidget($sector$ext) -highlight 0
        }
    }
    return 0 
}

proc MakeActionWidget {widget args} {
    APSParseArguments {parent}

    set w $parent$widget
    APSFrame $widget -parent $parent -label "Actions" \
      -contextHelp "Frame for containing action buttons."
    if {0} {
    APSButton .default -parent $w.frame -text "BRIEF VIEW" \
      -contextHelp "only display the difference between setpoints and download values" \
      -command "MakeSectorsTable .sectorsTable -parent .userFrame -brief 1"
    APSButton .expand -parent $w.frame -text "FULL VIEW" \
      -contextHelp "display setpoints, readback and download values" \
      -command "MakeSectorsTable .sectorsTable -parent .userFrame -brief 0"
    
    APSButton .switch -parent $w.frame -text "SWITCH VIEW" \
      -contextHelp "switch between brief view which only displays the differences and full view" \
      -command "MakeSectorsTable .sectorsTable -parent .userFrame -switch 1"
    }
    APSButton .readOffsets -parent $w.frame -text "READ OFFSETS/RECALCULATE" \
      -command {MakeChannelArrays; ReadOffsets} -contextHelp \
      "Reads the bpm offsets from the SR snap file selected, and determines the values of the trip limits for the BPLDs."
    APSButton .changeperm -parent $w.frame -text "Toggle BPM Permission" \
	-command "ToggleBPMPermission" \
	-contextHelp "This button resets the access mode so that the pvs can be written."
}

proc ToggleBPMPermission {args} {
    SetSRBPLDLoadingStatus "reset the access mode ..."
    if [catch {exec cavget -list=S:bpm:accessControlMBBO.VAL -pend=10 -numerical -printErrors} orig] {
	return -code error "Unable to toggle the access mode(1): $orig"
    }
    if {$orig==1} {
	set value 0
    } else {
	set value 1
    }
    if [catch {exec cavput -list=S:bpm:accessControlMBBO.VAL=$value -pend=10} result] {
	return -code error "Unable to toggle the access mode(2): $result"
    }
    after 1000
    if [catch {exec cavput -list=S:bpm:accessControlMBBO.VAL=$orig -pend=10} result] {
	return -code error "Unable to toggle the access mode(3): $result"
    }
    SetSRBPLDLoadingStatus "done."
}
proc ReadOffsets {args} {
    global snapDir snapFile
    global BPLDList  firstChannelBPM secondChannelBPM IsDigitalList
    global xLimit yLimit xLimitMax yLimitMax xScale yScale
    global OffsetRead 
    global xHiDownload xLoDownload yHiDownload yLoDownload 
    global xHiAO xLoAO yHiAO yLoAO xHiDiff xLoDiff yHiDiff yLoDiff

    SetSRBPLDLoadingStatus "Calculating trip limits from offsets..."
    # pick out the offsets related to the bpld bpms
    set matchList ""
    foreach sector $BPLDList isDigital $IsDigitalList {
        lappend matchList ControlName=$firstChannelBPM($sector):ms:x:OffsetAO
    }
    set firstMatch [lindex $matchList 0]
    set matchList [lreplace $matchList 0 0] 
    set matchOption -match=col,$firstMatch,[join $matchList ,|,],|
    set x1tmpfile /tmp/[APSTmpString].x1Offsets
    if [catch {exec sddsprocess $snapDir/$snapFile $x1tmpfile \
                 $matchOption \
                 -scan=col,Offset,ValueString,%lf \
                 -noWarning \
             } results] {
        SetSRBPLDLoadingStatus $results
        return 1
    }
    set matchList ""
    foreach sector $BPLDList {
        lappend matchList ControlName=$secondChannelBPM($sector):ms:x:OffsetAO
    }
    set firstMatch [lindex $matchList 0]
    set matchList [lreplace $matchList 0 0] 
    set matchOption -match=col,$firstMatch,[join $matchList ,|,],|
    set x2tmpfile /tmp/[APSTmpString].x2Offsets
    if [catch {exec sddsprocess $snapDir/$snapFile $x2tmpfile \
                 $matchOption \
                 -scan=col,Offset,ValueString,%lf \
                 -noWarning \
             } results] {
        SetSRBPLDLoadingStatus $results
        return 1
    }
    set matchList ""
    foreach sector $BPLDList {
        lappend matchList ControlName=$firstChannelBPM($sector):ms:y:OffsetAO
    }
    set firstMatch [lindex $matchList 0]
    set matchList [lreplace $matchList 0 0] 
    set matchOption -match=col,$firstMatch,[join $matchList ,|,],|
    set y1tmpfile /tmp/[APSTmpString].y1Offsets
    if [catch {exec sddsprocess $snapDir/$snapFile $y1tmpfile \
                 $matchOption \
                 -scan=col,Offset,ValueString,%lf \
                 -noWarning \
             } results] {
        SetSRBPLDLoadingStatus $results
        return 1
    }
    set matchList ""
    foreach sector $BPLDList {
        lappend matchList ControlName=$secondChannelBPM($sector):ms:y:OffsetAO
    }
    set firstMatch [lindex $matchList 0]
    set matchList [lreplace $matchList 0 0] 
    set matchOption -match=col,$firstMatch,[join $matchList ,|,],|
    set y2tmpfile /tmp/[APSTmpString].y2Offsets
    if [catch {exec sddsprocess $snapDir/$snapFile $y2tmpfile \
                 $matchOption \
                 -scan=col,Offset,ValueString,%lf \
                 -noWarning \
             } results] {
        SetSRBPLDLoadingStatus $results
        return 1
    }
    set gainfile /tmp/[APSTmpString]
    if [catch {exec sddsprocess /home/helios/oagData/SCR/snapshots/SBPMs/SBPMs-Preferred.gz \
                 -match=col,ControlName=*:ms:x:GainAO -scan=col,Gain,ValueString,%lf $gainfile.x
        exec sddsprocess /home/helios/oagData/SCR/snapshots/SBPMs/SBPMs-Preferred.gz \
                 -match=col,ControlName=*:ms:y:GainAO -scan=col,Gain,ValueString,%lf $gainfile.y} result] {
        return -code error $result
    }
    set x1OffsetList [exec sdds2stream -col=ControlName,Offset $x1tmpfile]
    set y1OffsetList [exec sdds2stream -col=ControlName,Offset $y1tmpfile]
    set x2OffsetList [exec sdds2stream -col=ControlName,Offset $x2tmpfile]
    set y2OffsetList [exec sdds2stream -col=ControlName,Offset $y2tmpfile]
    set xgainPVList [exec sdds2stream -col=ControlName $gainfile.x]
    set xgainValueList [exec sdds2stream -col=Gain $gainfile.x]
    set ygainPVList [exec sdds2stream -col=ControlName $gainfile.y]
    set ygainValueList [exec sdds2stream -col=Gain $gainfile.y]
   # file delete -force -- $x1tmpfile $y1tmpfile $x2tmpfile $y2tmpfile $gainfile.x $gainfile.y
    # determine average of offset for each bpld bpm pair
    puts $x1tmpfile
    puts $x1OffsetList
    foreach sector $BPLDList isDigital $IsDigitalList {
        # search for offset value of a bpm of a particular sector
        set index [lsearch -regexp $x1OffsetList $firstChannelBPM($sector)]
        
        if {$index == -1} {
            set x1Offset 0
        } else {
            set x1Offset [lindex $x1OffsetList [expr $index + 1]]
        }
        puts "$sector $index  $firstChannelBPM($sector) $x1Offset"
        set index [lsearch -regexp $x2OffsetList $secondChannelBPM($sector)]
        if {$index == -1} {
            set x2Offset 0 
        } else {
            set x2Offset [lindex $x2OffsetList [expr $index + 1]]
        }
        set index [lsearch $xgainPVList $firstChannelBPM($sector):ms:x:GainAO]
        if {$index == -1} {
            set x1gain 1.0
        } else {
            set x1gain [lindex $xgainValueList $index]
        }
        set index [lsearch $xgainPVList $secondChannelBPM($sector):ms:x:GainAO]
        if {$index == -1} {
            set x2gain 1.0
        } else {
            set x2gain [lindex $xgainValueList $index]
        }
        if {$x1gain>$x2gain} {
            set xCalibration $x1gain
        } else {
            set xCalibration $x2gain
        }
        if {!$isDigital} {
           # puts "$sector: xcal=$xCalibration"
            set xAveDownload($sector) [expr ($x1Offset + $x2Offset) /2]
            set xHiDownload($sector) [expr ($xLimit($sector) + $xAveDownload($sector)) / $xCalibration]
            if [expr $xHiDownload($sector) > $xLimitMax] {
                set xHiDownload($sector) $xLimitMax
            }
            set xLoDownload($sector) [expr ($xLimit($sector) * -1 + $xAveDownload($sector)) / $xCalibration]
            if [expr $xLoDownload($sector) < -$xLimitMax] {
                set xLoDownload($sector) -$xLimitMax
            }
            
            set xHiDiff($sector) [format %.7f [expr [set xHiAO($sector)] - [set xHiDownload($sector)]]]
            set xLoDiff($sector) [format %.7f [expr [set xLoAO($sector)] - [set xLoDownload($sector)]]]
        } else {
           # puts "$sector: x1gain=$x1gain, x2gain=$x2gain"
            set xHiDownload(${sector}u) [expr ($xLimit($sector) + $x1Offset) / $x1gain]
            if [expr $xHiDownload(${sector}u) > $xLimitMax] {
                set xHiDownload(${sector}u) $xLimitMax
            }
            set xLoDownload(${sector}u) [expr ($xLimit($sector) * -1 + $x1Offset) / $x1gain]
            if [expr $xLoDownload(${sector}u) < -$xLimitMax] {
                set xLoDownload(${sector}u) -$xLimitMax
            }
            set xHiDownload(${sector}d) [expr ($xLimit($sector) + $x2Offset) / $x2gain]
            if [expr $xHiDownload(${sector}d) > $xLimitMax] {
                set xHiDownload(${sector}d) $xLimitMax
            }
            set xLoDownload(${sector}d) [expr ($xLimit($sector) * -1 + $x2Offset) / $x2gain]
            if [expr $xLoDownload(${sector}d) < -$xLimitMax] {
                set xLoDownload(${sector}d) -$xLimitMax
            }
            set xHiDiff(${sector}u) [format %.7f [expr [set xHiAO(${sector}u)] - [set xHiDownload(${sector}u)]]]
            set xLoDiff(${sector}u) [format %.7f [expr [set xLoAO(${sector}u)] - [set xLoDownload(${sector}u)]]]
            set xHiDiff(${sector}d) [format %.7f [expr [set xHiAO(${sector}d)] - [set xHiDownload(${sector}d)]]]
            set xLoDiff(${sector}d) [format %.7f [expr [set xLoAO(${sector}d)] - [set xLoDownload(${sector}d)]]]
        }
        set index [lsearch -regexp $y1OffsetList $firstChannelBPM($sector)]
        if {$index == -1} {
            set y1Offset 0
        } else {
            set y1Offset [lindex $y1OffsetList [expr $index + 1]]
        }
        set index [lsearch -regexp $y2OffsetList $secondChannelBPM($sector)]
        if {$index == -1} {
            set y2Offset 0
        } else {
            set y2Offset [lindex $y2OffsetList [expr $index + 1]]
        }
        set index [lsearch $ygainPVList $firstChannelBPM($sector):ms:y:GainAO]
        if {$index == -1} {
            set y1gain 1.0
        } else {
            set y1gain [lindex $ygainValueList $index]
        }
        set index [lsearch $ygainPVList $secondChannelBPM($sector):ms:y:GainAO]
        if {$index == -1} {
            set y2gain 1.0
        } else {
            set y2gain [lindex $ygainValueList $index]
        }
        if {$y1gain>$y2gain} {
            set yCalibration $y1gain
        } else {
            set yCalibration $y2gain
        }
        if {!$isDigital} {
            set yAveDownload($sector) [expr ($y1Offset + $y2Offset) / 2]
            set yHiDownload($sector) [expr ($yLimit($sector) + $yAveDownload($sector)) / $yCalibration]
            if [expr $yHiDownload($sector) > $yLimitMax] {
                set yHiDownload($sector) $yLimitMax
            }
            set yLoDownload($sector) [expr ($yLimit($sector) * -1 + $yAveDownload($sector)) / $yCalibration] 
            if [expr $yLoDownload($sector) < -$yLimitMax] {
                set yLoDownload($sector) -$yLimitMax
            }
            set yHiDiff($sector) [expr [set yHiAO($sector)] - [set yHiDownload($sector)] ]
            set yLoDiff($sector) [expr [set yLoAO($sector)] - [set yLoDownload($sector)] ]
        } else {
            set yHiDownload(${sector}u) [expr ($yLimit($sector) + $y1Offset) / $y1gain]
            if [expr $yHiDownload(${sector}u) > $yLimitMax] {
                set yHiDownload(${sector}u) $yLimitMax
            }
            set yLoDownload(${sector}u) [expr ($yLimit($sector) * -1 + $y1Offset) / $y1gain]
            if [expr $yLoDownload(${sector}u) < -$yLimitMax] {
                set yLoDownload(${sector}u) -$yLimitMax
            }
            set yHiDownload(${sector}d) [expr ($yLimit($sector) + $y2Offset) / $y2gain]
            if [expr $yHiDownload(${sector}d) > $yLimitMax] {
                set yHiDownload(${sector}d) $yLimitMax
            }
            set yLoDownload(${sector}d) [expr ($yLimit($sector) * -1 + $y2Offset) / $y2gain]
            if [expr $yLoDownload(${sector}d) < -$yLimitMax] {
                set yLoDownload(${sector}d) -$yLimitMax
            }
            set yHiDiff(${sector}u) [expr [set yHiAO(${sector}u)] - [set yHiDownload(${sector}u)] ]
            set yLoDiff(${sector}u) [expr [set yLoAO(${sector}u)] - [set yLoDownload(${sector}u)] ]
            set yHiDiff(${sector}d) [expr [set yHiAO(${sector}d)] - [set yHiDownload(${sector}d)] ]
            set yLoDiff(${sector}d) [expr [set yLoAO(${sector}d)] - [set yLoDownload(${sector}d)] ]
        }
    }
    set OffsetRead 1
    foreach sector $BPLDList isDigital $IsDigitalList {
        if {!$isDigital} {
            CheckBPLDSetpoints -sector $sector -extensions {brief full}
        } else {
            CheckBPLDSetpoints -sector ${sector}u -extensions {brief full}
            CheckBPLDSetpoints -sector ${sector}d -extensions {brief full}
        }            
    }
    update
    SetSRBPLDLoadingStatus "Done."
}

proc CheckLockStatus {args} {
    global applyButtonWidget LockStatus
    set locklist ""
    set lockInitialStatus ""
    foreach sector [array names LockStatus] {
        lappend locklist LockStatus($sector)
        lappend lockInitialStatus $LockStatus($sector)
    }
    if {[pv getw $locklist]} {
        APSSetVarAndUpdate SRBPLDLoadingStatus "error checking lock status"
        after 1000 "CheckLockStatus"
        return
    }
    set lockNewStatus ""
    foreach sector [array names LockStatus] {
        lappend lockNewStatus $LockStatus($sector)
    }
    foreach new $lockNewStatus \
      initial $lockInitialStatus \
      sector [array names LockStatus] {
          if {$new != $initial} {
              SetSRBPLDLoadingStatus "LockStatus($sector) $LockStatus($sector)"
              if {![string compare [string tolower $LockStatus($sector)] "locked"]} {
                  APSDisableButton $applyButtonWidget(${sector}brief)
                  APSDisableButton $applyButtonWidget(${sector}full)
              } else {
                  APSEnableButton $applyButtonWidget(${sector}brief)
                  APSEnableButton $applyButtonWidget(${sector}full)
                  SetSRBPLDLoadingStatus "BPLD${sector} is now unlocked."
                  after 250
                  bell
                  after 250
                  bell
              }
          }
      }
    after 1000 "CheckLockStatus"
}

proc ApplySetpoints {args} {
    global xHiDownload xLoDownload yHiDownload yLoDownload  pagerNumbers
    global applyButtonWidget LockStatus
    global firstChannelBPM secondChannelBPM
    APSParseArguments {sector}
    if ![string compare [string tolower $LockStatus($sector)] "locked"] {
        SetSRBPLDLoadingStatus "BPLD $sector is locked. Unlock before apply can be performed."
        return 0
    }
    # Variable sector may have format <nn>, <nn>u or <nn>d
    if {![regexp {(.*)([ud])$} $sector {} sector0]} {
        # old style bplds
        # applies drive high and drive low limits to PVs
        if [catch {exec cavput -list=S${sector}BPLD: \
                     -list=xUpTripLimitAO.DRVH=3.4,xLowTripLimitAO.DRVL=-3.4,yUpTripLimitAO.DRVH=3.7,yLowTripLimitAO.DRVL=-3.7 \
                 } result ] {
            SetSRBPLDLoadingStatus $result
            return
        }
        if [catch {exec cavput -list=S${sector}BPLD: \
                     -list=xUpTripLimitAO=$xHiDownload($sector),xLowTripLimitAO=$xLoDownload($sector),yUpTripLimitAO=$yHiDownload($sector),yLowTripLimitAO=$yLoDownload($sector) \
                 } result ] {
            SetSRBPLDLoadingStatus $result
            return
        }
    } else {
        # digital bpld
        set sector1 [expr $sector0 + 1]
        switch -regexp $sector {
            u {
                set channel $firstChannelBPM($sector0)
            }
            d {
                set channel $secondChannelBPM($sector0)
            }
        }
        if [catch {exec cavput -list=$channel:dbpld: \
                     -list=xhiAO=$xHiDownload($sector),xloAO=$xLoDownload($sector),yhiAO=$yHiDownload($sector),yloAO=$yLoDownload($sector) \
                 } result ] {
            SetSRBPLDLoadingStatus $result
            return   
        }
    }
    SetSRBPLDLoadingStatus "Downloaded new BPLD${sector} trip limits."
    if [string length $pagerNumbers] {
        set pagerList [split $pagerNumbers " ,"]
        exec echo "ID $sector set.  Proceed to next, human." | /usr/ucb/mail $pagerList
    }
    APSChangeButtonHighlight $applyButtonWidget(${sector}brief) -highlight 0 
    APSChangeButtonHighlight $applyButtonWidget(${sector}full) -highlight 0 
    return 0
}

proc MakeChannelArrays {} {
    global BPLDList BPLDConfig firstChannelBPM secondChannelBPM IsDigitalList
    global XAXSTFList XAXSTFConfig
    global xLimit yLimit 
    global xLimitNormal yLimitNormal
    set Channel1  [lindex $BPLDConfig(Column.Channel1) 0]
    set Channel2  [lindex $BPLDConfig(Column.Channel2) 0]
    set IsDigitalList  [lindex $BPLDConfig(Column.IsDigital) 0]
    foreach sector $BPLDList chan1 $Channel1 chan2 $Channel2 {
        set sector1 [expr $sector + 1]
        set firstChannelBPM($sector) S${sector}B:$chan1
        set secondChannelBPM($sector) S${sector1}A:$chan2
        set xLimit($sector) [set xLimitNormal($chan1)]
        set yLimit($sector) [set yLimitNormal($chan1)]
        # special case for ID4 with 135 urad deflection at 7 GeV, but 
        # with beam energy at 6.3 GeV.
        if {$sector == 4} {
            if {$chan1 == "P1"} {
                set L 2.5
                set angle 0.135
                set xLimit($sector) [expr $xLimit($sector) - $angle * 7.0 / 6.3 * $L]
            }
        }
        if {$sector == 29} {
            if {$chan1 == "P1"} {
                set yLimit($sector) [expr $yLimit($sector) / 2.0]
            }
        }
        #special case for 2ID, reduce the limit from 2.5mm to 1.69mm
        if {$sector==2} {
            set xLimit($sector) 1.69
        }
        # XAXSTF sectors need modification
    }
}


set apsSCRSnapDir /home/helios/oagData/SCR/snapshots
set apsSCRSystem SR
set snapDir $apsSCRSnapDir/$apsSCRSystem
set refFile $apsSCRSystem-BPMOffsetReference.gz
set snapFile $refFile
# the x and y Limits are in mm units.
set xLimitNormal(P2) 3.0
set yLimitNormal(P2) 1.4
set xLimitNormal(P1) 2.25
set yLimitNormal(P1) 1.04
set xLimitNormal(P0) 2.25
set yLimitNormal(P0) 1.00
# These scale values are determined from the calibration differences
# between P1 and P2 bpms. Obsolete I think.
set xScale 1
set yScale 1

set BPLDFile /home/helios/oagData/sr/BPLDs/sectors.sdds
sdds load $BPLDFile BPLDConfig
# index 0 means take data from first page. 
# (it's the only page present anyway)
set BPLDList [lindex $BPLDConfig(Column.Sector) 0]

set XAXSTFFile /home/helios/oagData/sr/XAXSTF/sectors.sdds
sdds load $XAXSTFFile XAXSTFConfig
# index 0 means take data from first page. 
# (it's the only page present anyway)
set XAXSTFList [lindex $XAXSTFConfig(Column.Sector) 0]

set OffsetRead 0
set xLimitMax 3.18
set yLimitMax 3.47
set tolerance 0.1

MakeChannelArrays
MakeOptionFrame .options -parent .userFrame
MakeActionWidget .action  -parent .userFrame
APSDisableButton .userFrame.action.frame.readOffsets.button
MakeSectorsTable .sectorsTable -parent .userFrame 
ReadOffsets
APSEnableButton .userFrame.action.frame.readOffsets.button
