#!/bin/sh  
# \
exec oagwish "$0" "$@"

# $Log: not supported by cvs2svn $
# Revision 1.22  2004/11/18 21:24:51  soliday
# Added the ability to export interpolated data.
#
# Revision 1.21  2004/08/23 15:15:45  soliday
# Updated to work properly when the hour fields are in HH:MM:SS format.
#
# Revision 1.20  2002/06/17 22:37:09  borland
# Added radiation monitors.
#
# Revision 1.19  2002/05/29 20:37:59  soliday
# Fixed a problem with launching sddsplot.
#
# Revision 1.18  2002/05/28 14:15:13  soliday
# Added linacDiag
#
# Revision 1.17  2000/06/02 21:52:55  emery
# Added context help to filter entry.
#
# Revision 1.16  2000/04/27 21:04:32  soliday
# Added fixForName option to sddsplot commands.
#
# Revision 1.15  2000/04/25 16:01:04  soliday
# Fixed a bug when saving custom plots.
#
# Revision 1.14  2000/03/31 23:03:40  soliday
# Added the ability to append to custom plot files.
#
# Revision 1.13  2000/03/17 19:54:43  soliday
# Fixed label
#
# Revision 1.12  2000/03/15 22:05:34  soliday
# Now has more options to design custom plots.
#
# Revision 1.11  2000/03/02 16:36:22  soliday
# Added preset and custom plots.
#
# Revision 1.10  1999/11/04 01:05:29  emery
# Replaced the general <Key> binding to the column filter entry
# by a carriage return (<Return>) binding, making the selection
# process much faster.
#
# Revision 1.9  1999/11/03 22:37:57  borland
# Removed bindings that resulted in erasing the users choices when the
# date/time entries are changed.
#
# Revision 1.8  1999/07/15 17:24:53  borland
# Removed & from sddsplot command in APSExecLog.  If this isn't done, one
# has to hit return to get the plots to come up.
#
# Revision 1.7  1999/07/06 16:29:29  soliday
# It now can plot multiple columns from the same group when Time is not used
# for the X axis.
#
# Revision 1.6  1999/03/03 16:20:24  soliday
# The time filters now get passed to quickSDDSplot and the hours filter works now.
#
# Revision 1.5  1999/03/01 18:42:50  soliday
# Changed column search to glob from regexp
#
# Revision 1.4  1999/03/01 17:58:06  soliday
# Alted column search feature so that you can search of a sub string anywhere
# in the column name.
#

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)]


#
# This allows the user to set date boundaries.
#
proc MakeDateTimeFrame {widget args} {
    set parent .
    APSStrictParseArguments {parent}
    set label "Date/Time Range of Interest"
    APSFrame $widget -parent $parent -label $label -packOption "-side bottom"
    set w $parent$widget.frame

    APSDateTimeAdjEntry .startDate -parent $w \
      -yearVariable StartYear \
      -monthVariable StartMonth \
      -dayVariable StartDay \
      -hourVariable StartHour \
      -label "Starting date/time (year, month, day, hour): " -defaultHour 0
    APSDateTimeAdjEntry .endDate -parent $w \
      -yearVariable EndYear \
      -monthVariable EndMonth \
      -dayVariable EndDay \
      -hourVariable EndHour \
      -label "Ending date/time (year, month, day, hour):   " -defaultHour 24
    #bindtags $w.startDate.entries.frame.entry4 "Entry . all $w.startDate.entries.frame.entry4"
    #bindtags $w.endDate.entries.frame.entry4 "Entry . all $w.endDate.entries.frame.entry4"
    #bind $w.startDate.entries.frame.entry4 <Key> "ProcessData;CheckColumns"
    #bind $w.endDate.entries.frame.entry4 <Key> "ProcessData;CheckColumns"

    SetDateTimeToToday -rootname Start -hour 0
    SetDateTimeToToday -rootname End  -hour 24
}

#
# This initializes the date boundary to today.
#
proc SetDateTimeToToday {args} {
    set rootname ""
    set hour 0
    APSStrictParseArguments {rootname hour}

    global ${rootname}Month ${rootname}Year ${rootname}Day ${rootname}Hour
    
    APSDateBreakDown -dayVariable ${rootname}Day -yearVariable ${rootname}Year \
      -monthVariable ${rootname}Month -twoDigitYear 0 -leadingZeros 0
    set ${rootname}Hour $hour
}

#
# This procedure executes when the user double clicks on a column name.
# It then searches through the logColumns file to get information about that
# column.
#
proc NewColumn {column} {
    APSSetVarAndUpdate status "Searching for available groups"
    global selectedColumn ColumnData
    set selectedColumn $column
    .userFrame.f1.lb2 delete 0 end
    update

    set groups [lsort -dictionary [LocatePV -pv $column]]
    if {[string length $groups] > 0} {
        foreach groupItem $groups {
            .userFrame.f1.lb2 insert end $groupItem        
        }
        .userFrame.f1.lb2 selection set 0
    }
    set ColumnData $groups
    APSSetVarAndUpdate status "Ready"
}



#
# This procedure adds the selected column and group to the selected
# list under the X or Y axis depending on which button was pressed.
# It also ensures that a column/group pair is only chosen once.
#
proc AddXY {axis} {
    global selectedColumn BOXES ColumnData AllColumnData
    if {![llength $selectedColumn]} {return}
    if {[.userFrame.f1.lb2 curselection] == ""} {return}
    if {$axis == "X"} {
        set index 0
        foreach axisItem [.userFrame.f4.lb1 get 0 end] {
            if {$axisItem == "X"} {
                foreach lb $BOXES {$lb delete $index}
                set AllColumnData [lreplace $AllColumnData $index $index]
                break
            }
            incr index
        }
    }
    set index 0
    foreach columnItem [.userFrame.f4.lb2 get 0 end] groupItem [.userFrame.f4.lb3 get 0 end] {
        if {($columnItem == $selectedColumn) && ($groupItem == [.userFrame.f1.lb2 get [.userFrame.f1.lb2 curselection]])} {
            foreach lb $BOXES {$lb delete $index}
            set AllColumnData [lreplace $AllColumnData $index $index]
            break
        }
        incr index                
    }
    .userFrame.f4.lb1 insert end $axis
    .userFrame.f4.lb2 insert end $selectedColumn
    .userFrame.f4.lb3 insert end [.userFrame.f1.lb2 get [.userFrame.f1.lb2 curselection]]
    lappend AllColumnData $ColumnData
    APSSetVarAndUpdate status "Added column to $axis axis"
}

#
# This procedure is used for the 3 listboxes that make up the selected 
# axis/column/group pairs.
#
proc LBset {args} {
    global BOXES
    foreach lb $BOXES {eval $lb $args}
}

#
# This procedure is used for the 3 listboxes that make up the selected 
# axis/column/group pairs.
#
proc LBscroll {args} {
    eval .userFrame.f4.scroll1 set $args
    LBset yview moveto [lindex $args 0]
}

#
# When a selected item is right clicked on a remove message pops up.
#
proc deleteItem {x y index} {
    destroy .deleteWin
    global apsMenuBackground
    menu .deleteWin -tearoff 0
    .deleteWin add command -label "Remove" -command "removeItem $index"
    tk_popup .deleteWin $x $y 
    if {![llength [.userFrame.f4.lb1 get 0 end]]} {
        .deleteWin entryconfigure 0 -state disabled
    }
}

#
# This procedure removes a selected column/group pair.
#
proc removeItem {index} {
    global BOXES AllColumnData
    foreach lb $BOXES {
        $lb delete $index
    }
    set AllColumnData [lreplace $AllColumnData $index $index]
    APSSetVarAndUpdate status "Removed column"
}

