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

#
# $Log: not supported by cvs2svn $
# Revision 1.13  2001/01/11 15:55:44  emery
# added sectors 27 28 to list of sectors which have new timing PVs.
#
# Revision 1.12  2001/01/11 15:52:29  emery
# replaced exec rm with file delete commands
#
# Revision 1.11  2000/10/24 14:20:32  borland
# Kludged to exclude processing of sectors 25 and 26.
#
# Revision 1.10  2000/07/30 17:14:10  borland
# Kludged processing to skip sector 25.
#
# Revision 1.9  2000/07/30 16:18:36  borland
# No longer attempts to process sector 25 data.
#
# Revision 1.8  2000/01/27 21:34:17  borland
# Added runID to the review/install plots.
#
# Revision 1.7  1999/07/27 13:14:50  emery
# Changed the delay increment from 20 to 30 for the definition
# of NewDelay.
#
# Revision 1.6  1999/05/24 19:01:53  borland
# Now displays data on 3x3 grid.
#
# Revision 1.5  1997/05/23 00:19:43  borland
# Fixed problem with preexisting PVs in xref file.  Now delete some
# items to make sure they aren't present in analysis procedures.
#
# Revision 1.4  1997/04/03 21:56:57  borland
# Now shows list of BPMs for which no changes are made.
#
# Revision 1.3  1997/04/02 16:33:58  borland
# Fixed problems with creation of the burt snapshot file for restoring
# the reviewed/altered timing values.
#
# Revision 1.2  1997/04/02 14:48:01  emery
# Fixed several small bugs.
#
# Revision 1.1  1997/03/24 23:21:24  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 TimingScanArchivalDir /home/helios/oagData/sr/bpmTimingScans

proc RunTimingScanExperiment {args} {
    set outputDir ""
    set outputRoot ""
    set runIndex -1
    set points 37
    set pause 1
    set samples 5
    set initial -153
    set final 153
    set statusCallback APSNoOp
    set scanCallback APSNoOp
    global TimingScanArchivalDir
    APSStrictParseArguments {outputDir outputRoot runIndex points pause \
                               statusCallback initial final scanCallback}

    if $points<=2 {
        eval $statusCallback {"points must be >2"}
        return -code error "RunTimingScanExperiment: points must be >2"
    }
    if {$initial>=$final} {
        eval $statusCallback {"initial must be < final"}
        return -code error "RunTimingScanExperiment: initial must be < final"
    }
    if $pause<0 {
        eval $statusCallback {"pause must be >=0"}
        return -code error "RunTimingScanExperiment: pause must be >=0"
    }

    # Check the output directory and rootname 
    if ![string length $outputDir] {
        set outputDir .
    }
    if ![file exists $outputDir] {
        if {[catch {file mkdir $outputDir} result]} {
            eval $statusCallback {"$result"}
            return -code error "RunTimingScanExperiment: $result"
        }
    }
    if ![string length $outputRoot] {
        eval $statusCallback {"output root is blank"}
        return -code error "RunTimingScanExperiment: output root is blank"
    }
    if {$runIndex<0} {
        # search for the next available "slot" for an output file.
        set existingFiles [glob -nocomplain $outputDir/$outputRoot\[0-9\]\[0-9\]*]
        set runIndex 0
        if [llength $existingFiles] {
            while 1 {
                set outputFile [format $outputDir/$outputRoot%02ld $runIndex]
                if [lsearch -glob $existingFiles ${outputFile}*]==-1 break
                incr runIndex
            }
        }
    }
    set outputFile [format $outputDir/$outputRoot%02ld.raw $runIndex]
    eval $statusCallback {"Main output file is $outputFile"}

    if [file exists $outputFile] {
        # Make sure the user wants to overwrite the existing file.
        set response [APSMultipleChoice [APSUniqueName .] -question "$outputFile exists.  Overwrite it?" \
                        -labelList {Yes No} -returnList {Yes No} -name "File overwrite choice" ]
        switch $response {
            Yes { 
                if [catch {file delete [glob -nocomplain ${outputFile}*]} result] {
                    eval $statusCallback {"Unable to remove files!"}
                    return
                }
                eval $statusCallback {"$outputFile will be overwritten."}
                
            }
            No { 
                eval $statusCallback {"Give a new output file name."}
                return -code error "RunTimingScanExperiment: Duplicate filename"
            }
        }
    }

    set inputDir $TimingScanArchivalDir/inputFiles
    set template $inputDir/timingScanTemplate.exp
    set inputFile /tmp/[APSTmpString]
    APSAddToTempFileList $inputFile 
    # do replacements on the template file to make the sddsexperiment input file
    if [catch \
          {exec replace $template $inputFile \
             -original=<points>,<initial>,<final>,<pause>,<samples>,<inputDir> \
             -replacement=$points,$initial,$final,$pause,$samples,$inputDir} result] {
        eval $statusCallback {"$result"}
        return -code error "RunTimingScanExperiment: $result"
    }

    # make a snapshot of timing data for individual BPMs
    if [catch {exec sddssnapshot $inputDir/individualTiming.req -nameOfData=DELYNow \
                 [file root $outputFile].indivDelays} result] {
        eval $statusCallback {"$result"}
        return -code error "RunTimingScanExperiment: $result"
    }

    set execID [APSExecLog [APSUniqueName .] -width 120 -contextHelp \
                  "Execution window for sddsexperiment scan of BPM timing" \
                  -unixCommand "sddsexperiment -verbose $inputFile $outputFile -echo -summarize" \
                  -abortCallback "$scanCallback -code abort" \
                  -cancelCallback "$scanCallback -code cancel" \
                  -callback "$scanCallback -code ok -fileRoot $outputFile"]
}

