#!/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)]
APSDebugPath

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

set SrIhistDataDir /home/helios/oagData/monitoring/Charge
set SrIhistMaxAbsDCCT 300

proc SRCurrentHistoryOverview {} {
    return "This is the storage current history review utility.\n\
It allows you to review archived data on storage ring current and lifetime.  You may select either current, lifetime, or both\
and have a plot generated.  The plot interface allows printing and saving the plot.  An option is also provided to permit specifying\
the type of particle (electron is the default).\n\
  Another type of plot that is available is the monthly integrated current plot.  This gives the mA-hours from each day, plus a\
  total for the month."
        }

APSApplication . -name SRCurrentHistory -version $CVSRevisionAuthor -overview [SRCurrentHistoryOverview] 

proc SetSrIhistStatus {text} {
    global SrIhistStatus
    set SrIhistStatus $text
    update
} 

proc MakeDailyPlotButtons {widget args} {
    # make widget containing checkbuttons and action button for
    # daily plots

    global SrIhistYear SrIhistMonth SrIhistDay SrIhistShift SrIhistLifetime SrIhistCurrent
    global SrIhistPositrons SrIhistMaxAbsDCCT SrIhistDataDir
    set parent ""
    set command DoIhistPlot 
    APSParseArguments {parent command}
    set w $parent$widget
    frame $w
    pack $w -side top -fill x

    set SrIhistLifetime  0
    set SrIhistCurrent   1
    set SrIhistPositrons 1

    APSCheckButtonFrame .cb -parent $w -label "    Plot: " -orientation horizontal \
      -buttonList {Current Lifetime} \
      -variableList {SrIhistCurrent SrIhistLifetime}
#    APSRadioButtonFrame .rb -parent $w -label "Particle: " -orientation horizontal \
#      -buttonList {Electrons Positrons} \
#      -valueList {0 1} \
#      -variable SrIhistPositrons

    frame $w.op 
    pack $w.op -side top -fill x
    APSButton .plot -parent $w.op -text PLOT -command "$command"
}

proc DoIhistPlot {} {
    # prepare and execute command to make daily plot
    global SrIhistYear SrIhistMonth SrIhistDay SrIhistShift SrIhistLifetime SrIhistCurrent
    global SrIhistPositrons SrIhistMaxAbsDCCT SrIhistDataDir SrIhistTimeStart SrIhistTimeEnd
    SetSrIhistStatus "Working..." 

    SetSrIhistStatus \
      [MakeCurrentHistoryPlots -year $SrIhistYear -month $SrIhistMonth -day $SrIhistDay \
         -shift $SrIhistShift -doLifetime $SrIhistLifetime -doCurrent $SrIhistCurrent  \
         -positrons $SrIhistPositrons -limitDCCT $SrIhistMaxAbsDCCT \
         -dataDir $SrIhistDataDir -timeStart $SrIhistTimeStart -timeEnd $SrIhistTimeEnd]
}

proc DoIhistRangePlot {} {
    # prepare and execute command to make daily plot
    global SrIhistYearStart SrIhistMonthStart SrIhistYearEnd SrIhistMonthEnd
    global SrIhistDayStart SrIhistDayEnd SrIhistHourStart SrIhistHourEnd
    global SrIhistPositrons SrIhistMaxAbsDCCT SrIhistDataDir 
    global SrIhistLifetime SrIhistCurrent SrIhistPlotSparsing
        
    if $SrIhistHourStart<0 { set SrIhistHourStart 0 }
    if $SrIhistHourEnd<0 { set SrIhistHourEnd 0 }
    if $SrIhistHourStart>24  { set SrIhistHourStart  24 }
    if $SrIhistHourEnd>24  { set SrIhistHourEnd  24 }
    if {$SrIhistYearStart==$SrIhistYearEnd && $SrIhistMonthStart==$SrIhistMonthEnd && \
          $SrIhistDayStart==$SrIhistDayEnd && $SrIhistHourEnd<=$SrIhistHourStart} {
        set SrIhistHourStart 0
        set SrIhistHourEnd 24
    }

    SetSrIhistStatus "Working..." 
    SetSrIhistStatus \
      [MakeCurrentHistoryRangePlots \
         -startDate [list $SrIhistYearStart $SrIhistMonthStart $SrIhistDayStart] \
         -endDate [list $SrIhistYearEnd $SrIhistMonthEnd $SrIhistDayEnd] \
         -startHour $SrIhistHourStart -endHour $SrIhistHourEnd \
         -doLifetime $SrIhistLifetime -doCurrent $SrIhistCurrent  \
         -positrons $SrIhistPositrons -limitDCCT $SrIhistMaxAbsDCCT \
         -dataDir $SrIhistDataDir -sparse $SrIhistPlotSparsing]
}


