#!/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 archivalData 1
set archivalDir /home/helios/oagData/sr/PSStats
set archiveSubdir beam
set family Q
set outputDir ""
set outputRoot ""
set selectedSector 0

proc ChangeOutputDirectory {args} {
    global outputDir outputRoot runIndex 
    global archivalDir archiveSubdir family
    set outputDir $archivalDir/$archiveSubdir/$family
    set outputRoot ""
}

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

    APSFrame $widget -parent $parent -label "Data specification"
    set w $parent$widget.frame
    
    APSRadioButtonFrame .opOrTest -parent $w -label "Mode: " \
      -variable archiveSubdir -buttonList {beam test} -valueList {beam test} \
      -commandList {ChangeOutputDirectory ChangeOutputDirectory} \
      -contextHelp \
      "Selects whether to collect data in beam or test area.  Beam-mode data is taken with the power supplies set up for beam operations.  Test data is taken with the power supplies set in a testing configuration (e.g., all supplies at the same current)." \
      -packOption "-side left"

    APSRadioButtonFrame .family -parent $w -label "PS family: " \
      -variable family -buttonList {Q S H V FH FV QT SQ} -valueList {Q S H V FH FV QT SQ} \
      -commandList {ChangeOutputDirectory ChangeOutputDirectory ChangeOutputDirectory ChangeOutputDirectory ChangeOutputDirectory ChangeOutputDirectory ChangeOutputDirectory ChangeOutputDirectory} \
      -contextHelp \
      "Selects which power supply family to work with." \
      -packOption "-side left"
    
    ChangeOutputDirectory
}

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

proc MakeActionFrame {widget args} {
    set parent ""
    APSStrictParseArguments {parent}
    APSFrameGrid $widget -parent $parent -label "" -yList {one two three four}
    set w $parent$widget

    APSButton .collect -parent $w.one -text "Collect data" \
      -command CollectPSStats -contextHelp \
      "Initiates collection of statistics data for the power supplies you've selected.  The data is also processed at the completion of collection."
    APSButton .settest -parent $w.one -text "Apply test settings" \
      -command {SendPSTestSetings -family $family} -contextHelp \
      "Sets the selected PS family to 90% of the maximum output."
    global apsScriptUser
    if [string compare $apsScriptUser borland]==0 {
        APSButton .reprocessall -parent $w.two -text "Reprocess ALL data" \
          -command {ProcessPSStatsDataAll -family $family -mode $archiveSubdir} -contextHelp \
          "Reprocesses raw data files.  Not normally used."
        APSButton .reprocess -parent $w.two -text "Reprocess data" \
          -command {ProcessPSStatsDataChoice -family $family -mode $archiveSubdir} -contextHelp \
          "Reprocesses raw data files.  Not normally used."
    }
    APSButton .printout -parent $w.two -text "Analysis printouts" \
      -command {DisplayPSStats -family $family -mode $archiveSubdir} \
      -contextHelp "Creates a printout of the PS statistics from a dataset that you select."
    APSButton .printoutSel -parent $w.two -text "Selected analysis printouts" \
      -command {DisplayPSStats -family $family -mode $archiveSubdir -sector $selectedSector} \
      -contextHelp "Creates a printout of the PS statistics from a dataset that you select, for the sector selected below."
    APSButton .histogram -parent $w.two -text "Analysis histograms" \
      -command {DisplayPSStats -family $family -mode $archiveSubdir -displayMode histogram} \
      -contextHelp "Creates a histogram of the PS statistics from a dataset that you select."
    APSButton .history -parent $w.three -text "History plots" \
      -command {PlotPSStatHistory -family $family -mode $archiveSubdir} \
      -contextHelp "Plots statistics histories for the family you've selected.  Produces a very large number of plots and takes a while."
    APSButton .historyWorst10 -parent $w.three -text "Worst 10 history plots" \
      -command {PlotPSStatHistory -family $family -mode $archiveSubdir -worst 10} \
      -contextHelp "Plots statistics histories for the family you've selected, but only for the 10 worst power supplies as judged by the most recent set of measurements."
    APSButton .historySelected -parent $w.three -text "Selected history plots" \
      -command {PlotPSStatHistory -family $family -mode $archiveSubdir -sector $selectedSector} \
      -contextHelp "Plot history for the sector entered below."
    APSLabeledEntry .selection -parent $w.four -label "Selected sector: " \
      -textVariable selectedSector -width 4 -contextHelp \
      "Enter the sector number to show history data for when Selected History Plots is pressed." 
}

