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

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

APSStandardSetup

APSApplication . -name "SRCollectGapFFData"   \
  -overview "Does undulator gap scans to determine required H1/V1 magnet setpoints for feedforward. Can be used for calculating ID first and second integrals. Orbit correction in both planes must be running externally."
set status ""

# Is archiveDir ever used? 
# The path  /home/helios/oagData/sr/gapScans/feedforwardDataFiles doesn't exist
set archiveDir /home/helios/oagData/sr/gapScans/data/gapScanFull
set corrArchiveDir /home/helios/oagData/sr/gapScans/data/corrector

set orbitControlDir /home/helios/oagData/sr/orbitControllaw/lattices
set bpmOffsetRef /home/helios/oagData/SCR/snapshots/SR/SR-BPMOffsetReference.gz

APSScrolledStatus .status -parent .userFrame -width 120 -textVariable status

# make a widget to allow selecting individual IDs and specifying their
# minimum gap
 
proc MakeIDSelectionWidget {widget args} {
    set parent ""
    APSStrictParseArguments {parent}
    
    APSFrame $widget -parent $parent -label "ID selection and minimum gap specification"
    set parent $parent$widget.frame
   
    global IDMinGap IDUseFlag DeltaToMinimumGap checkButtonVariableList entryVariableList AllgapList
    global checkButtonCommandList AllIDList buttonNameList lockedIDList 
    if [catch {APSSRGetDeviceLimits -default 1 -initial 1 -gapVar IDMinGap \
                   -deltaToMinGap $DeltaToMinimumGap } result] {
        return -code error $result
    }
    APSSRGapSetThresholds -thresholdVar GapThreshold 
   
    set commList ""
    foreach ID $AllIDList {
        lappend commList "APSUpdateIDScanSelection $ID"
    }
    
    set buttonNameList [APSCheckButtonEntryFrame .check -parent $parent -buttonList $AllgapList  -commandList $commList   \
                            -variableList $checkButtonVariableList -labelFont bold -fgColor blue \
                            -allNone 1 -limitPerRow 8 -entryWidth 8 -entryVariableList $entryVariableList -label ""]
    
    
    #puts $buttonNameList
    set lockedIDList [APSIDGetBadDeviceList -closeGap 1]
    foreach ID $lockedIDList {
        set index [lsearch $AllIDList $ID]
        if {$index>=0} {
	    [lindex $buttonNameList $index] configure -state disabled
	    set var [lindex $checkButtonVariableList $index]
	    set $var 0
        }
    }
    
    APSSetVarAndUpdate status "Buttons for [join $lockedIDList ,] disabled."
    
    #APSFrameGrid .grid -parent $parent.check.frame.frame5 -yList {y1 y2 y3}
    APSFrameGrid .grid -parent $parent.check.frame.frame5 -yList {y1 y2}

    set w $parent.check.frame.frame5.grid
    
    APSButton .group1 -parent $w.y1 -text "group1" \
        -command "APSSRResetDefaultSelection -selectType group1 -closeGap 1"  -size small 
    APSButton .group2 -parent $w.y1 -text "group2" \
        -command "APSSRResetDefaultSelection -selectType group2 -closeGap 1"   -size small 
    
    APSButton .group3 -parent $w.y1 -text "group3" \
        -command "APSSRResetDefaultSelection -selectType group3 -closeGap 1" -size small 
    APSButton .group4 -parent $w.y1 -text "group4" \
        -command "APSSRResetDefaultSelection -selectType group4 -closeGap 1"  -size small 
    APSButton .d -parent $w.y2 -text "default" \
              -command "APSSRResetDefaultSelection -selectType default -closeGap 1"   -size small
    
    APSButton .da -parent $w.y2 -text "default a" \
        -command "APSSRResetDefaultSelection -selectType defaultA -closeGap 1"  -size small 
    APSButton .db -parent $w.y2 -text "default b" \
        -command "APSSRResetDefaultSelection -selectType defaultB -closeGap 1"  -size small 
}

# global values for entry boxes
set end 140.0
set readingType LowPass1s
set numToAve 30
set pause 10
set minStep 0.25
set maxStep 30.0
set stepInterval 7
set factor 2
set stepCounter 0
set rootname IDscan
set archive 0
set outputDir [APSGoToDailyDirectory -subdirectory gapScanFull]
set outputFile ""
set transferOrbit 0
set ignoreXbpms 1
set gainSetpointFF ""
set DeltaToMinimumGap 0.5
set closeInterval 3
set takeTunes 0
APSAddToTmpFileList -ID FF -fileList $gainSetpointFF
# make widgets for entering common values for experiments