proc MakeDailyChargeFile {args} {
    # Find and/or prepare the processed file from the current data logs.
    # Contains no references to anything else in this file.

    global env
    set date ""
    set positrons 0
    set dataDir /home/helios/oagData/monitoring/Charge
    APSStrictParseArguments {date positrons dataDir}

    # check if requested date is today.  If so, need to process raw file.
    set today [APSTodaysDateInfo -dateFormat Y-J-MD]
    set defaultFile $dataDir/ChargeFastProc-${date}.gz
    if {[string compare $today $date] && [file exists $defaultFile]} {
        return $defaultFile
    }

    # find all the files for today, and see if any is newer than the processed
    # file if it exists
    set force 0
    if [string compare $today $date]==0 {
        set dataFileList [glob -nocomplain $dataDir/ChargeFast-${date}.????]
        if ![llength $dataFileList] {
            return ""
        }
        set lastDataFile [lindex $dataFileList end]
        if [file exists $defaultFile] {
            set timeData [file mtime $lastDataFile]
            set timeProc [file mtime $defaultFile]
            if {$timeData>$timeProc} {
                set force 1
            }
        }
    }

    # move to the data log directory and process the file
    set oldDir [pwd]
    set targetDir $dataDir
    cd $dataDir
    if {[string compare $env(USER) "oag"]} { 
        # only user oag can replace the -proc file in the data log directory
        # so use /tmp
        set targetDir /tmp
        set filename /tmp/ChargeFastProc-${date}.gz
        if [file exists $filename] {
            exec rm -f $filename
        }
    }
    if [catch {exec ./processDailyFile -tag $date -positrons $positrons \
                 -targetDir $targetDir -force $force} result] {
        APSInfoWindow [APSUniqueName .] -infoMessage "Possible processing problem: $result" 
    }
    cd $oldDir
    return $targetDir/ChargeFastProc-${date}.gz
}

proc MakeCurrentHistoryPlots {args} {
    # make daily plot of chosen quantities, for chosen shift or time range

    set year ""
    set day ""
    set month ""
    set shift All
    set doLifetime 0
    set doCurrent 1
    set limitDCCT 300
    set positrons 0
    set dataDir /home/helios/oagData/monitoring/Charge
    set timeStart 0
    set timeEnd 24
    APSParseArguments {year day month shift doLifetime doCurrent dataDir limitDCCT positrons timeStart timeEnd}
    if {!$doLifetime && !$doCurrent} {
        return "Choose current and/or lifetime plots."
    }

    # set hour filters for the chosen shift
    set shiftText "      Shift: $shift"
    switch $shift {
        All       {set timeStart 0 ; set timeEnd 24 }
        Owl       {set timeStart 0 ; set timeEnd 8  }
        Day       {set timeStart 8 ; set timeEnd 16 }
        Evening   {set timeStart 16; set timeEnd 24 }
        Custom    {
            if {$timeStart>=$timeEnd} {
                return "Invalid start and end times for custom shift plot."
            }
            set shiftText ""
        }
        default {
            return "Invalid shift: must be All, Owl, Day, Evening, or Custom"
        }
    }
    return [MakeCurrentHistoryRangePlots \
              -startDate [list $year $month $day] \
              -endDate [list $year $month $day] \
              -startHour $timeStart -endHour $timeEnd \
              -sparse 1 -doCurrent $doCurrent -doLifetime $doLifetime \
              -limitDCCT $limitDCCT -positrons $positrons]
}