proc ScanDoneCallback {args} {
    set code ""
    set fileRoot ""
    APSStrictParseArguments {code fileRoot}

    APSEnableButton .userFrame.run.button
    bell
    switch $code {
        ok {
            set message "Scan completed successfully."
            APSSetVarAndUpdate status $message
            APSInfoWindow [APSUniqueName .] \
              -infoMessage $message
            bell
        }
        - {
            set message "Scan aborted or cancelled---check for proper condition of timing."
            APSSetVarAndUpdate status $message
            APSAlertBox [APSUniqueName .] \
              -errorMessage $message
            bell
            return
        }
    }
    if ![string length $fileRoot] {
        APSSetVarAndUpdate status "Scan aborted or cancelled---check for proper condition of timing."
        return
    }
    set files [glob -nocomplain ${fileRoot}*]
    if [llength $files] {
        APSSetVarAndUpdate status "Compressing file..."
        if [catch {eval exec gzip $files} result] {
            APSSetVarAndUpdate status "$result"
        }
        APSSetVarAndUpdate status "Done."
    } else {
        APSSetVarAndUpdate status "No data was collected!"
    }
}

proc ProcessTimingScanChoice {args} {
    set script ""
    set statusCallback APSNoOp
    APSStrictParseArguments {script statusCallback}

    global TimingScanArchivalDir 
    set files [lsort -decreasing [glob $TimingScanArchivalDir/data/????-????/scan??.raw.gz]] 
    if ![llength $files] {
        eval $statusCallback {"No data."}
        return -code error "ProcessTimingScanChoice: No data."
    }
    regsub -all $TimingScanArchivalDir/data/ $files {} tails0
    regsub -all .raw.gz $tails0 {} tails
    regsub -all /scan $tails . tails0
    set w [APSUniqueName .]
    global dataToProcess
    set dataToProcess ""
    APSScrolledListWindow $w -height 10 -name "Timing Scan Choices" \
      -label "" -selectionVar dataToProcess -itemList $tails0 \
      -contextHelp \
      "Select the data you want to process or review.  The names are of the form <year>-<month><day>.<ID>" \
      -acceptButton 0 -clearButton 1 
    $w.userFrame.sl.listbox configure -selectmode single
    tkwait variable dataToProcess
    if ![string length $dataToProcess] {
        return
    }

    if [catch {eval $script -runID $dataToProcess -statusCallback $statusCallback} result] {
        eval $statusCallback {"$result"}
        return -code error "ProcessTimingScanChoice: $result"
    }
}

