#!/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: soliday $"

APSStandardSetup
        
set configDir /home/helios/oagData/sr/rfMonitorFiles

APSApplication . -name SRrfMonitor -version $CVSRevisionAuthor \
  -overview {This is the SRrfMonitor utility.  It provides a simple way to set up storage ring rf data logging and review.  The data can be plotted after it is collected, or during collection.  You can also manipulate and display the data offline using the SDDS toolkit programs.}

lappend SectorVarList S36 S37 S40 
lappend SectorClassList S36.* S37.* S40.* 
lappend CavityVarList Cav1 Cav2 Cav3 Cav4 CavSum 
lappend CavityClassList S??.C1.* S??.C2.* S??.C3.* S??.C4.* S??.All.* 
lappend RfSysVarList Vacuum Voltage FwdPower RevPower ProbePower CavityPhase \
  CouplerIRDet CouplerIRDet FlangeTemp \
  WaterTemp WaterSupplyTemp WgAirTemp TunerTemp RFFingerTemp TunerFingerTemp \
  AbsorberTemp CavityTemp HybridTemp HybridFlow TunerPos CouplerTemp \
  BlowerTemp TunerSetpt
lappend RfSysClassList S??.*Vacuum S??.*GapVoltage S??.*ForwardPower \
  S??.*ReversePower S??.*ProbePower S??.*Phase S??.*CplTemp \
  S??.*IrDet \
  S??.*FlangeTemp S??.*WaterTemp S??.*WaterSupplyTemp S??.*WGAirTemp \
  S??.*Tuner*Temp S??.*RFFingerTemp S??.*TunerFingerTemp \
  S??.*AbsorberTemp S??.*CavityTemp S??.*HybridTemp S??.*HybridFlow \
  S??.*TunerPos S??.*CouplerTemp \
  S??.*.AirTemp S??.*.TunerSetpoint

lappend KVarList K1 K2 K3 K4
lappend KClassList K1.* K2.* K3.* K4.*
lappend KSysVarList HVPS Kalmus KFwdPower KRevPower KDrivePower \
  KFBCavPhase KFBPowerPhase KFBAGC KDrivePhaseOffset KPowerPhaseOffset \
  KCavityPhaseOffset \
  KFlow KTemp
lappend KSysClassList K?.Misc.HVPS K?.RF.Kalmus* K?.RF.ForwardPower \
  K?.RF.ReversePower \
  K?.RF.DrivePower K?.Feedback.CavityPhase K?.Feedback.PowerPhase K?.Feedback.AGC \
  K?.PhaseOffset.Drive K?.PhaseOffset.Power K?.PhaseOffset.Cavity \
  K?.Misc.Flow K?.Misc.Temp

set orderMode bySector
set printMode color
set printerName mcr2
set printPlots 0
set graphicType line,vary
set layoutChoice default

set mainStatus "Ready."

proc SetMainStatus {text} {
    global mainStatus
    set mainStatus "$text ([exec date +%H:%M:%S])"
    update
}

proc FileIsOnTmpDisk {filename} {
    if {[string first "/tmp/" $filename]!=0 || ![file exists $filename]} {
        return 0
    }
    return 1
}

proc DeleteTmpFileOnly {filename} {
    if ![FileIsOnTmpDisk $filename] return
    file delete $filename
}

proc MakeTitleLabel {widget args} {
    set parent ""
    set title ""
    APSParseArguments {parent title}
    set w $parent$widget
    frame $w 
    pack  $w -side top -fill x

    label $w.label -text "$title" -relief ridge
    pack $w.label -fill x -side top
}

proc SetListOfVariables {value args} {
    foreach variable $args {
        global $variable
        set $variable $value
    }
}

proc ToggleListOfVariables {args} {
    foreach variable $args {
        global $variable
        set $variable [expr [subst \$$variable]?0:1]
    }
}

proc MakeRfCheckButtons {widget args} {
    set parent ""
    set label ""
    set buttonList ""
    set variableList ""
    set contextHelp ""
    APSParseArguments {parent label buttonList variableList contextHelp}

    foreach variable [split $variableList] {
        global $variable
        set $variable 0
    }
    set count [llength [split $variableList]]
    if $count>1 {
        set allNone 1
    } else { 
        set allNone 0
    }
    APSCheckButtonFrame $widget -parent $parent -buttonList $buttonList \
      -variableList $variableList -label $label \
      -contextHelp $contextHelp -allNone $allNone  \
      -packOption "-side left -fill y"
}

set RFCompareChoice CompareNone

proc MakeAllNoneButtons {widget args} {
    set parent ""
    set groupName "NoName"
    set variableList {}
    APSParseArguments {parent variableList groupName}
    if [llength $variableList]==0 {
        return 
    }
    APSFrame $widget -parent $parent -label Group \
      -contextHelp "These buttons control settings for all signals in the $groupName group."
    set w $parent$widget.frame
    APSButton .all -parent $w -text "ALL" \
      -command "SetListOfVariables 1 $variableList" -packOption "-side top -fill x"
    APSButton .none -parent $w -text "NONE" \
      -command "SetListOfVariables 0 $variableList" -packOption "-side top -fill x"
    APSButton .toggle -parent $w -text "TOGGLE" \
      -command "ToggleListOfVariables $variableList" -packOption "-side top -fill x"

}