proc DisplayPSStats {args} {
    set family ""
    set mode ""
    set sector 0
    set displayMode printout
    APSStrictParseArguments {family mode sector displayMode}
    global archivalDir
    set files [lsort -decreasing [glob -nocomplain $archivalDir/$mode/$family/????-???-????.??????.stat]]
    regsub -all $archivalDir/$mode/$family/ $files "" files1
    regsub -all .stat $files1 "" files

    set choice [APSChooseItemFromList -name "List $family $mode-mode data" \
                  -itemList $files -returnList $files \
                  -multiItem 0 -contextHelp \
                  "Choose which run you want a $displayMode for.  The names are YYYY-JJJ-MMDD.HHMMSS, where YYYY is the year, JJJJ the Julian day, MMDD the month/day, and HHMMSS the time in hours, minutes, and seconds."]
    if [string length $choice]==0 {
        setStatusText "Display cancelled."
        return
    }
    setStatusText "$choice chosen.  Working..."
    if [lsearch {Q S} $family]!=-1 {
        if [catch {exec sddsquery $archivalDir/$mode/$family/$choice.stat -column \
                     | fgrep Resistance} result] {
            set resistance 0
        } else {
            set resistance 1
        }
        set collectOptions \
          [list \
             -collect=suffix=:VoltageMDRange,column=VoltageMDRange \
             -collect=suffix=VoltageMQRange,column=VoltageMQRange \
             ]
        set printoutOptions \
          [list \
             -column=VoltageMDRange -column=VoltageMQRange ]
        set histDataList \
          [list VoltageMDRange VoltageMQRange \
             MeasCurrentMDRange MeasCurrentMQRange ]
        set histBinSize \
          [list 0.05 0.01 0.0001 0.0001]
        if $resistance {
            lappend collectOptions -collect=suffix=Resistance 
            lappend printoutOptions -column=Resistance
            lappend histDataList  Resistance
            lappend histBinSize 0.2
        }
        set sortColumn VoltageMDRange
        set width 132
    } else {
        set collectOptions ""
        set printoutOptions ""
        set sortColumn MeasCurrentMDRange
        set width 80
        set resistance 0
        set histDataList \
          [list MeasCurrentMDRange MeasCurrentMQRange ]
        set histBinSize \
          [list 0.0001 0.0001]
    }
    
    set tmpFile /tmp/[APSTmpString]
    APSAddToTempFileList $tmpFile
    set sector [expr int($sector)]
    if {$sector<1 || $sector>40} {
        set sectorSelectionCmd "cat"
    } else {
        set sectorSelectionCmd "sddsprocess -pipe -match=column,Rootname=S${sector}\\\[AB\\\]*"
    }
    if [catch {eval exec sddscollect $archivalDir/$mode/$family/$choice.stat -pipe=out \
                 -collect=suffix=:MeasCurrentMDRange,column=MeasCurrentMDRange \
                 -collect=suffix=:MeasCurrentMQRange,column=MeasCurrentMQRange \
                 $collectOptions \
                 | sddsprocess -pipe \
                    -redefine=column,%s,%s,units=A,select=*Current* \
                 | sddssort -pipe -column=$sortColumn,decr \
                 | $sectorSelectionCmd > $tmpFile} result] {
        setStatusText "$result"
        return
    }
    if [string compare $displayMode histogram]==0 {
        set plotOptions ""
        set index -1
        foreach item $histDataList {
            incr index
            setStatusText "Histogramming $item..."
            if [catch {exec sddshist $tmpFile $tmpFile.$item \
                         -data=$item -size=[lindex $histBinSize $index]} result] {
                setStatusText "$result"
                return
            }
            lappend plotOptions -column=$item,frequency 
            lappend plotOptions $tmpFile.$item 
        }
        eval exec sddsplot -separate=request $plotOptions &
    } else {
        if [catch {eval exec sddsprintout $tmpFile $tmpFile.print -width=$width \
                     {"-title=Printout of statistics for $family in $mode mode"} \
                     -parameter=TimeStamp \
                     -format=double=%10.5f -column=Rootname,label=PSName \
                     -column=MeasCurrentMDRange -column=MeasCurrentMQRange \
                     $printoutOptions} result] {
            setStatusText "$result"
            return
        }
        APSFileDisplayWindow [APSUniqueName .] -comment "" -width $width -height 40 \
          -fileName $tmpFile.print -deleteOnClose 1 -sddsExportableFile $tmpFile 
        if {$resistance} {
            if [catch {exec sddsprocess $tmpFile -pipe=out \
                         -edit=column,FamilyName,Rootname,Z: \
                         -scan=column,FamilyNumber,FamilyName,$family%ld,type=long \
                         | sddssort -pipe -column=FamilyName \
                         | sddsbreak -pipe -change=FamilyNumber \
                         | sddsprocess -pipe \
                         -process=Resistance,median,ResistanceMedian \
                         -process=Resistance,qrange,ResistanceQRange \
                         "-define=column,ResistanceDeviation,Resistance ResistanceMedian - abs,units=mOhms" \
                         "-define=column,NormResistanceDeviation,ResistanceDeviation ResistanceQRange /" \
                         | sddssort -pipe -column=ResistanceDeviation,decr \
                         | tee $tmpFile.res \
                         | sddsprintout -pipe=in $tmpFile.print1 \
                         -parameter=Resistance* -format=double=%10.3f \
                         "-title=Printout of resistance data for $family in $mode mode" \
                         -column=Rootname,label=PSName -column=Resistance \
                         -column=ResistanceDeviation \
                         "-column=NormResistanceDeviation,label=ResistanceDeviation/QRange"} result] {
                setStatusText "$result"
                return
            }
            APSFileDisplayWindow [APSUniqueName .] -comment "" -width $width -height 40 \
              -fileName $tmpFile.print1 -deleteOnClose 1 -sddsExportableFile $tmpFile.res
        }
    }
}

