#!/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
package require math

set CVSRevisionAuthor "\$Revision: 1.84 $ \$Author: flood $"

proc ConvertToDateString {seconds} {
    return [clock format [expr round($seconds)] -format "%m/%d %H:%M"]
}
proc ConvertToDateStringWithYear {seconds} {
    return [clock format [expr round($seconds)] -format "%m/%d/%Y %H:%M"]
}

proc MakeDateTimeFrame {widget args} {
    set parent .
    set label "Date of Interest"
    set rootname ""
    APSStrictParseArguments {parent label rootname}

    APSFrame $widget -parent $parent -label $label
    set w $parent$widget.frame

    APSDateTimeAdjEntry .startDate \
      -parent $w \
      -yearVariable Year$rootname \
      -monthVariable Month$rootname \
      -dayVariable Day$rootname
}

proc FillSelectionDialog {} {

    global fillNumber saveCommandChoice

    set parent [APSUniqueName .]
    APSDialogBox $parent \
      -name "Select Fill for Editing" 
    set w $parent.userFrame

    APSLabeledEntry .fn \
      -parent $w \
      -label "Fill Number for Entry or Editing" \
      -textVariable fillNumber \
      -width 6 
    $parent.buttonRow.cancel.button configure -command "set saveCommandChoice 0"
    $parent.buttonRow.ok.button configure -command "set saveCommandChoice 1"
    APSEnableButton $parent.buttonRow.ok.button
    bind $parent <Return> {set saveCommandChoice 1}
    wm protocol $parent WM_DELETE_WINDOW {set saveCommandChoice 0}

    focus -force $w.fn.entry
    catch {grab $parent}
    tkwait variable saveCommandChoice
    destroy $parent
    return $saveCommandChoice
}
proc ReasonEntryDialog {fillNumber} {

    global choice returnString dtAfterFill dtBeforeFill runID saveFileDir dumpCause dumpReason useReasons downtimeReason dumpGroup downtimeGroup

    set reasonFile $saveFileDir/$runID.reasons

    set parent [APSUniqueName .]
    set choice 4
    set returnVal 0
    set returnString ""
    set dtAfterFill ""
    set dtBeforeFill ""
    set dumpCause Unknown
    set dumpReason Unknown
    set downtimeReason Unknown
    set dumpGroup Unknown
    set downtimeGroup Unknown

    if [catch {sdds open $reasonFile r} fd] {
        SetFillReviewStatus "unable to open $reasonFile: $fd (ReasonEntryDialog)"
        bell
        return
    }
    set fillList [sdds getColumn $fd FillNumber]

    set numberOfFills [llength $fillList]
    for {set i 0} {$i < $numberOfFills } {incr i} {
        if {$fillNumber == [lindex $fillList $i] } {
            set rlList [sdds getColumn $fd ReasonLost]
            set dtbList [sdds getColumn $fd DowntimeBefore]
            set dtaList [sdds getColumn $fd DowntimeAfter]
            set idList [sdds getColumn $fd IntDump]
            set returnVal [lindex $idList $i]
            set returnString [lindex $rlList $i]
            set dtAfterFill [lindex $dtaList $i]
            set dtBeforeFill [lindex $dtbList $i]
            if {$useReasons} {
                if [catch {sdds getColumn $fd DumpReason} dumpReasonList] {
                    set dumpReason Unknown
                } else {
                    set dumpReason [lindex $dumpReasonList $i]
                }
                if [catch {sdds getColumn $fd DumpGroup} dumpGroupList] {
                    set dumpGroup Unknown
                } else {
                    set dumpGroup [lindex $dumpGroupList $i]
                }
                if [catch {sdds getColumn $fd DowntimeReason} downtimeReasonList] {
                    set downtimeReason Unknown
                } else {
                    set downtimeReason [lindex $downtimeReasonList $i]
                }
                if [catch {sdds getColumn $fd DowntimeGroup} downtimeGroupList] {
                    set downtimeGroup Unknown
                } else {
                    set downtimeGroup [lindex $downtimeGroupList $i]
                }
            } else {
                if [catch {sdds getColumn $fd DumpCause} dumpCauseList] {
                    set dumpCause Unknown
                } else {
                    set dumpCause [lindex $dumpCauseList $i]
                }
            }
        }
    }
    catch {sdds close $fd}

    set catagories [list "Int Dump: End of Period" "Int Refill: Low Current" "Fill Ongoing" "Tornado Warning" ""]

    APSDialogBox $parent -name "Reason Entry for Fill $fillNumber"
    wm protocol $parent WM_DELETE_WINDOW {set choice 5}

    set w $parent.userFrame

    APSLabeledEntry .dtBefore -parent $w -label "Downtime Before Fill: " \
      -textVariable dtBeforeFill  -width 52 

    frame $w.ft -bd 1
    label $w.ft.label -text "Reason Fill Terminated:"
    menubutton $w.ft.mb -text Reason -relief raised -bd 2 -menu $w.ft.mb.menu
    pack $w.ft.label $w.ft.mb -side left -fill x
    menu $w.ft.mb.menu
    $w.ft.mb.menu add radiobutton -label [lindex $catagories 0] -variable choice -value 0
    $w.ft.mb.menu add radiobutton -label [lindex $catagories 1] -variable choice -value 1
    $w.ft.mb.menu add radiobutton -label [lindex $catagories 2] -variable choice -value 2
    $w.ft.mb.menu add radiobutton -label [lindex $catagories 3] -variable choice -value 3
    $w.ft.mb.menu add separator
    $w.ft.mb.menu add radiobutton -label "Fill Lost Because..." -variable choice -value 4

    pack $w.ft -side top -anchor w

    label $w.ft.answer -text $returnString
    pack $w.ft.answer -side right -anchor e

    if {$useReasons} {
        global reasonsChoiceList groupsChoiceList
        APSRadioButtonFrame .dumpReason -parent $w -label "    Dump Reason" -limitPerRow 7 \
          -buttonList $reasonsChoiceList -valueList $reasonsChoiceList \
          -orientation horizontal -packOption "-side top" \
          -variable dumpReason 
        APSRadioButtonFrame .dumpGroup -parent $w -label "  Dump\n  Related Group" -limitPerRow 7 \
          -buttonList $groupsChoiceList -valueList $groupsChoiceList \
          -orientation horizontal -packOption "-side top" \
          -variable dumpGroup 
        APSRadioButtonFrame .downtimeReason -parent $w -label "Downtime Reason" -limitPerRow 7 \
          -buttonList $reasonsChoiceList -valueList $reasonsChoiceList \
          -orientation horizontal -packOption "-side top" \
          -variable downtimeReason 
        APSRadioButtonFrame .downtimeGroup -parent $w -label "  Downtime\n  Related Group" -limitPerRow 7 \
          -buttonList $groupsChoiceList -valueList $groupsChoiceList \
          -orientation horizontal -packOption "-side top" \
          -variable downtimeGroup 
    } else {
        global dumpCauseChoiceList
        APSRadioButtonFrame .dumpCause -parent $w -label "" -limitPerRow 7 \
          -buttonList $dumpCauseChoiceList -valueList $dumpCauseChoiceList \
          -orientation horizontal -packOption "-side top" \
          -variable dumpCause 
    }
    APSLabeledEntry .dtAfter -parent $w -label "Downtime After Fill: " \
      -textVariable dtAfterFill  -width 52 

    #    pack $w.dtBefore $w.ft $w.dtAfter -side top -anchor w

    $parent.buttonRow.cancel.button configure -command "set choice 5"
    $parent.buttonRow.ok.button configure -command "set choice 6"
    APSEnableButton $parent.buttonRow.ok.button
    
    focus $parent
    catch {grab $parent}
    while { $choice < 9 } {
        tkwait variable choice
        if { $choice >= 0 && $choice <= 3 } then {
            if { [winfo exists $w.ft.answer] == 1 } then {
                destroy $w.ft.answer
            }
            set returnString [lindex $catagories $choice]
            set returnVal [expr $choice + 1]
            label $w.ft.answer -text $returnString
            pack $w.ft.answer -side right -anchor e
        } elseif { $choice == 4 } then {
            set newParent [APSUniqueName .]
            set returnVal 0
            APSDialogBox $newParent -name "Reason Fill Lost" 
            set w1 $newParent.userFrame
            APSLabeledEntry .text -parent $w1 -label "Reason Fill Lost: " -textVariable returnString -width 24 
            $newParent.buttonRow.cancel.button configure -command "set choice 7"
            $newParent.buttonRow.ok.button configure -command "set choice 8"
            bind $newParent <Return> {set choice 8}
            focus -force $w1.text.entry
            catch {grab $newParent}

        } elseif { $choice == 5 || $choice == 6 } {
            if { $choice == 5 } then {
                set choice -1
            }

            set dtAfterFill [APSMakeSafeQualifierString $dtAfterFill]
            set dtBeforeFill [APSMakeSafeQualifierString $dtBeforeFill]
            set returnString [APSMakeSafeQualifierString $returnString]

            set returnList [list $choice $fillNumber $returnVal $returnString $dtAfterFill $dtBeforeFill]
            destroy $parent
            return $returnList
        } elseif { $choice == 7 || $choice == 8 } {
            destroy $newParent
            if { [winfo exists $w.ft.answer] } {
                $w.ft.answer configure -text $returnString
            } else {
                label $w.ft.answer -text $returnString
                pack $w.ft.answer -side right -anchor e
            }
            focus $parent
            catch {grab $parent}
        }
    }
}

proc EditReasons {} {

    global historyFile fillNumber tempReasonFile runID saveFileDir dumpCause dumpReason useReasons downtimeReason dumpGroup downtimeGroup

    if {![file exists $historyFile]} {

        if [catch {sdds open /home/helios/oagData/sr/runHistory/runFile} fd] {
            return
        }
        set runID [lindex [APSGetSDDSColumn -sddsFD $fd -column RunName] end]
        catch {sdds close $fd}
        set reasonFile $saveFileDir/$runID.reasons
        exec sddsedit -fileName $reasonFile &
        #        SetFillReviewStatus "Search for Fills Not Performed, this list must exist to proceed (EditReasons)"
        #	bell
        return
    }
    set reasonFile $saveFileDir/$runID.reasons

    if {![FillSelectionDialog]} {
        SetFillReviewStatus "Edit cancelled."
        bell
        return
    }
    if [catch {sdds open $historyFile r} fd] {
        SetFillReviewStatus "unable to open $historyFile: $fd (EditReasons)"
        bell
        return
    }
    set fillList [sdds getColumn $fd FillNumber]
    catch {sdds close $fd}

    foreach fill $fillList {
        lappend tempFillList [expr round($fill)]
    }
    set fillList $tempFillList

    if {[lsearch -exact $fillList $fillNumber] == -1} {
        SetFillReviewStatus "Not a Valid Fill for This Time Period, Edit cancelled"
        SetFillReviewStatus "Valid fill numbers are: $fillList"
        bell
        return	
    }

    set dialogList [ReasonEntryDialog $fillNumber]
    if {[lindex $dialogList 0] == -1} {
        SetFillReviewStatus "Edit cancelled."
        bell
        return
    }

    set lostText [lindex $dialogList 3]
    if {[string length $lostText ] == 0} {
        SetFillReviewStatus "No Reason Given: Edit cancelled."
        bell
        return
    }

    if {[string length $lostText ] > 25 } {
        SetFillReviewStatus "Warning, string truncated"
        bell
        set lostText [string range $lostText 0 24]
    }

    set dtAfterText [lindex $dialogList 4]
    if {[string length $dtAfterText ] > 52 } {
        SetFillReviewStatus "Warning, string truncated"
        bell
        set dtAfterText [string range $dtAfterText 0 52]
    }

    set dtBeforeText [lindex $dialogList 5]
    if {[string length $dtBeforeText ] > 52 } {
        SetFillReviewStatus "Warning, string truncated"
        bell
        set dtBeforeText [string range $dtBeforeText 0 52]
    }

    #   this next section takes the text and numbers returned and create a one row SDDS file
    #   with the same structure as the 'reasons' file    

    set intDumpVal [lindex $dialogList 2]
    set tsVal [clock seconds]

    set empty ""
    if {$useReasons} {
        if {[catch {exec sddssequence -pipe=out -define=index -seq=beg=1,end=1,delta=1 \
                      | sddsprocess -pipe -defi=col,FillNumber,$fillNumber,type=double \
                      -print=col,ReasonLost,$lostText \
                      -print=col,DowntimeBefore,$dtBeforeText \
                      -print=col,DowntimeAfter,$dtAfterText \
                      -defi=col,IntDump,$intDumpVal,type=long \
                      -define=col,TimeStamp,$tsVal,type=double \
                      -print=column,DumpReason,$dumpReason \
                      -print=column,DumpGroup,$dumpGroup \
                      -print=column,DowntimeReason,$downtimeReason \
                      -print=column,DowntimeGroup,$downtimeGroup \
                      | sddsconvert -pipe=in $tempReasonFile -delete=col,index -ascii} results]} {
            file delete $tempReasonFile
            SetFillReviewStatus "error: $results (EditReasons)"
            bell
            return
        }
    } else {
        if {[catch {exec sddssequence -pipe=out -define=index -seq=beg=1,end=1,delta=1 \
                      | sddsprocess -pipe -defi=col,FillNumber,$fillNumber,type=double \
                      -print=col,ReasonLost,$lostText \
                      -print=col,DowntimeBefore,$dtBeforeText \
                      -print=col,DowntimeAfter,$dtAfterText \
                      -defi=col,IntDump,$intDumpVal,type=long \
                      -define=col,TimeStamp,$tsVal,type=double \
                      -print=column,DumpCause,$dumpCause \
                      | sddsconvert -pipe=in $tempReasonFile -delete=col,index -ascii} results]} {
            file delete $tempReasonFile
            SetFillReviewStatus "error: $results (EditReasons)"
            bell
            return
        }
    }

    #   This section takes the one line SDDS file, combines it with the existing 'reasons' file and 
    #   then either overwrite the existing entry or adds it in the order of 'FillNumber'

    if {[catch {exec sddscombine $reasonFile $tempReasonFile -merge -pipe=out \
                  | sddssort -pipe -col=FillNumber -col=TimeStamp,dec \
                  | sddsbreak -pipe -changeOf=FillNumber \
                  | sddsprocess -pipe "-test=col,i_row 0 ==" \
                  | sddscombine -pipe=in $tempReasonFile.1 -merge -overWrite} results]} {
        file delete $tempReasonFile $tempReasonFile.1
        SetFillReviewStatus "error: $results (EditReasons)"
        bell
        return	
    }
    #    file copy -force $tempReasonFile.1 $reasonFile
    exec cp $tempReasonFile.1 $reasonFile
    file delete $tempReasonFile $tempReasonFile.1

    return
}