proc MakeCavityChoicesFrame {widget args} {
    global RFCompareChoice
    set parent ""
    APSParseArguments {parent}
    set w $parent$widget

    frame $w  -bd 4 
    pack  $w -side top 

    MakeRfCheckButtons .sectors -parent $w -buttonList "36 37 40" \
      -label "Sectors" \
      -variableList "S36 S37 S40" \
      -contextHelp "These buttons select which sectors will be used for cavity data logging or review." 
    MakeRfCheckButtons .cavities -parent $w -buttonList "1 2 3 4 sum" \
      -variableList "Cav1 Cav2 Cav3 Cav4 CavSum" -label Cavities \
      -contextHelp "These buttons select which cavities will be used for cavity data logging or review.  The sum button selects data pertaining to all cavities, like voltage voltage or hybrid temperatures." 
    MakeRfCheckButtons .misc -parent $w -buttonList "vacuum hybrid-flow tuner-pos tuner-setpt" \
      -variableList "Vacuum HybridFlow TunerPos TunerSetpt" -label Misc. \
      -contextHelp "These buttons select miscellaneous systems for data logging or review." 
    MakeRfCheckButtons .rfdata -parent $w -buttonList "voltage fwd-power rev-power probe-power cavity-phase" \
      -variableList "Voltage FwdPower RevPower ProbePower CavityPhase" -label "RF" \
      -contextHelp "These buttons select monitoring of gap voltage, forward power, reverse power, probe power, and cavity phase." 
    MakeRfCheckButtons .ctempdata -parent $w -buttonList "coupler coupler-IR flanges water {water supply} tuners rf-fingers tuner-fingers body" \
      -variableList "CouplerTemp CouplerIRDet FlangeTemp WaterTemp WaterSupplyTemp TunerTemp RFFingerTemp TunerFingerTemp CavityTemp" -label "Cavity Temps" \
      -contextHelp "These buttons select monitoring of cavity temperature data." 
    MakeRfCheckButtons .mtempdata -parent $w -buttonList "wg-air absorber hybrid blower-air" \
      -variableList "WgAirTemp AbsorberTemp HybridTemp BlowerTemp"  -label "Misc Temps" \
      -contextHelp "These buttons select monitoring of miscellaneous temperature data."
    MakeAllNoneButtons .allnone -parent $w -groupName Cavity \
      -variableList {S36 S37 S40 Cav1 Cav2 Cav3 Cav4 CavSum Vacuum HybridFlow TunerPos TunerSetpt \
                       Voltage FwdPower RevPower ProbePower CavityPhase CouplerTemp CouplerIRDet FlangeTemp \
                       WaterTemp WaterSupplyTemp TunerTemp RFFingerTemp TunerFingerTemp CavityTemp WgAirTemp AbsorberTemp HybridTemp BlowerTemp } 
    
}

proc MakeKlystronChoicesFrame {widget args} {
    set parent ""
    APSParseArguments {parent}
    set w $parent$widget
    frame $w  -bd 4 
    pack  $w -side top

    MakeRfCheckButtons .klystron -parent $w -buttonList "1 2 3 4" \
      -variableList "K1 K2 K3 K4" -label Klystrons \
      -contextHelp "These buttons select which stations will be logged or reviewed." 
    MakeRfCheckButtons .hvps -parent $w -buttonList "HVPS Water Temps" \
      -variableList "HVPS KFlow KTemp" -label "Misc."\
      -contextHelp "This button selects high-voltage power-supply logging/reviewing."
    MakeRfCheckButtons .rfdata -parent $w -buttonList "Kalmus drive-power fwd-power rev-power" \
      -variableList "Kalmus KDrivePower KFwdPower KRevPower" -label "RF" \
      -contextHelp "These buttons select which klystron rf data will be logged or reviewed." 
    MakeRfCheckButtons .feedback -parent $w -buttonList "cavity-phase power-phase AGC" \
      -variableList "KFBCavPhase KFBPowerPhase KFBAGC" -label "Feedback" \
      -contextHelp "These buttons select which klystron feedback data will be logged or reviewed." 
    MakeRfCheckButtons .phase -parent $w -buttonList "drive power cavity" \
      -variableList "KDrivePhaseOffset KPowerPhaseOffset KCavityPhaseOffset" -label "Phase Offset" \
      -contextHelp "These buttons select which klystron phase offset data will be logged or reviewed." 
    MakeAllNoneButtons .allnone -parent $w -groupName Klystron \
      -variableList {K1 K2 K3 K4 HVPS KFlow KTemp Kalmus KDrivePower KFwdPower KRevPower \
                       KFBCavPhase KFBPowerPhase KFBAGC KDrivePhaseOffset KPowerPhaseOffset KCavityPhaseOffset }
    
}