proc PlotPSStatHistory {args} {
    set family ""
    set mode ""
    set worst 0
    set sector 0
    APSStrictParseArguments {family mode worst sector}
    global archivalDir
    set files [lsort [glob -nocomplain $archivalDir/$mode/$family/????-???-????.??????.stat]]
    if ![llength $files] {
        setStatusText "No data for family $family in $mode area."
        return
    }
    if [llength $files]<2 {
        setStatusText "Insufficient data for family $family in $mode area."
        return
    }
    setStatusText "Plotting data from [llength $files] runs."
    if $worst {
        if [lsearch -exact [list Q S] $family]!=-1 {
            set criterion VoltageQRange
        } else {
            set criterion CurrentQRange
        }
        set procFiles [lsort [glob -nocomplain \
                                $archivalDir/$mode/$family/????-???-????.??????.proc]]
        if ![llength $procFiles] {
            setStatusText "No processed data for family $family in $mode area."
            return
        }
        set lastFile [lindex $procFiles end]
        if [catch {exec sddssort $lastFile -pipe=out -column=$criterion,decr \
                 | sddsprocess -pipe -clip=10,0,invert \
                 | sdds2stream -pipe=in -column=Rootname} rootnameList]  {
            setStatusText "Problem finding worst power supplies: $rootnameList"
            return
        }
    } elseif {$sector<1 || $sector>40} {
        set rootnameList *
    } else {
        if {$sector<10} {
            set z "0"
        } else {
            set z ""
        }
        set rootnameList "{S${z}${sector}\\\[ABC\\\]}"
    }
    eval exec sddsplot -unsuppress=y -labelsize=0.02 -title= \
      -graph=symbol {"-topline=Statistics history for family $family"} \
      -layout=2,2 -groupby=namestring,fileindex -separate=namestring -ticks=xtime \
      "-column=Time,([join $rootnameList *QRange,]*QRange)" \
      "-column=Time,([join $rootnameList *DRange,]*DRange)"  \
      $files &
    setStatusText "Plot launched."
}