set xlabel ""
set ylabel ""
set title ""
set topline ""
set includeS35DCCT 0
#
# This procedure is used to plot the data by sending all the needed
# information to quickSDDSplots.
#
proc PlotData {args} {
    set quickSDDSplot 1
    set export 0
    set exportFileName ""
    APSStrictParseArguments {quickSDDSplot export exportFileName}
    global sparsingInterval plotDevice sameScaleY optionOverride yOffsetMode
    global layoutChoice printerName labelSizeOption
    global repeatPlotMode designUserOptions env includeS35DCCT
    global xlabel ylabel title topline

    if {![info exists designUserOptions]} {
        set designUserOptions ""
    }
    if {![info exists sparsingInterval]} {
	set sparsingInterval 1
	set plotDevice motif
	set repeatPlotMode 0
	set sameScaleY 0
	set yOffsetMode 0
	set optionOverride 0
	set layoutChoice -layout=1,1
	set labelSizeOption -labelsize=0.03
	set designUserOptions ""
	if [info exists env(PRINTER)] {
	    set printerName $env(PRINTER)
	} else {
	    set printerName mcr1
	}
    }
    global RootDir DataList StartYear StartMonth StartDay StartHour EndYear EndMonth EndDay EndHour timeOnXAxis
    set w .userFrame.f4
    if [catch {APSConvertTimeToHours $StartHour} starthour] {
        APSSetVarAndUpdate status "Invalid starting hour: $StartHour"
        return
    }
    if [catch {APSConvertTimeToHours $EndHour} endhour] {
        APSSetVarAndUpdate status "Invalid starting hour: $EndHour"
        return
    }

    if {[catch {exec timeconvert \
		    -breakDown=year=$StartYear,month=$StartMonth,day=$StartDay,hour=$starthour} \
	     time0] || \
	    [catch {exec timeconvert \
			-breakDown=year=$EndYear,month=$EndMonth,day=$EndDay,hour=$endhour} \
		 time1]} {
	APSSetVarAndUpdate status "Error in time syntax for time filter"
	return
    }

    set StartTime [clock format [clock scan "$StartMonth/$StartDay/$StartYear"] -format "%Y %j %m %d"]              
    set EndTime [clock format [clock scan "$EndMonth/$EndDay/$EndYear"] -format "%Y %j %m %d"]              
    if {([llength [$w.lb1 get 0 end]] < 2) && (!$timeOnXAxis)} {
        APSSetVarAndUpdate status "You must select at least two columns"
        return
    }
    if {([llength [$w.lb1 get 0 end]] < 1) && ($timeOnXAxis)} {
        APSSetVarAndUpdate status "You must select at least one column"
        return
    }
    set dataFileList ""
    set groupList ""
    foreach axis [$w.lb1 get 0 end] column [$w.lb2 get 0 end] group [$w.lb3 get 0 end] {
        if {$axis == "X"} {
            set xChoice $column
        } else {
            lappend yChoice $column
	    lappend yGroup $group
        }
        set match 0
        foreach {groupName PartialDir Rootname} $DataList {
            if {$groupName == $group} {
                set match 1
                set match2 0
                foreach item $groupList {
                    if {$item == $group} {
                        set match2 1
                        break
                    }
                }
                if {!$match2} {
                    lappend groupList $group
                    set FileList  \
                      [APSFindFilesBetweenDates \
                         -rootname ${Rootname}- \
                         -directory $RootDir$PartialDir \
                         -startDateList $StartTime \
                         -endDateList $EndTime]
                    if {[llength $FileList]} {
                        append dataFileList "$FileList "
                        if {$axis == "X"} {
                            set XdataFileList $FileList
                            set XRootname ${Rootname}-
                        } else {
                            set YdataFileList $FileList
                            set YRootname ${Rootname}-
                        }
                    } else {
                        APSSetVarAndUpdate status "No files found for $group in the current Date/Time range"
                        return
                    }
                } else {
                    set FileList  \
                      [APSFindFilesBetweenDates \
                         -rootname ${Rootname}- \
                         -directory $RootDir$PartialDir \
                         -startDateList $StartTime \
                         -endDateList $EndTime]
                    if {[llength $FileList]} {
                        if {$axis == "X"} {
                            set XdataFileList $FileList
                            set XRootname ${Rootname}-
                        } else {
                            set YdataFileList $FileList
                            set YRootname ${Rootname}-
                        }
                    }                  
                }
                break
            }
        }
        if {!$match} {
            APSSetVarAndUpdate status "PlotData: invalid group"
            return
        }  
      
    }
    if {$timeOnXAxis} {set xChoice "Time"}
    if {(![info exists xChoice]) || (![info exists yChoice])} {
        APSSetVarAndUpdate status "Select at least one column for both X and Y axes"
        return
    }
    if $repeatPlotMode {
        set time1 1e300
    }
    set extraOptions ""
    if  $repeatPlotMode {
        append extraOptions " -repeat"
    }
    append extraOptions " -title= $layoutChoice -presparse=$sparsingInterval"
    if {$repeatPlotMode && [string compare $plotDevice motif]==0} {
        append extraOptions " \"-device=$plotDevice,-movie true -keep 1\""
    } else {
        append extraOptions " -device=$plotDevice"
    }
    append extraOptions " $labelSizeOption"
    if $sameScaleY {
        append extraOptions " -same=x,y,global"
    } else {
        append extraOptions " -same=x,global"
    }
    if $yOffsetMode {
        append extraOptions " -mode=y=offset"
    }
    append extraOptions " $designUserOptions"

    set appendOptions ""
    if {$optionOverride} {
	append appendOptions $extraOptions
	set extraOptions ""
    }
    if [string compare $plotDevice motif] {
        append appendOptions " -end | lpr -P$printerName"
    } else {
	append appendOptions " -end"
    }
    set userLabels ""
    if {[llength $xlabel]} { append userLabels " -xlabel=$xlabel" }
    if {[llength $ylabel]} { append userLabels " -ylabel=$ylabel" }
    if {[llength $title]} { append userLabels " -title=$title" }
    if {[llength $topline]} { append userLabels " -topline=$topline" }
    if {$includeS35DCCT} {
	set dcct "-column=Time,S35DCCT -yscale=id=dcct -graph=line,type=0,fixForName -legend"
    } else {
	set dcct ""
    }

    if {$xChoice == "Time"} {
        if {$quickSDDSplot} {
            exec quickSDDSplot \
		-dataFileList $dataFileList \
		-useGraphicTypeModifier 0 -plotNow 1 -horizontalMode "time" \
		-xChoice $xChoice -yChoice $yChoice \
		-timeFilterStart "$StartYear $StartMonth $StartDay $StartHour" \
		-timeFilterEnd "$EndYear $EndMonth $EndDay $EndHour" &
        } elseif {$export} {
            #for each file strip all data but the data we need
            set days ""
            set modDataFileList ""
            foreach f $dataFileList {
                set fileName /tmp/[APSTmpString]
                APSAddToTempFileList $fileName ${fileName}.0
                lappend modDataFileList $fileName
                if {[catch {exec sddsconvert $f $fileName -delete=parameters,* -retain=columns,Time,$xChoice,[join $yChoice ,]} result]} {
                    APSSetVarAndUpdate status $result
                    return
                }
                set d [file tail [file rootname $f]]
                set d [string range $d [expr {1 + [string first - $d]}] end]
                lappend days $d
                lappend day($d) $fileName
            }
            set uniqueDays [lsort -unique $days ]

            set fdays ""
            foreach d $uniqueDays {
                if {[llength $day($d)] == 1} {
                    lappend fdays $day($d)
                } else {
                    #Create file for each day that only has the Time column and include all Time values
                    set fileName0 /tmp/[APSTmpString]
                    APSAddToTempFileList $fileName0
                    if {[catch {eval exec sddscombine $day($d) \
                                  -pipe=out -merge -retain=columns,Time | \
                                  sddssort -pipe=in $fileName0 \
                                  -col=Time -unique -nowarnings} result]} {
                        APSSetVarAndUpdate status $result
                        return
                    }
                    #Interp values for each file against master Time file
                    foreach f $day($d) {
                        if {[catch {exec sddsinterp $f ${f}.0 -columns=Time,[join $yChoice ,]\
                                      -fileValues=$fileName0,column=Time} result]} {
                            APSSetVarAndUpdate status $result
                            return
                        }
                    }
                    set f0 [lindex $day($d) 0].0
                    set f1 $f0
                    set i 0
                    #Xref files for each day together
                    foreach f [lrange $day($d) 1 end] {
                        set f2 ${f0}.$i
                        APSAddToTempFileList $f2
                        if {[catch {exec sddsxref $f1 ${f}.0 $f2 -take=* -equate=Time} result]} {
                            APSSetVarAndUpdate status "$result"
                            return
                        }
                        incr i
                        set f1 ${f2}
                    }
                    lappend fdays $f2
                }
            }
            #Combine all days into one file
            if {[catch {eval exec sddscombine $fdays -pipe=out -merge -delete=parameter,* | \
                          sddssort -pipe=in $exportFileName -col=Time -unique -nowarnings} result]} {
                APSSetVarAndUpdate status $result
                return
            }
            APSSetVarAndUpdate status "Data exported to $exportFileName"
        } else {
            destroy .execLog
            APSExecLog .execLog -name "Plot" -unixCommand "sddsplot $extraOptions $dataFileList -column=Time,([join $yChoice ,]) -legend -graphic=line,vary,type=1,fixForName -ticks=xtime $userLabels $dcct -filter=column,Time,$time0,$time1 $appendOptions"
            wm withdraw .execLog
        }
    } else {
        if {[llength $yChoice] != 1} {
	    foreach YGroupName $yGroup {
		if {$YGroupName != [lindex $yGroup 0]} {
		    APSSetVarAndUpdate status "Currently only one group can be ploted on the Y axis when Time is not used"
		    return
		    
		}
	    }
        }
        set interpFileList ""
        foreach XFile $XdataFileList {
            set XDay [string range [file tail [file rootname $XFile]] [string length $XRootname] end]
            foreach YFile $YdataFileList {
                set YDay [string range [file tail [file rootname $YFile]] [string length $YRootname] end]
                if {$XDay == $YDay} {
                    append interpFileList "$XFile $YFile "
                    break
                }
            }
        }
        if {![llength $interpFileList]} {
            APSSetVarAndUpdate status "No matching files found"
            return
        }
        set modifiedDataFileList ""
        foreach {XFile YFile} $interpFileList {
            set fileName /tmp/[APSTmpString]
            APSAddToTempFileList $fileName $fileName.0 $fileName.1
            append modifiedDataFileList "$fileName.1 "
            exec sddsconvert $XFile $fileName.0 -retain=columns,Time,$xChoice
            exec sddsinterp $YFile $fileName -columns=Time,[join $yChoice ,]\
              -fileValues=$fileName.0,column=Time
            exec sddsxref $fileName.0 $fileName $fileName.1 -take=[join $yChoice ,] -equate=Time 
        }
        if {$quickSDDSplot} {
            exec quickSDDSplot \
		-dataFileList $modifiedDataFileList \
		-useGraphicTypeModifier 0 -plotNow 1 \
		-xChoice $xChoice -yChoice $yChoice \
		-timeFilterStart "$StartYear $StartMonth $StartDay $StartHour" \
		-timeFilterEnd "$EndYear $EndMonth $EndDay $EndHour" &
        } elseif {$export} {
            #Combine all days into one file
            if {[catch {eval exec sddscombine $modifiedDataFileList -pipe=out -merge -delete=parameter,* | \
                          sddssort -pipe=in $exportFileName -col=Time -unique -nowarnings} result]} {
                APSSetVarAndUpdate status $result
                return
            }
            APSSetVarAndUpdate status "Data exported to $exportFileName"

        } else {
            destroy .execLog
            APSExecLog .execLog -name "Plot" -unixCommand "sddsplot $extraOptions $modifiedDataFileList \"-column=$xChoice,([join $yChoice ,])\" -legend -graphic=line,vary,type=1,fixForName $userLabels -filter=column,Time,$time0,$time1 $appendOptions"
            wm withdraw .execLog
        }
    }
}