proc AnalyzeTimingScan {args} {
    global TimingScanArchivalDir 
    set inputDir $TimingScanArchivalDir/inputFiles

    set runID ""
    set statusCallback APSNoOp
    APSStrictParseArguments {runID statusCallback}

    # construct name of main data file 
    regsub \\.  $runID /scan runID
    set runFile $TimingScanArchivalDir/data/$runID.raw.gz
    if ![file exists $runFile] {
        eval $statusCallback {"$runFile not found"}
        return -code error "AnalyzeTimingScan: $runFile not found"
    }
    eval $statusCallback {"Working on analysis of $runID"}

    set fileRoot [file rootname [file rootname $runFile]]
    set evalFile $fileRoot.eval

    # remove old file if there is one
    catch {file delete -f $evalFile} 

    if [catch {exec sddsconvert $runFile -pipe=out \
                 -retain=column,*sum.RVAL,*olddata*,*P0DL \
                 | sddsprocess -pipe \
                 "-define=column,%s:sum.Gated,%s:sum.RVAL 1 %s:olddata_sum_bi - *,type=float,select=S*:P?:sum.RVAL,edit=%/:sum.RVAL//" \
                 | sddsconvert -pipe=in $evalFile \
                 -retain=column,*P0DL,*Gated} result] {
        eval $statusCallback {"$result"}
        return -code error "AnalyzeTimingScan: $result"
    }

    set outputFile $fileRoot.newDelays
    catch {file delete -f $outputFile}

    # Make a list of sddsprocess options for finding the edge for
    # each BPM as a function of its sector timing delay.
    set processList ""
    set newTimingSectors {25 26 27 28}
    for {set sector 1} {$sector<41} {incr sector} {
        if {-1 < [lsearch $newTimingSectors $sector]} continue
        lappend processList "-process=S${sector}\[AB\]*olddata_sum_bi,zeroCrossing,%sEdge,functionOf=S:bpm${sector}:time.P0DL,offset=-0.5" 
    }

    # Steps in processing:
    # 1. delete unneeded columns
    # 2. process to find edge positions
    # 3. retain only edge results
    # 4. rename columns to change, e.g., S2 to S02
    # 5. transpose to get a column of BPM names and a column of edge positions
    # 6. rename column of edge positions to "EdgeValue"
    # 7. sort by BPM name (this is why step 4 is needed).
    # 8. break into sectors
    # 9. remove data for edge positions beyond +/-10000 ns
    #    find minimum delay for each page (sector)
    #    compute delta delay relative to this
    #    rename leading zeros in BPM names (e.g., S02->S2)
    # 10. save a copy of this data with one page per sector
    # 11. merge all the data pages

    set tmpRoot /tmp/[APSTmpString]
    APSAddToTempFileList $tmpRoot.0 $tmpRoot.1 $tmpRoot.2 $tmpRoot.3 $tmpRoot.4
    if [catch \
          {eval exec sddsconvert $runFile -pipe=out -delete=col,Sigma*,*sum.RVAL \
             | sddsprocess -pipe $processList -nowarning \
             | sddscollapse -pipe \
             | sddsconvert -pipe -retain=column,*Edge \
             -edit=column,S\\\[1-9\\\]\\\[AB\\\]*,%/S/S0/ \
             | sddstranspose -pipe -oldColumn=EdgeName \
             | sddsconvert -pipe -rename=column,Column=EdgeValue \
             | sddssort -pipe -column=EdgeName \
             | sddsbreak -rowlimit=9 -pipe \
             | sddsconvert -pipe -dele=column,DeltaEdgeValue,BPMName \
             | sddsprocess -pipe -filter=column,EdgeValue,-1e4,1e4 -nowarning \
             {"-test=parameter,n_rows 0 >"} \
             -process=EdgeValue,min,EdgeValueMin \
             {"-define=column,DeltaEdgeValue,EdgeValue EdgeValueMin -,units=ns"} \
             "-edit=column,BPMName,EdgeName,7f5Da%/S0/S/" \
             | tee $tmpRoot.1 \
             | sddscombine -merge -pipe=in $tmpRoot.0} result] {
        eval $statusCallback {"$result"}
        return -code error "AnalyzeTimingScan: $result"
    }

    eval $statusCallback {"Good results: [exec sdds2stream -rows $tmpRoot.0]"}

    # make snapshot file for P0DL values
    # 1. collapse file containing all min edge positions
    # 2. create new file that is acceptable to burtwb
    #    limit values between -3.6us and 3.6us
    #    add 20ns offset
    if [catch {exec sddscollapse $tmpRoot.1 -pipe=out \
                 | sddsprocess -pipe=in $tmpRoot.2 \
                 "-define=column,Sector,i_row 1 + 24 > ? pop 2 + : pop \$ ,type=long" \
                 "-print=column,ControlName,S:bpm%ld:time.P0DL,Sector" \
                 -filter=column,EdgeValueMin,-3600,3600 \
                 "-define=column,NewDelay,EdgeValueMin 30 +,units=ns" \
                 "-print=column,ValueString,%21.15e,NewDelay" \
                 "-print=column,ControlType,pv" \
                 "-print=column,Lineage,-" "-define=column,Count,1,type=long" \
                 "-print=parameter,SnapType,Absolute" } result] {
        eval $statusCallback {"$result"}
        return -code error "AnalyzeTimingScan: $result"
    }

    # Make file with new individual delay values
    # 1. process individual delay snapshot file
    #    to make BPM name column
    # 2. xref in delta edge values (relative to minimum edge value)
    # 3. compute new delays by adding delta edge value to old delay
    #    make output acceptable to burtwb
    # make combined snapshot
    # make list of BPMs for which no edge was found
    # make printouts
    if [catch {exec sddsconvert $fileRoot.indivDelays -pipe=out \
                 -dele=column,BPMName,DELYNew,ValueString,Lineage \
                 -dele=column,SnapType \
                 | sddsprocess -pipe \
                 "-edit=column,BPMName,ControlName,%/:B0:time.DELY//" \
                 | sddsxref -pipe $tmpRoot.0 -match=BPMName -take=* -nowarning \
                 | sddsprocess -pipe=in $tmpRoot.3 \
                 "-define=column,DELYNew,DELYNow DeltaEdgeValue +,units=ns" \
                 "-print=column,ValueString,%21.15e,DELYNew" \
                 "-print=column,Lineage,-" "-define=column,Count,1,type=long" \
                 "-print=parameter,SnapType,Absolute"
        exec sddscombine -merge $tmpRoot.2 $tmpRoot.3 -pipe=out \
                 | tee $outputFile \
                 | sddsprintout -pipe=in $tmpRoot.4 \
                 "-title=Timing scan results for scan $fileRoot" \
                 -column=ControlName,format=%32s -column=ValueString,format=%20s
        exec sddsselect $inputDir/individualTiming.req \
                 $tmpRoot.0 -match=BPMName -invert -pipe=out \
                 | sddsprintout -pipe=in $tmpRoot.5 \
                 -column=BPMName "-title=BPMs for which scan failed to find edge for scan $fileRoot" \
             } result] {
        eval $statusCallback {"$result"}
        return -code error "AnalyzeTimingScan: $result"
    }

    # display as a printout
    APSFileDisplayWindow [APSUniqueName .] -fileName $tmpRoot.4 -deleteOnClose 1 \
      -width 80
    APSFileDisplayWindow [APSUniqueName .] -fileName $tmpRoot.5 -deleteOnClose 1 \
      -width 80

}