proc fitData {args} {

    set datafile ""
    set plots 0
    set runId ""
    APSStrictParseArguments {datafile plots runId}

    if {![file exists $datafile]} {
        return -code error "File not found: $datafile (fitData)"
    }

    set plotFile /tmp/[APSTmpString]fitplot
    set fitFile /tmp/[APSTmpString]fitfit
    set binSize 1.0
    set halfBinSize [expr $binSize * 0.5]
    if {[catch {exec sddshist $datafile -pipe=out -data=duration -sizeOfBins=$binSize \
                  -lowerLimit=$halfBinSize -sides \
                  | sddsprocess -pipe=in $plotFile \
                  "-redefine=column,duration, $halfBinSize duration + sto duration"} results]} {
        return -code error "error: $results (fitData)"
    }
    APSAddToTempFileList $plotFile

    if {$plots} {
        catch {exec sddsplot $plotFile -column=duration,frequency -unsuppress=y -graph=impulse &}
    } 

    # The next two 'if statements' handle the case of only one fill. The Poisson 
    # fitting routine cannot the case of only one fill, so this sends it back with the
    # mean value equal to the length of the one fill

    if {[catch {exec sdds2stream -rows $datafile} rows]} {
        SetFillReviewStatus "datafile not found in $datafile (fitData)"
        set returnList [list N 0.0 ]
        return -code ok $returnList
    }
    scan $rows "%d rows" num_fills
    #    puts stdout $num_fills
    if { $num_fills <= 1 } {
        set mean [APSGetSDDSParameter -fileName $datafile -parameter meanFill]
        set returnList [list N $mean ]
        return -code ok $returnList
    }

    if {[catch {exec sddsprocess $plotFile -pipe=out -noWarnings \
                  "-rpnExpression=0 sto tmpSum" \
                  "-define=column,RunningSum,tmpSum frequency + sto tmpSum" \
                  -process=RunningSum,last,SumTotal \
                  "-define=column,RunningSumNorm, RunningSum SumTotal /" \
                  "-define=column,Probability, 1.0 RunningSumNorm -" \
                  -filter=column,Probability,.0001,1.0 \
                  "-define=column,Logc, Probability ln" \
                  | sddspfit -pipe=in $fitFile \
                  -column=duration,Logc \
                  -order=1} results]} {
        return -code error "error: $results (fitData)"
    }
    APSAddToTempFileList $fitFile

    if [catch {sdds open $fitFile r} fd] {
        SetFillReviewStatus  "unable to open $datafile: $fd (fitData)"
        set returnList [list N 0.0 ]
        return -code ok $returnList
    }

    set mean 0
    set slope [sdds getParameter $fd Slope]
    set validFit [sdds getParameter $fd FitIsValid]
    if {$slope != 0 } {
        set mean [expr -1.0/$slope]
    }
    catch {sdds close $fd}

    if {$plots} {
        catch {exec sddsplot \
                 "-xLabel=Store Duration in Hours" "-yLabel=" \
                 -topTitle "-title=Mean Fill Duration $mean" "-topline=[clock format [clock seconds]]" \
                 -graph=symbol,connect,vary=type,scale=2 \
                 -scales=0,100,-5,0, -tickSettings=grid,xspacing=10 \
                 -subTickSettings=grid,xdivision=5,ydivision=2,linetype=2 \
                 -column=duration,Logc "-legend=specified=ln F(t)"  $fitFile \
                 -column=duration,LogcFit -legend=specified=Fit $fitFile \
                 -graph=line,type=1 &}
    }

    set returnList [list $validFit $mean]
    return $returnList
}

proc AnalysisDoubleInt {args} {

    global doubIntLogLin
    set datafile ""
    set runId ""
    APSStrictParseArguments {datafile runId}

    set pScales "-scales=-1.699,1.699,0,1"
    set pTicks "-tickSettings=xlog,xnonexp"
    set pMode "-mode=x=log"

    if {$doubIntLogLin == 0} {
        set pScales "-scales=0,50,0,1"
        set pTicks "-tickSettings=xspacing=5"
        set pMode "-mode=x=linear"
    }

    set diFile /tmp/[APSTmpString]difile
    set cpsFile /tmp/[APSTmpString]cpsfile

    if [catch {sdds open $datafile r} fd] {
        SetFillReviewStatus "Fill File has not been generated. (AnalysisDoubleInt)"
        bell
        return
    }


    set sList [sdds getColumn $fd NumRows]
    set stores [llength $sList]


    set maxRowVal [sdds getParameter $fd maxRowVal]
    set maxRowVal [expr int($maxRowVal)]
    set TotalUser [sdds getParameter $fd TotalUser]
    set NBins [sdds getParameter $fd NBins]
    set MeasInt [expr $TotalUser/$NBins]
    catch {sdds close $fd}

    if {[catch {exec sddssequence -pipe=out -define=Index,type=long \
                  -sequence=begin=1,number=$maxRowVal,delta=1 \
                  | sddsprocess -pipe=in $diFile -define=col,bins,0} results]} {
        bell
        SetFillReviewStatus "error: $results (AnalysisDoubleInt)"
        return
    }
    APSAddToTempFileList $diFile ${diFile}~

    set i 0 
    while { $i < $stores } {
        set StoreLength [lindex $sList $i ]
        if {[catch {exec sddsprocess $diFile \
                      "-rpnExpression=$StoreLength 1 + sto temp" \
                      "-redefine=col,bins, temp 1 - 0 < ? 0 : pop $ sto temp bins + " \
                      -noWarnings} results]} {
            bell
            SetFillReviewStatus "error: $results (AnalysisDoubleInt)"
            return
        }	    
        incr i
    }

    if {[catch {exec sddsprocess $diFile \
                  "-define,col,Pbins,bins $NBins / " \
                  "-define,col,Time,Index $MeasInt * " \
                  "-define=column,PGoal90,Time 24 / chs exp 0.9 *" \
                  "-define=column,PGoal95,Time 24 / chs exp 0.95 *" \
                  -noWarnings} results]} {
        bell
        SetFillReviewStatus "error: $results (AnalysisDoubleInt)"
        return
    }


    if {[catch {exec sddsplot -labelsize=0.03 -dev=cpost -output=$cpsFile \
                  "-title=APS Reliability in $runId" -toptitle \
                  "-xLabel=Experiment Duration in Hours"  "-yLabel=Reliability" \
                  -graph=line,vary $pScales $pTicks $pMode $diFile \
                  -column=Time,Pbins -end \
                  -column=Time,Pbins -legend=spec=Actual \
                  -column=Time,PGoal90 -legend=spec=90%/24Hrs} results]} {
        bell
        SetFillReviewStatus "error: $results (AnalysisDoubleInt)"
        return
    }
    APSAddToTempFileList $cpsFile

    catch {exec ghostview $cpsFile &}
}

proc AnalysisProc {args} {

    set analTemp /tmp/[APSTmpString]analTemp

    set datafile ""
    set useOngoing 1 
    set doubInt 0
    set plots 0
    set runId ""
    set mergeFills 1

    APSStrictParseArguments {datafile useOngoing doubInt plots runId mergeFills}

    if {[catch {sdds open $datafile r} fd]} {
        SetFillReviewStatus "Fill File has not been generated. (AnalysisProc)"
        bell
        return
    }
    set userBeam [sdds getParameter $fd TotalDeliv]
    set intDumpList [sdds getColumn $fd IntDump]
    set duration [sdds getColumn $fd duration]
    set numRows [sdds getColumn $fd NumRows]
    set totalFills [llength $intDumpList]
    catch {sdds close $fd}

    if {[catch {exec sddsprocess $datafile -pipe=out \
                  -define=parameter,lastID,0 \
                  -define=parameter,newFill0,0 \
                  {-define=column,newFill,lastID 0 > ? 0 : 1 $ newFill0 + sto newFill0 IntDump sto lastID pop  ,type=long} \
                  | sddsprocess -pipe \
                  "-define=parameter,mergeFills,$mergeFills" \
                  {-redefine=column,newFill,mergeFills 1 == ? newFill : i_row $ } \
                  | sddsbreak  -pipe \
                  -changeOf=newFill \
                  | sddsprocess -pipe \
                  -process=duration,sum,duration \
                  -process=NumRows,sum,NumRows \
                  -process=SecPerRow,average,SecPerRow \
                  -process=FillNumber,first,FillNumber \
                  -process=IntDump,first,IntDump \
                  | sddscollapse -pipe \
                  | sddsprocess -pipe \
                  -process=TotalUser,first,TotalUser \
                  -process=NBins,first,NBins \
                  | sddsconvert -pipe=in $analTemp \
                  -retain=col,FillNumber,IntDump,NumRows,duration,SecPerRow,} results]} {
        SetFillReviewStatus "error: $results (AnalysisProc)"
        bell
        return
    }

    APSAddToTempFileList $analTemp ${analTemp}~
    # if option selected to delete ongoing fills in calculations, do so now

    #If only one fill exists set useOngoing to 1
    if {$totalFills == 1} {
        set useOngoing 1
    }
    if { $useOngoing == 0 } then {
        if {[catch {exec sddsprocess $analTemp -noWarnings \
                      "-test=col,IntDump 3 == !"} results]} {
            SetFillReviewStatus "error: $results (AnalysisProc)"
            bell
            return
        }
    }

    if {[catch {exec sddsprocess $analTemp -noWarnings \
                  -process=duration,average,meanFill \
                  -process=duration,median,medFill \
                  -process=NumRows,maximum,maxRowVal} results]} {
        SetFillReviewStatus "error: $results (AnalysisProc)"
        bell
        return
    }

    if [catch {sdds open $analTemp r} fd1] {
        SetFillReviewStatus "unable to open $datafile: $fd1 (AnalysisProc)"
        bell
        return
    }
    set meanSdds [sdds getParameter $fd1 meanFill]
    set medianFillDuration [sdds getParameter $fd1 medFill]
    catch {sdds close $fd1}

    #    call the data fitting routing to obtain the tau from a Poisson statical model

    if {[catch {fitData -datafile $analTemp -plots $plots -runId $runId} fittedMean]} {
        SetFillReviewStatus "error: $fittedMean (AnalysisProc)"
        bell
        return
    }

    if {$doubInt} {
        AnalysisDoubleInt -datafile $analTemp -runId $runId
    }

    set talliedFills 0
    set faults 0
    for {set i 0} {$i < $totalFills } {incr i} {
        set k [lindex $intDumpList $i]
        if { $k == 0 || $k == 3 } {
            incr talliedFills
        }
        if { $k == 0 } {
            incr faults
        }
    }

    if { $talliedFills == 0 } {
        set talliedFills 1
    }
    set meanFillDuration [expr $userBeam / $talliedFills]
    set returnList [concat [list $totalFills $talliedFills $meanFillDuration $meanSdds $medianFillDuration $faults] $fittedMean ]
}