set ffDir  /home/helios/oagData/feedForwardFiles/IDgap
proc SetOutputDir {args} {
    global archiveDir corrArchiveDir ignoreXbpms outputDir rootname archive ffDir end
    if $ignoreXbpms {
        if $archive {
            set outputDir $corrArchiveDir
        } else {
            set outputDir [APSGoToDailyDirectory -subdirectory correctorScan]
        }
        set rootname CorrScan
        set ffDir /home/helios/oagData/sr/gapScans/data/corrector
	set end 140
    } else {
        if $archive {
            set outputDir $archiveDir 
        } else {
            set outputDir [APSGoToDailyDirectory -subdirectory gapScanFull]
        }
        set rootname IDscan
        set ffDir /home/helios/oagData/feedForwardFiles/IDgap
	set end 34
    }
}

proc MakeEntryWidgets {widget args} {
    set parent ""
    APSStrictParseArguments {parent}
    
    APSFrame .entry -parent $parent
    set parent $parent.entry.frame
    APSFrameGrid .grid -parent $parent -xList {x1 x2}
    APSLabeledEntry .rootname -parent $parent.grid.x1 -width 60 \
      -label "Output rootname: " -textVariable rootname \
      -contextHelp \
      "Enter a rootname for generation of the output filenames."
    APSLabeledEntry .dir -parent $parent.grid.x1 -width 60 \
      -label "Output dir: " -textVariable outputDir \
      -contextHelp \
      "Enter a directory in which the output files will be written."
    APSButton .dialy -parent $parent.grid.x1.dir -text "daily" -size small \
      -command {set archive 0;SetOutputDir} \
      -packOption "-side right" \
      -contextHelp "Set the output dir to APS daily directory"
    APSButton .archive -parent $parent.grid.x1.dir -text "archive" -size small \
      -command {set archive 1;SetOutputDir} \
      -packOption "-side right" \
      -contextHelp "Set the output directory to APS archive dir"
    
    APSLabeledOutput .output -parent $parent.grid.x1 -width 55 \
      -label "Output file: " -textVariable outputFile 
    APSLabeledEntry .pause -parent $parent.grid.x1 -width 10 \
      -label "Pause for orbit correction after gap change (s): " \
      -textVariable pause -contextHelp \
      "Length of pause after gap change completion to allow convergence of orbit correction."
      
    APSLabeledOutput .stpCount -parent $parent.grid.x1 -width 10 \
      -label "Step counter display: " \
      -textVariable stepCounter -contextHelp \
      "Displays current step run."
    
    APSRadioButtonFrame .rbf -parent $parent.grid.x1 -label "Reading type: " \
      -orientation horizontal -variable readingType -buttonList "SampledM LowPass1sM LowPass8sM" \
      -valueList "Sampled LowPass1s LowPass8s" -contextHelp \
      "Choose the type of BPM reading you want to use.  The names of the BPM data in the output files will be of the type SnA:Pm"
    APSRadioButtonFrame .ignoreXbpms -parent $parent.grid.x1 \
      -label "Ignore checking of X-ray bpms gains:" \
      -variable ignoreXbpms -buttonList {"Yes, I'm scanning\nfrom 140 mm!" "No, I'm doing important\nX-ray bpm work"} -valueList {1 0} \
      -packOption "-side top" -orientation horizontal -contextHelp \
      "Ignores checking of X-ray bpms gains.\n\nIgnoring will allow a scan starting from open gaps of 180 mm." \
      -commandList {SetOutputDir SetOutputDir}
    APSRadioButtonFrame .takeTunes -parent $parent.grid.x1 \
      -label "Take Dimtel tunes:" \
      -variable takeTunes -buttonList {"Yes" "No"} -valueList {1 0} \
      -packOption "-side top" -orientation horizontal -contextHelp \
      "Takes tunes for possible FF." 
    
    
    APSLabeledEntry .stop -parent $parent.grid.x2 -width 10 \
      -label "Maximum gap value (mm):" -textVariable end \
      -contextHelp "Enter the maximum gap for the scan."
    APSLabeledEntry .maxStep -parent $parent.grid.x2 -width 10 \
      -label "Maximum step value (mm):" -textVariable maxStep \
      -contextHelp "Enter the maximum step for the scan."
    APSLabeledEntry .start -parent $parent.grid.x2 -width 10 \
      -label "Minimum gap value (mm):" -textVariable globalMinGap \
      -contextHelp "Enter the minimum gap for the scan.  Overrides individual gaps."
    bind $parent.grid.x2.start.entry <Return> SetAllMinGaps 
    APSLabeledEntry .minStep -parent $parent.grid.x2 -width 10 \
      -label "Minimum step value (mm):" -textVariable minStep \
      -contextHelp "Enter the minimum step for the scan.  Overrides individual gaps."
    
    
    APSLabeledEntry .stepInt -parent $parent.grid.x2 -width 10 \
      -label "Number of the same size steps:" -textVariable stepInterval \
      -contextHelp "Enter the number of the same-size steps."
    APSLabeledEntry .factor -parent $parent.grid.x2 -width 10 \
      -label "Factor for a step increase: " \
      -textVariable factor -contextHelp \
      "Enter a factor for the step increase."

    APSLabeledEntry .ptToAve -parent $parent.grid.x2 -width 10 \
      -label "Readings to average: " -textVariable numToAve \
      -contextHelp "Number of readings to average at each gap value." 

    APSLabeledEntry .delta -parent $parent.grid.x2 -width 10 \
      -label "Delta to Minimum Gap (mm):" -textVariable DeltaToMinimumGap \
      -contextHelp "A small value added to the device limit (minimum gap) to create a safe minimium gap value in the scan. Moving the gap to the minimum value which may cause problems."
    APSLabeledEntry .interval -parent $parent.grid.x1 -width 10 \
      -label "Interval between closing two gaps (seconds): " -textVariable closeInterval \
      -contextHelp "Due to on-going restrictions on the SR rf systems, we need to tagger the closing of the gaps by a selectable time interval, i.e. issuing the next gap close command after T seconds of the previous one."
    
    global customPlotOption 
    APSLabeledEntry .cust -parent $parent  -label "Custom plot option for lookup table review:" \
        -textVariable customPlotOption -width 80 -contextHelp "enter the custom plot option for lookup table review."
    
}