proc SelectPresetPlots {args} {
    set preset 1
    APSStrictParseArguments {preset}
    global sparsingInterval plotDevice sameScaleY optionOverride
    global layoutChoice printerName labelSizeOption
    global env customPlotsDir yOffsetMode presetLabel
    global MonDataGroupIndex presetUserOptions glitchDataFile
    global triggerSourceList group MonDataPresetPlotDir IsTimePlot FixedTimeScale
    global repeatPlotMode DataList customGroupNames

    set customGroupNames ""

    set sparsingInterval 1
    set plotDevice motif
    set repeatPlotMode 0
    set sameScaleY 0
    set yOffsetMode 0
    set optionOverride 0
    set layoutChoice -layout=1,1
    set labelSizeOption -labelsize=0.03
    set presetUserOptions ""
    if [info exists env(PRINTER)] {
        set printerName $env(PRINTER)
    } else {
        set printerName mcr1
    }
    
    global PresetPlotCommandList PresetPlotDescripList presetUserFilters scrollHeight
    if {$preset} {
	if ![UpdateMonDataFileList] {
	    APSSetVarAndUpdate status "No data selected or found."
	    return
	}
    }

    if {$preset} {
	set presetPlotsFile $MonDataPresetPlotDir/[lindex $DataList [expr [.userFrame.f6.f1.cb1 current] * 3 + 2]].sdds
	if ![file exists $presetPlotsFile] {
	    APSSetVarAndUpdate status "No preset plots available for [.userFrame.f6.f1.cb1 get]"
	    return
	}
	set presetLabel Preset
    } else {
        set customPlotsFile [APSFileSelectDialog .[APSTmpString] -listDir $customPlotsDir \
                               -contextHelp "File selection box for MonitorDataReview custom plots."]
        if {[llength $customPlotsFile]==0} {
            return
        }
        if {![file exists $customPlotsFile] || ![APSCheckSDDSFile -fileName $customPlotsFile]} {
            APSSetVarAndUpdate status "$customPlotsFile does not exist or is not an SDDS file."
            return
        }
 	if [catch {exec sdds2stream -parameters=PresetPlotFile $customPlotsFile} dummyVar] {
 	    set presetPlotsFile /tmp/[APSTmpString]
 	    exec sddscollapse $customPlotsFile $presetPlotsFile 
 	    set columns [APSGetSDDSNames -fileName $presetPlotsFile -class column]
 	    foreach elem {PlotDescription sddsplotOptions} {
 		if [lsearch -exact $columns $elem]==-1 {
 		    APSSetVarAndUpdate status "$customPlotsFile is not a valid file: missing $elem."
 		    return
 		}
 	    }
 	} else {
 	    set presetPlotsFile $customPlotsFile
 	}
        set customPlotDir [file dirname $customPlotsFile]
        set presetLabel Custom
	if [catch {sdds load $presetPlotsFile plotData} results] {
	    APSSetVarAndUpdate status "Problem reading $customPlotsFile : $results"
	    bell
	    return	    
	}
	if {[lsearch -exact $plotData(ColumnNames) PlotDataGroups] != -1} {
	    set customGroupNames [join $plotData(Column.PlotDataGroups)]
	}
    }

    set PresetPlotDescripList \
      [APSGetSDDSColumn -page 0 -fileName $presetPlotsFile -column PlotDescription]
    set PresetPlotCommandList \
      [APSGetSDDSColumn -page 0 -fileName $presetPlotsFile -column sddsplotOptions]
    if [catch {APSGetSDDSColumn -page 0 -fileName $presetPlotsFile -column \
                 IsTimePlot} IsTimePlot] {
        set IsTimePlot ""
    }
    if [catch {APSGetSDDSColumn -page 0 -fileName $presetPlotsFile -column FixedTimeScale} FixedTimeScale] {
        set FixedTimeScale ""
    }

    if [winfo exists .presetPlots] { 
        destroy .presetPlots
    }

    set scrollHeight 20

    APSFrameGrid .presetPlots -xList {one}


    APSFrameGrid .options -parent .presetPlots.one \
      -yList {y1 y2} -width 10 \
      -xList {x1 x2 x3 x4}
        
    APSRadioButtonFrame .layout -parent .presetPlots.one.options.x1.y1 \
      -label Layout -orientation vertical \
      -variable layoutChoice \
      -buttonList {1x1 1x2 2x1 2x2 3x3 4x4 5x5} \
      -valueList {-layout=1,1 -layout=1,2 -layout=2,1 -layout=2,2 -layout=3,3 -layout=4,4 -layout=5,5} \
      -contextHelp {Choose the number of plot panels horizontally and vertical on each page.}
    APSCheckButtonFrame .misc  -parent .presetPlots.one.options.x2.y1 \
      -label Misc. -orientation vertical \
      -variableList {sameScaleY yOffsetMode optionOverride} \
      -buttonList {"Same y scales." "y offset mode" "Option override."}  \
      -contextHelp "Miscellaneous options and controls.  Option override forces the options you choose here to override those in the original plot command.  If you select an option here and it doesn't affect the plot, you need to invoke the override."

    APSRadioButtonFrame .sparse  -parent .presetPlots.one.options.x3.y1 \
      -label Sparsing -orientation vertical \
      -variable sparsingInterval \
      -buttonList {None 2 4 8 16 32 64 128} \
      -valueList {1 2 4 8 16 32 64 128} \
      -contextHelp "For large amounts of data, a larger sparsing interval will result in\
faster display, but at the expense of only seeing a sample of the points."
    APSRadioButtonFrame .device  -parent .presetPlots.one.options.x4.y1 \
      -label Device -orientation vertical \
      -variable plotDevice \
      -buttonList {X-windows "B&W Postscript" "Color Postscript"} \
      -valueList {motif postscript cpostscript} \
      -contextHelp "Choose the plotting device.  Postscript is for delivery to a printer only."
    APSLabeledEntry .printer -parent .presetPlots.one.options.x4.y2 \
        -label "Printer: " -textVariable printerName -width 10 \
        -contextHelp "Enter the name of the printer for postscript output."
    APSRadioButtonFrame .repeat -parent .presetPlots.one.options.x4.y2 \
      -variable repeatPlotMode -label "Repeat: " -buttonList {Yes No} -valueList {1 0} \
      -contextHelp "Enable and disable repeat plotting mode.  If enabled, the data is replotted every time the data files update.  Not suitable for multipage plotting."

    APSRadioButtonFrame .labelsize -parent .presetPlots.one.options.x2.y2 \
        -label "Label size" -orientation vertical -variable labelSizeOption \
        -buttonList {normal +15% +30% +45% +60%} \
        -valueList {-labelsize=0.03 -labelsize=0.0345 -labelsize=0.039 -labelsize=0.0435 -labelsize=0.048} \
        -contextHelp "For layouts with many panels, the labels may be hard to read.  You can increase the size of the labels using these options."

    APSLabeledEntry .extra -parent .presetPlots.one \
      -label "Extra options: " -textVariable presetUserOptions \
      -width 40 -contextHelp "Enter extra sddsplot options to be included in each plot request."

    APSScrolledListWindow .plotlist -parent .presetPlots.one  -height $scrollHeight \
      -name  "MonitorDataReview plots" \
      -label "$presetLabel plots for [.userFrame.f6.f1.cb1 get]" \
      -itemList $PresetPlotDescripList \
      -callback MakePresetPlot \
      -contextHelp "List of preset or custom plots.  Note that for custom plots, some of the selections may not work because they are overridden by elements of the custom command. You can select single or multiple entry and deselect a single position in the list by clicking second mouse button over that position."
     bind .presetPlots.one.plotlist.userFrame.sl.listbox <Button-2> {
          .presetPlots.one.plotlist.userFrame.sl.listbox selection clear [.presetPlots.one.plotlist.userFrame.sl.listbox nearest %y]}

    pack forget .presetPlots.one.plotlist.buttonRow.close.button

    set oldAcceptCommand [.presetPlots.one.plotlist.buttonRow.accept.button cget -command]
    global newAcceptCommand 
    set newAcceptCommand "$oldAcceptCommand; Confirmation"
    pack forget .presetPlots.one.plotlist.buttonRow.accept.button

    APSFrameGrid .buttons -parent .presetPlots.one.plotlist.buttonRow \
      -yList {y1 y2 y3} -width 40m \
      -xList {x1 x2 x3}
    set g .presetPlots.one.plotlist.buttonRow.buttons
    APSButton .plot -parent $g.x1.y3 -text "Plot Choice" -command $newAcceptCommand \
       -packOption "-padx 1 -pady 1 -fill x"

    APSButton .filterBut -parent $g.x1.y1 -text "Apply Filter" \
       -packOption "-padx 1 -pady 1 -fill x" \
       -command setPresetPlotDescrFilter -contextHelp "Setting a filter patern(s) for preset plots. You can deselect
        a single position in the list by clicking second mouse button over that position."  
    APSButton .all -parent $g.x1.y2 -text "Accept All" \
       -packOption "-padx 1 -pady 1 -fill x" \
       -command selectAllEntriesInDescrList -contextHelp "Selecting whole list of preset plots for plotting. \
        You have to proceed with \"Plot choice\" button to invoke the plotting." 

    set doneCommand "set presetUserFilters {}; set presetFilterList {}; destroy .presetPlots"
    APSButton .done -parent $g.x3.y3 -text "Done" -command $doneCommand \
       -packOption "-padx 1 -pady 1 -fill x"
    APSButton .showComm -parent $g.x2.y3 -text "Show command" \
       -packOption "-padx 1 -pady 1 -fill x" \
       -command "wm deiconify .execLog; setActionButtons 0"
    setActionButtons 0 

    APSButton .remFilter -parent $g.x2.y1 -text "Remove Filter" -command RemoveFilter \
       -packOption "-padx 1 -pady 1 -fill x" -contextHelp \
       "Removing a filter patern(s) for preset plots and bringing initial description list back."
    setActionButtons_1 0

    APSButton .desAll -parent $g.x2.y2 -text "Deselect All" -command DeselectAll \
       -packOption "-padx 1 -pady 1 -fill x" -contextHelp \
       "Clears any selection of preset plots for plotting."
    setActionButtons_2 0
  
    set p .presetPlots.one.plotlist.userFrame
    APSFrame .filFrame -parent $p
    APSSetVarAndUpdate status "Choose plots from the list shown."
    APSLabeledEntry .filter -parent $p.filFrame.frame -label "Filter option: " \
      -textVariable presetUserFilters -width 40 -contextHelp \
      "Enter a patern, or set of paterns separated by commas, to select preset plots for [.userFrame.f6.f1.cb1 get]"


}