proc ListFillDataTwo {args} {

    global saveFileDir printoutFile runID tempFile fileDisplayWidget fitPlots onGoing calcDisplay mergeFills spinfo spinfoparam useReasons spextrainfo
    unset -nocomplain spinfo spinfoparam spextrainfo
    set web 0
    set sddsOutput 0
    set sddsFile ""
    APSStrictParseArguments {fileUser fileFillList web sddsOutput sddsFile}

    set reasonFile $saveFileDir/$runID.reasons
    set extraDowntimeFile $saveFileDir/$runID.extraDownTime
    if {[file exists $extraDowntimeFile]} {
        sdds load $extraDowntimeFile extraDownTime
    } else {
        unset -nocomplain extraDownTime
    }
    set fileID [open $printoutFile w]
    if {$web} {
        puts $fileID "<html><head><title>SR Fill History</title></head>"
        puts $fileID "<body bgcolor=\#ffffff><font size=-1><pre>"
    }
    puts $fileID "Listing of Statistics for $runID (Created [clock format [clock seconds]])"
    puts $fileID " "

    set TotalUser [APSGetSDDSParameter -fileName $fileUser -parameter TotalUser]
    global tornadoTotalUserDifference
    set TotalUser [expr {$TotalUser - ($tornadoTotalUserDifference / 3600.0)}]
    set spinfoparam(totaluser) [format "%6.2f" $TotalUser]
    puts $fileID "Total Amount of User Time in this interval [format "%6.2f" $TotalUser] Hours"
    puts $fileID " "

    puts $fileID "User periods in this interval"
    puts $fileID "-----------------------------"

    if [catch {sdds open $fileUser} fd] {
        SetFillReviewStatus "error: $fd (ListFillDataTwo)"
        bell
        return
    }

    set L1 [APSGetSDDSColumn -sddsFD $fd -column L1]
    set T1Period ""
    set T2Period ""
    foreach l $L1 {
        set l [join $l]
        set alterT1 0
        set alterT2 0
        if {[lrange $l 1 1] == "24:00"} {
            set l [lreplace $l 1 1 23:59:59]
            set alterT1 1
        }
        if {[lrange $l 4 4] == "24:00"} {
            set l [lreplace $l 4 4 23:59:59]
            set alterT2 1
        }
        set tmp [clock scan [lrange $l 0 1]]
        if {$alterT1} {
            set tmp [expr $tmp + 1]
        }
        lappend T1Period $tmp
        set tmp [clock scan [lrange $l 3 4]]
        if {$alterT2} {
            set tmp [expr $tmp + 1]
        }
        lappend T2Period $tmp
    }
    #    set periodLength [APSGetSDDSColumn -sddsFD $fd -column RunLength]
    #    set T1Period [APSGetSDDSColumn -sddsFD $fd -column t1]
    #    set T2Period [APSGetSDDSColumn -sddsFD $fd -column t2]
    set periodLength ""
    foreach t1 $T1Period t2 $T2Period {
        lappend periodLength [expr ($t2 - $t1) / 3600.0]
    }
    catch {sdds close $fd}

    #   bring in the information from the text file and xref in the text
    if [catch {exec sddsxref $fileFillList $reasonFile $tempFile -equate=FillNumber -fillIn -reuse -noWarnings} result] {
        SetFillReviewStatus "$result (ListFillDataTwo)"
        bell
        return
    }

    global suppFile suppTimeFound
    if {$suppTimeFound} {
        if {[catch {exec sdds2stream $suppFile -col=SRFillNumber,Time} suppInfo]} {
            SetFillReviewStatus "$result (ListFillDataTwo)"
            bell
            return        
        }
        sdds load $tempFile tempData
        set rows [llength [lindex $tempData(Column.FillNumber) 0]]
        set reasonListList [lindex $tempData(Column.ReasonLost) 0]
        set intDumpList [lindex $tempData(Column.IntDump) 0]
        set downtimeafterList [lindex $tempData(Column.DowntimeAfter) 0]
        foreach "f t" $suppInfo {
            set f [expr {int($f + .01)}]
            set t [expr {int($t)}]
            for {set i 0} {$i < $rows} {incr i} {
                set t2 [lindex [lindex $tempData(Column.T2) 0] $i]
                if {($t2 < $t) && ([expr {$t2 + 300}] > $t)} {
                    set reasonListList [lreplace $reasonListList $i $i "Starting Supplemental"]
                    set intDumpList [lreplace $intDumpList $i $i 1]
                    set downtimeafterList [lreplace $downtimeafterList $i $i ""]
                    break
                }
            }
        }
        set tempData(Column.ReasonLost) [list $reasonListList]
        set tempData(Column.IntDump) [list $intDumpList]
        set tempData(Column.DowntimeAfter) [list $downtimeafterList]
        sdds save $tempFile tempData
    }

    set stuff [AnalysisProc -datafile $tempFile -useOngoing $onGoing -doubInt 0 -plots $fitPlots -runId $runID -mergeFills $mergeFills]
    if {[llength $stuff]==0} {
        return
    }
    set onGoingText "not used"
    if {$onGoing} {
        set onGoingText "used"
    }


    if { $calcDisplay } {
        global diagText
        set diagText "Total Fills from TCL evaluation [lindex $stuff 0]"
        set diagText "Tallied Fills from TCL evaluation [lindex $stuff 1]"
        set diagText "Mean fill length from TCL evaluation [lindex $stuff 2]"
        set diagText "Mean fill length from SDDS evaluation [lindex $stuff 3]"
        set diagText "Median fill length from SDDS evaluation [lindex $stuff 4]"
        set diagText "Number of Faults [lindex $stuff 5]"
        set diagText "Status of fitted mean calculation [lindex $stuff 6]"
        set diagText "Mean fill length from Poisson model [lindex $stuff 7]"
        update
    }

    if [catch {sdds open $tempFile} fd2] {
        SetFillReviewStatus "error: $fd2 (ListFillDataTwo)"
        bell
        return
    }

    set TotalDeliv [APSGetSDDSParameter -sddsFD $fd2 -parameter TotalDeliv]
    set TotalDelivPC [APSGetSDDSParameter -sddsFD $fd2 -parameter TotalDelivPC]
    set runDownTime [APSGetSDDSParameter -sddsFD $fd2 -parameter runDownTime]
    set beamAvailability [APSGetSDDSParameter -sddsFD $fd2 -parameter beamAvailability]
    set totalAvgCurrent [APSGetSDDSParameter -sddsFD $fd2 -parameter totalAvgCurrent]
    set totalMaHour [APSGetSDDSParameter -sddsFD $fd2 -parameter totalMaHour]
    set T1 [APSGetSDDSColumn -sddsFD $fd2 -column T1]
    set FillNumber [APSGetSDDSColumn -sddsFD $fd2 -column FillNumber]
    set T2 [APSGetSDDSColumn -sddsFD $fd2 -column T2]
    set duration [APSGetSDDSColumn -sddsFD $fd2 -column duration]
    set dt [APSGetSDDSColumn -sddsFD $fd2 -column dt]
    set reasonLost [APSGetSDDSColumn -sddsFD $fd2 -column ReasonLost]
    if {$useReasons} {
        set dumpReasonList [APSGetSDDSColumn -sddsFD $fd2 -column DumpReason]
        set dumpGroupList [APSGetSDDSColumn -sddsFD $fd2 -column DumpGroup]
        set downtimeReasonList [APSGetSDDSColumn -sddsFD $fd2 -column DowntimeReason]
        set downtimeGroupList [APSGetSDDSColumn -sddsFD $fd2 -column DowntimeGroup]
    } else {
        set dumpCauseGroup [APSGetSDDSColumn -sddsFD $fd2 -column DumpCause]
    }
    set dtAfterText [APSGetSDDSColumn -sddsFD $fd2 -column DowntimeAfter]
    set dtBeforeText [APSGetSDDSColumn -sddsFD $fd2 -column DowntimeBefore]
    set period [APSGetSDDSColumn -sddsFD $fd2 -column period]
    catch {sdds close $fd2}

    set meanFillDuration [lindex $stuff 3]
    #    set faults [lindex $stuff 5]
    set faults 0

    set userPeriodBeamTime ""
    set periodFaults ""
    set fillsFound [llength $T1]

    if {(![llength [lindex $reasonLost end]])} {
        if {[catch {exec cavget -list=S:ActualMode -noQuotes -pend=20} result]} {
            set result "Fill Ongoing"
        } else {
            if {($result == "Delivered Beam") || 
                ($result == "Injecting")} {
                set result "Fill Ongoing"
            }
        }
        set reasonLost [lreplace $reasonLost end end $result]
    }
    set edt 0
    set edtlast 0
    set j -1
    for {set i 0} {$i < $fillsFound } {incr i} {
        if { ($i == 0) || 
             ([lindex $period $i] != [lindex $period [expr $i-1]]) } {
            incr j
            lappend periodFaults 0
        }
        # For tornado warnings you must edit the extradowntime file with the
        # related time. That amount of time will be subtracted from the schedualed 
        # time.
        if {[info exists extraDownTime]} {
            foreach dts [lindex $extraDownTime(Column.DowntimeStart) 0] \
              dte [lindex $extraDownTime(Column.DowntimeEnd) 0] \
              dtreason [lindex $extraDownTime(Column.Reason) 0] \
              dttornado [lindex $extraDownTime(Column.TornadoWarning) 0] \
              dtfault [lindex $extraDownTime(Column.Fault) 0] {
                  if {($dts >= [expr {[lindex $T1 $i] - 30}]) && ($dte <= [expr {[lindex $T2 $i] - 30}])} {
                      if {$dttornado != "y"} {
                          set duration [lreplace $duration $i $i [expr {[lindex $duration $i] - (($dte - $dts) / 3600.0)}]]
                          if {[expr $i+1] == $fillsFound} {
                              set edtlast [expr {($dte - $dts) / 3600.0}]
                          } else {
                              set dt [lreplace $dt [expr $i+1] [expr $i+1] [expr {[lindex $dt [expr $i+1]] + (($dte - $dts) / 3600.0)}]]
                          }
                          set edt [expr {$edt + (($dte - $dts) / 3600.0)}]
                      }
                      if {$dtfault == "y"} {
                          set periodFaults [lreplace $periodFaults $j $j [expr {[lindex $periodFaults $j] + 1}]]
                          incr faults
                      }
                  }
              }
        }
    }
    
    if {[info exists extraDownTime]} {
        set i 0
        foreach t1 $T1Period t2 $T2Period {
            foreach dts [lindex $extraDownTime(Column.DowntimeStart) 0] \
              dte [lindex $extraDownTime(Column.DowntimeEnd) 0] \
              dtreason [lindex $extraDownTime(Column.Reason) 0] \
              dttornado [lindex $extraDownTime(Column.TornadoWarning) 0] \
              dtfault [lindex $extraDownTime(Column.Fault) 0] {
                  if {($dttornado == "y") && \
                        ($dts >= [expr {round($t1)}]) && \
                        ($dte <= [expr {round($t2)}])} {
                      set tmptime [expr {($dte - $dts) / 3600.0}]
                      set periodLength [lreplace $periodLength $i $i [expr {[lindex $periodLength $i] - $tmptime}]]
                      set tmp [expr {$TotalDeliv / (.01 * $TotalDelivPC) - $tmptime}]
                      set TotalDelivPC [expr {$TotalDeliv * 100.0 / $tmp}]
                      set runDownTime [expr {$runDownTime - $tmptime}]
                  }
              }
            incr i
        }
    }

    if {$edt != 0} {
        set tmp [expr {$TotalDeliv / (.01 * $TotalDelivPC)}]
        set TotalDeliv [expr {$TotalDeliv - $edt}]
        set TotalDelivPC [expr {$TotalDeliv * 100.0 / $tmp}]
        set runDownTime [expr {$runDownTime + $edt}]
    }
    
    set j -1
    for {set i 0} {$i < $fillsFound } {incr i} {
        if { ($i == 0) || 
             ([lindex $period $i] != [lindex $period [expr $i-1]]) } {
            incr j
            lappend userPeriodBeamTime [lindex $duration $i]
            #	    lappend periodFaults 0
        } else {
            set userPeriodBeamTime [lreplace $userPeriodBeamTime $j $j [expr {[lindex $userPeriodBeamTime $j] + [lindex $duration $i]}]]
            #	    set periodFaults [lreplace $periodFaults $j $j [expr {[lindex $periodFaults $j] + 1}]]
        }
        if {([lindex $reasonLost $i] != "Int Dump: End of Period") &&
            ([lindex $reasonLost $i] != "Int Refill: Low Current") &&
            ([lindex $reasonLost $i] != "Tornado Warning") &&
            ([lindex $reasonLost $i] != "Starting Supplemental") &&
            ([lindex $reasonLost $i] != "Fill Ongoing")} {
            set periodFaults [lreplace $periodFaults $j $j [expr {[lindex $periodFaults $j] + 1}]]
            incr faults
        }
    }

    set faultsDivider $faults
    if { $faults == 0 } {
        set faultsDivider 1
    }
    set MTBF [expr $TotalDeliv / $faultsDivider]
    set deliveredDays [expr $TotalDeliv / 24.0]
    set faultsPerDay [expr $faults / $deliveredDays]
    set userperiod 1
    foreach l $L1 pl $periodLength userBeamTime $userPeriodBeamTime numFaults $periodFaults {
        if {![llength $numFaults]} {
            set numFaults 0
        }
        if {$numFaults} {
            set faultsDivider $numFaults
        } else {
            set faultsDivider 1
        }
        # I should not need this if statement but there is something funny with Run1-2001
        if {[llength $userBeamTime]} {
            set spinfoparam(userperiod$userperiod) "$l [format %6.2f $pl] Hours, Delivered Beam: [format %6.2f $userBeamTime] Hours, [format %2d $numFaults] Fault(s), [format %6.2f [expr {$userBeamTime / $faultsDivider}]] MTBF, [format %6.2f [expr {$userBeamTime * 100.0 / $pl}]]% of Sched. Time"
            set spinfoparam(userperiodtotal) $userperiod
            puts $fileID "$spinfoparam(userperiod$userperiod)"
            incr userperiod
        }
    }
    puts $fileID " "
    
    set spinfoparam(deliveredbeam) [format "%6.2f" $TotalDeliv]
    set spinfoparam(percentschedualed) [format "%6.2f" $TotalDelivPC]
    set spinfoparam(downtimeduringperiod) [format "%6.2f" $runDownTime]
    set spinfoparam(percentschedualed10) [format "%6.2f" $beamAvailability]
    set spinfoparam(avedeliveredcurrent) [format "%6.2f" $totalAvgCurrent]
    set spinfoparam(totalintegratedcurrent) [format "%6.2f" $totalMaHour]
    puts $fileID "Delivered Beam                                  [format "%6.2f" $TotalDeliv] Hours"
    puts $fileID "Percentage of Scheduled Time                    [format "%6.2f" $TotalDelivPC] %"
    puts $fileID "Downtime During Period                          [format "%6.2f" $runDownTime] Hours"
    puts $fileID "Percentage of scheduled time SR current > 10 ma [format "%6.2f" $beamAvailability] %"
    puts $fileID "Average Delivered Current During This Period    [format "%6.2f" $totalAvgCurrent] mA"
    if { $totalMaHour >= 1000.0 } then {
        puts $fileID "Total integrated  Current During This Period    [format "%6.2f" [expr $totalMaHour / 1000.0 ]] A-hr"
    } else {
        puts $fileID "Total integrated  Current During This Period    [format "%6.2f" $totalMaHour] mA-hr"
    }

    #    puts $fileID " "
    #    puts $fileID "Data from an on going fill (if one exists) is $onGoingText in Fill length calculations."
    global ScheduledTopupTime
    set spinfoparam(meanfillduration) [format "%6.2f" $meanFillDuration]
    set spinfoparam(meanfilldurationpoissonfit) [format "%6.2f" [lindex $stuff 7]]
    set spinfoparam(mtbf) [format "%6.2f" $MTBF]
    set spinfoparam(faultsperday) [format "%6.2f" $faultsPerDay]
    set spinfoparam(scheduledtopuptime) [format "%6.2lf" [expr {$ScheduledTopupTime / 3600.0}]]

    puts $fileID " "
    puts $fileID "Mean Fill Duration in Period                    [format "%6.2f" $meanFillDuration] Hours"
    puts $fileID "Mean Fill Duration from Poisson Fit             [format "%6.2f" [lindex $stuff 7] ] Hours"
    puts $fileID "Mean Time Between Faults (MTBF)                 [format "%6.2f" $MTBF] Hours"
    puts $fileID "Faults per Day of Delivered Beam                [format "%6.2f" $faultsPerDay]"
    puts $fileID "Total Number of Faults                          [format "%3d" $faults]"
    puts $fileID "Scheduled Topup Time                            [format "%6.2lf" [expr {$ScheduledTopupTime / 3600.0}]] Hours"

    puts $fileID "                                                                         Length       Downtime is associated with the end of a fill."
    puts $fileID " Valid fills Beginning in this Time Interval|        Reason for        |   of            The first fill of a period will have any"
    global minLength
    puts $fileID " Fill\#  Start            End       Duration |     Fill Termination     | Downtime        downtime before the fill on the line above."
    puts $fileID "                                 (min: ${minLength}) |                          |"

    for {set i 0} {$i < $fillsFound } {incr i} {
        if {($i == [expr $fillsFound - 1]) && (![llength [lindex $reasonLost $i]])} {
            if {[catch {exec cavget -list=S:ActualMode -noQuotes -pend=20} result]} {
                set result "Fill Ongoing"
            } else {
                if {$result == "Delivered Beam"} {
                    set result "Fill Ongoing"
                }
            }
            set reasonLost [lreplace $reasonLost end end $result]
        }
        #       write out first fill in period, including downtime before
        if { $i == 0 || [lindex $period $i] != [lindex $period [expr $i-1]] } {
            set thisPeriodIndex [expr [lindex $period $i] -1]
            set downTimeB4 [expr ([lindex $T1 $i] - [lindex $T1Period $thisPeriodIndex]) / 3600.0]
            if { $i == [expr $fillsFound-1] || [lindex $period $i] != [lindex $period [expr $i+1]] } {
                set downTime [expr ([lindex $T2Period $thisPeriodIndex] - [lindex $T2 $i]) / 3600.0]
            } else {
                set downTime [lindex $dt [expr $i+1]]
            }
            puts $fileID "------------------------------------------------------------------------------------------------------------------------------------"
            puts $fileID "                                            |                          | [format "%5.2f" $downTimeB4] [format %-.52s [lindex $dtBeforeText $i]]"
            puts $fileID "\#[format "%3.0f" [lindex $FillNumber $i]]  [ConvertToDateString [lindex $T1 $i]]  To  [ConvertToDateString [lindex $T2 $i]]  [format "%6.2f" [lindex $duration $i]]  | [format %-24.24s [lindex $reasonLost $i]] | [format "%5.2f" $downTime] [format %-.52s [lindex $dtAfterText $i]]"
            if {$useReasons} {
                set spinfo([expr round([lindex $FillNumber $i])]) \
                  [list \
                     [format "%3.0f" [lindex $FillNumber $i]] \
                     [ConvertToDateStringWithYear [lindex $T1 $i]] \
                     [ConvertToDateStringWithYear [lindex $T2 $i]] \
                     [format "%6.2f" [lindex $duration $i]] \
                     [format %-24.24s [lindex $reasonLost $i]] \
                     [format "%5.2f" $downTime] \
                     [format %-.52s [lindex $dtAfterText $i]] \
                     [lindex $dumpReasonList $i] \
                     [lindex $dumpGroupList $i] \
                     [lindex $downtimeReasonList $i] \
                     [lindex $downtimeGroupList $i] \
                     [lindex $T1 $i] \
                     [lindex $T2 $i]]
                if {$downTimeB4 > .01} {
                    set spextrainfo([expr round([lindex $FillNumber $i])]) \
                      [list \
                         [format "%3.0f" [lindex $FillNumber $i]] \
                         [ConvertToDateStringWithYear [lindex $T1Period $thisPeriodIndex]] \
                         [ConvertToDateStringWithYear [lindex $T1 $i]] \
                         [format "%6.2f" [expr $downTimeB4 * 60.0]] \
                         "" \
                         [format "%5.2f" $downTimeB4] \
                         [format %-.52s [lindex $dtBeforeText $i]] \
                         "Unknown" "Unknown" "Unknown" "Unknown" \
                         [lindex $T1Period $thisPeriodIndex] \
                         [lindex $T1 $i]]
                }
            } else {
                set spinfo([expr round([lindex $FillNumber $i])]) \
                  [list \
                     [format "%3.0f" [lindex $FillNumber $i]] \
                     [ConvertToDateStringWithYear [lindex $T1 $i]] \
                     [ConvertToDateStringWithYear [lindex $T2 $i]] \
                     [format "%6.2f" [lindex $duration $i]] \
                     [format %-24.24s [lindex $reasonLost $i]] \
                     [format "%5.2f" $downTime] \
                     [format %-.52s [lindex $dtAfterText $i]] \
                     [lindex $dumpCauseGroup $i] \
                     [lindex $T1 $i] \
                     [lindex $T2 $i]]
                if {$downTimeB4 > .01} {
                    set spextrainfo([expr round([lindex $FillNumber $i])]) \
                      [list \
                         [format "%3.0f" [lindex $FillNumber $i]] \
                         [ConvertToDateStringWithYear [lindex $T1Period $thisPeriodIndex]] \
                         [ConvertToDateStringWithYear [lindex $T1 $i]] \
                         [format "%6.2f" [expr $downTimeB4 * 60.0]] \
                         "" \
                         [format "%5.2f" $downTimeB4] \
                         [format %-.52s [lindex $dtBeforeText $i]] \
                         "Unknown" \
                         [lindex $T1Period $thisPeriodIndex] \
                         [lindex $T1 $i]]
                }
            }
            #       write out last fill in list
        } elseif { $i == [expr $fillsFound-1] || [lindex $period $i] != [lindex $period [expr $i+1]]} {
            set thisPeriodIndex [expr [lindex $period $i] -1]
            set downTime [expr {$edtlast + ([lindex $T2Period $thisPeriodIndex] - [lindex $T2 $i]) / 3600.0}]
            puts $fileID "\#[format "%3.0f" [lindex $FillNumber $i]]  [ConvertToDateString [lindex $T1 $i]]  To  [ConvertToDateString [lindex $T2 $i]]  [format "%6.2f" [lindex $duration $i]]  | [format %-24.24s [lindex $reasonLost $i]] | [format "%5.2f" $downTime] [format %-.52s [lindex $dtAfterText $i]] "
            if {$useReasons} {
                set spinfo([expr round([lindex $FillNumber $i])]) [list [format "%3.0f" [lindex $FillNumber $i]] [ConvertToDateStringWithYear [lindex $T1 $i]] [ConvertToDateStringWithYear [lindex $T2 $i]] [format "%6.2f" [lindex $duration $i]] [format %-24.24s [lindex $reasonLost $i]] [format "%5.2f" $downTime] [format %-.52s [lindex $dtAfterText $i]] [lindex $dumpReasonList $i] [lindex $dumpGroupList $i] [lindex $downtimeReasonList $i] [lindex $downtimeGroupList $i] [lindex $T1 $i] [lindex $T2 $i]]
            } else {
                set spinfo([expr round([lindex $FillNumber $i])]) [list [format "%3.0f" [lindex $FillNumber $i]] [ConvertToDateStringWithYear [lindex $T1 $i]] [ConvertToDateStringWithYear [lindex $T2 $i]] [format "%6.2f" [lindex $duration $i]] [format %-24.24s [lindex $reasonLost $i]] [format "%5.2f" $downTime] [format %-.52s [lindex $dtAfterText $i]] [lindex $dumpCauseGroup $i] [lindex $T1 $i] [lindex $T2 $i]]
            }
            #       write out all others
        } else {
            set downTime [lindex $dt [expr $i+1]]
            puts $fileID "\#[format "%3.0f" [lindex $FillNumber $i]]  [ConvertToDateString [lindex $T1 $i]]  To  [ConvertToDateString [lindex $T2 $i]]  [format "%6.2f" [lindex $duration $i]]  | [format %-24.24s [lindex $reasonLost $i]] | [format "%5.2f" $downTime] [format %-.52s [lindex $dtAfterText $i]] "
            if {$useReasons} {
                set spinfo([expr round([lindex $FillNumber $i])]) [list [format "%3.0f" [lindex $FillNumber $i]] [ConvertToDateStringWithYear [lindex $T1 $i]] [ConvertToDateStringWithYear [lindex $T2 $i]] [format "%6.2f" [lindex $duration $i]] [format %-24.24s [lindex $reasonLost $i]] [format "%5.2f" $downTime] [format %-.52s [lindex $dtAfterText $i]] [lindex $dumpReasonList $i] [lindex $dumpGroupList $i] [lindex $downtimeReasonList $i] [lindex $downtimeGroupList $i] [lindex $T1 $i] [lindex $T2 $i]]
            } else {
                set spinfo([expr round([lindex $FillNumber $i])]) [list [format "%3.0f" [lindex $FillNumber $i]] [ConvertToDateStringWithYear [lindex $T1 $i]] [ConvertToDateStringWithYear [lindex $T2 $i]] [format "%6.2f" [lindex $duration $i]] [format %-24.24s [lindex $reasonLost $i]] [format "%5.2f" $downTime] [format %-.52s [lindex $dtAfterText $i]] [lindex $dumpCauseGroup $i] [lindex $T1 $i] [lindex $T2 $i]]
            }
        }
        if {[info exists extraDownTime]} {
            foreach dts [lindex $extraDownTime(Column.DowntimeStart) 0] \
              dte [lindex $extraDownTime(Column.DowntimeEnd) 0] \
              dtreason [lindex $extraDownTime(Column.Reason) 0] {
                  if {($dts >= [expr {[lindex $T1 $i] - 30}]) && ($dte <= [expr {[lindex $T2 $i] + 30}])} {
                      puts $fileID " * Interruption of delivered beam between [ConvertToDateString $dts]  To  [ConvertToDateString $dte] $dtreason"
                  }
              }
        }
    }

    global topupInfo
    puts $fileID $topupInfo(data)
    set periodNum 0
    set constancy(n) 0.0
    set constancy(d) 0.0
    set injector(n) 0.0
    set injector(d) 0.0
    set output(1) ""
    set output(2) ""
    for {set i 0} {$i < $fillsFound } {incr i} {
        set n [expr int([lindex $FillNumber $i])]
        if {[info exists topupInfo($n,constancyNumerator)]} {
            if {($periodNum == 0) || ($periodNum != [lindex $period $i])} {
                set periodNum [lindex $period $i]
                set constancy($periodNum,n) 0.0;
                set constancy($periodNum,d) 0.0;
                set injector($periodNum,n) 0.0;
                set injector($periodNum,d) 0.0;
            }
            set constancy($periodNum,n) [expr $topupInfo($n,constancyNumerator) + $constancy($periodNum,n)]
            set constancy($periodNum,d) [expr $topupInfo($n,constancyDenominator) + $constancy($periodNum,d)]
            set constancy($periodNum) [expr 100.0 - ($constancy($periodNum,n) * 100.0) / $constancy($periodNum,d)]
            set injector($periodNum,n) [expr $topupInfo($n,injectorNumerator) + $injector($periodNum,n)]
            set injector($periodNum,d) [expr $topupInfo($n,injectorDenominator) + $injector($periodNum,d)]
            set injector($periodNum) [expr 100.0 - ($injector($periodNum,n) * 100.0) / $injector($periodNum,d)]
            
            set constancy(n) [expr $topupInfo($n,constancyNumerator) + $constancy(n)]
            set constancy(d) [expr $topupInfo($n,constancyDenominator) + $constancy(d)]
            set injector(n) [expr $topupInfo($n,injectorNumerator) + $injector(n)]
            set injector(d) [expr $topupInfo($n,injectorDenominator) + $injector(d)]
        }
    }
    set periodNum 0
    for {set i 0} {$i < $fillsFound } {incr i} {
        if {[info exists topupInfo([expr int([lindex $FillNumber $i])])]} {
            if {($periodNum == 0) || ($periodNum != [lindex $period $i])} {
                if {($periodNum != 0)} {
                    puts $fileID $output(1)
                    puts $fileID $output(2)
                    set output(1) ""
                    set output(2) ""
                } else {
                    append output(1) "Total\n"
                    append output(1) "  Current in Range during Scheduled Topup Time  [format "%6.2lf" [expr {100.0 - (($ScheduledTopupTime - $constancy(d) + $constancy(n)) * 100.0) / (1.0 * $ScheduledTopupTime)}]] %\n"
                    append output(1) "  Current in Range during Delivered Beam Time   [format "%6.2lf" [expr 100.0 - ($constancy(n) * 100.0) / $constancy(d)]] %\n"
                    append output(1) "  Injector Availability                         [format "%6.2lf" [expr 100.0 - ($injector(n) * 100.0) / $injector(d)]] %\n\n"
                }
                set periodNum [lindex $period $i]
                append output(1) "Period Beginning [lrange [lindex $L1 [expr {$periodNum - 1}]] 0 1]\n"
                append output(1) "Current in Range                                [format "%6.2lf" $constancy($periodNum)] %\n"
                append output(1) "Injector Availability                           [format "%6.2lf" $injector($periodNum)] %"
            }
            append output(2) $topupInfo([expr int([lindex $FillNumber $i])])
        }
    }
    puts $fileID $output(1)
    puts $fileID $output(2)
    #   display printoutFile


    if { [winfo exists $fileDisplayWidget] } {
        destroy $fileDisplayWidget
    }
    if {$web} {
        puts $fileID "</pre></font></body></html>"
    }
    flush $fileID
    if {!$web && !$sddsOutput} {
        APSFileDisplayWindow $fileDisplayWidget \
          -fileName $printoutFile \
          -deleteOnClose 1 \
          -width 132 \
          -height 50 \
          -comment "Fills" \
          -printCommand "enscript -rg -fCourier-Bold9" \
          -font "-adobe-courier-bold-r-normal--12-120-75-75-m-70-iso8859-1"
        APSDialogBoxAddButton .html -parent $fileDisplayWidget -text "Export to HTML" -command "SaveAsHTML -textWidget $fileDisplayWidget.userFrame.file.text"
        APSDialogBoxAddButton .excel -parent $fileDisplayWidget -text "Export to SDDS" -command "SaveAsSDDS -textWidget $fileDisplayWidget.userFrame.file.text"
    } else {
        global htmlOutput
        if $web {
            #	file copy -force $printoutFile $htmlOutput
            exec cp $printoutFile $htmlOutput
        } 
        if $sddsOutput {
            SaveAsSDDS -sddsFile $sddsFile
        }
    }
}