proc CheckIDStatus {args} {
    global buttonNameList AllIDList IDUseFlag lockedIDList
    APSSetVarAndUpdate status "check ID status..."
    set  lockedIDList [APSIDGetBadDeviceList -closeGap 1]
    APSSetVarAndUpdate status "Devices that can not be closed: [join $lockedIDList]"
    #puts $lockedIDList
    if [llength $lockedIDList] {
        foreach ID $AllIDList {
            if [lsearch $lockedIDList $ID]>=0 {
                set IDUseFlag($ID) 0
            }
        }
    }
    APSSRDisableLockedIDDeviceSelect -buttonNameList $buttonNameList \
				     -IDList $AllIDList -enable 1 -lockedIDList $lockedIDList
    APSSetVarAndUpdate status "done."
    
}

# make widgets for buttons to initiate actions

proc MakeActionButtons {widget args} {
    set parent ""
    APSStrictParseArguments {parent}

    global gainSetpointFF
    APSFrame .br1 -parent $parent -label "" -relief flat
    set w $parent.br1.frame
    
    APSButton .lock -parent $w -text "Check ID Status" \
        -command "CheckIDStatus"
   # APSButton .resetdefault -parent $w -text "Default Selection" \
   #     -command APSSRResetDefaultSelection
    APSButton .resetmin -parent $w -text "Reset Minimum Gap" \
        -command {
            global DeltaToMinimumGap IDMinGap
            if [catch {APSSRGetDeviceLimits -gapVar IDMinGap -deltaToMinGap $DeltaToMinimumGap \
                           -default 0 -initial 0} result] {
                return -code error $result
            }
        }
    
    APSButton .preview -parent $w -text "Preview" \
      -command {RunScan -preview 1} \
      -contextHelp "Gap scan preview. Gives the list of gap values in a plot. If there is an error reported it is because the conditions of the scan are not consistent."
    APSButton .run -parent $w -text "Run" \
      -command {RunScan -preview 0 } \
      -contextHelp "Runs the gap scan. The IDs are first ramped to the minimum values, so patience is needed. A cawait command is used to determine when the ramp is finished and when the real scan starts. If the gap target value is lower than is physically possible, then the wait is infinite."

    APSButton .review -parent $w -text "Review scan..." \
      -command ReviewGapScanData -contextHelp "Review results of gap scan experiment."
    APSButton .minimum -parent $w -text "Goto Minimum Gap ..." \
      -command GotoMinimumGap -contextHelp "Move the gaps to the value of minimum gap + the delta to the minimum gap."
    APSButton .update -parent $w -text "Update FF Table" \
	-command UpdateFFTable -contextHelp "update the FF table if gap threshold is changed in devices.sdds config."

    APSFrame .br2 -parent $parent -label "" -relief flat
    set w $parent.br2.frame

    APSButton .prepFF -parent $w -text "Prepare FF Data..." \
      -command PrepareFFData \
      -contextHelp "Process gap scan experiment to create and view data for running feedforward."

#  APSButton .prepFFgainsetpoint -parent $w -text "Gen. Gain-Setpoint FF Data" \
#    -command "GenerateGainAndSetpointActuatorFile -filename $gainSetpointFF" \
#   -contextHelp "generate the FF file of ID gain and setpoint pvs, required whenever the UBOP file changes"
    APSButton .runFF -parent $w -text "Run FF..." \
      -command RunFeedForward \
      -contextHelp "Run gap feedforward from local or archived data."
    APSButton .install -parent $w -text "Install ..." \
      -command InstallFeedForward \
      -contextHelp "Install the chosen FF file to /home/helios/oagData/feedForwardFiles/IDgap/FF"
    APSButton .info -parent $w -text "IDFeedforwardStatus" \
      -contextHelp "Display gap feedforward run control information." \
      -command "exec medm -x -attach -macro RCPV=S:ID:GapFeedForwardRC \
      ./sr/psApp/APSRunControlSingle.adl &"
    APSButton .rev -parent $w -text "Review Lookup Table ..." \
        -command ReviewLookupTable -contextHelp "review the lookup table."
     APSButton .rev1 -parent $w -text "Review FF Enable Parameters..." \
      -command ReviewLookupTableParameters -contextHelp "review the official lookup table enable pvs and conditions so that one would know the feedward \
   is enabled/disabled at what kind of condition."
   
}