proc RecomputeTimeData {varSet} {
    global Samples TotalTime Interval
    if {$varSet=="Samples"} {
        if {$Samples<1} { set Samples 1}
        set Interval [expr (3600.0*$TotalTime)/$Samples]
    } else {
        if {$Interval<=0} { set Interval 0.1 }
        set Samples [expr int($TotalTime*3600.0/$Interval+0.5)]
        if {$Samples<1} { set Samples 1 }
        #               make data consistent with integer number of Samples
        if {$varSet=="Interval"} {
            set TotalTime [expr $Interval*$Samples/3600.0]
        } else {
            set Interval [expr $TotalTime*3600.0/$Samples]
        }
    }
}


proc MakeMonitorSettingsWidget {widget args} {
    global Samples Interval TotalTime outputFile outputDir env
    set Interval 1
    set TotalTime 1
    RecomputeTimeData TotalTime
    #        set TotalTime [expr $Samples*$Interval/3600.0]
    set outputFile ""
    set outputDir $env(HOME)

    set parent ""
    set width 60
    APSParseArguments {parent width}
    set w $parent$widget
    frame $w -bd 4 
    pack $w -side top -fill x

    APSLabeledEntry .interval -parent $w -label "Interval (s): " \
      -textVariable Interval -width $width \
      -contextHelp "Enter the time between samples in seconds in this field.  Hitting return recalculates the number of samples."
    bind $w.interval.entry <Return> "RecomputeTimeData Interval"
    APSLabeledEntry .time -parent $w -label "Total time (h): " \
      -textVariable TotalTime -width $width \
      -contextHelp "Enter the total time of the data logging in hours in this field.  Hitting return recalculates the number of samples." 
    bind $w.time.entry <Return> "RecomputeTimeData TotalTime"
    APSLabeledEntry .samples -parent $w -label "Samples: " \
      -textVariable Samples -width $width \
      -contextHelp "Enter the number of samples in this field.  Hitting return recalculates the time interval between samples."
    bind $w.samples.entry <Return>  "RecomputeTimeData Samples"
    APSLabeledEntry .output -parent $w -label "Output file: " \
      -textVariable outputFile -width $width \
      -contextHelp "Enter a name for the output file to hold the data.  This file is not deleted by quickMonitor, so you can use the data for other purposes."
    APSLabeledEntry .direct -parent $w -label "Directory: " \
      -textVariable outputDir -width $width \
      -contextHelp "Enter the name of the directory in which to place the output file."
}

proc MakeMonitorOpsWidget {widget args} {
    set parent ""
    APSParseArguments {parent}
    set w $parent$widget
    frame $w 
    pack $w -side top -fill x
    
    APSButton .run -parent $w -text RUN -command RunMonitor \
      -contextHelp "Launches a monitoring subprocess to collect the data.  The data that is logged is determined by which checkbuttons are set from the choices above.  The number of samples and the time interval between samples are determined by the 'Interval', 'Total time', and 'Samples' entries above.  The data is logged into the file named in 'Output file', which is placed in the directory named in 'Directory'."
    APSButton .new -parent $w -text "NEW..." -command "exec SRrfMonitor &" \
      -contextHelp "Launches a new instance of the SRrfMonitor screen"
}

proc SupplyTmpFile {} {
    while 1 {
        set inputFile /tmp/[APSTmpString]
        if {![file exists $inputFile]} {
            break
        }
    }
    return $inputFile
}

set jobCounter 0
proc RunMonitor {} {
    global PVname outputFile outputDir Interval Samples 
    global jobCounter

    SetMainStatus "Working..."
    if {[string length $outputFile]==0} {
        SetMainStatus "Supply an output filename."
        bell
        return
    }
    set file $outputDir/$outputFile
    if {[string first " " $file]!=-1} {
        SetMainStatus "Spaces are not allowed in the filename"
        bell
        return
    }
    if {[file exists $file]} {
        if ![APSYesNoPopUp "Delete existing $outputFile?"] {
            SetMainStatus "Supply a new output filename or directory."
            return
        }
    }

    set inputFile /tmp/[APSTmpString]
    set choices [PrepareRfMonitorFile $inputFile]
    if ![APSYesNoPopUp "$choices process variables will be monitored.  Okay to continue?"]  {
        file delete $inputFile
        SetMainStatus "Ready."
        return
    }
    if $choices==0 { 
        file delete $inputFile
        SetMainStatus "No data chosen for logging."
        return 
    }
    set dtLimit [expr $choices*0.0006]
    if {$dtLimit>$Interval} {
        if ![APSYesNoPopUp "The time interval is too short for the chosen number of process variables.  The interval will actually turn out to be more like $dtLimit.  Continue anyways?"] {
            file delete $inputFile
            SetMainStatus "Run aborted."
            return
        }
    }

    set date [exec date]
    SetMainStatus "Run started $date."
    APSExecLog .mjob$jobCounter -unixCommand "sddsmonitor $inputFile $file \
                -erase -interval=$Interval,s -steps=$Samples -verbose -update=10 " \
      -contextHelp "This window is running an SRrfMonitor subprocess, started $date, writing into file $file."  \
      -callback "AlertToFinishedJob $file $date"
    incr jobCounter
    after 30000 "file delete $inputFile"
}