proc InstallTimingScanResults {args} {
    global TimingScanArchivalDir 
    global bpmTimingUserAcceptance bpmTimingInstallStatus
    global bpmTimingBPMName bpmTimingDelay bpmTimingUserAction

    set runID ""
    set statusCallback APSNoOp
    APSStrictParseArguments {runID statusCallback}
 
    # construct name of main data file 
    regsub \\.  $runID /scan runID
    set runFile $TimingScanArchivalDir/data/$runID.raw.gz
    set snapFile $TimingScanArchivalDir/data/$runID.newDelays
    set evalFile $TimingScanArchivalDir/data/$runID.eval
    if {![file exists $snapFile] || ![file exists $evalFile]} {
        eval $statusCallback {"$snapFile or $evalFile not found"}
        return -code error "InstallTimingScanResults(1): $snapFile or $evalFile not found"
    }
    eval $statusCallback {"Working on installation of $runID"}

    set delyFile /tmp/[APSTmpString]
    APSAddToTempFileList $delyFile
    if [catch {exec sddsprocess $snapFile $delyFile \
                 -match=column,ControlName=*:B0:time.DELY} result] {
        eval $statusCallback {"$result"}
        return -code error "InstallTimingScanResults(2): $result"
    }
    if {[catch {sdds open $delyFile r} fid] || \
          [catch {APSGetSDDSColumn -sddsFD $fid -column ControlName} controlNameList] || \
          [catch {APSGetSDDSColumn -sddsFD $fid -column EdgeValue} edgeValueList]} {
        eval $statusCallback {"Problem reading control names and edge locations."}
        return -code error "InstallTimingScanResults(3): Problem reading control names and edge locations."
    }
    set edgeValueList0 $edgeValueList
    
    set sddsplotList ""
    set acceptanceList ""
    set index 0
    foreach controlName $controlNameList {
        scan $controlName S%ld sector
        regsub :B0:time.DELY $controlName "" bpmTimingBPMName
        set bpmTimingDelay [lindex $edgeValueList $index]
        lappend sddsplotList -column=S:bpm${sector}:time.P0DL,${bpmTimingBPMName}:sum.Gated -graph=sym,connect -drawline=x0v=$bpmTimingDelay,x1v=$bpmTimingDelay,q0v=0,q1v=1,line=1 -end
        incr index
        lappend acceptanceList 1
        }
    eval exec sddsplot -topline=$runID -layout=3,3 $evalFile $sddsplotList  &

    set w [APSUniqueName .]
    APSDialogBox $w -name "Data evaluation dialog" \
      -contextHelp "Dialog for data evaluation for bpm timng scan installation." \
      -okCommand "set bpmTimingUserAction ok" \
      -cancelCommand "set bpmTimingUserAction cancel"
    APSEnableButton $w.buttonRow.ok.button
    APSSetContextHelp $w.buttonRow.ok.button -contextHelp \
      "Sends the timing values for the accepted BPMs to the IOCs."
    APSSetContextHelp $w.buttonRow.cancel.button -contextHelp \
      "Cancels the operation without changing any timing in the IOCs."
    set bpmTimingInstallStatus "Plotting data.  Please wait..."
    APSScrolledStatus .status -parent $w.userFrame -width 60 -height 10 \
      -textVariable bpmTimingInstallStatus

    APSLabeledOutput .bpm -parent $w -label "BPM: " \
      -textVariable bpmTimingBPMName -width 26
    APSLabeledEntry .delay -parent $w -label "Delay (ns): " \
      -textVariable bpmTimingDelay -width 26
    APSRadioButtonFrame .rbf -parent $w -label "Accept: " \
      -variable bpmTimingUserAcceptance -orientation horizontal \
      -valueList {1 0} -buttonList {Yes No}
    APSDialogBoxAddButton .fwd -parent $w -text "Forward"  \
      -command "set bpmTimingUserAction forward" \
      -contextHelp "Moves editing point forward one BPM"
    APSDialogBoxAddButton .bwd -parent $w -text "Backward" \
      -command "set bpmTimingUserAction backward" \
      -contextHelp "Move backward one BPM"
    APSDialogBoxAddButton .fwd9 -parent $w -text "Forward 9"  \
      -command "set bpmTimingUserAction forward9" \
      -contextHelp "Moves editing point forward nine BPMs"
    APSDialogBoxAddButton .bwd9 -parent $w -text "Backward 9" \
      -command "set bpmTimingUserAction backward9" \
      -contextHelp "Moves editing point backward nine BPMs"

    APSSetVarAndUpdate bpmTimingInstallStatus "Please review and evaluate plots."

    set index 0
    set maxIndex [expr [llength $controlNameList]-1]
    while 1 {
        if $index<0 {
            set index 0
        }
        if $index>$maxIndex {
            set index $maxIndex
        }
        set controlName [lindex $controlNameList $index]
        set bpmTimingDelay [lindex $edgeValueList $index]
        set bpmTimingUserAcceptance [lindex $acceptanceList $index]
        scan $controlName S%ld sector
        regsub :B0:time.DELY $controlName  "" bpmTimingBPMName
        tkwait variable bpmTimingUserAction
        set acceptanceList [lreplace $acceptanceList $index $index $bpmTimingUserAcceptance]
        set edgeValueList [lreplace $edgeValueList $index $index $bpmTimingDelay]
        switch $bpmTimingUserAction {
            ok {
                break
            }
            forward {
                incr index
            }
            forward9 {
                incr index 9
            }
            backward {
                incr index -1
            }
            backward9 {
                incr index -9
            }
            cancel {
                catch {destroy $w}
                return
            }
        }
    }
    catch {destroy $w}

    set outputControlName ""
    set outputDelay ""
    set outputCount 0
    for {set index 0} {$index<=$maxIndex} {incr index} {
        if [lindex $acceptanceList $index] {
            # form lists of output control names and delta values from user
            lappend outputControlName [lindex $controlNameList $index]
            lappend outputDelayDelta [expr [lindex $edgeValueList $index]-[lindex $edgeValueList0 $index]]
            incr outputCount
        }
    }
    eval $statusCallback {"$outputCount delays accepted.  Installing..."}
    
    set deltaFile /tmp/[APSTmpString]
    APSAddToTempFileList deltaFile
    if {[catch {sdds open $deltaFile w} fid] || \
          [catch {sdds defineColumn $fid ControlName -type SDDS_STRING 
              sdds defineColumn $fid DelayDelta -type SDDS_DOUBLE
              sdds writeLayout $fid
              sdds startPage $fid $outputCount
              eval sdds setColumn $fid ControlName $outputControlName
              eval sdds setColumn $fid DelayDelta $outputDelayDelta
              sdds writePage $fid 
              sdds close $fid} result]} {
        eval $statusCallback {"$fid $result"}
        return -code error "InstallTimingScanResults(4): $fid $result"
    }

    # pull delta delays into snapshot file
    # make altered ValueString column
    set delySnap /tmp/[APSTmpString]
    set P0DLSnap /tmp/[APSTmpString]
    set fullSnap /tmp/[APSTmpString]
    APSAddToTempFileList $P0DLSnap $delySnap $fullSnap
    if [catch {exec sddsxref $delyFile $deltaFile -match=ControlName -nowarning -pipe=out \
                 -take=* \
                 | sddsconvert -pipe -dele=column,ValueString \
                 | sddsprocess -pipe=in $delySnap \
                 "-redefine=column,DELYNew,DELYNew DelayDelta +" \
                 "-print=column,ValueString,%21.15e,DELYNew" 
        exec sddsprocess $snapFile $P0DLSnap -match=column,ControlName=*P0DL
        exec sddscombine $P0DLSnap $delySnap -merge $fullSnap } result] {
        eval $statusCallback {"$fid $result"}
        return -code error "InstallTimingScanResults(5): $fid $result"
    }

    set logFile /tmp/[APSTmpString]
    APSAddToTempFileList $logFile
    if {[catch {exec sddscasr -restore $fullSnap} result]} {
        eval $statusCallback {"Error restoring snapshot: $result"}
        return -code error "InstallTimingScanResults(6): Errors in restore of $fullSnap: $result"
    }
    
    # make list of BPMs that were not installed, either because the user
    # rejected them or because they didn't have good scans.
    set badList /tmp/[APSTmpString]
    APSAddToTempFileList $badList
    if [catch {exec sddsselect $TimingScanArchivalDir/inputFiles/individualTiming.req \
                $fullSnap -match=ControlName -pipe=out -invert \
                | sddsprintout -pipe=in $badList -column=ControlName \
                "-title=BPMs for which delay data was not changed." } result] {
        return -code error "InstallTimingScanResults(7): Error making list of bad BPMs: $result"
    }
    APSFileDisplayWindow [APSUniqueName .] -fileName $badList \
      -comment "BPMs for which delay data was not changed." \
      -width 40 

    eval $statusCallback {"Installation of timing data completed."}
}