proc SendPSTestSetings {args} {
    set family ""
    APSStrictParseArguments {family}

    if ![APSQueryToProceed -message "This will change the settings of all SR power supplies.  Are you sure you wish to proceed?"] {
        return 
    }
    if [catch {exec cavget -pend=5 -list=S-DCCT:CurrentM -printerrors} current] {
        setStatusText "Unable to read beam current--can't continue."
        return
    } elseif {$current>0.1} {
        setStatusText "There appears to be stored beam---can't go to test mode."
        return
    }
    if {[catch {exec cavget -pend=5 -list=S:DesiredMode -noQuotes -printerrors} mode]} {
        setStatusText "Could not read the machine state S:DesiredMode---can't go to test mode."
        return
    }
    if {[string compare $mode "ASD Studies"]!=0} {
        setStatusText "The machine is not in \"ASD Studies\" mode. Current mode = \"${mode}\"---can't go to test mode."
        return
    }
    if {![APSMultipleChoice [APSUniqueName .] -name "Test mode confirmation" \
            -question "You've asked to go to test mode on the ${family} power supplies.  This will change the power supply configuration.  Do you wish to proceed?" \
            -returnList {1 0} -labelList {Yes No}]} {
        setStatusText "Test mode setup was aborted."
        return
    }

    global archivalDir
    if [catch {
        eval exec sddsprocess "${archivalDir}/inputFiles/${family}.mon" -pipe=output\
        -reedit=column,ControlName,"1%/MeasCurrentM/SetCurrentC.DRVH/"\
        | sddscasr -pipe=input,output -save\
        | sddsprocess -pipe=input,output -scan=column,Value,ValueString,%le,type=double\
        | sddsconvert -pipe=input,output -rename=column,Value=ValueDRVH,ValueString=ValueStringDRVH\
        | sddsprocess -pipe=input,output {"-define=column,Value,ValueDRVH 0.9 *"}\
        | sddsprocess -pipe=input,output -print=column,ValueString,%le,Value\
        | sddsprocess -pipe=input,output -reedit=column,ControlName,"1%/SetCurrentC.DRVH/SetCurrentC/"\
        | sddscasr -pipe=input -restore
                } result] {
        setStatusText $result
        return
    }
    setStatusText "Test mode set for family $family."
}

proc CollectPSStats {} {
    global outputDir outputRoot runIndex
    global archivalDir archiveSubdir family
    set outputRoot [exec date +%Y-%j-%m%d.%H%M%S]
    set output $outputDir/$outputRoot
    set input $archivalDir/inputFiles/$family.mon
    setStatusText "Launching data collection..."
    set widget [APSUniqueName .] 
    APSExecLog $widget \
      -callback "CollectPSStatsCallback -mode ok -filename $output -widget $widget" \
      -abortCallback "CollectPSStatsCallback -mode error -filename $output -widget $widget" \
      -cancelCallback "CollectPSStatsCallback -mode error -filename $output -widget $widget" \
      -width 70 -height 20 -contextHelp \
      "Execution window for $family power supply statistics collection." \
      -unixCommand \
      "sddsmonitor $input $output -steps=30 -interval=2,s -update=30 -verbose -comment=Family,$family"
    APSDisableButton $widget.buttonRow.ok.button
}

proc CollectPSStatsCallback {args} {
    set mode ok
    set filename ""
    set widget ""
    APSStrictParseArguments {mode filename widget}

    if {[string length $widget] && [winfo exists $widget]} {
        catch {destroy $widget}
    }

    switch $mode {
        ok {
        }
        default {
            setStatusText "Data collection aborted or cancelled---deleting data."
            catch {exec rm $filename}
        }
    }

    ProcessPSStatsData -filename $filename
}

proc ProcessPSStatsDataAll {args} {
    set family ""
    set mode ""
    APSStrictParseArguments {family mode}
    global archivalDir
    set files [lsort -decreasing [glob -nocomplain $archivalDir/$mode/$family/????-???-????.??????.gz]]

    foreach choice $files {
        catch {exec rm -f [file rootname $choice].proc}
        catch {exec rm -f [file rootname $choice].stat}
        setStatusText "Working on [file tail $choice]."
        ProcessPSStatsData -filename $choice
    }
}