set activeDir .
proc ChooseDataFile {} {
    global rootname archiveDir  activeDir outputDir
    set archive 0
    
    set pattern ${rootname}*.sdds
    #set dir $rootname
    set filename [APSFileSelectDialog [APSUniqueName .] -width 70 -reverseSort 1 \
                    -path $outputDir -pattern $pattern ]
    if !$archive {
        set activeDir [file dirname $filename]
    }
    if ![string length $filename] return
    if [catch {exec sdds2stream -noquote -parameter=Description $filename} description] {
        APSSetVarAndUpdate status "$filename may be invalid: $description"
        set description ?
    }
    APSSetVarAndUpdate status "$filename"
    return [list $filename "$description"]
}

proc ReviewGapScanData {} {
    global ignoreXbpms
    if ![llength [set dataList [ChooseDataFile]]] return
    APSSetVarsFromList -valueList $dataList -variableList "input description"
    APSSRReviewGapFFData -gapScanFile $input -ignoreXbpms $ignoreXbpms
}

proc InstallFeedForward {} {
    global outputDir rootname ignoreXbpms
    
    if [catch {APSSRInstallFeedForward -outputDir $outputDir -rootname $rootname -fullScan 0 -ignoreXbpms $ignoreXbpms} result] {
        return -code error $result
    }
    APSSetVarAndUpdate status "new FF table installed."
}

proc RunFeedForward {} {
     
    global outputDir rootname gainSetpointFF
    set filename [APSFileSelectDialog .file -width 70  -path $outputDir -pattern *.FF*]
    if ![string length $filename] return

    set widget [APSUniqueName .]
    global dialogBoxChoice FFSteps FFInterval
    set dialogBoxChoice 0
    set FFInterval 0.1
    set FFSteps 100000
    APSDialogBox $widget -name "FF configuration" \
      -okCommand "set dialogBoxChoice ok" -cancelCommand "set dialogBoxChoice cancel"
    APSLabeledEntry .le1 -parent $widget.userFrame -label "Interval (s): " \
      -textVariable FFInterval
    APSLabeledEntry .le2 -parent $widget.userFrame -label "Steps: " \
      -textVariable FFSteps 
    tkwait variable dialogBoxChoice
    update
    if [string compare $dialogBoxChoice "cancel"]==0 return
    set RCPV  S:ID:GapFeedForwardRC
   # exec medm -x -attach -macro RCPV=$RCPV \
   #   ./sr/psApp/APSRunControlSingle.adl &
    
    
    APSExecLog $widget -width 80 -lineLimit 2048 -width 95 -height 30  -unixCommand \
        "sddsfeedforward $filename -interval=$FFInterval -verbose -steps=$FFSteps -runControlPV=string=$RCPV,pingTimeout=12 -runControlDescription=GapFeedforward" -callback "set feedforwardDone done" -cancelCallback "set feedforwardDone cancel" \
        -abortCallback "set feedforwardDone abort"
    
}


