#!/bin/sh  
# \
  exec oagtclsh "$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)]
APSDebugPath
APSStandardSetup

set CVSRevisionAuthor "\$Revision: 1.76 $ \$Author: borland $"

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

proc fitData {args} {
    set datafile ""
    set runId ""
    APSStrictParseArguments {datafile 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

    # 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]} {
        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] {
        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}

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


proc AnalysisProc {args} {
    set analTemp /tmp/[APSTmpString]analTemp

    set datafile ""
    set useOngoing 1 
    set runId ""
    set mergeFills 1

    APSStrictParseArguments {datafile useOngoing runId mergeFills}

    if {[catch {sdds open $datafile r} fd]} {
        return -code error $fd
    }
    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]} {
        return -code error "1: $results"
    }
    APSAddToTempFileList $analTemp ${analTemp}~
    # if option selected to delete ongoing fills in calculations, do so now
    set origDir [pwd]
    cd /tmp

    #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]} {
            return -code error $results
        }
    }
    
    if {[catch {exec sddsprocess $analTemp -noWarnings \
                  -process=duration,average,meanFill \
                  -process=duration,median,medFill \
                  -process=NumRows,maximum,maxRowVal} results]} {
        return -code error $results
    }
    cd $origDir
    if [catch {sdds open $analTemp r} fd1] {
        return -code error $fd1
    }
    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 -runId $runId} fittedMean]} {
        return -code error $fittedMean
    }

    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 onGoing mergeFills htmlOutput
    APSStrictParseArguments {fileUser fileFillList}

    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]

    puts $fileID "<html><head><title>SR Fill History</title></head>"
    puts $fileID "<body bgcolor=\#ffffff><font face='arial, helvetica' size=+1><pre>"
    
    puts $fileID "<b>Listing of Statistics for $runID (Created [clock format [clock seconds]])<br></b>"
    


    puts $fileID "<u>User periods in this interval</u><br>"
    

    if [catch {sdds open $fileUser} fd] {
        return -code error $fd
    }
    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] {
        return -code error $result
    }

    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
    }

    if {[catch {AnalysisProc -datafile $tempFile -useOngoing $onGoing -runId $runID -mergeFills $mergeFills} stuff]} {
        return -code error $stuff
    }
    if {[llength $stuff]==0} {
        return -error code "no data"
    }
    set onGoingText "not used"
    if {$onGoing} {
        set onGoingText "used"
    }

    if [catch {sdds open $tempFile} fd2] {
        return -code error $fd2
    }
    global T1 T2
    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]
    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 change the related ChargeFastSRFillHistory 
        # file and set the ShutterPermit to 1 for the related time. Otherwise
        # it will be counted as downtime. Instead they should be noted but not
        # counted as downtime. The schedualed time will be reduced accordingly.
        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]

    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]} {
            puts -nonewline $fileID  $l
            puts $fileID " [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 TotalUser [APSGetSDDSParameter -fileName $fileUser -parameter TotalUser]
    global tornadoTotalUserDifference
    set TotalUser [expr {$TotalUser - ($tornadoTotalUserDifference / 3600.0)}]
    puts $fileID "<table width=750 border=0><tr>"
    puts $fileID "<td><b>Total Amount of User Time in this interval</b> <td><b>[format "%6.2f" $TotalUser] Hours</b."
    
    puts $fileID "<tr><td>Delivered Beam                                <td>  [format "%6.2f" $TotalDeliv] Hours <tr>"
    puts $fileID "<td><b>Percentage of Scheduled Time <a href=\"Mini[file tail $htmlOutput]\">(*)</a> </b>    <td > <b>          [format "%6.2f" $TotalDelivPC] %</b><tr>"
    puts $fileID "<td><b>Mean Time Between Faults (MTBF)                </b> <td><b>[format "%6.2f" $MTBF] Hours</b><tr>"
    puts $fileID "<td>Downtime During Period                        <td>[format "%6.2f" $runDownTime] Hours<tr>"
    #puts $fileID "<td>Percentage of scheduled time SR current > 10 ma <td >[format "%6.2f" $beamAvailability] %<tr>"
    #puts $fileID "<td>Average Delivered Current During This Period  <td>[format "%6.2f" $totalAvgCurrent] ma<tr>"
    if { $totalMaHour >= 1000.0 } then {
        puts $fileID "<td>Total integrated  Current During This Period <td>[format "%6.2f" [expr $totalMaHour / 1000.0 ]] A-hr<tr>"
    } else {
        puts $fileID "<td>Total integrated  Current During This Period   <td> [format "%6.2f" $totalMaHour] mA-hr<tr>"
    }

    #    puts $fileID " "
    #    puts $fileID "Data from an on going fill (if one exists) is $onGoingText in Fill length calculations."

    puts $fileID "<tr> "
    puts $fileID "<td>Mean Fill Duration in Period               <td>[format "%6.2f" $meanFillDuration] Hours<tr>"
    #puts $fileID "<td>Mean Fill Duration from Poisson Fit            <td> [format "%6.2f" [lindex $stuff 7] ] Hours<tr>"
    
    puts $fileID "<td>Faults per Day of Delivered Beam                <td>[format "%6.2f" $faultsPerDay]<tr>"
    puts $fileID "<td>Total Number of Faults                          <td>[format "%3d" $faults]<tr><BR>"
    global ScheduledTopupTime
    #puts $fileID "<td>Scheduled Topup Time                            <td>[format "%6.2lf" [expr {$ScheduledTopupTime / 3600.0}]] Hours</table>"
    #puts $fileID "<div><HR width=1450></div>"
    puts $fileID "<table width=1450 border=0>"   
    global minLength
    puts $fileID " <tr><td colspan=5 align=center valign=bottom><u>Valid fills Beginning in this Time Interval</u><td> &nbsp<td> &nbsp<td> &nbsp<tr> <td valign=bottom>Fill \# <td valign=bottom align=center> Start <td> &nbsp<td valign=bottom align=center>End <td valign=bottom>Duration<br> (min: ${minLength})  <td valign=bottom>      Reason for  Fill Termination <td>Length of Downtime <td align=center>Downtime is associated with the end of a fill. The first fill of a period will have any  downtime before the fill on the line above."
    
    
    

    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 "<tr><td colspan=8><hr>"
            puts $fileID " <tr>    <td colspan=6>&nbsp<td>   [format "%5.2f" $downTimeB4]<td> [format %-.52s [lindex $dtBeforeText $i]]"
            puts $fileID "<tr><td width=55>\#[format "%3.0f" [lindex $FillNumber $i]]<td width=160>  [ConvertToDateString [lindex $T1 $i]] <td width=45> To<td width=140>  [ConvertToDateString [lindex $T2 $i]] <td align=right width=95> [format "%6.2f" [lindex $duration $i]]&nbsp&nbsp&nbsp <td width=325>  [format %-24.24s [lindex $reasonLost $i]] <td width=100> [format "%5.2f" $downTime] <td width=*>[format %-.52s [lindex $dtAfterText $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 "<tr><td width=55>\#[format "%3.0f" [lindex $FillNumber $i]] <td width=160> [ConvertToDateString [lindex $T1 $i]] <td width=45> To<td width=140>  [ConvertToDateString [lindex $T2 $i]] <td  align=right width=95> [format "%6.2f" [lindex $duration $i]]&nbsp&nbsp&nbsp <td width=325 >  [format %-24.24s [lindex $reasonLost $i]]<td width=100>  [format "%5.2f" $downTime]    <td width=*>[format %-.52s [lindex $dtAfterText $i]] <tr><td colspan=8>"

            #       write out all others
        } else {
            set downTime [lindex $dt [expr $i+1]]
            puts $fileID "<tr><td width=55>\#[format "%3.0f" [lindex $FillNumber $i]]<td width=160>  [ConvertToDateString [lindex $T1 $i]] <td width=45> To  <td width=140>[ConvertToDateString [lindex $T2 $i]] <td  align=right width=95> [format "%6.2f" [lindex $duration $i]]&nbsp&nbsp&nbsp <td width=325>  [format %-24.24s [lindex $reasonLost $i]] <td width=100> [format "%5.2f" $downTime]    <td width=*>[format %-.52s [lindex $dtAfterText $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 "<tr> * Interruption of delivered beam between [ConvertToDateString $dts]  To  [ConvertToDateString $dte] $dtreason  "
                  }
              }
        }
    }
    #puts $fileID "<tr><td colspan=8><hr>"
    puts $fileID "</table>"
    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) "<table border=0 width=650><tr><td>  Current in Range during Scheduled Topup Time <td> [format "%6.2lf" [expr {100.0 - (($ScheduledTopupTime - $constancy(d) + $constancy(n)) * 100.0) / (1.0 * $ScheduledTopupTime)}]] %"
                    append output(1) " <tr><td>  Current in Range during Delivered Beam Time <td>  [format "%6.2lf" [expr 100.0 - ($constancy(n) * 100.0) / $constancy(d)]] %"
                    append output(1) "<tr><td>   Injector Availability <td> [format "%6.2lf" [expr 100.0 - ($injector(n) * 100.0) / $injector(d)]] %</table>"
                    
                }
                set periodNum [lindex $period $i]
                append output(1) "<table width=600><tr><td><u>Period Beginning [lrange [lindex $L1 [expr {$periodNum - 1}]] 0 1]</u>"
                append output(1) "<tr><td>Current in Range <td>[format "%6.2lf" $constancy($periodNum)] %</ul>"
                append output(1) "<tr><td>Injector Availability <td>[format "%6.2lf" $injector($periodNum)] %</table>"
            }
            append output(2) $topupInfo([expr int([lindex $FillNumber $i])])
        }
    }
    puts $fileID $output(1)
    puts $fileID $output(2)
    
    #   display printoutFile
    puts $fileID "The information on this page is automatically generated and may contain errors."
    puts $fileID "An official operations statistics page will be posted at the end of each user period.<br>"

    puts $fileID "</font></pre></body></html>"
    flush $fileID
    file copy -force $printoutFile $htmlOutput
    catch {exec chmod a+rw $htmlOutput}

    set fid [open [file join [file dirname $htmlOutput] Mini[file tail $htmlOutput]] w]
    puts $fid "<font size=+1><pre>"
    puts $fid "Listing of Statistics for $runID"
    puts $fid "(Created [clock format [clock seconds]])"
    puts $fid ""
    puts $fid "Percentage of Scheduled Time      <b><font color=red>[format "%6.2f" $TotalDelivPC] %</font></b>"
    puts $fid "Mean Time Between Faults (MTBF)   <b><font color=red>[format "%6.2f" $MTBF] Hours</font></b>"
    puts $fid "</pre></font>"
    flush $fid
    close $fid
    catch {exec chmod a+rw [file join [file dirname $htmlOutput] Mini[file tail $htmlOutput]]}

    # Same but larger font
    set fid [open [file join [file dirname $htmlOutput] Mini2[file tail $htmlOutput]] w]
    puts $fid "<font size=+3><b><pre>"
    puts $fid "Listing of Statistics for $runID"
    puts $fid "(Created [clock format [clock seconds]])"
    puts $fid ""
    puts $fid "Percentage of Scheduled Time      <font color=red>[format "%6.2f" $TotalDelivPC] %</font>"
    puts $fid "Mean Time Between Faults (MTBF)   <font color=red>[format "%6.2f" $MTBF] Hours</font>"
    puts $fid "</pre></b></font>"
    flush $fid
    close $fid
    catch {exec chmod a+rw [file join [file dirname $htmlOutput] Mini2[file tail $htmlOutput]]}

    ###Make an appended archive of MIniFillHistory

    set dfile [open [file join [file dirname $htmlOutput] FillHistorydata.sdds] a]
    
    puts $dfile "$runID [clock seconds] [format "%6.2f" $TotalDelivPC] [format "%6.2f" $MTBF]"
    flush $dfile
    close $dfile
    catch {exec chmod a+rw [file join [file dirname $htmlOutput] FillHistorydata.sdds]}


}


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
}