proc setPresetPlotDescrFilter {} {
     global PresetPlotDescripList presetUserFilters presetFilterList
     set secPresetPlotDescripList ""
     set secpresetFilterList ""
     setActionButtons 0
     if [llength $presetFilterList] {
         foreach sec $presetFilterList {
            lappend secPresetPlotDescripList $sec
         }
     } else {
         foreach sec $PresetPlotDescripList {
            lappend secPresetPlotDescripList $sec
         }
     }

     set initpresetUserFilters $presetUserFilters
     set initpresetUserFilters [split $initpresetUserFilters ,]
     foreach elem $initpresetUserFilters {
       set index 0
       while {$index >= 0} {
        set index [lsearch -glob $secPresetPlotDescripList $elem]
        if {$index >= 0} {
	    set match [lindex $secPresetPlotDescripList $index]
            lappend secpresetFilterList $match
            set secPresetPlotDescripList [lreplace $secPresetPlotDescripList $index $index]
	}
       }
     }
     if [llength $secpresetFilterList] {
         set presetFilterList ""
         foreach item $secpresetFilterList {
            lappend presetFilterList $item
         }
	 updateScrolledList $presetFilterList 
         setActionButtons_1 1
         setActionButtons_2 0
     }
}

# This procedure helps to roll back whole setup of Preset Plots to the initial state with PresetPlotDescripList
proc RemoveFilter {} {
     global PresetPlotDescripList presetFilterList presetUserFilters
     set presetUserFilters ""
     updateScrolledList $PresetPlotDescripList
     setActionButtons_1 0
     setActionButtons_2 0
     set presetFilterList ""
     update
}

# This procedure conducts visual setup for all descriptions selection and restates command
# for "Plot Choice" button.
proc selectAllEntriesInDescrList {} {
     setActionButtons 0
     .presetPlots.one.plotlist.buttonRow.buttons.x1.y3.plot.button configure \
     -command "InvokeAcceptAllSelection; setActionButtons 1"
     APSSetVarAndUpdate status "All preset plots are selected for a plotting" 
     .presetPlots.one.plotlist.userFrame.sl.listbox selection set 0 end
     setActionButtons_2 1
}