proc PrepareFFData {} {
    global orbitControlDir outputDir rootname CUSectorList
    if ![info exist hSteeringConfig] {
        set lattice [file tail [file readlink /home/helios/oagData/sr/orbitControllaw/lattices/default]]
        set hSteeringConfig $lattice/h.defaultDP
        set vSteeringConfig $lattice/v.defaultDP
    }
    
    if ![llength [set dataList [ChooseDataFile]]] return
    APSSetVarsFromList -valueList $dataList -variableList "input description"
    if [catch {APSSRPrepareFFData -input $input -gapThresholdVar GapThreshold \
                 -statusCallback "APSSetVarAndUpdate status" \
                 -CUSectorList $CUSectorList} result] {
        return -code error $result
    }
}

# set the minimum gap for all IDs to the global value
proc SetAllMinGaps {} {
    global globalMinGap IDMinGap IDDeviceLimit
    APSSRSetGlobalMinimumGaps -gapVar IDMinGap \
        -minGap $globalMinGap -statusCallback "APSSetVarAndUpdate status"
}

# run a gap scan experiment
set fixedIDList ""
set fixedGapList ""
set togetherList ""
proc RunScan {args} {
    global outputDir rootname end points pause transferOrbit readingType numToAve hSteeringConfig vSteeringConfig
    global outputFile minStep maxStep factor IDMinGap IDUseFlag DeltaToMinimumGap stepInterval
    global ignoreXbpms FixedIDList FixedGapList TogetherList takeTunes
    set preview 0
    APSStrictParseArguments {preview}
    
    set IDList ""
    foreach ID [lsort [array names IDUseFlag]] {
        if $IDUseFlag($ID) {
            lappend IDList $ID
            lappend minGapList $IDMinGap($ID.minGap)
        }
    }
    if [catch {APSSRCheckUndulatorScanType -IDList $IDList} result] {
	APSSetVarAndUpdate status "$result."
	return
    }
    if !$preview {
        set minGapList ""
        foreach ID $IDList { 
            lappend minGapList $IDMinGap($ID.minGap)
        }
        if [llength $FixedIDList] {
            foreach ID $FixedIDList {
                set index [lsearch $IDList $ID]
                if $index>=0 {
                    set IDList [lreplace $IDList $index $index]
                    set minGapList [lreplace $minGapList $index $index]
                }
            }
            foreach ID $FixedIDList val $FixedGapList {
                lappend putcom ${ID}.GapSetC=$val
                lappend putcom1 ${ID}.StartC=1
                append pos "$ID = $val\n"
            }
            set answer [APSMultipleChoice [APSUniqueName .] \
                            -question "Please check if following gaps are in their desired positions\n\n$pos\nClick \"Continue\" if the above gaps are in the desired position;\n  \"MoveGaps\" to move the above gaps to the desired position;\n \"Abort\" to abort experiment.\n" \
                            -returnList {Continue Move Abort} \
                            -labelList {Continue MoveGap Abort}]
            switch $answer {
                Abort {
                    APSSetVarAndUpdate status "SR gap scan was aborted."
                    return
                }
                Move {
                    APSSetVarAndUpdate satus "Move the fixed gaps to their desired values..."
                    if [catch {exec cavput -list=[join $putcom ,] } result] {
                        return -code eorr "Unable to set the gap setpoints of fixed gaps: $result"
                    }
                    if [catch {exec cavput -list=[join $putcom1 ,] } result] {
                        return -code error "Unable to move the fixed gaps: $result"
                    } 
                    if {[catch {WaitForTaskToFinish \
                                    -cavget "APScavget -list=[join $FixedIDList ,] -list=:BusyM -pend=30 -label" \
                                    -waitLimit 500 \
                                    -updateInterval 1 \
                                    -checkExpression {($value)=="Moving"}} results]} {
                        APSSetVarAndUpdate status  "Problem occurred while waiting for setting $FixedIDList gaps: $results" 
                        return
                    }
                }
            }
        }
    }
    
    if [catch {APSSRGapFullScan -outputDir $outputDir -rootname $rootname -readingType $readingType \
                   -statusCallback "APSSetVarAndUpdate status" \
                   -maxGap $end -pause $pause -preview $preview -IDList $IDList \
                   -transferOrbit $transferOrbit -readingType $readingType \
                   -numToAve $numToAve -minStep $minStep -maxStep $maxStep \
                   -stepInterval $stepInterval -factor $factor \
                   -minGapList $minGapList -deltaToMinGap $DeltaToMinimumGap \
                   -ignoreXbpms $ignoreXbpms -fixedIDList $FixedIDList -fixedGapList $FixedGapList -togetherList $TogetherList \
                   -takeTunes $takeTunes \
               } result] {
        APSSetVarAndUpdate status "$result"
        return
    }
    set outputFile $result
    APSSetVarAndUpdate status "Running of scan completed."
}