proc SearchForFills {args} {
    global inputFile tempFile outputFile historyFile suppFile
    global userTimeFile printoutFile runID saveFileDir minLength

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


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

    if { $startTime > $endTime } {
        return -code error "invalid time"
    }

    if {$startTime >= [clock scan 01/01/2001]} {
        set FillNumberOption first
    } elseif {$endTime < [clock scan 01/01/2001]} {
        set FillNumberOption median
    } else {
        return -code error "invalid time"
    }
    if {$startTime >= [clock scan 10/01/2002]} {
        set minLength 1.0
    } elseif {$endTime < [clock scan 10/01/2002]} {
        set minLength 0.5
    } else {
        return -code error "invalid time"
    }
    if {$startTime >= [clock scan 01/01/2024]} {
        set currentMin 15.0
    } else {
        set currentMin 50.0
    }

    if [catch {sdds open /home/helios/oagData/sr/runHistory/runFile} fd] {
        return -code error $fd
    }
    global runList
    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]])} {
            }
            set runID $l
            break
        }
        incr i
    }
    regsub -all " " $runID "" idNoBlanks

    set idFile $saveFileDir/$idNoBlanks.reasons    

    #  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)"
        eval file delete $fileListFiltered
        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
    }	
    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
    }
    global suppTimeFound
    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]} {
        return -code error $results
    }

    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]} {
        return -code error "2: $results"
    }
    #   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]} {
        return -code error $results
    }
	
    
    #   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]} {
        return -code error $results
    }
    #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) "\n<u><b>Top-Up Mode Statistics</b></u><br>\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: $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) "<table border=0 width=900><tr><td width=200> Out of Range at: <td width=240> [clock format [expr int($downStart)] -format "%m/%d/%Y %H:%M:%S"]<TD> to<TD width=240> [clock format [expr int($downEnd)] -format "%m/%d/%Y %H:%M:%S"] :<td width=160 align=right> [format "%6.2lf" [expr (int($downEnd) - int($downStart)) / 60.0]] minutes</table>"
            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) "<table border=0 width=900><tr><td width=200>Injector downtime:<td width=240>[clock format [expr int($idownStart)] -format "%m/%d/%Y %H:%M:%S"]<TD> to <TD width=240> [clock format [expr int($idownEnd)] -format "%m/%d/%Y %H:%M:%S"] : <td width=160 align=right>[format "%6.2lf" [expr (int($idownEnd) - int($idownStart)) / 60.0]] minutes</table>"
                }
            }
            if {($istart) && ([expr {$downStart - 60 * 5}] > $iend)} {
                if {5 < $minInjDowntime} {
                    set estDownTime $minInjDowntime
                } else {
                    set estDownTime 5
                }
                append topupInfo($fillNum) "<table border=0 width=900><tr><td width=200>Injector downtime:<td width=240>[clock format [expr int($downStart) - int(60 * $estDownTime)] -format "%m/%d/%Y %H:%M:%S"]<TD> to <TD width=240> [clock format [expr int($downStart)] -format "%m/%d/%Y %H:%M:%S"] : <td width=160 align=right>~[format "%6.2lf" $estDownTime] minutes</table>"
                set topupInfo($fillNum,injectorNumerator) [expr {$topupInfo($fillNum,injectorNumerator) + 60 * $estDownTime}]
            }
            set iend $downEnd
        }
    }
    #end topup info
    
    if {[catch {ListFillDataTwo -fileUser $userTimeFile -fileFillList $historyFile} results]} {
        return -code error $results
    }
    if {[catch {exec sddsconvert $historyFile \
                  -retain=col,FillNumber,T1,T2,duration,NumRows,SecPerRow,ReasonLost,dt,period,avgCur,maHour,currentAtDump \
                  -noWarnings} results]} {
        return -code error "3: $results"
    }
}