# This procedure is called by "Plot Chioce" button when "Accept All" action was invoked in prior
proc InvokeAcceptAllSelection {} {
     global PresetPlotDescripList presetFilterList 
     set selectionList ""

     foreach item [.presetPlots.one.plotlist.userFrame.sl.listbox curselection] {
        if [llength $presetFilterList] {
            lappend selectionList [lindex $presetFilterList $item]
        } else {
            lappend selectionList [lindex $PresetPlotDescripList $item]
	}
     }
     MakePresetPlot $selectionList
}

# This procedure invokes de-selection of all descriptions in the description list only 
# if an acceptance of all of them was done previously. It also configures command for
# "Plot Choice" button to initial setup.
proc DeselectAll {} {
     global newAcceptCommand
     .presetPlots.one.plotlist.userFrame.sl.listbox selection clear 1 end
     .presetPlots.one.plotlist.buttonRow.buttons.x1.y3.plot.button configure -command $newAcceptCommand
     setActionButtons_2 0
     APSSetVarAndUpdate status "All preset plots are deselected for a plotting" 
}

# This procedure updates a description scrolled list after button "Apply Filter" or
# "Remove Filter" was set to action.
proc updateScrolledList {scrolledList} {
     global scrollHeight presetLabel presetUserFilters

     if [winfo exists .presetPlots.one.plotlist.userFrame.sl] {
         destroy .presetPlots.one.plotlist.userFrame.sl
         destroy .presetPlots.one.plotlist.userFrame.filFrame
     }
     APSScrolledList .sl -parent .presetPlots.one.plotlist.userFrame  -height $scrollHeight \
        -itemList $scrolledList \
        -contextHelp "List of preset or custom plots.  Note that for custom plots, some of the selections may not work because they are overridden by elements of the custom command. You can select single or multiple entry and deselect a single position in the list by clicking second mouse button over that position."
     APSFrame .filFrame -parent .presetPlots.one.plotlist.userFrame
     APSLabeledEntry .filter -parent .presetPlots.one.plotlist.userFrame.filFrame.frame \
     -label "Filter option: " -textVariable presetUserFilters -width 40 -contextHelp \
      "Enter a patern, or set of paterns separated by coma, to select preset plots for [.userFrame.f6.f1.cb1 get]"

     bind .presetPlots.one.plotlist.userFrame.sl.listbox <Button-2> {
          .presetPlots.one.plotlist.userFrame.sl.listbox selection clear [.presetPlots.one.plotlist.userFrame.sl.listbox nearest %y]}
}

# This procedure is making sure that "Show Command" button stays disable when "Plot Choice"
# was invoke without a previous description selection. 
proc Confirmation {} {
     global confFlag
     if $confFlag {
        setActionButtons 0
     } else {
        setActionButtons 1
     }
}

proc MakePresetPlot {descriptionList} {
    global sparsingInterval plotDevice sameScaleY optionOverride layoutChoice printerName
    global MonDataFileList DataDir labelSizeOption yOffsetMode presetUserOptions repeatPlotMode

    global PresetPlotCommandList PresetPlotDescripList IsTimePlot FixedTimeScale
    global StartMonth StartYear StartDay StartHour
    global EndMonth EndYear EndDay EndHour
    global presetLabel group
    global newAcceptCommand confFlag customGroupNames
    
    if [winfo exists .execLog] {
        destroy .execLog
    }
    setActionButtons 0
    set confFlag 0

    if {[llength $customGroupNames]} {
	set customFileList ""
	foreach description $descriptionList {
	    set index [lsearch $PresetPlotDescripList $description]
	    if $index==-1 {
		APSSetVarAndUpdate status "Error: no match for description $description!"
		return
	    }
	    foreach group [lindex $customGroupNames $index] {
		MonDataFindFiles -group $group
		append customFileList " $MonDataFileList"
	    }
	}
	set MonDataFileList $customFileList
    } else {
	if ![UpdateMonDataFileList] {
	    APSSetVarAndUpdate status "No data selected or found."
	    return
	}
    }
    if [catch {APSConvertTimeToHours $StartHour} hour] {
        APSSetVarAndUpdate status "Invalid starting hour: $StartHour"
        return
    }
    set StartTime \
      [exec timeconvert \
         -breakDown=year=$StartYear,day=$StartDay,month=$StartMonth,hour=$hour]
    if [catch {APSConvertTimeToHours $EndHour} hour] {
        APSSetVarAndUpdate status "Invalid ending hour: $EndHour"
        return
    }
    set EndTime \
      [exec timeconvert \
         -breakDown=year=$EndYear,day=$EndDay,month=$EndMonth,hour=$hour]

    set EndTime1 [exec timeconvert -now | token -last]
    if $EndTime<$EndTime1 {
        set EndTime1 $EndTime
    }
    set TimeRange [expr $EndTime1-$StartTime]
    set StartTimePlot [expr $StartTime-0.05*$TimeRange]
    set EndTimePlot   [expr $EndTime1+0.05*$TimeRange]
    if $repeatPlotMode {
        set EndTime 1e300
        set EndTimePlot 1e300
    }

#    set origDir [pwd]
#    cd $DataDir
    set cshFile /tmp/[APSTmpString]
    set cshFID [open $cshFile w]
    set timeFilterFlag 0
    if [catch {APSConvertTimeToHours $StartHour} starthour] {
        APSSetVarAndUpdate status "Invalid starting hour: $StartHour"
        return
    }
    if [catch {APSConvertTimeToHours $EndHour} endhour] {
        APSSetVarAndUpdate status "Invalid starting hour: $EndHour"
        return
    }
    if {$starthour!=0 || $endhour!=24} {
        set extraOptions -filter=column,Time,$StartTime,$EndTime
	set timeFilterFlag 1
    } else {
        set extraOptions ""
    }

    if [string compare $group "OPI"]==0 {
        set extraOptions "$extraOptions -topline=[.userFrame.f6.f1.cb1 get]"
    }

    set extraOptions "$extraOptions -title= $layoutChoice -presparse=$sparsingInterval"
    if {$repeatPlotMode && [string compare $plotDevice motif]==0} {
        append extraOptions " -device=$plotDevice,'-movie true -keep 1'"
    } else {
        append extraOptions " -device=$plotDevice"
    }
    append extraOptions " $labelSizeOption"
    if $sameScaleY {
        set extraOptions "$extraOptions -same=x,y,global"
    } else {
        set extraOptions "$extraOptions -same=x,global"
    }
    if $yOffsetMode {
        set extraOptions "$extraOptions -mode=y=offset"
    }
    set dataFile $MonDataFileList
    if $timeFilterFlag {
        puts $cshFID "sddsplot \\"
    } else {
        puts $cshFID "sddsplot -filter=column,Time,1,1e10 \\"
    }
    if $repeatPlotMode {
        puts $cshFID "-repeat \\"
    }
    if !$optionOverride {
        puts $cshFID " $extraOptions $presetUserOptions $dataFile \\"
    } else {
        puts $cshFID "$MonDataFileList $presetUserOptions \\"
    }
    set plotsFound 0

    if ![llength $descriptionList] {
        APSSetVarAndUpdate status "No plot selected."
	set confFlag 1
        return
    }

    foreach description $descriptionList {
        set index [lsearch $PresetPlotDescripList $description]
        if $index==-1 {
            APSSetVarAndUpdate status "Error: no match for description $description!"
        }
        APSSetVarAndUpdate status "Will plot $description"
        set plotsFound 1
        puts -nonewline $cshFID " [lindex $PresetPlotCommandList $index] "
        if {[llength $IsTimePlot] && [lindex $IsTimePlot $index]} {
            if {![llength $FixedTimeScale] || [lindex $FixedTimeScale $index]} {
                puts -nonewline $cshFID " -limit=xmin=$StartTimePlot,xmax=$EndTimePlot "
            }
        }
        if !$optionOverride {
            puts $cshFID " -end \\"
        } else {
            puts $cshFID " $extraOptions -end \\"
        }
    }
    if [string compare $plotDevice motif] {
        puts $cshFID " | lpr -P$printerName"
    } else {
        puts $cshFID ""
    }

    flush $cshFID
    close $cshFID
    if $plotsFound {
        global APSExecIDList
        exec chmod +x $cshFile
        set callback {APSSetVarAndUpdate status "Plotting is done."}
        lappend APSExecIDList [APSExecLog .execLog -name "Plot" -unixCommand "[list cat -u $cshFile]"]
        APSExecLog .execLog -name "Plot" -unixCommand "$cshFile" \
           -callback "$callback"
        wm withdraw .execLog
        APSSetVarAndUpdate status "Plotting..."
    }
    if [catch {LogMonitorDataReviewAction -action ${presetLabel}Plot} result] {
        APSSetVarAndUpdate status "$result"
    }
#    after 5000 "exec rm $cshFile"
     .presetPlots.one.plotlist.buttonRow.buttons.x1.y3.plot.button configure -command $newAcceptCommand
#    cd $origDir
}