proc SaveAsSDDS {args} {
    set textWidget ""
    set sddsFile ""
    APSStrictParseArguments {textWidget sddsFile}
    global sp spinfo minLength useReasons spextrainfo
    set sp(1) [set sp(2) [set sp(3) 0]]
    if ![string length $sddsFile] {
        toplevel .sp
        wm title .sp "Save Text to SDDS File:"
        set sp(1) 1
        APSCheckButtonFrame .cbf \
          -parent .sp \
          -packOption "-side bottom" \
          -label "" \
          -orientation "vertical" \
          -buttonList {"MTBF & downtime for each division" "Convert to comma separated values file"} \
          -variableList {sp(1) sp(2)}
        set selection [APSFileSelectDialog .savesdds \
                         -parent .sp \
                         -checkValidity 0 \
                         -title "Save Text to SDDS File:" \
                         -contextHelp "Enter a SDDS filename in which to save text" \
                         -modal 0 \
                         -pattern "*"]
        destroy .sp
        if {![llength $selection]} {
            return
        }
        
        if {[file exists $selection]} {
            if {[tk_messageBox -icon question -message "Overwrite existing file?" -default no -type yesno] != "yes"} {
                return
            }
        }
    } else {
        set selection $sddsFile
    }
    global runID spinfoparam
    set fillNumbers [lsort -integer [array names spinfo]]
    set data(ParameterNames) "RunID TotalUserTime"
    if {$useReasons} {
        set data(ColumnNames) "FillNumber Start End StartTime EndTime Duration ReasonForTermination LengthOfDowntime ExtraInfo DumpReason DumpGroup DowntimeReason DowntimeGroup"
    } else {
        set data(ColumnNames) "FillNumber Start End StartTime EndTime Duration ReasonForTermination LengthOfDowntime ExtraInfo DumpCause"
    }
    for {set n 1} {$n <= $spinfoparam(userperiodtotal)} {incr n} {
        append data(ParameterNames) " UserPeriod$n"
        set data(Parameter.UserPeriod$n) [list $spinfoparam(userperiod$n)]
    }
    append data(ParameterNames) " DeliveredBeam PercentOfSchedualedTime DowntimeDuringPeriod PercentOfSchedualedTime10ma AveDeliveredCurrent TotalIntegratedCurrent MeanFillDuration MeanFillDurationPoissonFit MTBF FaultsPerDay ScheduledTopupTime MinimumDuration"
    set data(ParameterInfo.TotalUserTime) "type SDDS_DOUBLE units Hours"
    set data(ParameterInfo.MinimumDuration) "type SDDS_DOUBLE units Hours"
    set data(ParameterInfo.DeliveredBeam) "type SDDS_DOUBLE units Hours"
    set data(ParameterInfo.PercentOfSchedualedTime) "type SDDS_DOUBLE units %"
    set data(ParameterInfo.DowntimeDuringPeriod) "type SDDS_DOUBLE units Hours"
    set data(ParameterInfo.PercentOfSchedualedTime10ma) "type SDDS_DOUBLE units %"
    set data(ParameterInfo.AveDeliveredCurrent) "type SDDS_DOUBLE units mA"
    set data(ParameterInfo.TotalIntegratedCurrent) "type SDDS_DOUBLE units mA-hr"
    set data(ParameterInfo.MeanFillDuration) "type SDDS_DOUBLE units Hours"
    set data(ParameterInfo.MeanFillDurationPoissonFit) "type SDDS_DOUBLE units Hours"
    set data(ParameterInfo.MTBF) "type SDDS_DOUBLE units Hours"
    set data(ParameterInfo.FaultsPerDay) "type SDDS_DOUBLE"
    set data(ParameterInfo.ScheduledTopupTime) "type SDDS_DOUBLE units Hours"

    set data(ColumnInfo.FillNumber) "type SDDS_LONG"
    set data(ColumnInfo.Duration) "type SDDS_DOUBLE units Hours"
    set data(ColumnInfo.LengthOfDowntime) "type SDDS_DOUBLE units Hours"
    set data(ColumnInfo.StartTime) "type SDDS_DOUBLE"
    set data(ColumnInfo.EndTime) "type SDDS_DOUBLE"
    
    set data(Parameter.RunID) [list $runID]
    set data(Parameter.TotalUserTime) [list $spinfoparam(totaluser)]
    set data(Parameter.MinimumDuration) [list $minLength]
    set data(Parameter.DeliveredBeam) [list $spinfoparam(deliveredbeam)]
    set data(Parameter.PercentOfSchedualedTime) [list $spinfoparam(percentschedualed)]
    set data(Parameter.DowntimeDuringPeriod) [list $spinfoparam(downtimeduringperiod)]
    set data(Parameter.PercentOfSchedualedTime10ma) [list $spinfoparam(percentschedualed10)]
    set data(Parameter.AveDeliveredCurrent) [list $spinfoparam(avedeliveredcurrent)]
    set data(Parameter.TotalIntegratedCurrent) [list $spinfoparam(totalintegratedcurrent)]
    set data(Parameter.MeanFillDuration) [list $spinfoparam(meanfillduration)]
    set data(Parameter.MeanFillDurationPoissonFit) [list $spinfoparam(meanfilldurationpoissonfit)]
    set data(Parameter.MTBF) [list $spinfoparam(mtbf)]
    set data(Parameter.FaultsPerDay) [list $spinfoparam(faultsperday)]
    set data(Parameter.ScheduledTopupTime) [list $spinfoparam(scheduledtopuptime)]

    if {$sp(1)} {
        set downtimeReasons ""
        if {$useReasons} {
            foreach n $fillNumbers {
                if {[string trim [lindex $spinfo($n) 4]] != "Int Dump: End of Period"} {
                    if {![info exists dc([lindex $spinfo($n) 9])]} {
                        lappend downtimeReasons "[lindex $spinfo($n) 9]"
                        set dc([lindex $spinfo($n) 9]) 1
                        set dc([lindex $spinfo($n) 9].timelist) [lindex $spinfo($n) 5]
                    } else {
                        incr dc([lindex $spinfo($n) 9])
                        append dc([lindex $spinfo($n) 9].timelist) " [lindex $spinfo($n) 5]"
                    }
                }
            }
        } else {
            foreach n $fillNumbers {
                if {[string trim [lindex $spinfo($n) 4]] != "Int Dump: End of Period"} {
                    if {![info exists dc([lindex $spinfo($n) 7])]} {
                        lappend downtimeReasons "[lindex $spinfo($n) 7]"
                        set dc([lindex $spinfo($n) 7]) 1
                        set dc([lindex $spinfo($n) 7].timelist) [lindex $spinfo($n) 5]
                    } else {
                        incr dc([lindex $spinfo($n) 7])
                        append dc([lindex $spinfo($n) 7].timelist) " [lindex $spinfo($n) 5]"
                    }
                }
            }
        }
        foreach n [lsort $downtimeReasons] {
            append data(ParameterNames) " MTBF_$n"
            set data(ParameterInfo.MTBF_$n) "type SDDS_DOUBLE units Hours"
            set data(Parameter.MTBF_$n) [list [format "%6.2f" [expr {$spinfoparam(deliveredbeam) * 1.0 / $dc($n)}]]]

            append data(ParameterNames) " Downtime_$n"
            set data(ParameterInfo.Downtime_$n) "type SDDS_DOUBLE units Hours"
            set data(Parameter.Downtime_$n) [list [eval math::sum $dc($n.timelist)]]

            append data(ParameterNames) " AveDowntime_$n"
            set data(ParameterInfo.AveDowntime_$n) "type SDDS_DOUBLE units Hours"
            set data(Parameter.AveDowntime_$n) [list [eval math::mean $dc($n.timelist)]]

            append data(ParameterNames) " MedianDowntime_$n"
            set data(ParameterInfo.MedianDowntime_$n) "type SDDS_DOUBLE units Hours"
            set i1 [expr ([llength $dc($n.timelist)] - 1) / 2]
            set i2 [expr ([llength $dc($n.timelist)] - 1) / 2.5]
            if {$i1 == $i2} {
                set data(Parameter.MedianDowntime_$n) [list [lindex $dc($n.timelist) $i1]]
            } else {
                set data(Parameter.MedianDowntime_$n) [list [expr ([lindex $dc($n.timelist) $i1] + [lindex $dc($n.timelist) [expr {$i1 + 1}]]) / 2.0]]
            }
            append data(ParameterNames) " MinDowntime_$n"
            set data(ParameterInfo.MinDowntime_$n) "type SDDS_DOUBLE units Hours"
            set data(Parameter.MinDowntime_$n) [list [eval math::min $dc($n.timelist)]]

            append data(ParameterNames) " MaxDowntime_$n"
            set data(ParameterInfo.MaxDowntime_$n) "type SDDS_DOUBLE units Hours"
            set data(Parameter.MaxDowntime_$n) [list [eval math::max $dc($n.timelist)]]
        }
    }
    foreach n $fillNumbers {
        if {[info exists spextrainfo($n)]} {
            lappend data(Column.FillNumber) [lindex $spextrainfo($n) 0]
            lappend data(Column.Start) [lindex $spextrainfo($n) 1]
            lappend data(Column.End) [lindex $spextrainfo($n) 2]
            lappend data(Column.Duration) [lindex $spextrainfo($n) 3]
            lappend data(Column.ReasonForTermination) [lindex $spextrainfo($n) 4]
            lappend data(Column.LengthOfDowntime) [lindex $spextrainfo($n) 5]
            lappend data(Column.ExtraInfo) [lindex $spextrainfo($n) 6]
            if {$useReasons} {
                lappend data(Column.DumpReason) [lindex $spextrainfo($n) 7]
                lappend data(Column.DumpGroup) [lindex $spextrainfo($n) 8]
                lappend data(Column.DowntimeReason) [lindex $spextrainfo($n) 9]
                lappend data(Column.DowntimeGroup) [lindex $spextrainfo($n) 10]
                lappend data(Column.StartTime) [lindex $spextrainfo($n) 11]
                lappend data(Column.EndTime) [lindex $spextrainfo($n) 12]
            } else {
                lappend data(Column.DumpCause) [lindex $spextrainfo($n) 7]
                lappend data(Column.StartTime) [lindex $spextrainfo($n) 8]
                lappend data(Column.EndTime) [lindex $spextrainfo($n) 9]
            }
            
        }
        lappend data(Column.FillNumber) [lindex $spinfo($n) 0]
        lappend data(Column.Start) [lindex $spinfo($n) 1]
        lappend data(Column.End) [lindex $spinfo($n) 2]
        lappend data(Column.Duration) [lindex $spinfo($n) 3]
        lappend data(Column.ReasonForTermination) [lindex $spinfo($n) 4]
        lappend data(Column.LengthOfDowntime) [lindex $spinfo($n) 5]
        lappend data(Column.ExtraInfo) [lindex $spinfo($n) 6]
        if {$useReasons} {
            lappend data(Column.DumpReason) [lindex $spinfo($n) 7]
            lappend data(Column.DumpGroup) [lindex $spinfo($n) 8]
            lappend data(Column.DowntimeReason) [lindex $spinfo($n) 9]
            lappend data(Column.DowntimeGroup) [lindex $spinfo($n) 10]
            lappend data(Column.StartTime) [lindex $spinfo($n) 11]
            lappend data(Column.EndTime) [lindex $spinfo($n) 12]
        } else {
            lappend data(Column.DumpCause) [lindex $spinfo($n) 7]
            lappend data(Column.StartTime) [lindex $spinfo($n) 8]
            lappend data(Column.EndTime) [lindex $spinfo($n) 9]
        }
    }
    foreach name $data(ColumnNames) {
        set data(Column.$name) [list $data(Column.$name)]
    }

    if {[catch {sdds save $selection data} results]} {
        SetFillReviewStatus "error: $results"
        bell
        return
    }
    if {$sp(2)} {
        set csvFile /tmp/[APSTmpString]csv

        if {[catch {exec sdds2spreadsheet $selection $csvFile -delimiter=\\,} results]} {
            SetFillReviewStatus "error: $results"
            bell
            return
        }
        file rename -force $csvFile $selection
    }
    
    #output two files, fill data ($selection.fill) and SR downtime data ($selection.sr)
    set file1 $selection.fill
    set file2 $selection.srdowntime
    set fid1 [open $file1 "w"]
    puts $fid1 "SDDS1"
    puts $fid1 "&parameter name=RunName, type=string, &end"
    puts $fid1 "&parameter name=TotalUserTime, units=hours, type=double, &end"
    puts $fid1 "&parameter name=DeliveredBeam, units=hours, type=double, &end"
    puts $fid1 "&parameter name=TotalDownTime, units=hours, type=double, &end"
    puts $fid1 "&column name=FillNumber, type=long, &end"
    puts $fid1 "&column name=StartTime, type=double, units=seconds, &end"
    puts $fid1 "&column name=EndTime, type=double, units=seconds, &end"
    puts $fid1 "&column name=Duration, type=double, units=hours, &end"
    puts $fid1 "&column name=StartDate, type=string, &end"
    puts $fid1 "&column name=EndDate, type=string, &end"
    puts $fid1 "&data mode=ascii, no_row_counts=1, &end"
    #write data
    puts $fid1 $runID
    puts $fid1 [format %.0f $spinfoparam(totaluser)]
    puts $fid1 $spinfoparam(deliveredbeam)
    puts $fid1 $spinfoparam(downtimeduringperiod)
    for {set n 1} {$n<=$spinfoparam(userperiodtotal)} {incr n} {
        set text $spinfoparam(userperiod$n)
        set tmpList [split $text " "]
        set start [lrange $tmpList 0 1]
        set end [lrange $tmpList 5 6]
        if [regexp {24:00} $start] {
            set starttime [expr [clock scan [regsub {24:00} $start "23:59"]] + 60]
        } else {
            set starttime [clock scan $start]
        }
        if [regexp {24:00} $end] {
            set endtime [expr [clock scan [regsub {24:00} $end "23:59"]] + 60]
        } else {
            set endtime [clock scan $end]
        }
        set index [lsearch $tmpList "Hours,"]
        set duration [lindex $tmpList [expr $index -1]]
        # puts "$index $duration\n$tmpList"
        puts $fid1 "$n $starttime $endtime $duration \"$start\" \"$end\""
    }
    puts $fid1 ""
    close $fid1
    
    set fid2 [open $file2 "w"]
    puts $fid2 "SDDS1"
    puts $fid2 "&parameter name=RunName, type=string, &end"
    puts $fid2 "&parameter name=TotalUserTime, units=hours, type=double, &end"
    puts $fid2 "&parameter name=DeliveredBeam, units=hours, type=double, &end"
    puts $fid2 "&parameter name=TotalDownTime, units=hours, type=double, &end"
    puts $fid2 "&column name=FillNumber, type=long, &end"
    puts $fid2 "&column name=StartTime, type=double, units=seconds, &end"
    puts $fid2 "&column name=EndTime, type=double, units=seconds, &end"
    puts $fid2 "&column name=DownTime, type=double, units=hours, &end"
    puts $fid2 "&column name=StartDate, type=string, &end"
    puts $fid2 "&column name=EndDate, type=string, &end"
    puts $fid2 "&data mode=ascii, no_row_counts=1, &end"
    puts $fid2 $runID
    puts $fid2 [format %.0f $spinfoparam(totaluser)]
    puts $fid2 $spinfoparam(deliveredbeam)
    puts $fid2 $spinfoparam(downtimeduringperiod)
    set index 0
    set len [llength $fillNumbers]
    foreach n $fillNumbers {
        if {[info exists spextrainfo($n)]} {
            if {$useReasons} {
                set start [lindex $spextrainfo($n) 11]
                set end [lindex $spextrainfo($n) 12]
            } else {
                set start [lindex $spextrainfo($n) 8]
                set end [lindex $spextrainfo($n) 9]
            }
            set downtime [lindex $spextrainfo($n) 5]
            if $downtime>0 {
                puts $fid2 "[lindex $spinfo($n) 0] $start $end $downtime \"[clock format [format %.0f $start]]\" \"[clock format [format %.0f $end]]\"" 
            }
        }
        set downtime [lindex $spinfo($n) 5]
        if {$downtime>0} {
            # puts "$downtime [lindex $spinfo($n) 11] [lindex $spinfo($n) 12]"
            if {$useReasons} {
                if {$index==$len-1} {
                    set n1 [lindex $fillNumbers [expr $index-1]]
                    set start [lindex $spinfo($n1) 12]
                    set end [lindex $spinfo($n) 11]
                } else {
                    set start [lindex $spinfo($n) 12]
                    # puts "$index [lindex $fillNumbers [expr $index+1]]"
                    set end [lindex $spinfo([lindex $fillNumbers [expr $index+1]]) 11]
                }
            } else {
                set start [lindex $spinfo($n) 9]
                # puts "$index [lindex $fillNumbers [expr $index+1]]
                set end [lindex $spinfo([lindex $fillNumbers [expr $index+1]]) 8]
            }
            set diff [expr ($end-$start)/3600.0]
            if {[format %.1f $diff]!=[format %.1f $downtime]} {
                puts stderr "Error, start=$start, end=$end, down=$diff hour, not equal to recorded down=$downtime hours."
                puts stderr "Change the start time based the downtime and end time."
                set start [expr $end - $downtime*3600.0]
            }
            puts $fid2 "[lindex $spinfo($n) 0] $start $end $downtime \"[clock format [format %.0f $start]]\" \"[clock format [format %.0f $end]]\""
        }
        incr index
    }
    puts $fid2 ""
    close $fid2
    if [catch {exec sddssort $file2 -col=StartTime -unique -nowarnings } result] {
        return -code error $result
    }
}