proc AbortControlLaw {args} {
    set runcontrolPV ""
    set statusCallback ""
    APSStrictParseArguments {runcontrolPV statusCallback} 
    if ![string length $runcontrolPV] {
        return -code error "AbortControlLaw: bad arguments!"
    }
    set status [exec cavget -list=$runcontrolPV.RUN]
    if $status {
        exec cavput -list=$runcontrolPV.ABRT=1 -pend=30
        if [string length $statusCallback] {
            eval $statusCallback {"Waiting for $runcontrolPV to clear..."}
        }
        exec cawait -waitfor=$runcontrolPV.RUN,equal=0
    }
    exec cavput -list=$runcontrolPV.CLR=1 -pend=30
}
# these two procedures handle returns from the gap scan experiment


proc GotoMinimumGap {args} {
    global IDMinGap IDUseFlag undulatorSectorList IDFixGap IDScanType ScanTypeChecked FixedIDList FixedGapList closeInterval
    set IDList ""
    foreach ID [lsort [array names IDUseFlag]] {
        if $IDUseFlag($ID) {
            lappend IDList $ID 
        }
    }
    if ![llength $IDList] {
        APSSetVarAndUpdate status "No IDs selected."
        return
    }
    
    if [catch {APSSRCheckUndulatorScanType -IDList $IDList} result] {
        APSSetVarAndUpdate status "$result\nGoto minimum gap was not performed."
        return
    }
    
    foreach ID $IDList { 
        lappend minGapList $IDMinGap($ID.minGap)
    }
    
    APSSetVarAndUpdate status "fixed $FixedIDList $FixedGapList"
    if [catch {APSSRMoveIDGaps -pem 0 -moveTo MinimumGap -IDList $IDList -minGapList $minGapList \
                 -closeInterval $closeInterval \
                   -fixedIDList $FixedIDList -fixedGapList $FixedGapList} result] {
        APSSetVarAndUpdate status "$result"
        return
    }
    APSSetVarAndUpdate status "Please wait untill all gaps stop moving."
}

proc GetLookupTableList {args} {
    global lookupTableList lookupItemList ffDir
   # set ffDir /home/helios/oagData/feedForwardFiles/IDgap
    set oldDir [pwd]
    cd $ffDir
    set lookupTableList [lsort -decreasing [glob FF.????]]
    set lookupItemList ""
    foreach file $lookupTableList {
        if [catch {exec sdds2stream -par=Filename -page=1 $file} result] {
            continue
        }
        if ![file exist $result] {
            set lastIndex [string last F $result]
            set result [string range $result 0 $lastIndex]
            if ![file exist $result] {
                set result "original file no longer exists"
            }
        }
        set date [clock format [file mtime $file] -format %Y-%m%d:%H:%M:%S]
        lappend lookupItemList "$file      $date     $result"
    }
    cd $oldDir
}
 