proc LogMonitorDataReviewAction {args} {
    global DataList
    global StartMonth StartYear StartDay StartHour
    global EndMonth EndYear EndDay EndHour
    global apsScriptCommand apsScriptHost apsScriptUser
    set action ?
    APSStrictParseArguments {action}
    
    if [APSStrictParseArguments {action}]==-1 {
        return -code error "APSSCRLogAction: invalid arguments"
    }
    if [catch {exec whoami} user] {
        set user ?
    }
    if [catch {exec uname -snr} host] {
        set host ?
    }
    if [catch {APSConvertTimeToHours $StartHour} hour] {
        APSSetVarAndUpdate status "Invalid starting hour: $StartHour"
        return
    }
    if [catch {exec timeconvert -breakdown=year=$StartYear,day=$StartDay,month=$StartMonth,hour=$hour} \
          startTime] {
        APSSetVarAndUpdate status "$startTime"
        return
    }

    if [catch {APSConvertTimeToHours $EndHour} hour] {
        APSSetVarAndUpdate status "Invalid ending hour: $EndHour"
        return
    }
    if [catch {exec timeconvert -breakdown=year=$EndYear,day=$EndDay,month=$EndMonth,hour=$hour} \
          endTime] {
        APSSetVarAndUpdate status "$endTime"
        return
    }

    if [catch {exec logMessage -sourceId=MonitorDataReview \
                 -tag=User $apsScriptUser \
                 -tag=Host $apsScriptHost \
                 -tag=Action $action \
                 -tag=Group [lindex $DataList [expr [.userFrame.f6.f1.cb1 current] * 3 + 2]] \
                 -tag=dataStartTime $startTime \
                 -tag=dataEndTime $endTime \
                 -tag=Script $apsScriptCommand} result] {
        return -code error $result
    }
}

proc setActionButtons {state} {
    if [winfo exists .presetPlots.one.plotlist.buttonRow.buttons.x2.y3.showComm.button] {
        if $state {
            APSEnableButton .presetPlots.one.plotlist.buttonRow.buttons.x2.y3.showComm.button
        } else {
            APSDisableButton .presetPlots.one.plotlist.buttonRow.buttons.x2.y3.showComm.button
        }
    }
}

proc setActionButtons_1 {state} {
    if [winfo exists .presetPlots.one.plotlist.buttonRow.buttons.x2.y1.remFilter.button] {
        if $state {
            APSEnableButton .presetPlots.one.plotlist.buttonRow.buttons.x2.y1.remFilter.button
        } else {
            APSDisableButton .presetPlots.one.plotlist.buttonRow.buttons.x2.y1.remFilter.button
        }
    }
}

proc setActionButtons_2 {state} {
    if [winfo exists .presetPlots.one.plotlist.buttonRow.buttons.x2.y2.desAll.button] {
        if $state {
            APSEnableButton .presetPlots.one.plotlist.buttonRow.buttons.x2.y2.desAll.button
        } else {
            APSDisableButton .presetPlots.one.plotlist.buttonRow.buttons.x2.y2.desAll.button
        }
    }
}

proc UpdateMonDataFileList {} {
    global MonDataFileList
    MonDataFindFiles
    return [llength $MonDataFileList]
}

proc MonDataFindFiles {args} {
    set group ""
    global StartMonth StartYear StartDay StartHour
    global EndMonth EndYear EndDay EndHour
    global MonDataFileList DataDir
    global DataList RootDir
    APSParseArguments {group}

    if {![llength $group]} {
	set Rootname [lindex $DataList [expr [.userFrame.f6.f1.cb1 current] * 3 + 2]]
	set DataDir ${RootDir}[lindex $DataList [expr [.userFrame.f6.f1.cb1 current] * 3 + 1]]
    } else {
        foreach {groupName partial root} $DataList {
	    if {$groupName == $group} {
		set Rootname $root
		set DataDir ${RootDir}${partial}
		break
	    }
	}
	if {![info exists Rootname]} {
	    set Rootname [lindex $DataList [expr [.userFrame.f6.f1.cb1 current] * 3 + 2]]
	    set DataDir ${RootDir}[lindex $DataList [expr [.userFrame.f6.f1.cb1 current] * 3 + 1]]
	}
    }
    set MonDataFileList  \
      [APSFindFilesBetweenDates -tailsOnly 1 \
         -rootname ${Rootname}- \
         -directory $DataDir \
         -startDateList [APSFormatDate -year $StartYear -month $StartMonth \
                           -day $StartDay -dateFormat list] \
         -endDateList [APSFormatDate -year $EndYear -month $EndMonth \
                         -day $EndDay -dateFormat list] ]
    set filelist ""
    foreach file $MonDataFileList {
	append filelist " [file join $DataDir $file]"
    }
    set MonDataFileList $filelist
    APSSetVarAndUpdate status "[llength $MonDataFileList] files found."
}