proc MakeCurrentHistoryRangePlots {args} {
    # make plot of chosen quantities for chosen range of days
    # contains no reference to global variables elsewhere in this file

    set startDate ""
    set endDate ""
    set doLifetime 0
    set doCurrent 1
    set limitDCCT 300
    set positrons 0
    set startHour 0
    set endHour 24
    set dataDir /home/helios/oagData/monitoring/Charge
    set sparse 1
    APSParseArguments {startDate endDate doLifetime doCurrent limitDCCT positrons dataDir startHour endHour sparse}
    if {!$doLifetime && !$doCurrent} {
        return "Choose current and/or lifetime plots."
    }

    set startYear [APSMakeFourDigitYear [lindex $startDate 0]]
    set startMonth [lindex $startDate 1]
    set startDay [lindex $startDate 2]
    set endYear [APSMakeFourDigitYear [lindex $endDate 0]]
    set endMonth [lindex $endDate 1]
    set endDay [lindex $endDate 2]

    SetSrIhistStatus "Processing..."

    set fileList ""
    set endTag [APSOffsetDateInfo -year $endYear -day $endDay -month $endMonth -offset 0 -dateFormat Y-J-MD]
    set dateList [APSOffsetDateInfo -year $startYear -day $startDay -month $startMonth -offset 0 -dateFormat list]
    set tag [APSOffsetDateInfo -dateList $dateList -offset 0 -dateFormat Y-J-MD]
    while 1 {
        set newFile [MakeDailyChargeFile -date $tag -positrons $positrons]
        if [string length $newFile] {
            lappend fileList $newFile
        }
        if [string compare $tag $endTag]==0 break
        set dateList [APSOffsetDateInfo -dateList $dateList -offset 1]
        set tag [APSOffsetDateInfo -dateList $dateList -offset 0 -dateFormat Y-J-MD]
    }


    if [llength $fileList]==0 {
        return "No data found for that range of dates"
    }

    set startTime \
      [exec timeconvert \
         -breakDown=year=$startYear,month=$startMonth,day=$startDay,hour=$startHour]
    set endTime \
      [exec timeconvert \
         -breakDown=year=$endYear,month=$endMonth,day=$endDay,hour=$endHour]

    # process data to get statistics for plot
    set oldDir [pwd]
    cd $dataDir
    set tmpFile /tmp/[APSTmpString]
    set tmpID [APSUniqueName tmp]
    APSAddToTmpFileList -ID $tmpID -fileList $tmpFile
    eval exec sddscombine $fileList -pipe=out -recover=clip \
      | sddsprocess -pipe -filter=column,Time,1,1e10 -filter=column,Time,$startTime,$endTime -nowarning \
      | sddsconvert -pipe \
        -dele=parameter,S35DCCTIntegDay,S35DCCTGrandIntegDay,S35DCCTPeak,S35DCCTAverage,BeamOver1mAPercent,BeamDeliveredPercent \
      | sddsprocess -pipe -process=S35DCCTGrandInteg,last,S35DCCTGrandInteg \
      -process=S35DCCT,max,S35DCCTPeak \
      {{-define=column,BeamOver1mA,S35DCCT 1 > ? 1 : 0 $,type=long}} \
      {{-define=column,BeamDelivered,BeamOver1mA ShutterPermit *,type=long}} \
      "-process=BeamOver1mA,sum,SamplesOver1mA" \
      "-process=BeamDelivered,sum,SamplesDelivered" \
      -define=param,Samples,n_rows,type=long \
      | sddscollapse -pipe \
      | sddsprocess -pipe -process=S35DCCTPeak,max,S35DCCTPeak1 \
      -process=S35DCCTGrandInteg,max,S35DCCTGrandInteg1 \
      {{-redefine=param,S35DCCTGrandInteg1,S35DCCTGrandInteg1 1e3 /,units=A-h}} \
      -process=SamplesOver1mA,sum,SamplesOver1mA1 \
      -process=SamplesDelivered,sum,SamplesDelivered1 \
      -process=Samples,sum,Samples1 \
      {{-define=parameter,BeamOver1mAPercent,SamplesOver1mA1 Samples1 / 100 *,units=%}} \
      {{-define=parameter,BeamDeliveredPercent,SamplesDelivered1 Samples1  / 100 *,units=%}} \
      {{-print=param,Label,Peak %.1fmA   Grand %.1f%s  >1mA %.0f%%  Deliv: %.0f%%,S35DCCTPeak1,S35DCCTGrandInteg1,S35DCCTGrandInteg1.units,BeamOver1mAPercent,BeamDeliveredPercent}} \
      | sddscollapse -pipe=in $tmpFile 
      
    set plotLabel [lindex [APSGetSDDSColumn -column Label -fileName $tmpFile] 0]
    set xLabel "Data from $startMonth/$startDay/$startYear@$startHour to $endMonth/$endDay/$endYear@$endHour"

    # make the plot
    if {$doLifetime && $doCurrent} {
        eval exec sddsplot -filter=column,Time,$startTime,$endTime -presparse=$sparse \
          -ticks=xtime \
          -sever=xgap=-1.5 -layout=1,2 "-title=" {-xlabel=$xLabel} \
          -column=Time,S35DCCT $fileList {-topline=$plotLabel} -end \
          -column=Time,Lifetime $fileList "-topline=" &
    } elseif {$doCurrent} {
        eval exec sddsplot -filter=column,Time,$startTime,$endTime -presparse=$sparse \
          -ticks=xtime {-xlabel=$xLabel} \
          -column=Time,S35DCCT $fileList \
          {-topline=$plotLabel} -sever=xgap=-1.5 &
    } else {
        eval exec sddsplot -filter=column,Time,$startTime,$endTime -presparse=$sparse \
          -ticks=xtime {-xlabel=$xLabel} \
          -column=Time,Lifetime $fileList \
          {-topline=$plotLabel} -sever=xgap=-1.5 &
    }
    cd $oldDir
    return "OK."
}