proc AlertToFinishedJob {file args} {
    bell
    APSInfoWindow .[APSTmpString] -name JobFinishedAlert \
      -infoMessage "Logging run for $file ($args) is done."
    bell
}

proc MakeMatchOption {varString classString} {
    set varList [split $varString]
    set classList [split $classString]
    set index 0
    set first 1
    set matchOpt ""
    foreach variable $varList {
        global $variable
        if [set $variable] {
            if $first { 
                set matchOpt "-match=col,Classification=[lindex $classList $index]"
                set first 0
            } else {
                set matchOpt "$matchOpt,Classification=[lindex $classList $index],|"
            }
        }
        incr index
    }
    return $matchOpt        
}

proc PrepareRfMonitorFile {file} {
    global SectorVarList CavityVarList RfSysVarList SectorClassList CavityClassList RfSysClassList 
    global KVarList KClassList KSysVarList KSysClassList
    global configDir
    
    set matchOpt1 [MakeMatchOption "$SectorVarList" "$SectorClassList"]
    set matchOpt2 [MakeMatchOption "$CavityVarList" "$CavityClassList"]
    set matchOpt3 [MakeMatchOption "$RfSysVarList" "$RfSysClassList"]
    if {[string length $matchOpt1]!=0 && [string length $matchOpt2]!=0 && [string length $matchOpt3]!=0} {
        exec sddsprocess $configDir/SRrf.mon $file.rf "$matchOpt1" "$matchOpt2" "$matchOpt3" -nowarning
        set rfChoices [lindex [split [exec sdds2stream -rows $file.rf ]] 0]
        set rfFile $file.rf
    } else {
        set rfChoices 0
        set rfFile ""
    }

    set matchOpt1 [MakeMatchOption "$KVarList" "$KClassList"]
    set matchOpt2 [MakeMatchOption "$KSysVarList" "$KSysClassList"]
    if {[string length $matchOpt1]!=0 && [string length $matchOpt2]!=0} {
        exec sddsprocess $configDir/SRrf.mon $file.kly "$matchOpt1" "$matchOpt2" -nowarning
        set klyChoices [lindex [split [exec sdds2stream -rows $file.kly]] 0]
        set klyFile $file.kly
    } else {
        set klyChoices 0
        set klyFile ""
    }


    if ![expr $rfChoices+$klyChoices] {
        return 0
    }
    exec sddsprocess $configDir/SRrf.mon $file.global "-match=column,Classification=S.Global" -nowarning

    eval exec sddscombine  $rfFile $klyFile $file.global -merge $file 

    set choices [lindex [split [exec sdds2stream -rows $file]] 0]

    return $choices
}

proc MakeChoicesFrame {widget args} {
    set parent ""
    APSParseArguments {parent}
    set w $parent$widget
    frame $w -bd 4 -relief raised
    pack $w -side top -fill x
    
    MakeTitleLabel .title -parent $w -title "RF System Data Logging/Review Choices"
    MakeCavityChoicesFrame .cavity -parent $w
    MakeKlystronChoicesFrame .klystron -parent $w
}

proc MakeMonitorFrame {widget args} {
    set parent ""
    set entryWidth 50
    APSParseArguments {parent entryWidth}
    set w $parent$widget
    frame $w -bd 4 -relief raised
    pack $w -side top -fill x

    MakeTitleLabel .title -parent $w -title "RF System Data Logging"
    MakeMonitorSettingsWidget .settings -parent $w -width $entryWidth
    MakeMonitorOpsWidget .ops -parent $w
}


set reviewDir "/home/helios/oagData/monitoring/SRrfg"
set lastOutputDir ""
set reviewFile ""
set timeLowerLimit 0
set timeUpperLimit 0
set sparsingInterval 1
set yLimitMin 0
set yLimitMax 0
set autoGapping 1
set dayOfInterest  ""
set yearOfInterest ""
set monthOfInterest ""

proc SelectReviewFile {} {
    global reviewDir outputDir lastOutputDir reviewFile
    if [string length $reviewDir]==0 { set reviewDir $outputDir }
    if {[string length $lastOutputDir]!=0 && [string compare $outputDir $lastOutputDir]!=0} {
        set reviewDir $outputDir
        set lastOutputDir $outputDir
    }
    set reviewFile [APSFileSelectDialog .chooseReviewFile -listDir $reviewDir]
    if [string length $reviewFile]==0 {
        SetMainStatus "No file chosen."
        return
        }
    set newDir [file dirname $reviewFile]
    if [string compare $newDir $reviewDir]!=0 {
        set reviewDir $newDir
    }
    SetMainStatus "File chosen. Ready to plot or print."
}