proc SaveAsCustomPlot {} {
    global includeS35DCCT xlabel ylabel title topline
    set w .userFrame.f4
    foreach axis [$w.lb1 get 0 end] column [$w.lb2 get 0 end] group [$w.lb3 get 0 end] {
        if {$axis == "X"} {
            set xChoice $column
        } else {
            lappend yChoice $column
	    lappend yGroup $group
        }
    }

    global timeOnXAxis customPlotData
    if {$timeOnXAxis} {set xChoice "Time"}
    if {(![info exists xChoice]) || (![info exists yChoice])} {
        APSSetVarAndUpdate status "Select at least one column for both X and Y axes"
        return
    }
    set userLabels ""
    if {[llength $xlabel]} { append userLabels " -xlabel=$xlabel" }
    if {[llength $ylabel]} { append userLabels " -ylabel=$ylabel" }
    if {[llength $title]} { append userLabels " -title=$title" }
    if {[llength $topline]} { append userLabels " -topline=$topline" }
    if {$includeS35DCCT} {
	set dcct "-column=Time,S35DCCT -yscale=id=dcct -graph=line,type=0,fixForName -legend"
    } else {
	set dcct ""
    }

    
    if {$xChoice == "Time"} {
	set customPlotData "-column=Time,'([join $yChoice ,])' -legend -graphic=line,vary,type=1,fixForName -ticks=xtime $userLabels $dcct"
    } else {
        if {[llength $yChoice] != 1} {
	    foreach YGroupName $yGroup {
		if {$YGroupName != [lindex $yGroup 0]} {
		    APSSetVarAndUpdate status "Currently only one group can be ploted on the Y axis when Time is not used"
		    return
		}
	    }
        }
	set customPlotData "-column=$xChoice,'([join $yChoice ,])' -legend -graphic=line,vary,fixForName $userLabels"
    }

    global customPlotSetupDone customPlotDescription
    set customPlotDescription ""
    set customPlotSetupDone -1
    update
    set customPlotSetupDone 0
    destroy .makeCustomPlotDialog
    APSDialogBox .makeCustomPlotDialog -cancelCommand {set customPlotSetupDone -1} -name "Monitor Data Review Plots"

    APSLabeledEntry .description -parent .makeCustomPlotDialog.userFrame \
	-label "Description:" -textVariable customPlotDescription -width 90
    APSLabeledEntry .plotArgs -parent .makeCustomPlotDialog.userFrame \
	-label "Plot Arguments:" -textVariable customPlotData -width 90

    .makeCustomPlotDialog.buttonRow.ok.button configure -command {set customPlotSetupDone 1; destroy .makeCustomPlotDialog} 
    tkwait variable customPlotSetupDone
    if {$customPlotSetupDone != 1} {
	return
    }
    set selection [APSFileSelectDialog .customPlotDialog -checkValidity 0 -title "Save Custom Plot To File" -contextHelp "Enter a file in which to save text" -modal 0]
    set answer 0
    if {[file exists $selection]} {
	set answer [tk_dialog .dialog "Warning" \
			"File already exists.\nWhat should I do?" \
			question -1 Overwrite Append Cancel]
	if {$answer == 2} {
	    return
	}
    }
    if {[llength $selection]} {
	if {![llength $customPlotDescription]} {
	    set customPlotDescription "No Description Given"
	}
	set data(ParameterNames) "PresetPlotFile"
	set data(ColumnNames) "sddsplotOptions IsTimePlot PlotDescription PlotDataGroups"
	set data(ColumnInfo.IsTimePlot) "type SDDS_SHORT"
	set data(ParameterInfo.PresetPlotFile) "type SDDS_SHORT"
	set data(Parameter.PresetPlotFile) 1
	if {$xChoice == "Time"} {
	    set data(Column.IsTimePlot) [list 1]
	} else {
	    set data(Column.IsTimePlot) [list 0]
	}
	set data(Column.PlotDescription) [list [list "$customPlotDescription"]]
	set data(Column.PlotDataGroups) [list [list "[$w.lb3 get 0 end]"]]
	set data(Column.sddsplotOptions) [list [list "$customPlotData"]]
	if {$answer == 0} {
	    set fileName $selection
	} else {
	    set fileName /tmp/[APSTmpString]
	}
	if [catch {sdds save $fileName data} results] {
	    APSSetVarAndUpdate status "error: $results"
	    bell
	    return
	}
	if {$answer == 1} {
	    if {[catch {exec sdds2stream $selection -col=PlotDescription} names]} {
		APSSetVarAndUpdate status "error: File may not be custom plot file: $names"
		file delete $fileName
		bell
		return
	    }
	    if {[lsearch $names $customPlotDescription] != -1} {
		APSSetVarAndUpdate status "error: The plot description given already exists in file"
		file delete $fileName
		bell
		return		
	    }	
	    set fileName2 /tmp/[APSTmpString]
	    file copy $selection $fileName2
	    if {[catch {exec sddscombine $fileName2 $fileName $selection -overwrite} results]} {
		APSSetVarAndUpdate status "error: $results"
		bell
		return	
	    }
	    file delete $fileName2 $fileName
	}
	APSSetVarAndUpdate status "Custom plot saved as $selection"
    }
}

proc DesignPlot {args} {
    global sparsingInterval plotDevice sameScaleY optionOverride yOffsetMode
    global layoutChoice printerName labelSizeOption
    global repeatPlotMode designUserOptions env includeS35DCCT

    if {![info exists sparsingInterval]} {
	set sparsingInterval 1
	set plotDevice motif
	set repeatPlotMode 0
	set sameScaleY 0
	set yOffsetMode 0
	set optionOverride 0
	set layoutChoice -layout=1,1
	set labelSizeOption -labelsize=0.03
	set presetUserOptions ""
	if [info exists env(PRINTER)] {
	    set printerName $env(PRINTER)
	} else {
	    set printerName mcr1
	}
    }

    if [winfo exists .designPlots] { 
        destroy .designPlots
    }

    set scrollHeight 20

    APSFrameGrid .designPlots -xList {one}


    APSFrameGrid .options -parent .designPlots.one \
      -yList {y1 y2} -width 10 \
      -xList {x1 x2 x3 x4}
        
    APSRadioButtonFrame .layout -parent .designPlots.one.options.x1.y1 \
      -label Layout -orientation vertical \
      -variable layoutChoice \
      -buttonList {1x1 1x2 2x1 2x2 3x3 4x4 5x5} \
      -valueList {-layout=1,1 -layout=1,2 -layout=2,1 -layout=2,2 -layout=3,3 -layout=4,4 -layout=5,5} \
      -contextHelp {Choose the number of plot panels horizontally and vertical on each page.}
    APSCheckButtonFrame .misc  -parent .designPlots.one.options.x2.y1 \
      -label Misc. -orientation vertical \
      -variableList {sameScaleY yOffsetMode optionOverride includeS35DCCT} \
      -buttonList {"Same y scales." "y offset mode" "Option override." "Include S35DCCT"}  \
      -contextHelp "Miscellaneous options and controls.  Option override forces the options you choose here to override those in the original plot command.  If you select an option here and it doesn't affect the plot, you need to invoke the override."

    APSRadioButtonFrame .sparse  -parent .designPlots.one.options.x3.y1 \
      -label Sparsing -orientation vertical \
      -variable sparsingInterval \
      -buttonList {None 2 4 8 16 32 64 128} \
      -valueList {1 2 4 8 16 32 64 128} \
      -contextHelp "For large amounts of data, a larger sparsing interval will result in\
faster display, but at the expense of only seeing a sample of the points."
    APSRadioButtonFrame .device  -parent .designPlots.one.options.x4.y1 \
      -label Device -orientation vertical \
      -variable plotDevice \
      -buttonList {X-windows "B&W Postscript" "Color Postscript"} \
      -valueList {motif postscript cpostscript} \
      -contextHelp "Choose the plotting device.  Postscript is for delivery to a printer only."
    APSLabeledEntry .printer -parent .designPlots.one.options.x4.y2 \
        -label "Printer: " -textVariable printerName -width 10 \
        -contextHelp "Enter the name of the printer for postscript output."
    APSRadioButtonFrame .repeat -parent .designPlots.one.options.x4.y2 \
      -variable repeatPlotMode -label "Repeat: " -buttonList {Yes No} -valueList {1 0} \
      -contextHelp "Enable and disable repeat plotting mode.  If enabled, the data is replotted every time the data files update.  Not suitable for multipage plotting."

    APSRadioButtonFrame .labelsize -parent .designPlots.one.options.x2.y2 \
        -label "Label size" -orientation vertical -variable labelSizeOption \
        -buttonList {normal +15% +30% +45% +60%} \
        -valueList {-labelsize=0.03 -labelsize=0.0345 -labelsize=0.039 -labelsize=0.0435 -labelsize=0.048} \
        -contextHelp "For layouts with many panels, the labels may be hard to read.  You can increase the size of the labels using these options."

    APSLabeledEntry .extra -parent .designPlots.one \
      -label "Extra options: " -textVariable designUserOptions \
      -width 40 -contextHelp "Enter extra sddsplot options to be included in each plot request."

    APSFrame .customPlotLabels -parent .designPlots.one \
	-label "Custom Plot Labels"
    APSLabeledEntry .xLabel -parent .designPlots.one.customPlotLabels.frame \
	-label "x label: " -textVariable xlabel -width 45
    APSLabeledEntry .yLabel -parent .designPlots.one.customPlotLabels.frame \
	-label "y label: " -textVariable ylabel -width 45
    APSLabeledEntry .title -parent .designPlots.one.customPlotLabels.frame \
	-label "  title: " -textVariable title -width 45
    APSLabeledEntry .topline -parent .designPlots.one.customPlotLabels.frame \
	-label "topline: " -textVariable topline -width 45
    

    APSButton .done -parent .designPlots.one -text [format "%30s%25s" Done ""] \
	-command {destroy .designPlots}



}

proc ExportData {} {
    set fileName [APSFileSelectDialog .save \
                    -checkValidity 0 \
                    -title "Export Data to File:" \
                    -contextHelp "Enter a file in which to export SDDS data"]
    if {[string length $fileName]} {
        APSSetVarAndUpdate status "Exporting data to $fileName"
        update
        PlotData -quickSDDSplot 0 -export 1 -exportFileName $fileName
    }
    
}