proc SwitchArchivalMode {args} {
    set archival 0
    set nonArchivalWidgets ""
    APSStrictParseArguments {archival nonArchivalWidgets}
    global outputDir outputRoot runIndex 
    global TimingScanArchivalDir 
    if $archival {
        foreach elem $nonArchivalWidgets {
            $elem configure -state disabled
        }
        set outputDir $TimingScanArchivalDir/data/[exec date +%Y-%m%d]
        set outputRoot scan
        set runIndex -1
    } else {
        foreach elem $nonArchivalWidgets {
            $elem configure -state normal
        }
        set outputDir [pwd]
        set outputRoot ""
        set runIndex 0
    }
}

set nonArchivalWidgets ""
set archivalWidgets ""
proc MakeNonArchivalFrame {widget args} {
    set parent ""
    APSStrictParseArguments {parent}

    global nonArchivalWidgets archivalWidgets
    APSFrame $widget -parent $parent -label "Nonarchival output specification"
    set w $parent$widget.frame
    
    APSLabeledEntry .outputDir -parent $w -label "Directory: " \
      -width 60 -textVariable outputDir -contextHelp \
      "The directory for the files to which data will be saved."
    lappend nonArchivalWidgets $w.outputDir.entry
    APSLabeledEntry .output -parent $w    -label "Rootname:  " \
      -width 60 -textVariable outputRoot -contextHelp \
      "The root name for the files to which data will be saved.  The output file is <rootname>-<runIndex>.sdds"
    lappend nonArchivalWidgets $w.output.entry
    APSLabeledEntry .index -parent $w     -label "Run index: " \
      -width 60 -textVariable runIndex -contextHelp \
      "The run index for the next experiment.  Automatically incremented after each experiment."
    lappend nonArchivalWidgets $w.index.entry

    APSRadioButtonFrame .archival -parent $w -label "Archival: " \
      -variable archivalData -buttonList {Yes No} -valueList {1 0} \
      -orientation horizontal -commandList \
      {"SwitchArchivalMode -archival 1 -nonArchivalWidgets $nonArchivalWidgets" \
         "SwitchArchivalMode -archival 0 -nonArchivalWidgets $nonArchivalWidgets"} \
      -contextHelp "Selects whether to collect and review archival data.  \
 The data is placed in an archival area for long-term use." 

    SwitchArchivalMode -archival 1 -nonArchivalWidgets $nonArchivalWidgets 
}

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

    APSFrame $widget -parent $parent -label "Scan parameters"
    set w $parent$widget.frame
    APSLabeledEntry .points -parent $w -label "Points: " \
      -width 10 -textVariable points -contextHelp \
      "The number of points at which to take data."
    APSLabeledEntry .samples -parent $w -label "Samples: " \
      -width 10 -textVariable samples -contextHelp \
      "The number of samples to take per point."
    APSLabeledEntry .pause -parent $w -label "Pause (s): " \
      -width 10 -textVariable pause -contextHelp \
      "The amount of time to pause between samples."
    APSLabeledEntry .initial -parent $w -label "Initial (ns): " \
      -width 10 -textVariable initial -contextHelp \
      "The initial delay offset for the experiment."
    APSLabeledEntry .final -parent $w -label "Final (ns): " \
      -width 10 -textVariable final -contextHelp \
      "The final delay offset for the experiment."

}