proc ReviewLookupTableParameters {args} {
    set file /home/helios/oagData/feedForwardFiles/IDgap/FF
    set tmpRoot /tmp/[APSTmpString]
    if [catch {exec sddscollapse $file -pipe=out \
                 | sddsconvert -pipe -retain=col,ReadbackName,ActuatorName,FeedforwardEnablePV,Feedforward* \
                 | sddsprocess -pipe "-match=col,FeedforwardEnablePV=,!,FeedforwardEnable2PV=,!,|" \
                 | sddsprintout -pipe=in $tmpRoot.printout -col=ReadbackName,label=Gap,format=%10s -col=ActuatorName,label=SetpointPV,format=%22s  \
                 -col=FeedforwardEnablePV,label=EnablePV1,format=%21s -col=FeedforwardEnableLowerLimit,label=LowerLimit1,format=%5.2f \
                 -col=FeedforwardEnableUpperLimit,label=UpperLimit1,format=%5.2f \
                 -col=FeedforwardEnable2PV,label=EnablePV2,format=%17s -col=FeedforwardEnable2LowerLimit,label=LowerLimit2,format=%5.2f \
                 -col=FeedforwardEnable2UpperLimit,label=UpperLimit2,format=%5.2f  } result] {
        return -code error $result
    }
   # puts $tmpRoot.printout
    APSFileDisplayWindow [APSUniqueName .] -width 150 -deleteOnClose 1 \
      -fileName $tmpRoot.printout -font "Courier 11"
    

}
proc UpdateFFTable {args} {
    if [catch {APSUpdateFFTable -statusCallback "APSSetVarAndUpdate status"} result] {
	return -code error $result
    }
    if [string length $result] {
	if [APSYesNoPopUp "New table $result was generated, do you want to install it?"] {
	    cd  /home/helios/oagData/feedForwardFiles/IDgap
	    catch {exec rm FF}
	    catch {exec ln -s [file tail $result] FF}
	    APSSetVarAndUpdate status "new FF table installed."
	}
    }
}

set customPlotOption ""
proc ReviewLookupTable {args} {
    global lookupTableList lookupItemList customPlotOption lookupSelection ignoreXbpms ffDir
   
    GetLookupTableList
    set label "[format %11s "LookupTable"]   [format %16s InstallationDate]     [format %50s "Original File Name"] [format %50s " "]"
    set widget [APSUniqueName .]
    APSScrolledListWindow $widget -name "Select tables for review" \
        -label $label \
        -itemList $lookupItemList -selectionVar lookupSelection
    while [winfo exist $widget] {
        tkwait variable lookupSelection
        set fileList ""
        foreach item $lookupSelection {
            lappend fileList [lindex $item 0]       
        }
        if ![llength $fileList] {
            return
        }
        set oldDir [pwd]
        cd $ffDir
        set len [llength $fileList]
        set sectorList [exec sdds2stream -col=Sector /home/helios/oagData/sr/IDs/sectors.sdds]
        set plotList ""
        foreach sector $sectorList {
            set sectorf [format %02ld $sector]
            append plotList " -col=ReadbackValue,ActuatorValue $fileList -match=par,ActuatorName=S${sectorf}ID*P1*x*OffsetAO -endp"
            append plotList " -col=ReadbackValue,ActuatorValue $fileList -match=par,ActuatorName=S${sectorf}ID*P2*x*OffsetAO -endp"
            append plotList " -col=ReadbackValue,ActuatorValue $fileList -match=par,ActuatorName=S${sectorf}ID*P1*y*OffsetAO -endp"
            append plotList " -col=ReadbackValue,ActuatorValue $fileList -match=par,ActuatorName=S${sectorf}ID*P2*y*OffsetAO -endp"
        }
        eval exec sddsplot -layout=2,2 -split=page -sep -xlabel=@ReadbackName \
            -topline=@ActuatorName -leg=file  \
            -grap=line,vary -clip=0,1 $customPlotOption  $plotList &
            
        cd $oldDir
    }
}
set  CUdataDir /home/helios/oagData/feedForwardFiles/IDgap
if [catch {exec sddsprocess $CUdataDir/cantingLogic.sdds -pipe=out \
               -filter=col,TreatedAsCU,1,1 \
               | sdds2stream -pipe -col=Sector} CUSectorList] {
    return -code error "$CUSectorlist"
}
set status "Working..."
update

APSSRSetupUndulatorGap

MakeIDSelectionWidget .idsel -parent .userFrame
#MakeIDFixedGapWidget .fix -parent .userFrame

MakeEntryWidgets .entries -parent .userFrame
MakeActionButtons .action -parent .userFrame

set status "Ready."
SetOutputDir