proc ClearReviewFile {} {
    global reviewFile
    set reviewFile ""
    SetMainStatus "File cleared. Will plot or print files for given date."
}

set confirmPlotPVs 1
proc PlotReviewFile {args} {
    global reviewFile configDir timeLowerLimit timeUpperLimit confirmPlotPVs
    global yLimitMin yLimitMax autoGapping
    global RFCompareChoice printerName printMode sparsingInterval orderMode graphicType
    global yearOfInterest dayOfInterest monthOfInterest layoutChoice

    set printPlots 0
    APSParseArguments {printPlots}

    SetMainStatus "Working..."
    if [string length $reviewFile] {
        lappend reviewFileList $reviewFile
    } else {
        set dateList [APSFormatDate -year $yearOfInterest -day $dayOfInterest -month $monthOfInterest \
                        -dateFormat list -twoDigitYear 0]
        set reviewFileList [APSFindFilesBetweenDates -rootname SRrf- \
                              -directory /home/helios/oagData/monitoring/SRrfg \
                              -tailsOnly 0 -startDateList $dateList \
                              -endDateList $dateList \
                              -extensionList {"" ".\[0-9\]\[0-9\]\[0-9\]\[0-9\]" ".gz"}]
    }

    if [llength $reviewFileList]==0 {
        SetMainStatus "No file or files for review were chosen."
        return
    }

    set dataPresentFileList {}
    if [llength $reviewFileList]>1 {
        foreach file $reviewFileList {
            if ![file exists $file] {
                SetMainStatus "File $file does not exist."
                return
            }
            if ![APSCheckSDDSFile -fileName $file] {
                SetMainStatus "$file is not an SDDS file."
                return
            }
            set dataPresentFile /tmp/[APSTmpString]
            lappend dataPresentFileList $dataPresentFile
            # get the names of all data columns in the data file
            exec sddsquery $file -sddsOutput=$dataPresentFile -column
        }
        set dataPresentFile /tmp/[APSTmpString]
        eval exec sddscombine $dataPresentFileList -merge -pipe=out | sddssort -column=Name -unique -pipe=in $dataPresentFile 
        eval file delete $dataPresentFileList
    } else {
        set file [lindex $reviewFileList 0]
        set dir [file dirname $file]
        set root [file tail [file rootname $file]]
        set dataPresentFile /tmp/[APSTmpString]
        if ![file exists $dir/columnIndices/$root.index.gz] {
            # get the names of all data columns in the data file
            exec sddsquery $file -sddsOutput -column \
              | sddssort -pipe=in -column=Name $dataPresentFile 
        } else {
            exec cp $dir/columnIndices/$root.index.gz $dataPresentFile.gz
            set dataPresentFile $dataPresentFile.gz
        }
    }


    set tLowerLimit 0
    set tUpperLimit 0
    if {[string length $timeLowerLimit] && [string length $timeUpperLimit]} {
        set tLowerLimit [APSConvertTimeToHours $timeLowerLimit]
        set tUpperLimit [APSConvertTimeToHours $timeUpperLimit]
        if {[string length $tLowerLimit] && [string length $timeUpperLimit]} {
            if $tLowerLimit>$tUpperLimit {
                SetMainStatus "Lower limit greater than upper limit for time."
                return
            }
        } else {
            SetMainStatus "Warning: invalid time limit value--values ignored."
        }
    }
    
    set requestedReadbackFile /tmp/[APSTmpString]
    set count [PrepareRfMonitorFile $requestedReadbackFile]
    if {$confirmPlotPVs && ![APSYesNoPopUp "$count process variables will be plotted.  Okay to continue?"]}  {
        SetMainStatus "Ready."
        return
    }

    if $count==0 {
        SetMainStatus "No data chosen for plotting."
        return
    }

    # select the subset that are in the request for plotting
    set readbackListFile /tmp/[APSTmpString]
    exec sddsselect -nowarning $dataPresentFile $requestedReadbackFile $readbackListFile -match=Name=ReadbackName 

    if [string compare $orderMode "byQuantity"]==0 {
        set sortName1 QuantityGroup
        set sortName2 SectorNumber
    } else {
        set sortName1 SectorNumber
        set sortName2 QuantityGroup
    }

    # get the PlotCommandGroup for each, and make a unique list of these
    # get the corresponding plot commands
    set plotCommandListFile /tmp/[APSTmpString]
    exec sddsselect -nowarning $readbackListFile $requestedReadbackFile -match=Name=ReadbackName -pipe=out \
      | sddsxref -nowarning $configDir/SRrf.mon.xref -pipe -match=Name=ReadbackName -take=PlotCommandGroup,QuantityGroup,SectorNumber \
      | sddssort -pipe -column=PlotCommandGroup -unique  \
      | sddssort -pipe -column=$sortName1 -column=$sortName2 \
      | sddsxref -nowarning -pipe=in $configDir/SRrf.plotcoms \
            $plotCommandListFile -match=PlotCommandGroup -take=sddsplotOptions

    eval file delete [glob -nocomplain ${requestedReadbackFile}*] $dataPresentFile

    set count [lindex [split [exec sdds2stream -rows $readbackListFile]] 0]
    if $count==0 {
        file delete $readbackListFile $plotCommandListFile
        SetMainStatus "No valid data in data file(s)."
        return
    }

    set extraArgs {}
    if [string compare $RFCompareChoice "CompareNone"]!=0 {
        switch $RFCompareChoice {
            CompareVoltage {
                set editstring "s/./10Di/GapVoltage.Cavity/"
            }
            CompareFwdPower {
                set editstring "s/./10Di/ForwardPower.Cavity/"
            }
            CompareBeamCurrent {
                set editstring "10Di/S.S35DCCT/"
            }
            - {
                APSAlertBox .[APSTmpString] \
                -modeless 1 \
                -errorMessage "Invalid rf comparison choice: $RFCompareChoice---using voltage."
                set editstring "s/./10Di/GapVoltage.Cavity/"
            }
        }
        if [string compare $RFCompareChoice CompareBeamCurrent]==0 {
            #  compare with beam current, so can do for anything 
            set normalGroupFile /tmp/[APSTmpString]
            exec sddsprocess $plotCommandListFile -pipe=out -nowarnings \
              "-edit=column,PlotCommandGroup1,PlotCommandGroup,$editstring" \
              | sddsconvert -pipe -rename=col,sddsplotOptions=sddsplotOptions0 \
              | sddsxref -pipe $configDir/SRrf.plotcoms -match=PlotCommandGroup1=PlotCommandGroup -reuse \
              -take=sddsplotOptions -nowarnings \
              | sddsconvert -pipe -rename=col,sddsplotOptions=sddsplotOptions1 \
              | sddsprocess -pipe=in $normalGroupFile -nowarnings \
              "-print=column,sddsplotOptions,%s %s,sddsplotOptions0,sddsplotOptions1"
            exec sddscombine -merge -overwrite $normalGroupFile $plotCommandListFile 
            file delete $normalGroupFile
        } else {
            # compare with sector data (voltage, fwd power), so can only do
            # for other sector data
            set normalGroupFile /tmp/[APSTmpString]
            exec sddsprocess $plotCommandListFile -pipe=out -nowarnings \
              "-match=col,PlotCommandGroup=S.*,PlotCommandGroup=K*,\|,\!" \
              "-edit=column,PlotCommandGroup1,PlotCommandGroup,$editstring" \
              | sddsconvert -pipe -rename=col,sddsplotOptions=sddsplotOptions0 \
              | sddsxref -pipe $configDir/SRrf.plotcoms -match=PlotCommandGroup1=PlotCommandGroup -reuse \
              -take=sddsplotOptions -nowarnings \
              | sddsconvert -pipe -rename=col,sddsplotOptions=sddsplotOptions1 \
              | sddsprocess -pipe=in $normalGroupFile -nowarnings \
              "-print=column,sddsplotOptions,%s %s,sddsplotOptions0,sddsplotOptions1"
            set oddGroupFile /tmp/[APSTmpString]
            exec sddsprocess $plotCommandListFile $oddGroupFile "-match=column,PlotCommandGroup=S.*,PlotCommandGroup=K*,\|" -nowarnings
            exec sddscombine -merge -overwrite $normalGroupFile $oddGroupFile $plotCommandListFile 
            file delete $normalGroupFile $oddGroupFile
        }
        lappend extraArgs -layout=1,2
    }

    lappend extraArgs -graphic=$graphicType,eachfile

    if [string compare $layoutChoice default] {
        lappend extraArgs -layout=$layoutChoice
    }

    if {$yLimitMin!=$yLimitMax} {
        set limitArgs "-limit=ymin=$yLimitMin\\,ymax=$yLimitMax"
    } else {
        set limitArgs ""
    }

    set parameterNames [APSGetSDDSNames -class parameter -fileName [lindex $reviewFileList 0]]
    if [lsearch -exact $parameterNames PlotVsDayOfMonth]==-1 {
        set timeVariable TimeOfDay
    } else {
        set timeVariable DayOfMonth
    }

    set deleteDataFile 0
    set dataFile [join $reviewFileList]
    if {$sparsingInterval>1} {
        SetMainStatus "Sparsing..."
        set tmpFile /tmp/[APSTmpString]
        eval exec sddscombine $reviewFileList -pipe=out | sddsprocess -pipe=in $tmpFile -sparse=$sparsingInterval
        set dataFile $tmpFile
        set deleteDataFile 1
    }

    set cshFile /tmp/[APSTmpString]
    if $autoGapping {
        set severArg -sever=xgap=-1.5
    } else {
        set severArg ""
    }

    set rootname [file tail [file rootname $dataFile]]
    regsub SRrf- $rootname {} tag
    set dateList [split $tag -]
    catch {exec timeconvert -breakdown=year=[lindex $dateList 0],julian=[lindex $dateList 1],hour=0 -textOutput} dateString
    if $printPlots {
        # do the plots one at a time to avoid making huge files that will be too large for the spool area
        switch $printMode {
            B&W   { set device postscript }
            color { set device cpostscript}
        }
        if $tLowerLimit==$tUpperLimit {
            set commandHead  \
            "sddsplot '-title=Data collected starting $dateString' -device=$device $dataFile $extraArgs $severArg -same=x,global "
        } else {
            set commandHead \
            "sddsplot '-title=Data collected starting $dateString' -device=$device $dataFile $extraArgs $severArg -same=x,global -limit=xmin=$tLowerLimit,xmax=$tUpperLimit "
        }
        exec sddsprocess $plotCommandListFile -pipe=out -nowarnings \
          "-print=column,Command0,[APSMakeSafeQualifierString $commandHead] %s | lpr -P$printerName,sddsplotOptions" \
          "-edit=column,Command,Command0,%/-end/$limitArgs -end/100%/TimeOfDay/$timeVariable/" \
          | sdds2stream -pipe=in -noquotes -column=Command > $cshFile 
        if {$deleteDataFile && [FileIsOnTmpDisk $dataFile]} {
            exec echo "rm -f $dataFile" >> $cshFile
        }
    } else {
        # screen plotting
        # open file this way because echo -n doesn't work on Solaris.
        set cshFID [open $cshFile w]
        if $tLowerLimit==$tUpperLimit {
            puts -nonewline $cshFID "sddsplot '-title=Data collected starting $dateString' $dataFile $extraArgs $severArg -same=x,global " 
        } else {
            puts -nonewline $cshFID "sddsplot '-title=Data collected starting $dateString' $dataFile $extraArgs $severArg -same=x,global -limit=xmin=$tLowerLimit,xmax=$tUpperLimit "
        }
        close $cshFID
        exec sddsprocess $plotCommandListFile -pipe=out -nowarnings \
          "-edit=column,sddsplotOptions2,sddsplotOptions,%/-end/$limitArgs -end/100%/TimeOfDay/$timeVariable/" \
          | sdds2stream -pipe=in -col=sddsplotOptions2 -noquotes | tr "\n" " " >> $cshFile
        exec echo " " >> $cshFile
        if {$deleteDataFile && [FileIsOnTmpDisk $dataFile]} {
            exec echo "rm -f $dataFile" >> $cshFile
        }
    }
    SetMainStatus "Plotting..."
    set cshFID [open $cshFile r]
    set data [read $cshFID]
    close $cshFID

    set i [string first \"-ylabel $data]
    while {$i != -1} {
	set data [string replace $data $i $i ']
	set i [string first \" $data $i]
	set data [string replace $data $i $i ']
	set i [string first \"-ylabel $data]
    }
    set cshFID [open $cshFile w]
    puts $cshFID $data
    close $cshFID
    exec csh -f $cshFile &
    file delete $plotCommandListFile $readbackListFile
}

proc MakeReviewFrame {widget args} {
    global reviewFile  timeLowerLimit timeUpperLimit confirmPlotPVs
    global printMode printerName sparsingInterval orderMode graphicType RFCompareChoice
    global yLimitMin yLimitMax autoGapping
    global dayOfInterest yearOfInterest monthOfInterest

    set parent ""
    set entryWidth 60
    APSParseArguments {parent entryWidth}
    set w $parent$widget
    frame $w -bd 4 -relief raised
    pack $w -side top -fill x
    MakeTitleLabel .title -parent $w -title "RF System Data Review"

    APSFrame .filesel -parent $w -label " " -packOption "-side top" -relief flat
    APSButton .select -parent $w.filesel.frame  -text "SELECT..." \
      -command SelectReviewFile -packOption "-side left" \
      -contextHelp "Brings up a file selection dialog box, with the selected file going into the File: entry." 
    APSButton .clear -parent $w.filesel.frame  -text "CLEAR FILE" \
      -command ClearReviewFile -packOption "-side left" \
      -contextHelp "Clears the review file name (use if you want to select data by date)."
    APSDateEntry .date -parent $w.filesel.frame -dayVariable dayOfInterest \
      -yearVariable yearOfInterest -monthVariable monthOfInterest \
      -packOption "-side left" 
    APSDateBreakDown -dayVariable dayOfInterest -yearVariable yearOfInterest \
      -monthVariable monthOfInterest -twoDigitYear 0 -leadingZeros 0 
    APSFrame .filesel2 -parent $w -label " " -packOption "-side top" -relief flat
    APSLabeledEntry .file -parent $w.filesel2.frame -label "File: " -textVariable reviewFile \
      -width $entryWidth -packOption "-side bottom" \
      -contextHelp "Enter a filename from which to extract data for review." 

    APSFrame .plotprint -parent $w
    APSButton .plot  -parent $w.plotprint.frame -text PLOT -command {PlotReviewFile -printPlots 0} \
      -contextHelp "Launches a subprocess to plot the selected data from the selected file.  Select the data you want to see using the labeled checkbuttons above."
    APSButton .print -parent $w.plotprint.frame -text PRINT -command {PlotReviewFile -printPlots 1 } \
      -contextHelp "Launches a subprocess to print plots for the selected data from the selected file.  Select the data you want to see using the labeled checkbuttons .  Specify the printer and mode prior to pressing, if desired."
    APSLabeledEntry .printer -parent $w.plotprint.frame -label "Printer: " \
      -textVariable printerName -width 10 -packOption "-side left" \
      -contextHelp "Entry the name of the printer to use for Postscript plotting."
    APSRadioButtonFrame .mode -parent $w.plotprint.frame -label "Print mode: " \
      -orientation horizontal \
      -buttonList {B&W color} -valueList {B&W color} \
      -variable printMode -packOption "-side left" \
      -contextHelp "Choose color or black-and-white Postscript plotting for plot printouts."

    frame $w.options 
    pack $w.options -side top 
    APSRadioButtonFrame .layout -parent $w.options \
        -buttonList "default 1x2 2x2 3x3 4x4" \
        -valueList "default 1,2 2,2 3,3 4,4" \
        -variable layoutChoice -label "Layout" -packOption "-side left" \
        -contextHelp "Select the type of layout, which determines the number and arrangement of plots on a page.  For example, 3x3 is an array of 3 plots horizontally by 3 plots vertically."

    APSRadioButtonFrame .compare -parent $w.options -buttonList "voltage fwd-power beam-current none" \
      -valueList {CompareVoltage CompareFwdPower CompareBeamCurrent CompareNone} \
      -variable RFCompareChoice -label "Compare with" -packOption "-side left" \
      -contextHelp "Select a set of quantities to plot together with other data for comparison."

    APSRadioButtonFrame .order -parent $w.options -label "Order by: " \
      -buttonList {sector quantity} -valueList {bySector byQuantity} \
      -variable orderMode -packOption "-side left" \
      -contextHelp "Choose to order data on successive panels by sector or by quantity.  The latter choice brings together similar data from different sectors."
    APSRadioButtonFrame .graphic -parent $w.options -label "Graphic type: " \
      -buttonList {dot line symbol} -valueList {dot,vary line,vary symbol,vary=subtype} \
      -variable graphicType  -packOption "-side left" \
      -contextHelp "Choose the type of plotting for data, either points or lines."

    APSCheckButtonFrame .miscgraph -parent $w.options -label "Miscellaneous: " \
      -buttonList {"Auto gapping" "Confirm plots"} -variableList {autoGapping confirmPlotPVs} \
      -orientation vertical -packOption "-side left"  \
      -contextHelp "Set miscellaneous settings for plotting control.  Auto-gapping refers to a feature that automatically breaks a line in a graph when a gap is seen in the time values of the data; it may malfunction for small numbers of points."

    frame $w.filter
    pack $w.filter -fill x -side top
    APSLabeledEntry .sparse -parent $w.filter -label "Sparsing interval: " \
      -textVariable sparsingInterval -width 4 -contextHelp "An integer value causing plotting of every Nth point rather than every point."  \
      -packOption "-side left"
    APSLabeledEntryFrame .timelimit -parent $w.filter -label "Time limits (start, end): " \
      -packOption "-side left" \
      -variableList {timeLowerLimit timeUpperLimit} \
      -orientation horizontal -width 10  \
      -contextHelp "Enter lower and upper time limits for data to be plotted.  The entries should use 24-hour time.  For example for 2:30pm, use 14:30 or 14.5 ."

    APSLabeledEntryFrame .ylimit -parent $w.filter    -label "y axis limits: " \
      -packOption "-side left" \
      -variableList {yLimitMin yLimitMax} \
      -orientation horizontal -width 10  \
      -contextHelp "Enter lower and upper limits for vertical axes, which override the default limits. This probably won't work the way you want unless all the data you've chosen to plot is similar (e.g., all temperatures or all vacuum)."

}

proc MakeMonitorWindow {widget} {
    if ![winfo exists $widget] {
        APSWindow $widget -name "RF Data Logging Setup"
        MakeMonitorFrame .monitor -parent $widget.userFrame -entryWidth 75
    } else {
        raise $widget
    }
}


APSStatusLine .status -parent .userFrame -variable mainStatus -width 80
APSFrame .other -parent .userFrame -packOption "-side top -fill x"
APSButton .monitor -parent .userFrame.other.frame -text "Monitor..." \
        -command {MakeMonitorWindow .monitorApp} \
        -contextHelp "Brings up a window from which to start a monitoring subprocess to collect data." 
        
MakeChoicesFrame .choices -parent .userFrame
MakeReviewFrame .review -parent .userFrame -entryWidth 75