proc ProcessPSStatsDataChoice {args} {
    set family ""
    set mode ""
    APSStrictParseArguments {family mode}
    global archivalDir
    set files [lsort -decreasing [glob -nocomplain $archivalDir/$mode/$family/????-???-????.??????.gz]]
    regsub -all $archivalDir/$mode/$family/ $files "" files1
    regsub -all .stat $files1 "" files
    set choice [APSChooseItemFromList -name "List $family $mode-mode data" \
                  -itemList $files -returnList $files \
                  -multiItem 0 -contextHelp \
                  "Choose data file to process.  The names are YYYY-JJJ-MMDD.HHMMSS, where YYYY is the year, JJJJ the Julian day, MMDD the month/day, and HHMMSS the time in hours, minutes, and seconds."]
    if [string length $choice]==0 {
        setStatusText "Display cancelled."
        return
    }
    setStatusText "$choice chosen.  Working..."
    catch {exec rm -f $archivalDir/$mode/$family/[file rootname $choice].proc}
    catch {exec rm -f $archivalDir/$mode/$family/[file rootname $choice].stat}
    ProcessPSStatsData -filename $archivalDir/$mode/$family/$choice
}

proc ProcessPSStatsData {args} {
    set filename ""
    APSStrictParseArguments {filename}
    
    if ![file exists $filename] {
        setStatusText "File not found: $filename"
        return
    }
    if [catch {exec sdds2stream -parameter=Family $filename} family] {
        setStatusText $family
        return
    }
    setStatusText "Processing data for family $family."
    set rootname [APSRemoveGzipExtension $filename]

    if [lsearch -exact [list Q S] $family]!=-1 {
        if [catch \
              {exec sddsprocess $filename -pipe=out \
                 -process=*:*,ave,%sMean \
                 -process=*:*,drange,%sDRange -proc=*:*,qrange,%sQRange \
                 -process=Time,first,Time \
                 | sddscollapse -pipe \
                 | sddsprocess -pipe \
                 "-define=column,%sResistance,%sVoltageMMean abs %sMeasCurrentMMean abs 1e-16 + / 1e3 *,select=*VoltageMMean,edit=%/VoltageMMean//,units=mOhms" \
                 | tee $rootname.stat \
                 | sddscollect \
                 -collect=suffix=VoltageMMean,column=VoltageMean \
                 -collect=suffix=VoltageMDRange,column=VoltageDRange \
                 -collect=suffix=VoltageMQRange,column=VoltageQRange \
                 -collect=suffix=MeasCurrentMMean,column=CurrentMean \
                 -collect=suffix=MeasCurrentMDRange,column=CurrentDRange \
                 -collect=suffix=MeasCurrentMQRange,column=CurrentQRange \
                 -collect=suffix=Resistance \
                 -pipe \
                 | sddsprocess -pipe \
                 "-define=column,VoltageStatRatio,VoltageQRange VoltageDRange 1e-16 + /" \
                 "-define=column,CurrentStatRatio,CurrentQRange CurrentDRange 1e-16 + /" \
                 | sddssort -col=VoltageQRange,decr -pipe=in $rootname.proc } result] {
            setStatusText $result
        }
    } else {
        if [catch \
              {exec sddsprocess $filename -pipe=out \
                 -process=*:*,drange,%sDRange -proc=*:*,qrange,%sQRange \
                 -process=Time,first,Time \
                 | sddscollapse -pipe \
                 | tee $rootname.stat \
                 | sddscollect \
                 -col=suf=MeasCurrentMDRange,column=CurrentDRange \
                 -col=suf=MeasCurrentMQRange,column=CurrentQRange \
                 -pipe \
                 | sddsprocess -pipe \
                 "-define=column,CurrentStatRatio,CurrentQRange CurrentDRange 1e-16 + /" \
                 | sddssort -col=CurrentQRange,decr -pipe=in $rootname.proc } result] {
            setStatusText $result
        }
    }
    if {[string compare [file extension $filename] .gz] && \
        [catch {exec gzip $filename} result]} {
        setStatusText $result
        return
    }
    setStatusText "Done processing data for family $family."
}

set CVSRevisionAuthor "\$Revision: 1.16 $ \$Author: lobach $"
APSApplication . -name SRPSStats \
  -version $CVSRevisionAuthor \
  -overview "Collects, archives, and analyzes storage-ring power supply statistics for quads and sextupoles."

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

MakeOutputFrame .output -parent .userFrame
MakeActionFrame .action -parent .userFrame