proc SaveAsHTML {args} {
    set textWidget ""
    APSStrictParseArguments {textWidget}
    set selection [APSFileSelectDialog .savehtml -checkValidity 0 -title "Save Text to HTML File:" -contextHelp "Enter an html file in which to save text" -modal 0 -pattern "*.htm*"]
    if {![llength $selection]} {
        return
    }
    set text "[$textWidget get 1.0 end]"
    if {[catch {open $selection w} fID]} {
        SetFillReviewStatus "error: $fID (SaveAsHTML)"
        bell
        return
    }
    puts $fID "<html><head>
<title>SR Fill History</title>
</head>
<body bgcolor=\#ffffff><font size=-1><pre>
$text
</pre></font></body></html>"
    catch {close $fID}
    SetFillReviewStatus "HTML file written"
}

proc LoadRunHistory {} {

    global saveFileDir printoutFile runID fitPlotButton doubIntButton relistButton
    global userTimeFile  historyFile reasonsButton savehistButton

    set fileNames [glob $saveFileDir/*.fillList]
    foreach name $fileNames {
        set date [file mtime $name]
        set dateText [clock format $date]
        lappend shortList "[format "%-24.24s" [file tail [file rootname $name]]] [format "%-28.28s" $dateText]"
    }

    set loadFileText [APSListSelectDialog .[APSTmpString] \
                        -itemList $shortList \
                        -name "Fill History Files"]
    set loadFile [lindex [split $loadFileText] 0 ]

    if {[string length $loadFile]==0} {
        return
    }
    set loadFile $saveFileDir/$loadFile

    if {![file exists $loadFile.fillList]} {
        SetFillReviewStatus "File $loadFile.fillList not found! (LoadRunHistory)"
        bell
        return
    }
    if {![APSCheckSDDSFile -fileName $loadFile.fillList]} {
        SetFillReviewStatus "File $loadFile.fillList is not an SDDS file. (LoadRunHistory)"
        bell
        return
    }


    #    file copy -force $loadFile.userTime $userTimeFile
    #    file copy -force $loadFile.fillList $historyFile
    exec cp $loadFile.userTime $userTimeFile
    exec cp $loadFile.fillList $historyFile

    set runID [APSGetSDDSParameter -fileName $historyFile -parameter RunIdentifier]

    ListFillDataTwo -fileUser $userTimeFile -fileFillList $historyFile
    APSEnableButton $fitPlotButton
    APSEnableButton $doubIntButton
    APSEnableButton $relistButton
    APSEnableButton $reasonsButton
    APSEnableButton $savehistButton
}

proc SaveRunHistoryEntryDialog {} {

    global saveFileName saveDescription saveCommandChoice saveFileDir

    set parent [APSUniqueName .]
    APSDialogBox $parent -name "Save Run History setup." 
    set w $parent.userFrame

    APSLabeledEntry .dirname -parent $w -label "Directory: " \
      -textVariable saveFileDir  -width 60 
    APSLabeledEntry .filename -parent $w -label "Filename: " \
      -textVariable saveFileName  -width 60 
    APSLabeledEntry .description -parent $w -label "Description: " \
      -textVariable saveDescription  -width 60 
    $parent.buttonRow.cancel.button configure -command "set saveCommandChoice 0"
    $parent.buttonRow.ok.button configure -command "set saveCommandChoice 1"
    APSEnableButton $parent.buttonRow.ok.button
    
    wm protocol $parent WM_DELETE_WINDOW {set saveCommandChoice 0}

    focus $parent
    catch {grab $parent}
    tkwait variable saveCommandChoice
    destroy $parent
    set saveFileDir [string trim $saveFileDir]
    set saveFileName [string trim $saveFileName]
    set saveDescription [string trim $saveDescription]
    return $saveCommandChoice
}

proc SaveRunHistory {} {

    global historyFile saveFileName saveFileDir saveDescription userTimeFile runID

    if {![file exists $historyFile]} {
        SetFillReviewStatus "No File to Save."
        bell
        return 
    }

    if {![SaveRunHistoryEntryDialog]} {
        SetFillReviewStatus "Save cancelled."
        bell
        return 
    }
    if {[string length $saveFileName]==0} {
        SetFillReviewStatus "No filename given for save."
        bell
        return 
    }
    #    if [string length $saveDescription]==0 {
    #        SetFillReviewStatus "No description given for command."
    #        return
    #    }
    set saveFileDir /home/helios/oagData/sr/runHistory 
    set filename $saveFileDir/$saveFileName

    set choice Overwrite
    if {[file exists $filename]} {
        if {[catch {APSMultipleChoice [APSUniqueName .] \
                      -question "File exists. What do you want to do?" \
                      -labelList {Append Overwrite Cancel} \
                      -returnList  {Append Overwrite Cancel}} choice]} {
            global errorInfo
            SetFillReviewStatus "$errorInfo (SaveRunHistory)"
            bell
            return
        }
    }
    switch $choice {
        Overwrite {
        }
        Append {
        }
        Cancel {
            SetFillReviewStatus "Save aborted."
            bell
            return
        }
        default {
            SetFillReviewStatus "Unknown return value: $choice (SaveRunHistory)"
            bell
            return
        }
    }

    #insert the runID as a parameter into the .fillList file

    if {[catch {exec sddsconvert $historyFile \
                  -nowarnings \
                  -dele=param,RunIdentifier} results]} {
        SetFillReviewStatus "error: $results (SaveRunHistory)"
        bell
        return
    }
    if {[catch {exec sddsprocess $historyFile \
                  -print=parameter,RunIdentifier,$runID \
                  -noWarnings} results]} {
        SetFillReviewStatus "error: $results (SaveRunHistory)"
        bell
        return
    }

    file rename -force $historyFile $filename.fillList
    file rename -force $userTimeFile $filename.userTime
    SetFillReviewStatus "Files $filename saved"
}

proc FindPVDataFiles {args} {
    set ReadbackName ""
    set StartTime [clock scan "Jan 01 00:00:00 1990"]
    set EndTime [clock seconds]
    set startDateList ""
    set endDateList ""
    set SampleIntervals "1 2 4 8 16 32 64 128 256"
    APSStrictParseArguments {ReadbackName StartTime EndTime SampleIntervals startDateList endDateList}

    if {[llength $startDateList]} {
        set StartTime [clock scan "[lindex $startDateList 2]/[lindex $startDateList 3]/[lindex $startDateList 0]"]
    }
    if {[llength $endDateList]} {
        set EndTime [clock scan "23:59:59 [lindex $endDateList 2]/[lindex $endDateList 3]/[lindex $endDateList 0]"]
    }
    
    set fileList ""
    set ReadbackName [join [split $ReadbackName / ] + ]
    set year [clock format $StartTime -format %Y]
    set month [clock format $StartTime -format %m]
    set endyear [clock format $EndTime -format %Y]
    set endmonth [clock format $EndTime -format %m]
    while {($year < $endyear) || (($year == $endyear) && ($month <= $endmonth))} {
        append fileList "[lsort [glob -nocomplain /home/helios/oagData/logging/Variable/[string index ${ReadbackName} 0]/${ReadbackName}/log-${year}-${month}.{gz,xz}]] "
        append fileList "[lsort [glob -nocomplain /home/helios/oagData/logging/\{[join $SampleIntervals ,]\}/${ReadbackName}/log-${year}-${month}.{gz,xz,????}]] "
        if {$month == 12} {
            set month 01
            incr year
        } else {
            scan $month %d month
            incr month
            set month [format %02d $month]
        }
    }
    return $fileList
}

set useReaons 1

proc SearchForFills {args} {
    global inputFile tempFile outputFile historyFile useReasons suppFile
    global userTimeFile printoutFile runID saveFileDir minLength minFillLength
    global plotOption fitPlotButton doubIntButton relistButton reasonsButton savehistButton

    #set DataDir /home/helios/oagData/monitoring/Charge
    set Rootname ChargeFast
    set startyear ""
    set startday ""
    set startmonth ""
    set endyear ""
    set endday ""
    set endmonth ""
    set web 0
    set sddsOutput 0
    set sddsFile ""
    APSStrictParseArguments {startday startmonth startyear endday endmonth endyear web sddsOutput sddsFile}


    #  Determine which run this data is from
    set startTime [clock scan ${startmonth}/${startday}/${startyear}]
    set endTime [clock scan ${endmonth}/${endday}/${endyear}]

    if { $startTime > $endTime } {
        APSAlertBox  .ab[APSUniqueNumber] -errorMessage "Start time later than end time."
        bell
        return
    }

    if {$startTime >= [clock scan 01/01/2001]} {
        set FillNumberOption first
    } elseif {$endTime < [clock scan 01/01/2001]} {
        set FillNumberOption median
    } else {
        APSAlertBox  .ab[APSUniqueNumber] -errorMessage "Years 2000 and 2001 must be searched separately"
        bell
        return
    }
    if {$startTime >= [clock scan 01/01/2004]} {
        set useReasons 1
    } elseif {$endTime < [clock scan 01/01/2004]} {
        set useReasons 0
    } else {
        APSAlertBox  .ab[APSUniqueNumber] -errorMessage "Years 2003 and 2004 must be searched separately"
        bell
        return
    }
    if {$startTime >= [clock scan 01/01/2024]} {
        set currentMin 15.0
    } else {
        set currentMin 50.0
    }


    if {$minFillLength == 1} {
        set minLength 0.0
    } else {
        if {$startTime >= [clock scan 10/01/2002]} {
            set minLength 1.0
        } elseif {$endTime < [clock scan 10/01/2002]} {
            set minLength 0.5
        } else {
            APSAlertBox  .ab[APSUniqueNumber] -errorMessage "Pre and post Oct 1, 2002 must be searched separately"
            bell
            return
        }
    }

    if [catch {sdds open /home/helios/oagData/sr/runHistory/runFile} fd] {
        SetFillReviewStatus "error: $fd (SearchForFills)"
        bell
        return
    }
    set runTimes [APSGetSDDSColumn -sddsFD $fd -column StartRun]
    set runList [APSGetSDDSColumn -sddsFD $fd -column RunName]
    catch {sdds close $fd}
    set runID [lindex $runList end]
    set i 0
    foreach l $runList {
        if {($startTime >= [lindex $runTimes $i]) &&
            ($startTime < [lindex $runTimes [expr $i + 1]])} {
            if {($endTime < [lindex $runTimes $i]) ||
                ($endTime > [lindex $runTimes [expr $i + 1]])} {
                SetFillReviewStatus "Error: Time frame covers more then one run."
                bell
                return
            }
            set runID $l
            break
        }
        incr i
    }
    regsub -all " " $runID "" idNoBlanks

    SetFillReviewStatus "Searching for fills in $runID"

    set idFile $saveFileDir/$idNoBlanks.reasons

    if { ![file exists $idFile] } {
        SetFillReviewStatus "Warning: $idFile not found. (SearchForFills)"
    }
    

    #  Using the entered dates, obtain the list of file names    

    set SDCCTFiles [FindPVDataFiles -ReadbackName S-DCCT:CurrentM -SampleIntervals 8 \
                      -startDateList [APSFormatDate -year $startyear -month $startmonth -day $startday -dateFormat list] \
                      -endDateList   [APSFormatDate -year $endyear -month $endmonth -day $endday -dateFormat list]]
    set ShutterPermitFiles [FindPVDataFiles -ReadbackName ShutterPermit -SampleIntervals 8 \
                              -startDateList [APSFormatDate -year $startyear -month $startmonth -day $startday -dateFormat list] \
                              -endDateList   [APSFormatDate -year $endyear -month $endmonth -day $endday -dateFormat list]]
    set SRFillNumberFiles [FindPVDataFiles -ReadbackName SRFillNumber -SampleIntervals 8 \
                             -startDateList [APSFormatDate -year $startyear -month $startmonth -day $startday -dateFormat list] \
                             -endDateList   [APSFormatDate -year $endyear -month $endmonth -day $endday -dateFormat list]]
    set SRModifiedDesiredModeFiles [FindPVDataFiles -ReadbackName SRModifiedDesiredMode -SampleIntervals 8 \
                                      -startDateList [APSFormatDate -year $startyear -month $startmonth -day $startday -dateFormat list] \
                                      -endDateList   [APSFormatDate -year $endyear -month $endmonth -day $endday -dateFormat list]]

    set fileList "$SDCCTFiles $ShutterPermitFiles $SRFillNumberFiles $SRModifiedDesiredModeFiles"
    set fileListFiltered ""
    foreach f $fileList {
        set f1 /tmp/[APSTmpString].SRFillHistory
        if {[catch {exec sddsprocess $f $f1 -filter=column,CAerrors,-.1,.1} results]} {
            continue
        }
        lappend fileListFiltered $f1
    }
    if {[catch {eval exec sddscombinelogfiles $fileListFiltered -pipe=out | \
                  sddsprocess -pipe=input $inputFile \
                  -filter=col,Time,[clock scan "${startmonth}/${startday}/${startyear}"],[clock scan "23:59:59 ${endmonth}/${endday}/${endyear}"] \
                  -define=param,numRows,n_rows} results]} {
        SetFillReviewStatus "error: $results (SearchForFills)"
        bell
        return
    }
    eval file delete $fileListFiltered

    #  define a parameter that is 10% greater than the number of rows to use in interpolation. This is to ensure that
    #  there are no small gaps in time that were inadvertently created while data was being taken

    set tempRows [APSGetSDDSParameter -fileName $inputFile -parameter numRows]
    set tempRows [expr int([expr $tempRows*1.1])]


    #   perform interpolation. Then filter out all data that was not taken during 'User Mode'
    #   Determine the amount of time that the SR current was greater than 10 ma. Save this 
    #   non-paginated file as tempFile (it will be turned into a file in /tmp)
    if {[catch {exec sddsinterp $inputFile ${suppFile}.2 \
                  -column=Time,* -sequence=$tempRows -forceMonotonic=increasing} results]} {
        SetFillReviewStatus "error: $results (SearchForFills)"
        bell
        return
    }
    global suppTimeFound withSupplimental
    if {$withSupplimental} {
        if {[catch {exec sddsprocess ${suppFile}.2 $tempFile \
                      -filter=col,SRModifiedDesiredMode,.999,2.001 \
                      -define=param,NBins,n_rows \
                      -process=S-DCCT:CurrentM,count,aboveCurrentMin,bottomLimit=$currentMin \
                      "-redefine=column,SRFillNumber,SRFillNumber 0.5 + int" \
                      "-define=par,beamAvailability,aboveCurrentMin NBins / 100.0 *"} results]} {
            SetFillReviewStatus "error: $results (SearchForFills)"
            bell
            return
        }
        set suppTimeFound 0
    } else {
        if {[catch {exec sddsprocess ${suppFile}.2 $tempFile \
                      -filter=col,SRModifiedDesiredMode,.999,1.001 \
                      -define=param,NBins,n_rows \
                      -process=S-DCCT:CurrentM,count,aboveCurrentMin,bottomLimit=$currentMin \
                      "-redefine=column,SRFillNumber,SRFillNumber 0.5 + int" \
                      "-define=par,beamAvailability,aboveCurrentMin NBins / 100.0 *"} results]} {
            SetFillReviewStatus "error: $results (SearchForFills)"
            bell
            return
        }
        if {[catch {exec sddsprocess ${suppFile}.2 -pipe=out -nowarn\
                      -filter=col,SRModifiedDesiredMode,1.999,2.001 \
                      -define=param,NBins,n_rows \
                      -process=S-DCCT:CurrentM,count,aboveCurrentMin,bottomLimit=$currentMin \
                      "-redefine=column,SRFillNumber,SRFillNumber 0.5 + int" \
                      "-define=par,beamAvailability,aboveCurrentMin NBins / 100.0 *" \
                      | sddsbreak -pipe -gapIn=Time \
                      | sddssort -pipe=in $suppFile -col=SRFillNumber -unique} results]} {
            set suppTimeFound 0
        } else {
            set suppTimeFound 1
        }
    }
    file delete ${suppFile}.2

    #   for later use in plotting, set SRModifiedDesiredMode to zero if it is not 1

    #    set origDir [pwd]
    #    cd /tmp
    if {[catch {exec sddsprocess $inputFile \
                  {-redefine=column,SRModifiedDesiredMode,SRModifiedDesiredMode 1 == ? 1 : 0 $ } \
                  -noWarnings} results]} {
        SetFillReviewStatus "error: $results (SearchForFills)"
        bell
        return
    }

    #    cd $origDir

    #   this section is used to determine how many user periods are in the inputed time of interest.
    #   the list of user periods is written to the output file, and the total user time derived. The only
    #   'output' from this section is the total user time, later used in the denominator of the availability
    #   calculation. Thus the use of the temporary file userTimeFile
    if {[catch {exec sddsbreak $tempFile -pipe=out -gapIn=Time \
                  | sddsprocess -pipe \
                  -process=Time,spread,RunLength \
                  -process=Time,first,t1 \
                  -process=Time,last,t2  \
                  | sddscollapse -pipe \
                  | sddsconvert -pipe \
                  -retain=col,RunLength,t1,t2 \
                  | sddstimeconvert -pipe \
                  -breakdown=col,t1,year=t1year,month=t1month,day=t1day,hour=t1hour \
                  -breakdown=col,t2,year=t2year,month=t2month,day=t2day,hour=t2hour \
                  | sddsprocess -pipe=in $userTimeFile \
                  -convert=col,RunLength,hours,s,0.0002777777778 \
                  -process=RunLength,sum,TotalUser \
                  "-redefine=col,t1hour, t1hour 60.0 * .5 + int 60.0 / abs" \
                  "-redefine=col,t2hour, t2hour 60.0 * .5 + int 60.0 / abs" \
                  "-define=col,t1h,t1hour int abs" \
                  "-define=col,t2h,t2hour int abs" \
                  "-define=col,t1m,t1hour t1h - 60.0 * abs" \
                  "-define=col,t2m,t2hour t2h - 60.0 * abs" \
                  "-print=col,L1,%.2d/%.2d/%04.0d %02.0f:%02.0f  To  %.2d/%.2d/%04.0d %02.0f:%02.0f,t1month,t1day,t1year,t1h,t1m,t2month,t2day,t2year,t2h,t2m"} results]} {
        SetFillReviewStatus "error: $results (SearchForFills)"
        bell
        return
    }

    #   this section is used to identify valid fills. The definition of a valid fill is one in which the
    #   shutter permit is granted while there is beam in the SR. If the shutter permit is valid at the beginning of the 
    #   the test will fail. Other data is derived such as duration, fill number, beginning and end times. The paginted 
    #   file is saved as 'outputFile' (which will also be moved to /tmp)
    
    if {[catch {exec sddsbreak $tempFile -pipe=out -gapIn=Time \
                  | sddsprocess  -pipe -noWarnings \
                  -define=param,period,i_page,type=long \
                  -filter=col,S-DCCT:CurrentM,${currentMin},300.0 \
                  -filter=col,ShutterPermit,.9,1.1 \
                  | sddsbreak -pipe -gapIn=Time \
                  | sddsprocess -pipe=in $outputFile -noWarnings \
                  -process=ShutterPermit,maximum,OnAtSomePoint \
                  -process=ShutterPermit,first,OnAlready \
                  "-define=param,ValidStore, OnAtSomePoint 1 ==  ? 1 : 0 \$" \
                  -filter=param,ValidStore,1,1 \
                  "-rpnExpression=0 sto tmpSum,repeat" \
                  "-rpnExpression=0 sto tmpPage" \
                  "-define=column,RunningSum,tmpSum ShutterPermit + sto tmpSum" \
                  -filter=col,RunningSum,.1,1000000.0\
                  -process=Time,first,T1\
                  -process=SRFillNumber,${FillNumberOption},FillNumber\
                  -process=Time,last,T2 \
                  -process=S-DCCT:CurrentM,average,avgCur \
                  "-define=param,maHour,avgCur T2 T1 - * 3600.0 /" \
                  "-define=parameter,PageNum, tmpPage 1 + sto tmpPage" \
                  -define=parameter,NumRows,n_rows,type=long \
                  -process=S-DCCT:CurrentM,last,currentAtDump,tail=-1 \
                  "-define=parameter,SecPerRow, T2 T1 - NumRows /,units=s,description=Interval between data" \
                  "-define=param,duration, T2 T1 - 3600.0 /,units=hours,description=Fill Duration" \
                  -filter=param,duration,-1.0,$minLength,! \
                  "-print=param,Label,Fill #%.0f  Duration %.2f Hours,FillNumber,duration"} results]} {
        SetFillReviewStatus "error: $results (SearchForFills)"
        bell
        return
    }
    #   Collapse the data; calculate total time beam delivered to users and Availability.
    if {[catch {exec sddscollapse $outputFile -pipe=out \
                  | sddsxref -pipe $userTimeFile \
                  -leave=* \
                  -transfer=param,TotalUser -noWarnings \
                  | sddsprocess -pipe=in $historyFile \
                  -process=beamAvailability,first,beamAvailability \
                  -process=duration,sum,TotalDeliv \
                  -process=NBins,first,NBins \
                  -process=maHour,sum,totalMaHour \
                  "-define=param,totalAvgCurrent,totalMaHour TotalDeliv /" \
                  "-define=param,runDownTime,TotalUser TotalDeliv -" \
                  "-define=param,TotalDelivPC,TotalDeliv TotalUser / 100.0 *" \
                  "-define=col,dt,T1 i_row 0 == ? 0 : pop 1 - &T2 \[ - 3600.0 / \$"} results]} {
        SetFillReviewStatus "error: $results (SearchForFills)"
        bell
        return
    }
    #topup info here
    global topupInfo targetCurrentRange minInjDowntime
    unset -nocomplain topupInfo
    set topupInfo(data) ""
    set topupFile /tmp/[APSTmpString]topup
    APSAddToTempFileList $topupFile
    if {[catch {exec sdds2stream  $historyFile -columns=T1,T2,FillNumber} topupRuns]} {
        set topupRuns ""
    }
    if {[catch {sdds load /home/helios/oagData/sr/runHistory/topupMode modeData} results]} {
        set topupRuns ""
    }
    set trueTopupRuns ""
    global ScheduledTopupTime
    set ScheduledTopupTime 0
    set endTime [expr {$endTime + 86400}]
    if {$endTime > [clock seconds]} {
        set endTime [clock seconds]
    }
    foreach FstartTime [lindex $modeData(Column.StartTime) 0] \
      FendTime [lindex $modeData(Column.EndTime) 0] {
          set FstartTime [clock scan $FstartTime]
          set FendTime [clock scan $FendTime]
          if {($startTime <= $FstartTime) && ($endTime >= $FendTime)} {
              set ScheduledTopupTime [expr {$ScheduledTopupTime + $FendTime - $FstartTime}]
          } elseif {($startTime >= $FstartTime) && ($endTime <= $FendTime)} {
              set ScheduledTopupTime [expr {$ScheduledTopupTime + $endTime - $startTime}]
          } elseif {($startTime <= $FstartTime) && ($endTime > $FstartTime) && ($endTime < $FendTime)} {
              set ScheduledTopupTime [expr {$ScheduledTopupTime + $endTime - $FstartTime}]
          } elseif {($startTime > $FstartTime) && ($startTime < $FendTime) && ($endTime >= $FendTime)} {
              set ScheduledTopupTime [expr {$ScheduledTopupTime + $FendTime - $startTime}]
          }
      }
    global saveFileDir runID
    set extraDowntimeFile $saveFileDir/$runID.extraDownTime
    if {[file exists $extraDowntimeFile]} {
        sdds load $extraDowntimeFile extraDownTime
    } else {
        unset -nocomplain extraDownTime
    }
    global tornadoTotalUserDifference
    set tornadoTotalUserDifference 0
    if {[info exists extraDownTime]} {
        foreach FstartTime [lindex $modeData(Column.StartTime) 0] \
          FendTime [lindex $modeData(Column.EndTime) 0] {
              set FstartTime [clock scan $FstartTime]
              set FendTime [clock scan $FendTime]
              foreach dts [lindex $extraDownTime(Column.DowntimeStart) 0] \
                dte [lindex $extraDownTime(Column.DowntimeEnd) 0] \
                dtreason [lindex $extraDownTime(Column.Reason) 0] \
                dttornado [lindex $extraDownTime(Column.TornadoWarning) 0] \
                dtfault [lindex $extraDownTime(Column.Fault) 0] {
                    if {($dttornado == "y") && \
                          ($dts >= [expr {round($FstartTime)}]) && \
                          ($dte <= [expr {round($FendTime)}])} {
                        set tmptime [expr {$dte - $dts}]
                        set ScheduledTopupTime [expr {$ScheduledTopupTime - $tmptime}]
                        set tornadoTotalUserDifference [expr {$tornadoTotalUserDifference + $tmptime}]
                    }
                }
          }
    }
    if {[llength $topupRuns]} {
        foreach "start end fill" $topupRuns {
            set found 0
            foreach FstartTime [lindex $modeData(Column.StartTime) 0] \
              FendTime [lindex $modeData(Column.EndTime) 0] \
              FtargetCurrent [lindex $modeData(Column.TargetCurrent) 0] {
                  #put 15 second boundary at end time.
                  if {($start >= [clock scan $FstartTime]) && ([expr {$end - 15}] <= [clock scan $FendTime])} {
                      set found 1
                      break
                  }
              }
            if {$found} {
                append trueTopupRuns "$start $end $fill $FtargetCurrent "
            }
        }
    }
    set topupRuns $trueTopupRuns
    if {[llength $topupRuns]} {
        append topupInfo(data) "\nTop-Up Mode Statistics\n----------------------\n"
        #	append topupInfo(data) "Target Current = ${targetCurrent}, Range +/- $targetCurrentRange, Minimum Injector Downtime = $minInjDowntime minutes\n"
        append topupInfo(data) "Target Current Range +/- $targetCurrentRange, Minimum Injector Downtime = $minInjDowntime minutes\n"
    }
    set topupDownTime ""
    set injDownTime ""
    foreach "start end fill targetCurrent" $topupRuns {
        set targetMin [expr {$targetCurrent - $targetCurrentRange}]
        set targetMax [expr {$targetCurrent + $targetCurrentRange}]
        exec sddsprocess $inputFile -pipe=out -noWarnings -filter=col,Time,$start,$end -filter=col,S-DCCT:CurrentM,0,$targetMin,S-DCCT:CurrentM,$targetMax,1000,| | sddsbreak -pipe=in $topupFile -gapin=Time,amount=200
        if {[catch {sdds load $topupFile topup} result]} {
            SetFillReviewStatus "unable to load $topupFile: $result"
            bell
            return
        }
        set topupDownTime ""
        foreach data $topup(Column.Time) {
            append topupDownTime "[lindex $data 0] [lindex $data end] "
        }
        set topupDown 0
        foreach "downStart downEnd" $topupDownTime {
            set topupDown [expr $topupDown + [expr $downEnd - $downStart]]
        }
        set fillNum [expr int($fill)]
        set topupInfo($fillNum,constancyNumerator) "$topupDown"
        set topupInfo($fillNum,constancyDenominator) "[expr {$end - $start}]"
        if {[llength $topupDownTime]} {
            # -SavitzkyGolay=1,1,1
            exec sddsprocess $topupFile -pipe=out "-test=param,n_rows 1 == !" | \
              sddssmooth -pipe -columns=S-DCCT:CurrentM -pass=2 | \
              sddsderiv -pipe -diff=S-DCCT:CurrentM -versus=Time | \
              sddsprocess -pipe -noWarnings "-filter=col,S-DCCT:CurrentMDeriv,0,1000,!" | \
              sddsbreak -pipe=in $topupFile.1 -gapin=Time,amount=200
            #	exec sddsprocess $topupFile -pipe=out -noWarnings "-rpnExpression=1000 sto tmpVar,repeat" "-redefine=col,S-DCCT:CurrentM,tmpVar sto tempVar S-DCCT:CurrentM sto tmpVar tmpVar tempVar > ? 1 : 0 $ " -filter=col,S-DCCT:CurrentM,-.1,.1 | sddsbreak -pipe=in $topupFile.1 -gapin=Time,amount=50
            set injDownTime ""
            if {[catch {sdds load $topupFile.1 inj} result]} {
                #		SetFillReviewStatus "unable to load $topupFile.1: $result"
                #		bell
                #		return
            } else {
                foreach data $inj(Column.Time) {
                    append injDownTime "[lindex $data 0] [lindex $data end] "
                }
            }
            file delete -force $topupFile $topupFile.1
        } else {
            set injDownTime ""
        }
        set injDown 0
        foreach "downStart downEnd" $injDownTime {
            if {[expr {$downEnd - $downStart}] > [expr {60 * $minInjDowntime}]} {
                set injDown [expr $injDown + [expr $downEnd - $downStart]]
            }
        }
        set topupInfo($fillNum,injectorNumerator) "$injDown"
        set topupInfo($fillNum,injectorDenominator) "[expr {$end - $start}]"
        set topupInfo($fillNum) ""
        if {[llength $topupDownTime]} {
            set topupInfo($fillNum) ""
        }
        set iend 0
        foreach "downStart downEnd" $topupDownTime {
            append topupInfo($fillNum) "  Out of Range at:     [clock format [expr int($downStart)] -format "%m/%d/%Y %H:%M:%S"] to [clock format [expr int($downEnd)] -format "%m/%d/%Y %H:%M:%S"] : [format "%6.2lf" [expr (int($downEnd) - int($downStart)) / 60.0]] minutes\n"
            set istart 1
            foreach "idownStart idownEnd" $injDownTime {
                if {($idownStart >= $downStart) && 
                    ($idownEnd <= $downEnd) &&
                    ([expr {$idownEnd - $idownStart}] > [expr {60 * $minInjDowntime}])} {
                    if {($istart) && ([expr {$idownStart - 60 * 5}] > $iend)} {
                        set idownStart [expr {$idownStart - 60 * 5}]
                        set topupInfo($fillNum,injectorNumerator) [expr {$topupInfo($fillNum,injectorNumerator) + 60 * 5}]
                    }
                    set istart 0
                    append topupInfo($fillNum) "    Injector downtime: [clock format [expr int($idownStart)] -format "%m/%d/%Y %H:%M:%S"] to [clock format [expr int($idownEnd)] -format "%m/%d/%Y %H:%M:%S"] : [format "%6.2lf" [expr (int($idownEnd) - int($idownStart)) / 60.0]] minutes\n"
                }
            }
            if {($istart) && ([expr {$downStart - 60 * 5}] > $iend)} {
                if {5 < $minInjDowntime} {
                    set estDownTime $minInjDowntime
                } else {
                    set estDownTime 5
                }
                append topupInfo($fillNum) "    Injector downtime: [clock format [expr int($downStart) - int(60 * $estDownTime)] -format "%m/%d/%Y %H:%M:%S"] to [clock format [expr int($downStart)] -format "%m/%d/%Y %H:%M:%S"] : [format "%6.2lf" $estDownTime] minutes (est)\n"
                set topupInfo($fillNum,injectorNumerator) [expr {$topupInfo($fillNum,injectorNumerator) + 60 * $estDownTime}]
            }
            set iend $downEnd
        }
    }
    #end topup info
    ListFillDataTwo -fileUser $userTimeFile -fileFillList $historyFile -web $web -sddsOutput $sddsOutput -sddsFile $sddsFile
    if {!$web && !$sddsOutput} {
        APSEnableButton $fitPlotButton
        APSEnableButton $doubIntButton
        APSEnableButton $relistButton
        APSEnableButton $reasonsButton
        APSEnableButton $savehistButton
    }
    if { $plotOption == "off" } {
        if {[catch {exec sddsconvert $historyFile \
                      -retain=col,FillNumber,T1,T2,duration,NumRows,SecPerRow,ReasonLost,dt,period,avgCur,maHour,currentAtDump \
                      -noWarnings} results]} {
            SetFillReviewStatus "error: $results (SearchForFills)"
            bell
        }
        return
    }
    #   display plots
    
    if [catch {sdds open $historyFile} fd] {
        SetFillReviewStatus "error: $fd (SearchForFills)"
        bell
        return
    }
    set T1List [APSGetSDDSColumn -sddsFD $fd -column T1]
    set T2List [APSGetSDDSColumn -sddsFD $fd -column T2]
    set labelList [APSGetSDDSColumn -sddsFD $fd -column Label]
    catch {sdds close $fd}
    
    SetFillReviewStatus "Ploting"
    foreach t1temp $T1List t2temp $T2List labeltemp $labelList {
        lappend options \
          -column=Time,S-DCCT:CurrentM $inputFile -title=$labeltemp -yscale=id=current \
          -column=Time,S-DCCT:CurrentM $inputFile -scale=0,0,0,115 -yscale=id=current \
          -filter=column,Time,$t1temp,$t2temp -graph=line,type=1 -leg \
          -column=Time,SRModifiedDesiredMode $inputFile -scale=0,0,0,4 -yscale=id=mode -leg -graph=line,type=4 \
          -column=Time,ShutterPermit $inputFile -scale=0,0,0,2 -yscale=id=Shutter -leg -graph=line,type=2 -end
    }
    
    catch {eval exec sddsplot -toptitle -xlabel= -ticks=xtime $options >& /dev/null &}
    
    if {[catch {exec sddsconvert $historyFile \
                  -retain=col,FillNumber,T1,T2,duration,NumRows,SecPerRow,ReasonLost,dt,period,avgCur,maHour,currentAtDump \
                  -noWarnings} results]} {
        SetFillReviewStatus "error: $results (SearchForFills)"
        bell
        return	
    }

}

proc ListRuns {} {

    global loadw

    if [catch {sdds open /home/helios/oagData/sr/runHistory/runFile} fd] {
        SetFillReviewStatus "error: $fd (ListRuns)"
        bell
        return
    }
    set runTimes [APSGetSDDSColumn -sddsFD $fd -column StartRun]
    set runList [APSGetSDDSColumn -sddsFD $fd -column RunName]
    catch {sdds close $fd}

    set runsFound [llength $runTimes]

    for {set i 0} {$i < $runsFound } {incr i} {
        set temp [format "%-15s  %s" [lindex $runList $i] [clock format [expr round([lindex $runTimes $i])] -format "%m/%d/%Y"]]
        lappend newList $temp
    }

    set loadw .listWidget[APSUniqueNumber]

    APSFrame $loadw \
      -parent "" \
      -name "Run List"

    APSScrolledList .list \
      -parent $loadw.frame \
      -itemList $newList \
      -name "Identified Runs"

    APSFrame .buttons \
      -parent $loadw.frame \
      -relief flat \
      -label ""
    APSButton .blah \
      -parent $loadw.frame.buttons.frame \
      -text "Define New Run" \
      -command AddRunDialog
    APSButton .cancel \
      -parent $loadw.frame.buttons.frame \
      -text "Close" \
      -command "destroy $loadw"

}

proc AddRunDialog {} {

    set addRun .ar[APSUniqueNumber]
    APSFrame $addRun \
      -parent "" \
      -name "Define Run"

    set w $addRun.frame
    set runID ""
    set OKdone 0

    APSLabeledEntry .dirname \
      -parent $w \
      -label "Enter Run Identifier:" \
      -textVariable runID \
      -width 24 
    MakeDateTimeFrame .time \
      -parent $w \
      -label "Define Run Start Date" \
      -rootname RunStart

    frame $w.buttonRow -relief raised -bd 2
    pack $w.buttonRow -side bottom -fill x
    APSButton .accept \
      -parent $w.buttonRow \
      -text Accept  \
      -command {AddRun \
                  -year $YearRunStart \
                  -month $MonthRunStart \
                  -day $DayRunStart \
                  -id $runID} \
      -contextHelp  "Check entries for validity and make new entry." \
      -size medium 
    APSButton .ok \
      -parent $w.buttonRow \
      -text Close  \
      -command "set OKdone 1" \
      -contextHelp  "Done interacting with this dialog box. Remove window." \
      -size medium

    wm protocol $addRun WM_DELETE_WINDOW {set OKdone 1}

    focus $addRun
    catch {grab $addRun}
    tkwait variable OKdone
    destroy $addRun
}

proc AddRun {args} {

    global loadw

    set year ""
    set day ""
    set month ""
    set id ""

    set newStuff /tmp/[APSTmpString]
    set newerStuff /tmp/[APSTmpString]

    APSStrictParseArguments {day month year id}

    set seconds [clock scan ${month}/${day}/${year}]
    if {[string length $id]==0} {
        APSAlertBox  .ab[APSUniqueNumber] -errorMessage "Please enter run identifier text."
        return
    }

    # Create a new file for this run that will contain information 
    # about why the fill was lost. The name of the
    # the file is the run identifier with the spaces removed.

    regsub -all " " $id "" idfile

    if {[file exists /home/helios/oagData/sr/runHistory/$idfile.sdds]==1} {
        APSAlertBox .ab[APSUniqueNumber]  -errorMessage "Run Identifier already exists"
        return
    }
    #    file copy -force /home/helios/oagData/sr/runHistory/reasonTemplate /home/helios/oagData/sr/runHistory/$idfile.reasons
    exec cp /home/helios/oagData/sr/runHistory/reasonTemplate /home/helios/oagData/sr/runHistory/$idfile.reasons

    if {[catch {exec sddssequence \
                  -define=index \
                  -sequence=beg=1,end=1,delta=1 \
                  -pipe=out \
                  | sddsprocess \
                  -pipe=in $newStuff \
                  -define=column,StartRun,$seconds \
                  -print=column,RunName,$id} results]} {
        SetFillReviewStatus "error: $results (AddRun)"
        bell
        return
    }
    if {[catch {exec sddscombine $newStuff \
                  /home/helios/oagData/sr/runHistory/runFile \
                  -merge -pipe=out \
                  | sddssort -pipe -column=StartRun \
                  | sddsconvert -pipe=in $newerStuff \
                  -delete=col,index -ascii} results]} {
        SetFillReviewStatus "error: $results (AddRun)"
        bell
        return
    }

    file rename -force $newerStuff /home/helios/oagData/sr/runHistory/runFile

    if {![winfo exists $loadw]} {
        ListRuns
    } else {
        $loadw.frame.list.listbox delete 0 end
        if [catch {sdds open /home/helios/oagData/sr/runHistory/runFile} fd] {
            SetFillReviewStatus "error: $fd (AddRun)"
            bell
            return
        }
        set runTimes [APSGetSDDSColumn -sddsFD $fd -column StartRun]
        set runList [APSGetSDDSColumn -sddsFD $fd -column RunName]
        catch {sdds close $fd}

        set runsFound [llength $runTimes]

        for {set i 0} {$i < $runsFound } {incr i} {
            set temp [format "%-30s  %-25s" [lindex $runList $i] [clock format [expr round([lindex $runTimes $i])]]]
            lappend newList $temp
        }
        eval $loadw.frame.list.listbox insert 0 $newList
    }
}

proc SetFillReviewStatus {text} {
    APSSetVarAndUpdate fillReviewStatus "[clock format [clock seconds] -format "%H:%M:%S"]: $text"
}

proc StartCalcDisplay {onOff} {
    global diagText calcDisplay 

    if {$onOff} {
        if { [winfo exists .diagData] } {
            destroy .diagData
            set calcDisplay 0
        }
    } else {
        if { [winfo exists .diagData] } {
            return
        }
        set diagText Ready
        APSScrolledStatus .diagData -name "Calculation Results" -textVariable diagText -width 70 -height 10
        set calcDisplay 1
    }
}

proc SaveTarget {} {
    global targetCurrent targetCurrentRange minInjDowntime
    if {[catch {sdds load /home/helios/oagData/sr/runHistory/targetCurrent targetData} results]} {
        SetFillReviewStatus "$results"
        return
    }
    set targetData(Parameter.TargetCurrent) [lreplace $targetData(Parameter.TargetCurrent) 0 0 $targetCurrent]
    set targetData(Parameter.Range) [lreplace $targetData(Parameter.Range) 0 0 $targetCurrentRange]
    set targetData(Parameter.MinInjDowntime) [lreplace $targetData(Parameter.MinInjDowntime) 0 0 $minInjDowntime]
    if {[catch {sdds save /home/helios/oagData/sr/runHistory/targetCurrent targetData} results]} {
        SetFillReviewStatus "$results"
        return
    }
    SetFillReviewStatus "Saved Target and Range"
}

proc MakeOptionsWidget {widget args} {
    set parent ""
    APSParseArguments {parent}
    set w $parent$widget.frame

    global fitPlots onGoing doubIntLogLin tempFile \
      fitPlotButton doubIntButton calcDisplay \
      runID mergeFills

    set fitPlots 0
    set onGoing 0
    set doubIntLogLin 1
    set calcDisplay 0
    set runID ""
    set mergeFills 1

    APSFrame $widget -parent $parent \
      -label "Analysis Options"  \
      -contextHelp "Provides buttons and options for analyzing run data"

    APSFrame .frame1 -parent $w -packOption "-side left -anchor n" -label "Top Up Target"
    set w1 $w.frame1.frame
    global targetCurrent targetCurrentRange minInjDowntime
    if {[catch {sdds load /home/helios/oagData/sr/runHistory/targetCurrent targetData} results]} {
        SetFillReviewStatus "$results"
        set targetCurrent 102
        set targetCurrentRange 1
        set minInjDowntime 8
    } else {
        set targetCurrent [format "%3.1f" [lindex $targetData(Parameter.TargetCurrent) 0]]
        set targetCurrentRange [format "%3.1f" [lindex $targetData(Parameter.Range) 0]]
        set minInjDowntime [format "%3.1f" [lindex $targetData(Parameter.MinInjDowntime) 0]]
    }
    #    APSLabeledEntry .e1 -parent $w1 -label "Target Current" -textVariable targetCurrent -width 5 -type real
    APSLabeledEntry .e2 -parent $w1 -label "Range +/-" -textVariable targetCurrentRange -width 5 -type real
    APSLabeledEntry .e3 -parent $w1 -label "Minimum Injector\nDowntime (minutes)" -textVariable minInjDowntime -width 5 -type real
    pack [button $w1.b1 -text "Save Range and\nMin Downtime" -command SaveTarget]

    APSFrame .pFit \
      -parent $w \
      -label "Poisson Fit"  \
      -packOption "-side left -anchor n"

    APSRadioButtonFrame .bf1 \
      -parent $w.pFit.frame \
      -label "Display Plots\nwhile fitting" \
      -variable fitPlots \
      -buttonList {No Yes} \
      -valueList {0 1} \
      -noPack 1 \
      -relief flat \
      -contextHelp "The Poisson fit is done every time a listing of the fills, and associated statistics is displayed. Normally one does not want to see the plots. The button allows the display of the plots as a 'stand alone' feature if desired." 

    APSButton .bf1a \
      -parent $w.pFit.frame \
      -text "Perform Poisson Fit\n(Forces Plots)" \
      -command {AnalysisProc \
                  -datafile $tempFile \
                  -useOngoing $onGoing \
                  -doubInt 0 \
                  -plots 1 \
                  -runId $runID \
                  -mergeFills $mergeFills} \
      -contextHelp "Performs the Poisson Fitting and forces the display of the Plots" \
      -noPack 1
    set fitPlotButton $w.pFit.frame.bf1a.button
    APSDisableButton $fitPlotButton

    pack $w.pFit.frame.bf1
    pack $w.pFit.frame.bf1a
    pack $w.pFit -side left

    APSFrame .doubInt \
      -parent $w \
      -label "Double Integral Plot"  \
      -packOption "-side left -anchor n"

    APSButton .bf2 \
      -parent $w.doubInt.frame \
      -text "Evaluate Integral\n(Forces Plots)" \
      -command {AnalysisProc \
                  -datafile $tempFile \
                  -useOngoing $onGoing \
                  -doubInt 1 \
                  -plots 0 \
                  -runId $runID \
                  -mergeFills $mergeFills} \
      -contextHelp "Evaluates the Integral and displays the resulting plot" \
      -noPack 1
    set doubIntButton $w.doubInt.frame.bf2.button
    APSDisableButton $doubIntButton

    APSRadioButtonFrame .bf2a \
      -parent $w.doubInt.frame \
      -label "Time Scale" \
      -variable doubIntLogLin \
      -buttonList {log lin} \
      -valueList {1 0} \
      -noPack 1 -relief flat \
      -contextHelp "Choose the method of displaying integral, the log is along the time (x) axis."


    pack $w.doubInt.frame.bf2
    pack $w.doubInt.frame.bf2a
    pack $w.doubInt -side left

    pack [frame $w.frame2] -side left
    set w2 $w.frame2
    APSRadioButtonFrame .bf0 \
      -parent $w2 \
      -label "Use ongoing fill\nin data Analysis" \
      -variable onGoing \
      -buttonList {Yes No} \
      -valueList {1 0} \
      -packOption "-side top" \
      -contextHelp "Allows the option of using the ongoing fill while analyzing run data"
    
    APSRadioButtonFrame .bf0a \
      -parent $w2 \
      -label "Merge fills if\nintentional dump" \
      -variable mergeFills \
      -buttonList {Yes No} \
      -valueList {1 0} \
      -packOption "-side top" \
      -contextHelp "Allows the option of merging or not merging successive fills if a fill was dumped intentionally.  Applies to Poisson fits and double integral plot."

    
    pack [frame $w.frame3] -side left
    set w3 $w.frame3
    APSRadioButtonFrame .bf3 \
      -parent $w3 \
      -label "Diagnostic\nData Display" \
      -buttonList {Display Terminate\nDisplay} \
      -variable calcDisplay \
      -valueList {1 0} \
      -packOption "-side top" \
      -commandList {"StartCalcDisplay 0" "StartCalcDisplay 1"} \
      -contextHelp "Intermediate results of calculations will be displayed."
    global minFillLength
    set minFillLength 0
    APSRadioButtonFrame .bf4 \
      -parent $w3 \
      -label "Min Fill Length" \
      -buttonList {Default Zero} \
      -variable minFillLength \
      -valueList {0 1} \
      -packOption "-side top" \
      -contextHelp "Min fill length of zero displays all the trips."
}

set saveFileDir /home/helios/oagData/sr/runHistory

#   define temporary files

set inputFile /tmp/[APSTmpString]inp
set printoutFile /tmp/[APSTmpString]print
set userTimeFile /tmp/[APSTmpString]ut
set outputFile /tmp/[APSTmpString]out
set historyFile /tmp/[APSTmpString]hist
set tempFile /tmp/[APSTmpString]temp
set suppFile /tmp/[APSTmpString]supp
set tempReasonFile /home/helios/oagData/sr/runHistory/[APSTmpString]tempr
set fileDisplayWidget [APSUniqueName .]

if [catch {APSGetSDDSColumn -fileName $saveFileDir/inputFiles/dumpCauses.sdds \
             -column DumpCause} dumpCauseChoiceList] {
    APSAlertBox [APSUniqueName .] -errorMessage "Fatal error: Unable to read $saveFileDir/inputFiles/dumpCauses.sdds: $dumpCauseChoiceList"
    exit 
}
if [catch {APSGetSDDSColumn -fileName $saveFileDir/inputFiles/technicalReasons.sdds \
             -column Reason} reasonsChoiceList] {
    APSAlertBox [APSUniqueName .] -errorMessage "Fatal error: Unable to read $saveFileDir/inputFiles/technicalReasons.sdds: $reasonsChoiceList"
    exit 
}
if [catch {APSGetSDDSColumn -fileName $saveFileDir/inputFiles/groups.sdds \
             -column GroupName} groupsChoiceList] {
    APSAlertBox [APSUniqueName .] -errorMessage "Fatal error: Unable to read $saveFileDir/inputFiles/groups.sdds: $groupsChoiceList"
    exit 
}



APSAddToTempFileList $inputFile ${inputFile}~ $printoutFile $userTimeFile $suppFile \
  $outputFile $historyFile ${historyFile}~ $tempFile $tempReasonFile ${tempReasonFile}.1

set fillReviewStatus Ready.

#MakeOptionsWidget .options -parent .userFrame

set plotOption off




proc UpdateWebPage {args} {
    SetFillReviewStatus "Updating web page (This takes about 60 seconds)"
    if {[catch {exec SRFillHistoryForWeb -htmlOutput /net/epics-ops/web_roots/ops/FillHistory.html} result]} {
        SetFillReviewStatus "Error: $result"
        return
    }
    SetFillReviewStatus "Done"
}


proc MakeWebPage {args} {
    if [catch {sdds open /home/helios/oagData/sr/runHistory/runFile} fd] {
        return
    }
    set runTimes [APSGetSDDSColumn -sddsFD $fd -column StartRun]
    catch {sdds close $fd}
    set t [clock seconds]
    for {set i 0} {$i < [llength $runTimes]} {incr i} {
        if {$t > [lindex $runTimes end-$i]} {
            break
        }
    }

    eval SearchForFills [clock format [expr int([lindex $runTimes end-$i])] -format "-startyear %Y -startmonth %m -startday %d"] [clock format [clock seconds] -format "-endyear %Y -endmonth %m -endday %d"] -web 1
    exit
}

set args $argv
set htmlOutput ""
set withSupplimental 0
set RunName ""
set minFillLength 0
if {[catch {sdds load /home/helios/oagData/sr/runHistory/targetCurrent targetData} results]} {
    SetFillReviewStatus "$results"
    set targetCurrent 102
    set targetCurrentRange 1
    set minInjDowntime 8
} else {
    set targetCurrent [format "%3.1f" [lindex $targetData(Parameter.TargetCurrent) 0]]
    set targetCurrentRange [format "%3.1f" [lindex $targetData(Parameter.Range) 0]]
    set minInjDowntime [format "%3.1f" [lindex $targetData(Parameter.MinInjDowntime) 0]]
}
set fitPlots 0
set onGoing 0
set doubIntLogLin 1
set calcDisplay 0
set runID ""
set mergeFills 1

APSParseArguments {htmlOutput withSupplimental RunName sddsFile}
if {[llength $htmlOutput]} {
    wm withdraw .
    MakeWebPage
} elseif [string length $RunName] {
    wm withdraw .
    set tmpFile /tmp/[APSTmpString]
    set tmpList [split $RunName "-"]
    set runName [lindex $tmpList 1]-[lindex $tmpList 0]
    puts "Searching for fill history for $RunName..."
    if [catch {exec sddsprocess /home/helios/oagData/sr/runHistory/runFile $tmpFile \
                 -match=col,RunName=$runName } result] {
        puts stderr "Error: $runName not found in /home/helios/oagData/sr/runHistory/runFile: $result"
        exit 1
    }
    APSAddToTmpFileList -ID fillhistory -fileList $tmpFile
    set startTime [expr int([exec sdds2stream -col=StartRun $tmpFile])]
    set endTime [expr int([exec sdds2stream -col=EndRun $tmpFile])]
    if $endTime==0 {
        set endTime [clock seconds]
    }
    set startyear [clock format $startTime -format %Y]
    set startmonth [clock format $startTime -format %m]
    set startday [clock format $startTime -format %d]
    set endyear [clock format $endTime -format %Y]
    set endmonth [clock format $endTime -format %m]
    set endday [clock format $endTime -format %d]
    SearchForFills -web 0 -sddsOutput 1 -sddsFile $RunName -startyear $startyear -startmonth $startmonth -startday $startday \
      -endyear $endyear -endmonth $endmonth -endday $endday
    puts "Fill history saved in $RunName, $RunName.fill and $RunName.srdowntime."
    exit 0
}

#sddsplot -legend "-topline=Time to recover beam" "-title=Run 2-2004" -ylabel=Hours Run2-2004.data.sdds "-column=Group,(Max,Ave,Median,Min)" -graph=impulse,vary,thickness=1 -stagger=x=.15,datanames -ticksettings=ygrid,ylinetype=5 -enumeratedScales=scale=1 -device=png,onwhite -output=run2-2004_downtime.png


APSApplication . -name SRFillHistory -version $CVSRevisionAuthor -overview \
  "Provides a way to use data such as the SR current, SRModifiedDesiredMode, etc., to identify valid stores during user beam and calculate reliabity and availability statistcs."
APSScrolledStatus .status -parent .userFrame -textVariable fillReviewStatus -width 87 -packOption "-side top -fill both -expand true"

MakeDateTimeFrame .starttime -parent .userFrame -label "Start Time" -rootname start
MakeDateTimeFrame .endtime -parent .userFrame -label "End Time" -rootname end
APSFrame .options -parent .userFrame -relief flat -label "" -orientation horizontal
APSRadioButtonFrame .plotOpt -parent .userFrame.options.frame -packOption "-side left" \
  -orientation horizontal -variable plotOption -label "Produce Plots?" \
  -buttonList {Yes No} -valueList {on off} -contextHelp \
  "Select if plots will be made in addition to the fill list."

APSButton .reasons -parent .userFrame.options.frame -text "Enter or Edit Reasons" \
  -command EditReasons \
  -contextHelp "Provides a means to enter or edit the reasons why a fill was terminated, and why there was downtime" 

APSButton .relist -parent .userFrame.options.frame -text "Redisplay List" \
  -command "ListFillDataTwo -fileUser $userTimeFile -fileFillList $historyFile" \
  -contextHelp "Redisplay the list after cllecting data" 
set reasonsButton .userFrame.options.frame.reasons.button
#APSDisableButton $reasonsButton

set relistButton .userFrame.options.frame.relist.button
APSDisableButton $relistButton
APSFrame .buttons -parent .userFrame -relief flat -label ""

APSButton .search -parent .userFrame.buttons.frame -command \
  {SearchForFills -startyear $Yearstart -startmonth $Monthstart -startday $Daystart \
     -endyear $Yearend -endmonth $Monthend -endday $Dayend} \
  -text "Search For Fills" \
  -contextHelp "Identifies valid fill on the day(s) selected."

APSButton .savehist -parent .userFrame.buttons.frame -text "Save Run History" \
  -command SaveRunHistory \
  -contextHelp "Saves the run data to a file" 

set savehistButton .userFrame.buttons.frame.savehist.button
APSDisableButton $savehistButton

APSButton .useplot -parent .userFrame.buttons.frame -text "Load Run History" \
  -command LoadRunHistory \
  -contextHelp "Allows use of saved plot commands on the present data."

APSButton .runlist -parent .userFrame.buttons.frame -text "List Runs" \
  -command ListRuns \
  -contextHelp "Displays the names and starting dates of identified runs"
APSButton .updateWebPage -parent .userFrame.buttons.frame -text "Update Web Page" \
  -command "UpdateWebPage" \
  -contextHelp "Updates the FillHistory web page"

MakeOptionsWidget .analOptions -parent .userFrame