proc MakeShiftEntry {widget args} {
    # make a widget for entering the shift (Owl Day Evening All Custom) and
    # custom time range

    global SrIhistTimeStart SrIhistTimeEnd
    set parent ""
    set variable ""
    APSParseArguments {parent variable}
    if {$variable == ""} { return 0 }
    global $variable
    APSFrame $widget -parent $parent
    set w $parent$widget.frame
    APSRadioButtonFrame .rb -parent $w -label "   Shift: " -orientation horizontal \
      -variable $variable -buttonList {Owl Day Evening All Custom } -valueList {Owl Day Evening All Custom } \
      -contextHelp "Select the shift for which you want to see data."
    APSLabeledEntryFrame .ef -parent $w -width 6 \
      -label "Custom time start, end (hours): " -variableList {SrIhistTimeStart SrIhistTimeEnd} \
      -orientation horizontal -contextHelp {Enter start and end time in hours for Custom shift mode.}
}

proc MakeCurrentMonthlyPlot {args} {
    # Make chosen plot for month or range of months.
    # Contains no references to anything else in this file.

    global env
    set yearStart ""
    set monthStart ""
    set yearEnd ""
    set monthEnd ""
    set limitDCCT 300
    set dataDir ""
    set dataName S35DCCTIntegDay
    APSParseArguments {yearStart monthStart yearEnd monthEnd limitDCCT dataDir dataName} 
    scan $monthStart "%ld" monthStart
    set monthStart [format %02ld $monthStart]
    scan $monthEnd "%ld" monthEnd
    set monthEnd [format %02ld $monthEnd]
    set yearStart [APSMakeFourDigitYear $yearStart]
    set yearEnd [APSMakeFourDigitYear $yearEnd]

    set tmpID [APSUniqueName tmp]

    # make a list of all the processed files for the range of time in question
    set procFileList \
      [lsort \
         [APSFindMonthlyFilesBetweenDates -rootname ChargeFastProc- -extensionList .gz \
            -directory $dataDir -tailsOnly 1 -startDateList [list $yearStart $monthStart] \
            -endDateList [list $yearEnd $monthEnd] ] ]
    if [llength $procFileList]==0 {
        return "No files found."
    }

    # look at files for the present month, if applicable, and update as needed.
    APSDateBreakDown -monthVariable thisMonth -yearVariable thisYear -twoDigitYear 0 -leadingZeros 1
    if {$yearEnd>$thisYear} {
        set yearEnd $thisYear
    }
    if {$yearEnd==$thisYear} {
        scan $thisMonth %ld month0
        scan $monthEnd %ld month1
        if {$month1>=$month0} {
            set monthEnd $thisMonth
        }
    }
    set tmpFile ""
    if {$thisYear==$yearEnd && $thisMonth==$monthEnd} {
        # need to check whether .proc file for this month is out of date
        set dataFiles [glob $dataDir/ChargeFastProc-${thisYear}-???-${thisMonth}??.gz]
        if [llength $dataFiles]==0 {
            return "No data for the present month."
        }

        set makeFile 0
        set dataFile $dataDir/ChargeFastProc-${thisYear}-${thisMonth}.gz 
        if [file exists $dataFile] {
            set mtime0 [file mtime $dataFile]
            foreach file $dataFiles {
                set mtime [file mtime $file]
                if {$mtime>$mtime0} {
                    set makeFile 1
                    break
                }
            }
        } else {
            set makeFile 1
        }

        if $makeFile {
            if $makeFile {
                set tmpFile /tmp/[APSTmpString]
                APSAddToTmpFileList -ID $tmpID -fileList $tmpFile
                eval exec sddscombine $dataFiles -pipe=out -collapse -recover=clip \
                  | sddsprocess -pipe=in -filter=column,Time,1,1e10  $tmpFile  \
                  -process=S35DCCTPeak,max,S35DCCTPeak \
                  -process=S35DCCTIntegDay,sum,S35DCCTIntegTotal \
                  {{-print=param,MonthlyLabel,Peak %.2f mA   Total: %.2f mA-h,S35DCCTPeak,S35DCCTIntegTotal}}
                if [string compare $env(USER) "oag"]==0 {
                    # install new file in oag area
                    exec cp $tmpFile $dataFile
                } else {
                    # append new filename to the list.
                    lappend $procFileList $tmpFile
                }
            } 
        }
    }

    set oldDir [pwd]
    cd $dataDir
    eval exec sddsplot  -unsup=y \
      -column=StartTime,$dataName -ticks=xtime $procFileList -sever=xgap=-1.5 -graph=impulse \
      {"-title=Current history for $monthStart/$yearStart to $monthEnd/$yearEnd"} &
    cd $oldDir

    if [string length $tmpFile] { after 30000 "exec rm $tmpFile" }

    return OK.
}