proc MakeWebPage {args} {
    if [catch {sdds open /home/helios/oagData/sr/runHistory/runFile} fd] {
        return -error $fd
    }
    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
        }
    }

    if {[catch {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"]} results]} {
        return -code error $results
    }
    #UpdateAvailableBeam
    exit
}

proc UpdateAvailableBeam {args} {
    global T1 T2 saveFileDir runID runList
    set extraDowntimeFile $saveFileDir/$runID.extraDownTime
    if {[file exists $extraDowntimeFile]} {
        sdds load $extraDowntimeFile extraDownTime
        set DS [lindex $extraDownTime(Column.DowntimeStart) 0]
        set DE [lindex $extraDownTime(Column.DowntimeEnd) 0]
        foreach ds $DS {
            lappend T2 $ds
        }
        foreach de $DE {
            lappend T1 $de
        }
        set T2 [lsort -real $T2]
        set T1 [lsort -real $T1]
    }
    set data(ParameterNames) "RunID"
    set data(ColumnNames) "StartTime EndTime"
    set data(ColumnInfo.StartTime) "type SDDS_DOUBLE"
    set data(ColumnInfo.EndTime) "type SDDS_DOUBLE"
    set data(Parameter.RunID) [list $runID]
    foreach t1 $T1 t2 $T2 {
        if {$t1 < $t2} {
            lappend data(Column.StartTime) $t1
            lappend data(Column.EndTime) $t2
        }
    }
    set data(Column.StartTime) [list $data(Column.StartTime)]
    set data(Column.EndTime) [list $data(Column.EndTime)]
    sdds save ${saveFileDir}/AvailableBeam/${runID}.sdds data
    set filenames ""
    foreach runName $runList {
        if {[file exists ${saveFileDir}/AvailableBeam/${runName}.sdds]} {
            lappend filenames ${saveFileDir}/AvailableBeam/${runName}.sdds
        }
    }
    eval exec sddscombine $filenames ${saveFileDir}/AvailableBeam/AllRuns.sdds -merge -overwrite

}

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

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

set onGoing 0
set runID ""
set mergeFills 1

if {[catch {sdds load /home/helios/oagData/sr/runHistory/targetCurrent targetData} 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 args $argv
set htmlOutput ""
APSParseArguments {htmlOutput}
if {[llength $htmlOutput]} {
    if {[catch {MakeWebPage} results]} {
        puts "error: $results"
    }
} else {
    puts "usage: SRFillHistoryForWeb -htmlOutput <fileName>"
}