proc setStatusText {text} {
    global status
    set status $text
    update
}

set outputDir [pwd]
set outputRoot ""
set runIndex 0
set points 37
set pause 1
set samples 5
set initial -153
set final 153
set archivalData 1

set CVSRevisionAuthor "\$Revision: 1.14 $ \$Author: emery $"
APSApplication . -name SRBPMTimingScan -version $CVSRevisionAuthor \
  -overview "Does SR BPM timing scans to determine best timing for BPM operation."

set status Ready.
APSScrolledStatus .status -parent .userFrame -textVariable status -width 60 -height 8

MakeNonArchivalFrame .nonarchival -parent .userFrame 
MakeScanParametersFrame .scan -parent .userFrame

APSButton .run -parent .userFrame -text Run -command \
  {catch {RunTimingScanExperiment -outputRoot $outputRoot -runIndex $runIndex \
            -outputDir $outputDir \
            -points $points -pause $pause -initial $initial -final $final \
            -statusCallback setStatusText -scanCallback ScanDoneCallback}} \
  -contextHelp "Does a BPM timing scan."

APSButton .review -parent .userFrame -text Process/Review \
  -command "ProcessTimingScanChoice -script AnalyzeTimingScan -statusCallback setStatusText" -contextHelp \
  "Allows processing and review of data."

APSButton .install -parent .userFrame -text Review/Install \
  -command "ProcessTimingScanChoice -script InstallTimingScanResults -statusCallback setStatusText" \
  -contextHelp \
  "Allows review and selective installation of processed results"