# index of SDDS element names vs. names from monthly plot radio button frame
set dataName(integCurrent) S35DCCTIntegDay
set dataName(maxCurrent) S35DCCTPeak
set dataName(aveLifetime) LifetimeAverage
set dataName(maxLifetime) LifetimePeak
set dataName(fractionUp) BeamOver1mAPercent
set dataName(percentDelivered) BeamDeliveredPercent

proc DoIhistMonthlyPlot {} {
    # prepare and execute command for making plot for month or range of 
    # months

    global dataName
    global SrIhistYearStart SrIhistMonthStart 
    global SrIhistYearEnd SrIhistMonthEnd
    global SrIhistPositrons SrIhistMaxAbsDCCT SrIhistDataDir monthlyPlotChoice
    SetSrIhistStatus "Working..." 
    SetSrIhistStatus [MakeCurrentMonthlyPlot \
                        -yearStart $SrIhistYearStart -monthStart $SrIhistMonthStart \
                        -yearEnd $SrIhistYearEnd -monthEnd $SrIhistMonthEnd \
                        -limitDCCT $SrIhistMaxAbsDCCT -dataDir $SrIhistDataDir \
                        -dataName [subst \$dataName($monthlyPlotChoice)] ] 
}

proc MakeDailyPlotsWidget {widget args} {
    # make frame and interior widgets for daily plots frame

    global SrIhistShift SrIhistDay SrIhistYear SrIhistMonth
    set parent ""
    APSParseArguments {parent}
    APSFrame $widget -parent $parent -label "Plots by Day and Shift"
    set w $parent$widget.frame

    APSDateEntry .date -dayVariable SrIhistDay -yearVariable SrIhistYear \
      -monthVariable SrIhistMonth -parent $w
    set SrIhistShift All

    MakeShiftEntry .shift -variable SrIhistShift -parent $w

    frame $w.ops
    pack $w.ops -fill x -side top
    MakeDailyPlotButtons .plbuttons -parent $w.ops -command DoIhistPlot
}