proc FilterColumns {args} {
    global columnNames columnFilter
    .userFrame.f1.lb1 delete 0 end
    foreach result $columnNames {
      catch {
	if {[lsearch -glob $result "$columnFilter"] != -1} {
	  .userFrame.f1.lb1 insert end $result
	}
      }
    }
}

proc LocatePV {args} {
    global timeSeriesData
    APSStrictParseArguments {pv}
    set output ""
    foreach groupname $timeSeriesData(Parameter.GroupName) pvs $timeSeriesData(Column.ReadbackName) {
        if {[lsearch -exact $pvs $pv] != -1} {
            lappend output $groupname
        }
    }
    return $output
}


set CVSRevisionAuthor "\$Revision: 1.23 $ \$Author: soliday $"

APSApplication . -name "Monitor Data Review (Extended)" -version $CVSRevisionAuthor \
  -overview "Monitor Data Review (Extended) is able to plot columns from different monitoring log files together."

set status "Getting column names"
APSScrolledStatus .status -parent .userFrame -textVariable status -packOption "-fill x"
set selectedColumn ""
set RootDir /home/helios/oagData/

set labelSizeOption -labelsize=0.03
set customPlotsDir .
set yOffsetMode 0
set presetLabel Preset
set MonDataGroupIndex 0
set glitchDataFile ""
set triggerSourceList ""
set group Main
set MonDataPresetPlotDir /home/helios/oagData/monitoring/MonitorDataReviewFiles
set MonDataFileListUpdateTime 0
set MonDataFileList {}

set presetFilterList ""


sdds load /home/helios/oagData/dataLoggerConfig/timeSeries.sdds timeSeriesData
foreach groupname $timeSeriesData(Parameter.GroupName) subdirectory $timeSeriesData(Parameter.subDirectory) rootname $timeSeriesData(Parameter.rootname) {
    lappend DataList $groupname $subdirectory $rootname
}


set w .userFrame
pack [frame $w.f5] -fill x -side bottom
APSButton .plot -parent $w.f5 -text "Plot" \
  -command "PlotData -quickSDDSplot 0"
APSButton .designPlot -parent $w.f5 -text "Design Plot" \
  -command "DesignPlot"
APSButton .showCommands -parent $w.f5 -text "Show Commands..." \
  -command {if {[winfo exists .execLog]} {wm deiconify .execLog}}
APSButton .quickSDDSplot -parent $w.f5 -text "quickSDDSplot..." \
  -command "PlotData" -contextHelp "Click here to launch quickSDDSplot"
APSButton .export -parent $w.f5 -text "Export..." \
  -command "ExportData" -contextHelp "Click here to export data"
pack [frame $w.f6 -relief ridge -bd 2] -fill x -side bottom
pack [frame $w.f6.f1] -fill x
pack [frame $w.f6.f2] -fill x
APSButton .presetPlots -parent $w.f6.f1 -text "Preset Plots" \
  -command "SelectPresetPlots" -contextHelp "Click here to select a preset plot"
foreach {groupName PartialDir Rootname} $DataList {
    lappend groupNameList $groupName
}
ttk::label $w.f6.f1.cblabel -text " Data Group:"
ttk::combobox $w.f6.f1.cb1 -width 42 -values $groupNameList -exportselection no
$w.f6.f1.cb1 current 0
$w.f6.f1.cb1 configure -state readonly
pack $w.f6.f1.cblabel  $w.f6.f1.cb1 -side left
bind $w.f6.f1.cb1 <<ComboboxSelected>> {.userFrame.f6.f1.cb1 selection clear}

APSButton .loadCustomPlot -parent $w.f6.f2 -text "Load Custom Plot" \
  -command "SelectPresetPlots -preset 0" -contextHelp "Click here to load a custom plot"
APSButton .createCustomPlots -parent $w.f6.f2 -text "Save as Custom Plot" \
  -command "SaveAsCustomPlot" -contextHelp "Click here to save a custom plot"
#pack [button $w.f5.quickSDDSplot -text "quickSDDSplot..." -command "PlotData"] -side left
MakeDateTimeFrame .mdtf -parent $w
pack [frame $w.f4] -fill x -side bottom
grid [label $w.f4.la1 -text "Axis"] -column 0 -row 0
grid [label $w.f4.la2 -text "Column"] -column 1 -row 0
grid [label $w.f4.la3 -text "Group"] -column 2 -row 0

grid [listbox $w.f4.lb1 -height 4 -width 4 -yscrollcommand LBscroll \
        -exportselection false] -column 0 -row 1
grid [listbox $w.f4.lb2 -height 4 -yscrollcommand LBscroll \
        -exportselection false] -column 1 -row 1 -sticky nsew
grid [listbox $w.f4.lb3 -height 4 -yscrollcommand LBscroll \
        -exportselection false] -column 2 -row 1 -sticky nsew
grid [scrollbar $w.f4.scroll1 -orient v -command [list LBset yview]] \
  -column 3 -row 1 -sticky ns
grid columnconfigure $w.f4 1 -weight 1
grid columnconfigure $w.f4 2 -weight 1
set BOXES "$w.f4.lb1 $w.f4.lb2 $w.f4.lb3"
foreach lb $BOXES {
    bind $lb <ButtonPress-1> {
        LBset select clear 0 end
        LBset select set [%W nearest %y]
    }
    bind $lb <B1-Motion> {
        LBset select clear 0 end
        LBset select set [%W nearest %y]
        LBset see [%W nearest %y]
    }
    bind $lb <ButtonRelease-1> {
        LBset select clear 0 end
        LBset select set [%W nearest %y]
    }
    bind $lb <ButtonPress-3> {
        LBset select clear 0 end
        LBset select set [%W nearest %y]
        deleteItem %X %Y [%W nearest %y]
    }
    bind $lb <ButtonRelease-3> {
        destroy .deleteWin
    }
}
pack [frame $w.f3] -fill x -side bottom
pack [button $w.f3.b1 -text "Add to X axis" -command {AddXY X}] -side left
pack [button $w.f3.b2 -text "Add to Y axis" -command {AddXY Y}] -side left
set timeOnXAxis 1
pack [checkbutton $w.f3.checkbutton1 -text "Time on X axis" \
        -variable timeOnXAxis -relief ridge -padx 4] -side left -fill y

pack [frame $w.f2] -fill x
pack [label $w.f2.la1 -text "Column Names"] -side left -fill x -expand true
pack [label $w.f2.la2 -text "Available Groups"] -side left -fill x -expand true
pack [frame $w.f1] -fill both -expand true
grid [listbox $w.f1.lb1 -yscrollcommand "$w.f1.scroll1 set" \
        -height 20 -exportselection false] -row 0 -column 0 -sticky nsew
set apsContextHelp($w.f1.lb1) "Double click on the columns you wish to plot"
grid [scrollbar $w.f1.scroll1 -command "$w.f1.lb1 yview"] -row 0 -column 1 -sticky ns
grid [listbox $w.f1.lb2 -yscrollcommand "$w.f1.scroll2 set" \
        -exportselection false] -row 0 -column 2 -rowspan 2 -sticky nsew
set apsContextHelp($w.f1.lb2) "Select the corresponding group wish to plot"
grid [scrollbar $w.f1.scroll2 -command "$w.f1.lb2 yview"] -row 0 -column 3 -rowspan 2 -sticky ns
set columnFilter "*"
grid [entry $w.f1.entry1 -textvariable columnFilter] -row 1 -column 0 -columnspan 2 -sticky ew
set apsContextHelp($w.f1.entry1) "Enter a filter string for searching data columns. Press <CR> to start search."
grid columnconfigure $w.f1 0 -weight 1
grid columnconfigure $w.f1 2 -weight 1
grid rowconfigure $w.f1 0 -weight 1
bind $w.f1.lb1 <Double-Button-1> {
    NewColumn [.userFrame.f1.lb1 get [.userFrame.f1.lb1 curselection]]
}
bindtags $w.f1.entry1 "Entry . all $w.f1.entry1"
bind $w.f1.entry1 <Return> "FilterColumns"
update


set columnNames [lsort -dictionary [join $timeSeriesData(Column.ReadbackName)]]
foreach result $columnNames {
    $w.f1.lb1 insert end $result
}


set status "Ready"