proc MakeRangePlotsWidget {widget args} {
    # make frame and interior widgets for range plots frame.
    # this allows plots from any date to another date.

    global SrIhistYearStart SrIhistMonthStart SrIhistYearEnd SrIhistMonthEnd
    global SrIhistDayStart SrIhistDayEnd SrIhistHourStart SrIhistHourEnd SrIhistPlotSparsing

    set parent ""
    APSParseArguments {parent}
    APSFrame $widget -parent $parent -label "Plots for Date Range"
    set w $parent$widget.frame

    APSDateTimeEntry .date1 -dayVariable SrIhistDayStart -yearVariable SrIhistYearStart \
      -monthVariable SrIhistMonthStart -hourVariable SrIhistHourStart -parent $w \
      -label "Start (year, month, day, hour): "
    set SrIhistHourStart 0
    APSDateTimeEntry .date2 -dayVariable SrIhistDayEnd -yearVariable SrIhistYearEnd \
      -monthVariable SrIhistMonthEnd -hourVariable SrIhistHourEnd -parent $w \
      -label "End   (year, month, day, hour): "
    set SrIhistHourEnd 24

    set SrIhistPlotSparsing 1
    APSRadioButtonFrame .sparse -parent $w -label "Sparsing: " \
      -buttonList {None 2 4 8 16 32 64 128} \
      -valueList {1 2 4 8 16 32 64 128} \
      -variable SrIhistPlotSparsing \
      -orientation horizontal

    frame $w.ops
    pack $w.ops -fill x -side top
    MakeDailyPlotButtons .plbuttons -parent $w.ops -command DoIhistRangePlot
}

proc MakeMonthlyPlotsWidget {widget args} {
    # make frame and interior widgets for monthly plots frame

    global SrIhistYearStart SrIhistMonthStart SrIhistYearEnd SrIhistMonthEnd monthlyPlotChoice
    set parent ""
    APSParseArguments {parent}

    APSFrame $widget -parent $parent -label "Plots by Month" 
    set w $parent$widget.frame
    APSYearMonthEntry .date0 -yearVariable SrIhistYearStart -monthVariable SrIhistMonthStart \
      -parent $w \
      -label "Start date (year, month): "
    APSYearMonthEntry .date1 -yearVariable SrIhistYearEnd   -monthVariable SrIhistMonthEnd   \
      -parent $w \
      -label "End date   (year, month): "

    set monthlyPlotChoice integCurrent
    APSRadioButtonFrame .selection -parent $w -label "Plot Choice"  \
      -variable monthlyPlotChoice \
      -buttonList {"Integrated current" "Maximum current" "Average lifetime" "Maximum lifetime" "Percent >1mA" "Percent delivered"} \
      -valueList {integCurrent maxCurrent aveLifetime maxLifetime fractionUp percentDelivered} \
      -contextHelp "Select the type of monthly data you want to see."

    frame $w.ops
    pack $w.ops -fill x -side top
    APSButton .plot -parent $w -text PLOT -command DoIhistMonthlyPlot
}

set SrIhistStatus "Ready."
APSScrolledStatus .status -parent .userFrame -textVariable SrIhistStatus  -width 60 -height 3

set args $argv
set shift 1
set range 1
set month 1
APSStrictParseArguments {shift range month}
if $shift {
    MakeDailyPlotsWidget .daily -parent .userFrame
}
if $month {
    MakeMonthlyPlotsWidget .monthly -parent .userFrame
}
if $range {
    MakeRangePlotsWidget .range -parent .userFrame
}

