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

# $Log: not supported by cvs2svn $
# Revision 1.65  2005/08/23 20:07:52  soliday
# Added APSRenameExecToAPSBGExec.
#
# Revision 1.64  2005/08/02 15:47:52  soliday
# Fixed problem plotting histograms.
#
# Revision 1.63  2005/05/03 18:22:00  soliday
# Replaced exec date command because it does not exist on Windows.
#
# Revision 1.62  2005/04/08 00:33:14  borland
# Fixed bug in launching the export application. In some cases, the
# variable "message" was not defined.
#
# Revision 1.61  2005/01/11 22:15:07  soliday
# Changed -graph=line,vary,eachfile to -graph=line,vary,fixForName
#
# Revision 1.60  2004/08/23 14:29:21  shang
# removed printing to default printer command for device = "PNG file(white)" and "PNG file(black)" choices.
#
# Revision 1.59  2004/07/23 21:16:03  shang
# added "Overwrite Abort Always_Overwrite" choices if creating plot to a png file
# and the png file already exists
#
# Revision 1.58  2004/07/23 14:26:30  shang
# added plotting to a PNG file feature
#
# Revision 1.57  2004/01/03 22:54:16  borland
# Added option to split pages.
#
# Revision 1.56  2003/12/22 20:30:22  soliday
# Added the ability to plot histograms.
#
# Revision 1.55  2003/11/21 22:09:37  soliday
# Fixed an issue with the -scales option. This option is only used now if the
# user sets the plot limits or if they add it to the extra options entry box.
#
# Revision 1.54  2003/11/11 18:20:49  borland
# Added ability to use tksddsplot instead of sddsplot.
#
# Revision 1.53  2003/11/03 16:24:29  soliday
# Added command line option to enable the display of the related controlnames.
#
# Revision 1.52  2003/11/03 16:15:06  soliday
# Added a checkbutton to select if related control names should be displayed.
#
# Revision 1.51  2003/10/31 23:06:30  soliday
# ControlNames are now listed next to ReadbackNames in the column selection dialogs.
#
# Revision 1.50  2003/05/21 15:46:40  soliday
# Added a button to quickly select Time as the x axis.
#
# Revision 1.49  2003/01/20 23:50:27  borland
# Fixed problems with /tmp disk being nonexistent on WIN32 architectures.
# Added limits entry boxes.
#
# Revision 1.48  2002/12/13 16:59:19  soliday
# Added the common offset button.
#
# Revision 1.47  2002/04/26 18:38:45  emery
# Changed some string compare to string match to simplify the reading.
# Replaced "lappend extraOptions -device=motif" with
# "lappend extraOptions $deviceOption", which prevented postscript
# devices from being used.
#
# Revision 1.46  2002/01/09 22:35:48  soliday
# These now work on Windows.
#
# Revision 1.45  2001/07/25 13:44:15  borland
# Now enforces single selection for x axis.
#
# Revision 1.44  2001/06/26 22:40:35  emery
# Used APSMakeSafeQualifierString for labels.
#
# Revision 1.43  2000/07/26 03:21:24  borland
# Commented out code that selects plot quantity automatically when there is
# only one item in the list.  Resulted in strange behavior (e.g., closing
# of y list after close was hit on x list).
#
# Revision 1.42  2000/01/11 15:07:18  borland
# Per D. Blachowicz: added repeat feature.
#
# Revision 1.40  1999/01/29 15:14:54  borland
# Bug fixes to exclusion filters per Blachowicz.
#
# Revision 1.39  1999/01/13 17:25:00  soliday
# Added the ability to pass more options such as xChoice, yChoice, plotNow,
# and horizontalMode.
#
# Revision 1.38  1998/11/25 21:37:53  soliday
# Recommiting after a cvs commit error
#
# Revision 1.37  1998/11/25 21:34:14  soliday
# Added ability to accept userCustomArguments, xNameFilter, and yNameFilter
# from command line.
#
# Revision 1.36  1998/10/12 14:53:10  borland
# Added exclusion filters for x and y.  Also will launch sddsExportData.
# These changes by D. Blachowicz.  Log mode now uses special scales
# (M. Borland).
# CVS:----------------------------------------------------------------------
# CVS:----------------------------------------------------------------------
#
# Revision 1.35  1998/07/20 21:24:26  borland
# Per D. Blachowicz: when MonitorDataReview passes time limits to
# quickSDDSplot and sddsExportData, it now adds an extra argument
# to tell these tools that they can allow the user to expand the
# time lmits to the day boundaries.
#
# Revision 1.34  1998/06/22 14:32:47  borland
# No longer displays string or character columns as plotting choices.
#
# Revision 1.33  1998/06/22 14:24:59  borland
# Now accepts user time filters when no commandline-supplied time limits
# are present.
#
# Revision 1.32  1998/05/29 14:25:07  borland
# Now accepts comma-separated list of patterns for x and y name filters
# (D. Blachowicz).
#
# Revision 1.31  1998/05/28 15:52:54  borland
# Changes by D. Blachowicz for time-filter mode:
# 1. Does not allow the user to expand the time range beyond the
# limits provided by the parent.
# 2. Requires that the start time preceed the end time.
#
# Revision 1.30  1997/11/06 14:49:59  borland
# Implemented -indexFileTemplate option to allow passing a format string
# for forming index file names from data file names.  If it exists, the
# index file gives the names of the columns in the data file, saving
# much time when files are large and gziped.
#
# Revision 1.29  1997/04/02 14:35:07  borland
# Now switches out of x time mode when something other than
# Time is selected as indepedent variable.
#
# Revision 1.28  1997/03/12 20:07:32  borland
# Fixed bug with interpretation of HH:MM time filter data.
#
# Revision 1.27  1997/03/12 20:03:36  borland
# Incrased width of entry boxes for time fitler.
#
# Revision 1.26  1997/03/07 21:43:01  borland
# Now accepts commandline time filter data (e.g., from MonitorDataReview).
#
# Revision 1.25  1997/03/06 19:26:45  borland
# Added time filter.
#
# Revision 1.24  1996/09/19 23:41:47  borland
# Changed some APSGetSDDSParameter calls to handle new list return.
#
# Revision 1.23  1996/09/19 21:51:36  borland
# Changed from using "exec wish" to "exec oagwish".
#
# Revision 1.22  1996/09/19 13:31:45  borland
# Now recognizes files typed into file entry box.  Use key binding to get this.
#

# Revision 1.21  1996/08/20 21:27:42  borland
# Added checking of and messages about filename and description for
# saving commands.
#
# Revision 1.20  1996/07/05  23:07:15  borland
# Added messages about file selection and addition.  Added APSDebugPath.
#
# Revision 1.19  1996/07/05  18:19:37  borland
# Added capability to select multiple times from plot selection dialog
# for Load Command... facility.
#
# Revision 1.18  1996/04/10  18:07:00  borland
# Switches automatically into horizontal time mode if x variable is "Time".
#
# Revision 1.17  1996/04/10  17:32:56  borland
# Added autosetting of separate to 1 and legend to 0 when layout other than
# 1x1 is chosen.
#
# Revision 1.16  1996/04/10  17:10:07  borland
# Added capability to choose and plot several files.
#
# Revision 1.15  1996/03/25  19:53:47  borland
# Removed reference to local file.
#
# Revision 1.14  1996/03/25  19:44:16  borland
# Added facility to save/load plot configurations.  Saved configurations can
# be used with MonitorDataReview.
#
# Revision 1.13  1996/03/07  19:50:55  borland
# Fixed context help message for FAST SCAN button.
#
# Revision 1.12  1996/03/04  20:14:22  saunders
# Added revision/author to Version menu.
#
# Revision 1.11  1996/02/22  18:40:58  borland
# Added fast scan feature when launched by another program with many input
# files.
#
# Revision 1.10  1996/02/22  18:04:00  borland
# Expanded support for invocation from other processes. Added horizontal plotting
# mode options.  Speeded repeated name scanning by keeping presorted file.
# Smarter use of groupby and separate options for multiple and single file
# plotting.
#
# Revision 1.9  1996/02/21  23:34:19  borland
# Removed unpacking features, since sdds routines now do this automatically.
#
# Revision 1.8  1996/02/01  22:07:42  borland
# Changed gunzip command to gzip command with "no-name" option.
#
# Revision 1.7  1996/01/19  21:58:45  borland
# Now uses APSScrolledList to present choices of what data to plot.
#
# Revision 1.6  1996/01/17  16:59:36  saunders
# Added /usr/local/oag/lib_patch to front to auto_path.
#
# Revision 1.5  1996/01/16  21:12:17  saunders
# Fixed log entry problem, so now comments and version numbers
# appear properly. Also, renames X.tcl files to just X.
#
# Revision 1.4  1996/01/12 22:36:53  saunders
# Removing dependence on ~borland/tcl/rel auto_path entry. There are still
# references to personal directories. Also fixed minor bugs as encountered.
#
# Revision 1.3  1995/12/15  20:12:39  saunders
# Added proper installation Makefile and Log
#

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)]
#set auto_path [linsert $auto_path 0 /home/oxygen/SOLIDAY/oag/apps/src/tcltklib]
#APSDebugPath
set apsttk 1
APSRenameExecToAPSBGExec

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

if [string compare $env(HOST_ARCH) WIN32]==0 {
    set tmpPrefix c:/TEMP
} else {
    set tmpPrefix /tmp
}

proc SetMainStatus {text} {
    global mainStatus
    set mainStatus $text
    update
}

proc SetLayoutRelatedVars {multi} {
    global separate sameScale layoutOption verticalMode horizontalMode graphicType deviceOption legends splitPages
    if $multi {
        set separate 1
        set legends 0
        set splitPages 0
    }
}

proc MakeOptionsWidget {widget args} {
    set parent ""
    APSParseArguments {parent}

    global separate sameScale layoutOption verticalMode horizontalMode graphicType 
    global deviceOption legends repeatPlotMode coffset splitPages
    set separate 0
    set sameScale 0
    set legends 1
    set layoutOption -layout=1,1
    set verticalMode linear
    #    set horizontalMode linear
    set graphicType -graph=line,vary
    set deviceOption -device=motif
    set coffset 0
    APSFrame $widget -parent $parent -label Options \
      -contextHelp "Provides buttons for choosing the most common sddsplot options."
    set w $parent$widget.frame

    APSCheckButtonFrame .bf1 -parent $w -label Grouping \
      -buttonList {separate "same scale" "split pages"} \
      -variableList {separate sameScale splitPages} \
      -packOption "-side left" \
      -contextHelp "Determines grouping of data onto plot panels.  By default, all data is on one panel.  Choosing separate puts each plot on a different panel.  In addition, choosing same-scale uses the same vertical scale for all panels.  Further, using split pages splits data from different pages into different panels."

    APSCheckButtonFrame .bf1b -parent $w -label Miscell. \
      -buttonList {legends "common offset" histogram} \
      -variableList {legends coffset histogram} \
      -packOption "-side left" \
      -contextHelp "Determines use of miscellaneous features." \
      -commandList {"" "" "ToggleHistogramMode"}

    APSRadioButtonFrame .bf1a -parent $w -label Layout \
      -variable layoutOption \
      -buttonList {1x1 2x2 3x3 4x4 5x5} \
      -valueList {-layout=1,1 -layout=2,2 -layout=3,3 -layout=4,4 -layout=5,5} \
      -commandList {"SetLayoutRelatedVars 0" "SetLayoutRelatedVars 1" "SetLayoutRelatedVars 1" "SetLayoutRelatedVars 1" "SetLayoutRelatedVars 1" } \
      -packOption "-side left" \
      -contextHelp "Chooses how plot panels are layed out on a plot page.  If you choose to separate data on panels using the Grouping choices, you may also want a Layout other than the default 1x1."

    APSRadioButtonFrame .bf2 -parent $w -label "Vertical mode" \
      -variable verticalMode \
      -buttonList {linear log} \
      -valueList {linear log,y=special} \
      -packOption "-side left" \
      -contextHelp "Chooses the mode for the vertical axis.  Choosing log scale is good for vacuum data."

    APSRadioButtonFrame .bf3 -parent $w -label "Horizontal mode" \
      -variable horizontalMode \
      -buttonList {normal time log} \
      -valueList {linear time log,x=special} \
      -packOption "-side left" \
      -contextHelp "Chooses the mode for the horizontal axis.  Choosing time mode is good for monitor data when plotting vs the Time column."

    APSRadioButtonFrame .bf4 -parent $w -label Graphic \
      -variable graphicType \
      -buttonList {"multicolor line" line symbol "multicolor symbol" dot "multicolor bar"} \
      -valueList {-graph=line,vary -graph=line -graph=symbol,vary -graph=symbol,vary=subtype -graph=dot,vary -graph=bar,vary,thickness=2 -graph=impulse,vary} \
      -packOption "-side left" \
      -contextHelp "Chooses the type of graphic element.  By default, data is plotted with lines, but you may choose symbols, dots, bars, etc."

    APSRadioButtonFrame .bf5 -parent $w -label Device \
      -variable deviceOption \
      -buttonList {X-windows "B&W Postscript" "Color Postscript" "PNG file (white)" "PNG file (black)"} \
      -valueList {-device=motif -device=post -device=cpost -device=png,onwhite -device=png,onblack} \
      -packOption "-side left" \
      -contextHelp "Chooses the graphics device to use.  X-windows plots to the screen, whereas the Postscript choices allow you to channel output to a printer. PNG file white or black option choices allow you to create a PNG file with white or black background (PNG filename is suppied by \"PNG file name\" entry)"

    set repeatPlotMode 0
    APSRadioButtonFrame .repeat -parent $w -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."
}

proc MakeTimeFilterWidget {widget args} {
    set parent ""
    APSParseArguments {parent}
    global hourStart dayStart monthStart yearStart
    global hourEnd dayEnd monthEnd yearEnd doTimeFilter

    if !$doTimeFilter {
        set hourStart 0
        set hourEnd 24
        APSDateBreakDown -dayVariable dayStart -monthVariable monthStart \
          -yearVariable yearStart -twoDigitYear 0 -leadingZeros 0
        APSDateBreakDown -dayVariable dayEnd -monthVariable monthEnd \
          -yearVariable yearEnd -twoDigitYear 0 -leadingZeros 0
    }
    
    APSFrame $widget -parent $parent -label "" -relief flat \
      -contextHelp "Provides for calendar-time-based filtering of the data.  Will work only if the data contains the Time column (e.g., sddsmonitor data)."
    set w $parent$widget.frame

    APSRadioButtonFrame .filter -parent $w -orientation horizontal \
      -variable doTimeFilter -label "Time filter: " -packOption "-side left" \
      -buttonList "Yes No" -valueList "1 0" -contextHelp \
      "Choose whether to apply an time filter to the data or not."
    APSLabeledEntryFrame .start -parent $w -label " Start (Y/M/D/H): " \
      -contextHelp "Enter the start time in year, month, day, and hour." \
      -variableList {yearStart monthStart dayStart hourStart} \
      -orientation horizontal -width 5 -packOption "-side left" 
    APSLabeledEntryFrame .end   -parent $w -label " End: " \
      -contextHelp "Enter the end time in year, month, day, and hour." \
      -variableList {yearEnd monthEnd dayEnd hourEnd} \
      -orientation horizontal -width 5 -packOption "-side left" 
    global pngFile
    APSLabeledEntry .pngfile -parent $parent -textVariable pngFile -width 100 \
      -packOption "-side top" -label "PNG file name:   " \
      -contextHelp "provide filename for PNG file if \"PNG file (white)\" or \"PNG file (black)\" device is chosen."
    
}

proc MakeFilterFrame {widget args} {
    global xNameFilter yNameFilter hist
    set parent ""
    set packOption ""
    APSParseArguments {parent packOption}
    APSFrame $widget -parent $parent -label "Name Filters" \
      -contextHelp "Provides entry widgets for filters to apply to names in files in order to create abbreviated lists of quantities to plot." \
      -packOption $packOption
    set w $parent$widget.frame
    APSLabeledEntry .xlabel -parent $w -textVariable xNameFilter -label "x: " \
      -width 30 \
      -contextHelp "Enter a wildcard string or set of strings separated by coma, with no empty space between them, for selecting a subset of names as x variable choices. E.g., *Time* matches anything containing the string 'Time'"
    bind $w.xlabel.entry <Return> {ScanFile fast} 
    APSLabeledEntry .ylabel -parent $w -textVariable yNameFilter -label "y: " \
      -width 30 \
      -contextHelp "Enter a wildcard string or set of strings separated by coma, with no empty space between them, for selecting a subset of names as y variable choices. E.g., *Time* matches anything containing the string 'Time'"
    bind $w.ylabel.entry <Return> {ScanFile fast}

    append hist(widgets2) "$w.ylabel.entry "
}

proc MakeExclusionFrame {widget args} {
    set parent ""
    set packOption ""
    APSParseArguments {parent packOption}
    global xNameExcl yNameExcl hist
    APSFrame $widget -parent $parent -label "Name Exclusions" \
      -contextHelp "Provides entry widgets for exclusions of the filters to apply to names in files in order to create abbreviated lists of quantities to plot." \
      -packOption $packOption
    set w $parent$widget.frame
    APSLabeledEntry .xlabelExcl -parent $w -textVariable xNameExcl -label "x: " \
      -width 30 \
      -contextHelp "Enter a wildcard string or set of strings separated by coma, with no empty space between them, for selecting a subset of names as x variable exclusion. E.g., *Time* matches anything containing the string 'Time'"
    bind $w.xlabelExcl.entry <Return> {ScanFile fast}
    APSLabeledEntry .ylabelExcl -parent $w -textVariable yNameExcl -label "y: " \
      -width 30 \
      -contextHelp "Enter a wildcard string or set of strings separated by coma, with no empty space between them, for selecting a subset of names as y variable exclusion. E.g., *Time* matches anything containing the string 'Time'"
    bind $w.ylabelExcl.entry <Return> {ScanFile fast}

    append hist(widgets2) "$w.ylabelExcl.entry "
}

proc MakeLimitsFrame {widget args} {
    set parent ""
    set packOption ""
    APSParseArguments {parent packOption}
    global xLimits yLimits
    foreach item {min max} {
        set xLimits($item) 0
        set yLimits($item) 0
    }
    APSFrame $widget -parent $parent -label "Plot limits" \
      -contextHelp "Provides entry widgets for minimum and maximum limits for plots.  If entries are equal for a plane, they are ignored." \
      -packOption $packOption
    set w $parent$widget.frame
    APSLabeledEntryFrame .xLimit -parent $w -variableList {xLimits(min) xLimits(max)} \
      -width 6 -label "x min, max: " -orientation horizontal \
      -contextHelp "Enter the minimum and maximum limits for x data.  If entries are equal, they are ignored."
    APSLabeledEntryFrame .yLimit -parent $w -variableList {yLimits(min) yLimits(max)} \
      -width 6 -label "y min, max: " -orientation horizontal \
      -contextHelp "Enter the minimum and maximum limits for y data.  If entries are equal, they are ignored."
}

proc MakeCustomArgFrame {widget args} {
    global userCustomArguments 
    set parent ""
    APSParseArguments {parent}
    APSFrame $widget -parent $parent -label "Custom sddsplot Arguments"
    set w $parent$widget.frame
    APSLabeledEntry .entry -parent $w -textVariable userCustomArguments \
      -label " " \
      -width 100 \
      -contextHelp "Enter text of options to be appended to the sddsplot command."
}

proc MakeLabelFrame {widget args} {
    global userXlabel userYlabel userTitle userTopline hist
    set parent ""
    APSParseArguments {parent}
    pack [ttk::frame $parent$widget]
    set parent $parent$widget
    APSFrame $widget -parent $parent -label "Custom Plot Labels" -packOption "-side left"
    set w $parent$widget.frame
    APSLabeledEntry .xlabel -parent $w -textVariable userXlabel -label "x label: " \
      -width 70 \
      -contextHelp "Enter text for the x label of the plots."
    APSLabeledEntry .ylabel -parent $w -textVariable userYlabel -label "y label: " \
      -width 70 \
      -contextHelp "Enter text for the y label of the plots."
    APSLabeledEntry .title -parent $w -textVariable userTitle -label "title: " \
      -width 70 \
      -contextHelp "Enter text for the title label of the plots."
    APSLabeledEntry .topline -parent $w -textVariable userTopline -label "topline: " \
      -width 70 \
      -contextHelp "Enter text for the topline label of the plots."
    
    APSFrame .hist -parent $parent \
        -label "Histogram Options" \
        -packOption "-side left"
    set w ${parent}.hist.frame
    APSLabeledEntry .bins -parent $w \
        -textVariable hist(bins) \
        -label "       Bins: " \
        -width 10 \
        -contextHelp "Number of bins for the histogram."
    APSLabeledEntry .sizeofbins -parent $w \
        -textVariable hist(sizeOfBins) \
        -label "Size Of Bins: " \
        -width 10 \
        -contextHelp "Size of bins for the histogram."
    APSLabeledEntry .lowerLimit -parent $w \
        -textVariable hist(lowerLimit) \
        -label "Lower Limit: " \
        -width 10 \
        -contextHelp "Lower limit of the histogram."
    APSLabeledEntry .upperLimit -parent $w \
        -textVariable hist(upperLimit) \
        -label "Upper Limit: " \
        -width 10 \
        -contextHelp "Upper limit of the histogram."
    append hist(widgets) "$w.bins.entry $w.sizeofbins.entry $w.lowerLimit.entry $w.upperLimit.entry "

}

proc ClearUserLabels {} {
    global userXlabel userYlabel userTitle userTopline
    set userXlabel ""
    set userYlabel ""
    set userTitle ""
    set userTopline ""
}

proc PickFilename {args} { 
    set addFile 0
    APSStrictParseArguments {addFile}
    global dataFileList xNameFilter yNameFilter pickFileDir 
    global pickFileMode dataFilename PresortedChoicesFile

    if [llength $dataFileList] {
        set dataFile [lindex $dataFileList 0]
        if [string length $dataFile] {
            set pickFileDir1 [file dirname $dataFile]
            if [string length $pickFileDir1] {
                set pickFileDir $pickFileDir1
            }
        }
    }

    set inputFlag 0
    if {[llength $dataFileList] && [lsearch $dataFileList $dataFilename] < 0} {
        if [file exists $dataFilename] {
            lappend dataFileList $dataFilename
            set addFile 1
            set inputFlag 1
        } else {
            SetMainStatus "File $dataFilename does not exists."
            return
        }
    }
    
    if !$addFile {
        set dataFileList ""
    }
    if !$inputFlag {
        set dataFilename1 [APSFileSelectDialog .[APSTmpString] -listDir $pickFileDir \
                             -contextHelp "File select box for quickSDDSplot data file."]
        
        if [string length $dataFilename1]==0 return
        set dataFilename $dataFilename1
        lappend dataFileList $dataFilename
    }
    set pickFileDir [file dirname $dataFilename]
    if $addFile {
        SetMainStatus "Added: $dataFilename"
    } else {
        SetMainStatus "Selected: $dataFilename"
    }
    set PresortedChoicesFile ""
    if [llength $dataFileList] {
        SetMainStatus "Scanning file..."
        preMakePlotQuantityChoices
    }
}

proc preMakePlotQuantityChoices {} {
    global dataFileList xNameFilter yNameFilter xNameExcl yNameExcl histogram
    if {$histogram} {
	MakePlotQuantityChoices \
	    -fileNameList $dataFileList \
	    -dimension x \
	    -mode radio \
	    -variable xChoice \
	    -nameFilter $xNameFilter \
	    -nameExclusion $xNameExcl
    } else {
	MakePlotQuantityChoices \
	    -fileNameList $dataFileList \
	    -dimension x \
	    -mode radio \
	    -variable xChoice \
	    -nameFilter $xNameFilter \
	    -nameExclusion $xNameExcl
	MakePlotQuantityChoices \
	    -fileNameList $dataFileList \
	    -dimension y \
	    -mode check \
	    -variable yChoice \
	    -nameFilter $yNameFilter \
	    -nameExclusion $yNameExcl
    }
}     

proc MakePrinterFrame {widget args} {
    set parent ""
    set packOption ""
    APSParseArguments {parent packOption}
    APSFrame $widget -parent $parent -label "Printer Choice" \
      -packOption $packOption -width 30
    set w $parent$widget.frame
    APSLabeledEntry .lentry -parent $w \
      -textVariable printerName -label "Printer: " -width 30 \
      -contextHelp "Holds the name of the printer for graphics other than X-windows." 
}

proc MakePlotQuantityChoices {args} {
    global PresortedChoicesFile tmpPrefix
    global tmpPrefix showControlNames
    set dimension x
    set fileNameList {}
    set mode all
    set variable ""
    set nameFilter ""
    set nameExclusion ""
    set indexFileTemplate ""
    APSParseArguments {dimension fileNameList mode variable nameFilter nameExclusion indexFileTemplate}
    if [llength $fileNameList]==0 {
        SetMainStatus "No filename(s) for making quantity choice list."
        return 
    }

    if [string length $variable]==0 {
        SetMainStatus "No variable name for making quantity choice list--internal error!"
        return
    }
    global $variable listOfNames listOfReadbackNames

    if [info exists $variable] { unset $variable }

    SetMainStatus "Working on list for $dimension..."

    if {![string length $PresortedChoicesFile] || ![file exists $PresortedChoicesFile]} {
        SetMainStatus "Please wait, making sorted list of data columns..."
        set tmpFileList {}
        if {[string compare $mode all] && [llength $fileNameList]>2} {
            set scanList [concat [lindex $fileNameList 0] [lindex $fileNameList end]]
        } else {
            set scanList [concat $fileNameList]
        }
        foreach fileName $scanList {
            set indexFile ""
            if {[string length $indexFileTemplate]} {
                set indexFile [format $indexFileTemplate [file rootname $fileName]]
                if ![file exists $indexFile] {
                    set indexFile ""
                }
            }
            if ![string length $indexFile] {
                set tmpFile $tmpPrefix/[APSTmpString]
                if ![file exists $fileName] {
                    SetMainStatus "$fileName does not exist."
                    return 
                }
                if {[string compare $mode all] && ![APSCheckSDDSFile -fileName $fileName]} {
                    SetMainStatus "$fileName is not an SDDS file."
                    return 
                }
                exec sddsquery $fileName -sddsOutput -column \
                  | sddsprocess -pipe=in $tmpFile -match=column,Type=string,! \
                  -match=column,Type=character,!
            } else {
                set tmpFile $tmpPrefix/[APSTmpString]
                if [string compare [file extension $indexFile] .gz]==0 {
                    set tmpFile $tmpFile.gz
                }
                file copy -force -- $indexFile $tmpFile
            }
            lappend tmpFileList $tmpFile
        }
        set PresortedChoicesFile $tmpPrefix/[APSTmpString]

        eval exec sddscombine $tmpFileList -merge -pipe=out \
          | sddsconvert -pipe -retain=column,Name \
          | sddssort -column=Name -pipe=in -unique -num $PresortedChoicesFile

        set count [lindex [split [exec sdds2stream -rows $PresortedChoicesFile]] 0]
        SetMainStatus "$count unique data columns found in [llength $fileNameList] files."
    }
    set tmpFile $tmpPrefix/[APSTmpString]
    set tmpNameFileList ""
    if [string length $nameFilter] {
        set nameFilterList [split $nameFilter ,]
        set nameList ""
        set name0 [lindex $nameFilterList 0]
        if [string length $nameExclusion] { 
            set ExclusionList ""
            set nameExclusionList [split $nameExclusion ,]
            foreach name $nameExclusionList {
                lappend ExclusionList "-match=col,Name=${name},!"
            }
            if {[llength $nameFilterList] == 1} {
                if [catch {eval exec sddsprocess $PresortedChoicesFile $tmpFile \
                             $ExclusionList {"-match=col,Name=${name0}"}} result] {
                    SetMainStatus "$result"
                    return
                }
            } else {
                for {set i 1} {$i < [llength $nameFilterList]} {incr i} {
                    lappend nameList "Name=[lindex $nameFilterList $i],|"
                    set nameString [join $nameList ,]
                }
                if [catch {eval exec sddsprocess $PresortedChoicesFile $tmpFile \
                             $ExclusionList {"-match=col,Name=$name0,${nameString}"}} result] {
                    SetMainStatus "$result"
                    return
                }
            }
        } else {
            if {[llength $nameFilterList] == 1} {
                exec sddsprocess $PresortedChoicesFile $tmpFile "-match=col,Name=${name0}"
            } else {
                for {set i 1} {$i < [llength $nameFilterList]} {incr i} {
                    lappend nameList "Name=[lindex $nameFilterList $i],|"
                    set nameString [join $nameList ,]
                }
                exec sddsprocess $PresortedChoicesFile $tmpFile "-match=col,Name=$name0,${nameString}"
            }
        }
    } else {
        if [string length $nameExclusion] { 
            set ExclusionList ""
            set nameExclusionList [split $nameExclusion ,]
            foreach name $nameExclusionList {
                lappend ExclusionList "-match=column,Name=$name,!"
            }
            if [catch {eval exec sddsprocess $PresortedChoicesFile $tmpFile \
                         $ExclusionList} result] {
                SetMainStatus "$result"
                return
            }
        } else {
            file copy -force -- $PresortedChoicesFile  $tmpFile 
        }
    }
    
    if {($showControlNames) && ([file exists /home/helios/oagData/dataLoggerConfig/timeSeries.sdds])} {
        if {[catch {exec sddscombine /home/helios/oagData/dataLoggerConfig/timeSeries.sdds ${tmpFile}2 -merge} retults]} {
            SetMainStatus "$results"
            file delete -force $tmpFile
            return
        }
        if {[catch {exec sddsxref $tmpFile ${tmpFile}2 ${tmpFile}3 -match=Name=ReadbackName -take=ControlName -fillIn -nowarnings} results]} {
            SetMainStatus "$results"
            file delete -force $tmpFile ${tmpFile}2
            return
        }
        set listOfControlNames [APSGetSDDSColumn -page 0 -column ControlName -fileName ${tmpFile}3]
        set listOfReadbackNames [APSGetSDDSColumn -page 0 -column Name -fileName ${tmpFile}3]
        set listOfNames ""
        set maxLen 0
        foreach i1 $listOfReadbackNames {
            set len [string length $i1]
            if {$maxLen < $len} {
                set maxLen $len
            }
        }
        foreach i1 $listOfReadbackNames i2 $listOfControlNames {
            if {[string length $i2] > 0} {
                set space ""
                for {set len [string length $i1]} {$len < $maxLen} {incr len} {
                    set space "$space "
                }
                append listOfNames "\"${i1}${space} / $i2\" "
            } else {
                append listOfNames "$i1 "
            }
        }
        file delete -force $tmpFile ${tmpFile}2 ${tmpFile}3
    } else {
        set listOfNames [APSGetSDDSColumn -page 0 -column Name -fileName $tmpFile]
        set listOfReadbackNames $listOfNames
        file delete -force $tmpFile
    }
    if ![llength $listOfNames] {
        SetMainStatus "No match located for a current setup for \"$dimension\" dimension."
        file delete -force $tmpFile
        return
    }
    switch $dimension {
        x {
            set pickLabel "pick 1"
        }
        y {
            set pickLabel "pick any number"
        }
        default {
            SetMainStatus "Invalid dimension for making quantity choice list--internal error!"
            return
        }
    }
    set w .qplot${dimension}
    if [winfo exists $w] {
        destroy $w
    }
    set maxlen 0

    if ![string compare $dimension y] {
        set selectMode extended
    } else  {
        set selectMode single
    }
    APSScrolledListWindow $w \
      -name "quickSDDSplot data selection" \
      -label "$dimension choices--$pickLabel" \
      -itemList $listOfNames \
      -selectionVar $variable \
      -callback dataSelectionCallback$dimension \
      -selectMode $selectMode
#    if {[llength $listOfNames] == 1} {
#        $w.userFrame.sl.listbox selection set 0 0
#    }
    if ![string compare $dimension y] {
        APSDialogBoxAddButton .all -parent $w -text "Accept All" -command "AcceptAll listOfReadbackNames"
    }
    set ti [lsearch $listOfReadbackNames "Time"]
    if {($dimension == "x") && ($ti != -1)} {
        APSDialogBoxAddButton .time -parent $w -text "Time" -command "AcceptTime $ti"
    }
}

proc AcceptTime {timeIndex} {
    global xChoice
    set xChoice "Time"
    .qplotx.userFrame.sl.listbox selection clear 0 end
    .qplotx.userFrame.sl.listbox selection set $timeIndex $timeIndex
    .qplotx.userFrame.sl.listbox yview $timeIndex
}

proc AcceptAll {yList} {
    global yChoice $yList
    set yChoice ""
    foreach elem [set $yList] {
        lappend yChoice $elem
    }
    update
    .qploty.userFrame.sl.listbox selection set 0 end
}

proc dataSelectionCallbackx {itemList} {
    global horizontalMode
    if {[llength $itemList]==1} {
        if [string compare [lindex $itemList 0] Time]==0 {
            set horizontalMode time
        } else {
            set horizontalMode linear
        }
    }
}

proc dataSelectionCallbacky {itemList} {
}

proc ScanFile {mode} {
    global dataFileList xChoice yChoice xNameFilter yNameFilter histogram
    global pickFileMode dataFilename indexFileTemplate xNameExcl yNameExcl

    if [llength $dataFileList]==0 {
        SetMainStatus "Supply a filename"
        return
    }

    set dataFile [lindex $dataFileList end]

    if ![file exists $dataFile] {
        SetMainStatus "$dataFile does not exist."
        return
    }
    set pickFileDir [file dirname $dataFile]

    if {$histogram} {
	MakePlotQuantityChoices \
	    -fileNameList $dataFileList \
	    -dimension x \
	    -mode radio \
	    -variable xChoice \
	    -parent .userFrame \
	    -nameFilter $xNameFilter \
	    -mode $mode \
	    -indexFileTemplate $indexFileTemplate \
	    -nameExclusion $xNameExcl 
    } else {
	MakePlotQuantityChoices \
	    -fileNameList $dataFileList \
	    -dimension x \
	    -mode radio \
	    -variable xChoice \
	    -parent .userFrame \
	    -nameFilter $xNameFilter \
	    -mode $mode \
	    -indexFileTemplate $indexFileTemplate \
	    -nameExclusion $xNameExcl 
	MakePlotQuantityChoices \
	    -fileNameList $dataFileList \
	    -dimension y \
	    -mode check \
	    -variable yChoice \
	    -parent .userFrame \
	    -nameFilter $yNameFilter \
	    -mode $mode \
	    -indexFileTemplate $indexFileTemplate \
	    -nameExclusion $yNameExcl
    }
    SetMainStatus "Ready."
}

proc LoadPlotCommand {args} {
    global xChoice yChoice dataFileList userCustomArguments dataFilename
    global userXlabel userYlabel userTitle userTopline printerName
    global separate sameScale layoutOption verticalMode horizontalMode graphicType deviceOption legends
    global saveFileDir xNameFilter yNameFilter splitPages
    global PlotDescriptionList loadFile selectedDescription pngFile

    set splitPages 0

    set loadFile [APSFileSelectDialog .[APSTmpString] -listDir $saveFileDir \
                    -contextHelp "File select box for quickSDDSplot saved plots."]
    if [string length $loadFile]==0 {
        return
    }
    if ![file exists $loadFile] {
        SetMainStatus "File $loadFile not found!"
        return
    }
    if ![APSCheckSDDSFile -fileName $loadFile] {
        SetMainStatus "File $loadFile is not an SDDS file."
        return
    }
    set parameterList [APSGetSDDSNames -fileName $loadFile -class parameter]
    set columnList [APSGetSDDSNames -fileName $loadFile -class column]
    foreach elem {xChoice yChoice PlotDescription quickSDDSplotCommands} {
        if [lsearch -exact $parameterList $elem ]==-1 {
            SetMainStatus "File $loadFile is not a valid file."
            return
        }
    }
    foreach elem {TclVariableName TclVariableValue} {
        if [lsearch -exact $columnList $elem ]==-1 {
            SetMainStatus "File $loadFile is not a valid file."
            return
        }
    }

    set saveFileDir [file dirname $loadFile]

    set PlotDescriptionList [APSGetSDDSParameter -fileName $loadFile -parameter PlotDescription]
    #    set list0 {}
    #    foreach elem $PlotDescriptionList {
    #        lappend list0 $elem
    #    }

    set widget [APSUniqueName .w] 
    APSScrolledListWindow $widget \
      -itemList $PlotDescriptionList -selectionVar selectedDescription \
      -callback LoadSelectedPlotCommand
}

proc LoadSelectedPlotCommand {itemList} {        
    global xChoice yChoice dataFileList userCustomArguments dataFilename
    global userXlabel userYlabel userTitle userTopline printerName splitPages
    global separate sameScale layoutOption verticalMode horizontalMode graphicType deviceOption legends
    global saveFileDir xNameFilter yNameFilter
    global PlotDescriptionList loadFile 

    set splitPages 0

    if [llength $itemList]!=1 {
        SetMainStatus "Select one plot command only."
        return
    }
    set selectedDescription [join $itemList]
    if [string length $selectedDescription]==0 {
        SetMainStatus "No plot command selected."
        return
    }
    set selectedDescriptionIndex 0
    foreach elem $PlotDescriptionList {
        if [string compare $selectedDescription $elem]==0 {
            break
        }
        incr selectedDescriptionIndex
    }
    SetMainStatus "Loading: [lindex $PlotDescriptionList $selectedDescriptionIndex]..."

    set page [expr $selectedDescriptionIndex+1]
    set xChoice [APSGetSDDSParameter -fileName $loadFile -parameter xChoice -page $page]
    set yChoice [split [join [APSGetSDDSParameter -fileName $loadFile -parameter yChoice -page $page]]]
    SetMainStatus "x: $xChoice"
    SetMainStatus "y: $yChoice"

    set variableList [APSGetSDDSColumn -fileName $loadFile -column TclVariableName -page $page]
    set valueList [APSGetSDDSColumn -fileName $loadFile -column TclVariableValue -page $page]
    set index 0
    foreach elem $variableList {
        if ![info exists $elem] {
            SetMainStatus "Bad load variable: $elem"
        } else {
            set $elem [lindex $valueList $index]
            incr index
        }
    }
}

proc SavePlotCommandEntryDialog {} {
    global saveFileName saveDescription saveCommandChoice saveFileDir

    set parent [APSUniqueName .]
    APSDialogBox $parent -name "Save command setup." 
    set w $parent.userFrame

    APSLabeledEntry .dirname -parent $w -label "Directory: " \
      -textVariable saveFileDir  -width 60 
    APSLabeledEntry .filename -parent $w -label "Filename: " \
      -textVariable saveFileName  -width 60 
    APSLabeledEntry .description -parent $w -label "Description: " \
      -textVariable saveDescription  -width 60 
    $parent.buttonRow.cancel.button configure -command "set saveCommandChoice 0"
    $parent.buttonRow.ok.button configure -command "set saveCommandChoice 1"
    APSEnableButton $parent.buttonRow.ok.button
    
    focus $parent
    grab $parent
    tkwait variable saveCommandChoice
    destroy $parent
    set saveFileDir [string trim $saveFileDir]
    set saveFileName [string trim $saveFileName]
    set saveDescription [string trim $saveDescription]
    return $saveCommandChoice
}

proc SavePlotCommand {} {
    global xChoice yChoice dataFileList userCustomArguments dataFilename
    global userXlabel userYlabel userTitle userTopline printerName splitPages
    global separate sameScale layoutOption verticalMode horizontalMode graphicType deviceOption legends
    global saveFileName saveFileDir saveDescription xNameFilter yNameFilter

    if ![info exists xChoice] {
        SetMainStatus "independent quantity not chosen"
        return
    }
    if {![llength $xChoice]} {
        SetMainStatus "independent quantity not chosen"
        return
    }
    if [llength $xChoice]!=1 {
        SetMainStatus "1 and only 1 independent quantity must be chosen."
        return
    }

    if ![info exists yChoice] {
        SetMainStatus "dependent quantities not chosen"
        return

    }
    if [llength $yChoice]==0 {
        SetMainStatus "dependent quantities not chosen"
        return
    }

    if [llength $dataFileList]==0 {
        SetMainStatus "no filename(s) chosen"
        return
    }

    if ![SavePlotCommandEntryDialog] {
        SetMainStatus "Save cancelled."
        return 
    }
    if [string length $saveFileName]==0 {
        SetMainStatus "No filename given for save."
        return 
    }
    if [string length $saveDescription]==0 {
        SetMainStatus "No description given for command."
        return
    }
    if [string length $saveFileDir]==0 {
        set saveFileDir "."
    }
    set filename $saveFileDir/$saveFileName

    set choice Overwrite
    if [file exists $filename] {
        if [catch {APSMultipleChoice [APSUniqueName .] \
                     -question "File exists. What do you want to do?" \
                     -labelList {Append Overwrite Cancel} \
                     -returnList  {Append Overwrite Cancel}} choice] {
            global errorInfo
            SetMainStatus "$errorInfo"
            return
        }
    }
    switch $choice {
        Overwrite {
            catch {file copy -force -- $filename $filename.bck}
            set sFID [open $filename w]
            set append 0
        }
        Append {
            set sFID [open $filename.tmp w]
            set append 1
        }
        Cancel {
            SetMainStatus "Save aborted."
            return
        }
        default {
            puts "Unknown return value: $choice"
            return
        }
    }
    foreach elem $yChoice {
        lappend yChoices "[lindex $elem 0]"
    }
    set sddsplotOptions [MakePlots -returnOptions 1]
    puts $sFID "SDDS1\n&parameter name=xChoice type=string &end"
    puts $sFID "&parameter name=yChoice type=string &end"
    puts $sFID "&parameter name=PlotDescription type=string &end"
    puts $sFID "&parameter name=sddsplotOptions type=string &end"
    puts $sFID "&parameter name=quickSDDSplotCommands type=long fixed_value=1 &end"
    puts $sFID "&column name=TclVariableName type=string &end"
    puts $sFID "&column name=TclVariableValue type=string &end"
    puts $sFID "&data mode=ascii no_row_counts=1 &end"
    puts $sFID [lindex [lindex $xChoice 0] 0]
    puts $sFID "$yChoices"
    puts $sFID "\\\"$saveDescription\\\""
    puts -nonewline $sFID "\""
    foreach elem $sddsplotOptions {
        puts -nonewline $sFID "'$elem' "
    }
    puts $sFID "\""
    foreach variable {userCustomArguments userXlabel userYlabel userTitle userTopline printerName xNameFilter yNameFilter \
                        separate splitPages sameScale layoutOption verticalMode horizontalMode graphicType deviceOption legends} {
        puts $sFID "$variable \"[subst \$$variable]\""
    }
    close $sFID
    if $append {
        exec sddscombine $filename $filename.tmp $filename.tmp1
        file rename -force -- $filename.tmp1 $filename
        file delete -force -- $filename.tmp
    }
    SetMainStatus "Command saved to file $filename"
}

proc TimeFilterControl {} {
    global hourStart dayStart monthStart yearStart tmpPrefix
    global hourEnd dayEnd monthEnd yearEnd 
    global inithourStart initdayStart initmonthStart inityearStart
    global inithourEnd initdayEnd initmonthEnd inityearEnd
    global time0 time1 timeFilterMode dataFileList

    if {[catch {APSConvertTimeToHours $hourStart} hour0] || \
          [catch {APSConvertTimeToHours $hourEnd} hour1]} {
        return -code error "Bad hour syntax in time filter"
    }
    if {[info exists inithourStart] && [string length $inithourStart]} {
        if {[catch {APSConvertTimeToHours $inithourStart} inithour0] || \
              [catch {APSConvertTimeToHours $inithourEnd} inithour1]} {
            return -code error "Bad hour syntax in initial time filter"
        }
    }
    if {[catch {exec timeconvert \
                  -breakDown=year=$yearStart,month=$monthStart,day=$dayStart,hour=$hour0} \
           time0] || \
          [catch {exec timeconvert \
                    -breakDown=year=$yearEnd,month=$monthEnd,day=$dayEnd,hour=$hour1} \
             time1]} {
        return -code error "Error in time syntax for time filter"
    }

    if {[info exists inithourStart] && [string length $inithourStart]} {
        if {[catch {exec timeconvert \
                      -breakDown=year=$inityearStart,month=$initmonthStart,day=$initdayStart,hour=0} \
               modeTime0] || \
              [catch {exec timeconvert \
                        -breakDown=year=$inityearEnd,month=$initmonthEnd,day=$initdayEnd,hour=24} \
                 modeTime1]} {
            return -code error "Error in time syntax for time filter"
        }
        if {[info exists inithourStart] && [string length $inithourStart]} {
            if {[catch {exec timeconvert \
                          -breakDown=year=$inityearStart,month=$initmonthStart,day=$initdayStart,hour=$inithour0} \
                   inittime0] || \
                  [catch {exec timeconvert \
                            -breakDown=year=$inityearEnd,month=$initmonthEnd,day=$initdayEnd,hour=$inithour1} \
                     inittime1]} {
                return -code error "Error in time syntax for initial time filter"
            }
            if {$time0 < $inittime0 || $time1 > $inittime1} {
                if ![string compare $timeFilterMode exact] {
                    set hourStart $inithourStart
                    set dayStart $initdayStart
                    set monthStart $initmonthStart
                    set yearStart $inityearStart
                    set hourEnd $inithourEnd
                    set dayEnd $initdayEnd
                    set monthEnd $initmonthEnd
                    set yearEnd $inityearEnd
                    update
                    return -code error "Error: Time filter range disagrees with the time range allowed for the transferred sdds files. Input has been reset to initial values."
                } elseif ![string compare $timeFilterMode day] {
                    if {$time0 < $modeTime0 || $time1 > $modeTime1} {
                        set hourStart $inithourStart
                        set dayStart $initdayStart
                        set monthStart $initmonthStart
                        set yearStart $inityearStart
                        set hourEnd $inithourEnd
                        set dayEnd $initdayEnd
                        set monthEnd $initmonthEnd
                        set yearEnd $inityearEnd
                        update
                        return -code error "Error: Time filter range disagrees with the time range allowed for the transferred sdds files. Input has been reset to initial values."
                    }
                } else {
                    return -code error "Error: invalid option for -timeFilterMode"
                }
            }
        }
    } else {
        set parameterFile $tmpPrefix/[APSTmpString]
        if [catch {eval exec sddscombine $dataFileList -pipe=out "-merge" \
                     | sddsprocess -pipe=in $parameterFile "-noWarnings" \
                     "-process=Time,minimum,firstTime" "-process=Time,maximum,lastTime"} result] {
            return -code error "Error: $result"
        } else {
            set statusFlag 0
            set fileStartTime [APSGetSDDSParameter -fileName $parameterFile -parameter firstTime]
            set fileEndTime [APSGetSDDSParameter -fileName $parameterFile -parameter lastTime]

            if {$time0 < $fileStartTime || $time0 > $fileEndTime} {
                set time0 $fileStartTime
                SetMainStatus "1Message!!!!Time filter range disagreed with the time range of the file. Input has been reset to the time range of the file." 
                set statusFlag 1 
            } 
            if {$time1 < $fileStartTime || $time1 > $fileEndTime} {
                set time1 $fileEndTime
                if !$statusFlag {
                    SetMainStatus "2Message!!!!Time filter range disagreed with the time range of the file. Input has been reset to the time range of the file."  
                }
            } 
            if [catch {exec timeconvert -seconds=$time0 -script=start} commands] {
                APSSetVarAndUpdate statusText "Error: $commands"
                return -code error "Error: $commands"
            }
            eval $commands
            set hourStart [format %.2d:%.2d:%.2d $startHours $startMinutes $startSeconds]
            set yearStart $startYear
            set monthStart $startMonth
            set dayStart $startDay
            
            if [catch {exec timeconvert -seconds=$time1 -script=end} commands] {
                APSSetVarAndUpdate statusText "Error: $commands"
                return -code error "Error: $commands"
            }
            eval $commands
            set hourEnd [format %.2d:%.2d:%.2d $endHours $endMinutes $endSeconds]
            set yearEnd $endYear
            set monthEnd $endMonth
            set dayEnd $endDay
            update
        }
    }
    if {$time0 >= $time1} {
        return -code error "Error: Start Time must be earlier than End Time. Please, correct this error."
    } else {
        return -code ok
    }
}

set alwaysOverwritePNGFile 0
proc MakePlots {args} {
    set returnOptions 0
    APSStrictParseArguments {returnOptions}
    
    global xChoice yChoice dataFileList userCustomArguments dataFileList 
    global userXlabel userYlabel userTitle userTopline printerName
    global separate sameScale layoutOption verticalMode horizontalMode graphicType deviceOption legends
    global doTimeFilter time0 time1 command repeatPlotMode xLimits yLimits splitPages
    global useTksddsplot histogram hist pngFile alwaysOverwritePNGFile
    setActionButtons 0

    if ![info exists xChoice] {
	SetMainStatus "independent quantity not chosen"
	return
    }
    if {![llength $xChoice]} {
	SetMainStatus "independent quantity not chosen"
	return
    }
    if {[llength $xChoice]!=1} {
	SetMainStatus "1 and only 1 independent quantity must be chosen."
	return
    }

    if {$histogram == 0} {
	if {![info exists yChoice]} {
	    SetMainStatus "dependent quantities not chosen"
	    return   
	}
	if {![llength $yChoice]} {
	    SetMainStatus "dependent quantities not chosen"
	    return
	}
	set yc $yChoice
    } else {
	set yc frequency
    }

    if {![llength $dataFileList]} {
	SetMainStatus "no filename(s) chosen"
	return
    }

    set yChoices ""
    set first 1
    foreach elem $yc {
        if {$first} {
            set yChoices [lindex $elem 0]
            set first 0
        } else {
            set yChoices "$yChoices,[lindex $elem 0]"
        }
    }
    if {$first} {
        SetMainStatus "dependent quantities not chosen"
        return
    }
    global coffset separate

    if {$coffset && $separate} {
        set requestOption ""
        foreach elem $yc {
            append requestOption "-column=[lindex [lindex $xChoice 0] 0],([lindex $elem 0]) "
        }
    } else {
        set requestOption "-column=[lindex [lindex $xChoice 0] 0],($yChoices)"
    }
    set extraOptions {}
    global useGraphicTypeModifier
    if {$useGraphicTypeModifier} {
        set graphicTypeModifier ",fixForName"
    } else {
        set graphicTypeModifier ""
    }
    if $separate {
        if $splitPages {
            lappend extraOptions -split=page -separate=page -groupby=namestring,page
            set graphicTypeModifier ""
        } else {
            lappend extraOptions -separate=namestring -groupby=namestring
            set graphicTypeModifier ""
        }
    } elseif $splitPages {
        lappend extraOptions -split=page
    }
    if $sameScale {
        lappend extraOptions -samescale=y
    }
    if $legends {
        if $separate {
            lappend extraOptions -legend=filename
        } else {
            lappend extraOptions -legend
        }
    }
    if $coffset {
        lappend extraOptions -mode=y=coffset
    }
    if [string length $userXlabel] {
        lappend extraOptions "-xlabel=[APSMakeSafeQualifierString $userXlabel]"
    }
    if [string length $userYlabel] {
        lappend extraOptions "-ylabel=[APSMakeSafeQualifierString $userYlabel]"
    }
    if [string length $userTitle] {
        lappend extraOptions "-title=[APSMakeSafeQualifierString $userTitle]"
    }
    if [string length $userTopline] {
        lappend extraOptions "-topline=[APSMakeSafeQualifierString $userTopline]"
    }
    foreach elem [split $userCustomArguments] {
        if [string length $elem] {
            lappend extraOptions $elem
        }
    }
    if [string compare $horizontalMode time]==0 {
        lappend modeOptions -mode=y=$verticalMode,x=linear -ticks=xtime
    } else {
        lappend modeOptions -mode=y=$verticalMode,x=$horizontalMode
    }

    if {($xLimits(min) != 0) || ($xLimits(max) != 0) ||
        ($yLimits(min) != 0) || ($yLimits(max) != 0)} {
        lappend extraOptions -scale=$xLimits(min),$xLimits(max),$yLimits(min),$yLimits(max)
    }
    if $doTimeFilter {
        if [catch {TimeFilterControl} result] {
            APSAlertBox [APSUniqueName .] -errorMessage $result
            return
        }
	if $repeatPlotMode {
            set time1 1e300
        }
        if {!$histogram} {
            lappend extraOptions -filter=column,Time,$time0,$time1
        }
    }

    if $returnOptions {
        return [concat $requestOption \
                  $graphicType$graphicTypeModifier $layoutOption \
                  $modeOptions $extraOptions]
    }


    SetMainStatus "Working on plot of [llength $yc] columns from [llength $dataFileList] files..."
    if {$repeatPlotMode && [string match $deviceOption "-device=motif"]} {
        lappend extraOptions "-device=motif,(-movie true -keep 1)"
        lappend extraOptions -repeat	
    } else {
        lappend extraOptions $deviceOption
        if [string match "-device=png*" $deviceOption] {
            if ![string length $pngFile] {
                SetMainStatus "The PNG filename is not provided!"
                return
            }
            if {[file exists $pngFile] && !$alwaysOverwritePNGFile} {
                set answer [APSMultipleChoice [APSUniqueName .] -question \
                              "$pngFile already exists, What do you want to do?" \
                              -returnList {Overwrite Abort "Always_Overwrite"} \
                              -labelList {Overwrite Abort "Always Overwrite"} ] 
                switch $answer {
                    Abort {
                        SetMainStatus "plot to existing png file - $pngFile is cancelled!"
                        return
                    }
                    Always_Overwrite {
                        set alwaysOverwritePNGFile 1
                    }
                }
            }
            lappend extraOptions -output=$pngFile
        }
    }
    set sddsplotCmd sddsplot
    if $useTksddsplot {
        set sddsplotCmd tksddsplot
    }
    if {$histogram} {
	global tmpPrefix
	set tmpFile $tmpPrefix/[APSTmpString]
	APSAddToTempFileList $tmpFile
	set histOptions ""
	if {[llength $hist(sizeOfBins)]} {
	    append histOptions "-sizeOfBins=$hist(sizeOfBins) "
	} else {
	    append histOptions "-bins=$hist(bins) "
	}
	if {[llength $hist(lowerLimit)]} {
	    append histOptions "-lowerLimit=$hist(lowerLimit) "
	}
	if {[llength $hist(upperLimit)]} {
	    append histOptions "-upperLimit=$hist(upperLimit) "
        }
        if $doTimeFilter {
            if {[catch {eval exec sddscombine $dataFileList -pipe=out -merge | sddsprocess -pipe -filter=column,Time,$time0,$time1 | sddshist -pipe=in $tmpFile -dataColumn=[lindex [lindex $xChoice 0] 0] $histOptions} results]} {
                SetMainStatus "error: $results"
                return
            }
        } else {
            if {[catch {eval exec sddscombine $dataFileList -pipe=out -merge | sddshist -pipe=in $tmpFile -dataColumn=[lindex [lindex $xChoice 0] 0] $histOptions} results]} {
                SetMainStatus "error: $results"
                return
            }
        }
	set dfl $tmpFile
    } else {
	set dfl $dataFileList
    }

    if {$coffset && $separate} {
        if {[string match $deviceOption "-device=motif"] || [string match"-device=png*"  $deviceOption]} {
            set command [concat $sddsplotCmd $dfl \
                             $graphicType$graphicTypeModifier $layoutOption \
                             $modeOptions $extraOptions $requestOption]
        } else {
            if [string length $printerName] {
                set command [concat $sddsplotCmd $dfl \
                                 $graphicType$graphicTypeModifier $layoutOption \
                                 $modeOptions $extraOptions $requestOption | lpr -P$printerName]
            } else {
                set command [concat $sddsplotCmd $dfl \
                                 $graphicType$graphicTypeModifier $layoutOption \
                                 $modeOptions $extraOptions $requestOption | lpr]
            }
        }
    } else {
        if {[string match $deviceOption "-device=motif"] || [string match "-device=png*" $deviceOption]} {
            set command [concat $sddsplotCmd $requestOption $dfl \
                             $graphicType$graphicTypeModifier $layoutOption \
                             $modeOptions $extraOptions]
        } else {
            if [string length $printerName] {
                set command [concat $sddsplotCmd $requestOption $dfl \
                                 $graphicType$graphicTypeModifier $layoutOption \
                                 $modeOptions $extraOptions | lpr -P$printerName]
            } else {
                set command [concat $sddsplotCmd $requestOption $dfl \
                                 $graphicType$graphicTypeModifier $layoutOption \
                                 $modeOptions $extraOptions | lpr]
            }
        }
    }
    APSExecLog .execLog -name "Plot" -unixCommand "$command" -callback "setActionButtons 1" \
      -contextHelp "Displays the sddsplot command used in producing the last \
        plot. Useful in obtaining error messages."

    # next command is used to hide .execLog window display
    wm withdraw .execLog

    set oldCancelCommand [.execLog.buttonRow.cancel.button cget -command]
    set newCancelCommand "$oldCancelCommand; SetMainStatus {Plot execution is canceled.}"
    .execLog.buttonRow.cancel.button configure -command $newCancelCommand
    set oldAbortCommand [.execLog.buttonRow.abort.button cget -command]
    set newAbortCommand "$oldAbortCommand; SetMainStatus {Plot execution is aborted.}"
    .execLog.buttonRow.abort.button configure -command $newAbortCommand
    SetMainStatus "Plot launched [clock format [clock seconds]]"
    setActionButtons 1
}

proc setActionButtons {state} {
    if $state {
        APSEnableButton .userFrame.plotops.frame.showComm.button
    } else {
        APSDisableButton .userFrame.plotops.frame.showComm.button
    }
}

proc LaunchsddsExportData {} {
    global originalDir
    global dataFileList dataDirectory message OldMonDataFileList
    global hourStart dayStart monthStart yearStart
    global hourEnd dayEnd monthEnd yearEnd 
    if ![info exists message] {
	    set message ""
    }

    if ![llength dataFileList] {
        SetMainStatus "No data selected or found."
        return
    }
    set oldDir [pwd]
    cd $originalDir
    exec sddsExportData -dataDirectory $dataDirectory -timeFilterMode "day" \
      -timeFilterStart "$yearStart $monthStart $dayStart $hourStart" \
      -timeFilterEnd "$yearEnd $monthEnd $dayEnd $hourEnd" \
      -dataFileList $dataFileList -message $message &
    cd $oldDir
    if [catch {LogAction -action sddsExportData} result] {
        SetMainStatus "$result"
    }
    SetMainStatus "sddsExportData launched with [llength $dataFileList] data files."
}

proc LogAction {args} {
    global groupMessage
    global hourStart dayStart monthStart yearStart
    global hourEnd dayEnd monthEnd yearEnd 
    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 $hourStart} hour] {
        SetMainStatus "Invalid starting hour: $hourStart"
        return
    }
    if [catch {exec timeconvert -breakdown=year=$yearStart,day=$dayStart,month=$monthStart,hour=$hour} \
          startTime] {
        SetMonDataStatus "$startTime"
        return
    }

    if [catch {APSConvertTimeToHours $hourEnd} hour] {
        SetMainStatus "Invalid ending hour: $hourEnd"
        return
    }
    if [catch {exec timeconvert -breakdown=year=$yearEnd,day=$dayEnd,month=$monthEnd,hour=$hour} \
          endTime] {
        SetMainStatus "$endTime"
        return
    }

    if [catch {exec logMessage -sourceId=quickSDDSplot \
                 -tag=User $apsScriptUser \
                 -tag=Host $apsScriptHost \
                 -tag=Action $action \
                 -tag=Group $groupMessage \
                 -tag=dataStartTime $startTime \
                 -tag=dataEndTime $endTime \
                 -tag=Script $apsScriptCommand} result] {
        return -code error $result
    }
}

proc ToggleHistogramMode {args} {
    global histogram hist graphicType legends
    if {$histogram} {
	set state normal
	set graphicType "-graph=bar,vary,thickness=2"
	set legends 0
    } else {
	set state disable
	set graphicType "-graph=line,vary"
	set legends 1
    }
    foreach w $hist(widgets) {
	$w configure -state $state
    }
    if {$histogram} {
	set state disable
    } else {
	set state normal
    }
    foreach w $hist(widgets2) {
	$w configure -state $state
    }
}

if [llength $argv] {
    set pickFileMode 0
    set quickSDDSplotOverview {This is a utility for making simple plots of SDDS data files.  It will list the available columns for you and let you specify basic command options.  This invocation has been made by another program, so the data files are preselected.  Use the SCAN FILE(s) button to get lists of choices of things to plot.  You may enter name filters prior to scanning to reduce the number of choices.}
} else {
    set pickFileMode 1
    set quickSDDSplotOverview {This is a utility for making simple plots of SDDS data files.  It will list the available columns for you and let you specify basic command options.  To start, enter a filename and SCAN it, or use the PICK FILE... button.}
}
APSApplication . -name quickSDDSplot -version $CVSRevisionAuthor \
  -overview "$quickSDDSplotOverview"

set dataFileList {}
set xNameFilter "*"
set yNameFilter "*"
set xNameExcl ""
set yNameExcl ""
set userCustomArguments ""
set pickFileDir ""
set PresortedChoicesFile ""
set message1 ""
set message2 ""
set doTimeFilter 0
set timeFilterMode 0
set originalDir [pwd]
set saveFileDir $originalDir
set dataDirectory ""
set indexFileTemplate ""
set dataFileList {}
set autoTimeMode 0
set timeFilterStart ""
set timeFilterEnd ""
set groupMessage ""
set xChoice ""
set yChoice ""
set useGraphicTypeModifier 1
set plotNow 0
set horizontalMode linear
set showControlNames 0
set histogram 0
set hist(bins) 20
set hist(sizeOfBins) ""
set hist(lowerLimit) ""
set hist(upperLimit) ""
if [llength $argv] {
    set args $argv
    set message ""
    APSStrictParseArguments {dataDirectory dataFileList autoTimeMode message timeFilterMode timeFilterStart timeFilterEnd indexFileTemplate groupMessage userCustomArguments xNameFilter yNameFilter xChoice yChoice useGraphicTypeModifier plotNow horizontalMode showControlNames}
    
    if [llength $dataFileList]==0 {
        APSAlertBox [APSUniqueName .] -errorMessage "Fatal error: no filenames passed to quickSDDSplot by parent." 
        exit
    }
    if {[string length $dataDirectory] && [catch {cd $dataDirectory} result]} {
        APSAlertBox [APSUniqueName .] -errorMessage "Fatal error: bad data directory passed to quickSDDSplot by parent.  $result"
        exit
    }
    if [string length $message] {
        set message1 $message
    }
    set message2 "[llength $dataFileList] data files passed by parent."
    if {[llength $timeFilterStart]==4 && [llength $timeFilterEnd]==4} {
        set doTimeFilter 1
        set index 0
        foreach elem {year month day hour} {
            set ${elem}Start [lindex $timeFilterStart $index]
            set init${elem}Start [lindex $timeFilterStart $index]
            set ${elem}End [lindex $timeFilterEnd $index]
            set init${elem}End [lindex $timeFilterEnd $index]
            incr index
        }
    } else {
        foreach elem {year month day hour} {
            set ${elem}Start ""
            set init${elem}Start ""
            set ${elem}End ""
            set init${elem}End ""
        }
    }
} else {
    set message1 Ready.
}

set mainStatus "$message1"
APSScrolledStatus .status -parent .userFrame \
    -textVariable mainStatus -width 80 \
    -packOption "-fill x"
if [string length $message2] { 
    set mainStatus "$message2"
}
#puts [.userFrame cget -background]
ttk::frame .userFrame.pair1
pack .userFrame.pair1  -side top 
MakeFilterFrame .filters -parent .userFrame.pair1 -packOption "-side left -fill x -padx 4"
MakeExclusionFrame .exclude -parent .userFrame.pair1 -packOption "-side left -fill x -padx 4"
MakeLimitsFrame .limits -parent .userFrame.pair1 -packOption "-side left -fill x -padx 4"
MakePrinterFrame .printer -parent .userFrame -packOption "-side top"

MakeCustomArgFrame .userArgs -parent .userFrame
MakeLabelFrame .labels -parent .userFrame
MakeOptionsWidget .options -parent .userFrame
MakeTimeFilterWidget .tfilter -parent .userFrame

APSFrame .fileops -parent .userFrame -packOption "-fill x -side top"

if $pickFileMode {
    APSLabeledEntry .file -parent .userFrame.fileops.frame -textVariable dataFilename -width 100 -label File: \
      -contextHelp "Holds the name of the file from which data will be taken.  You may enter the filename by typing or using the PICK FILE... button below.  If you have entered filename by typing and you want to add this filename to already existing file list press ADD FILE... button.  If you want to work just with that file, press RETURN-key on your keyboard."
    bind .userFrame.fileops.frame.file.entry <Return> {set dataFileList [list $dataFilename]}
    
    APSButton .pick -parent .userFrame.fileops.frame -text "PICK FILE..." -command "PickFilename -addFile 0" \
      -contextHelp "Brings up a file selection dialog to pick what file to plot." -width ""
    APSButton .add -parent .userFrame.fileops.frame -text "ADD FILE..." -command "PickFilename -addFile 1" \
      -contextHelp "Brings up a file selection dialog to add another file to plot." -width ""
    APSButton .scan -parent .userFrame.fileops.frame -text "SCAN FILE" -command "ScanFile all" \
      -contextHelp "Scans the file to make lists of plottable quantities.  Not necessary if the file is seleced with PICK FILE...  If you change the name filters below, press this button to bring up new name selection widgets." -width ""
    if {[file exists /home/helios/oagData/dataLoggerConfig/timeSeries.sdds]} {
        APSCheckButtonFrame .cbf1 -parent .userFrame.fileops.frame \
            -label "" \
            -buttonList {"Display Related Control Names"} \
            -variableList {showControlNames} \
            -packOption "-side left"
    }
} else {
    APSButton .scan -parent .userFrame.fileops.frame -text "SCAN FILE(s)" -command "ScanFile all" \
      -contextHelp "Scans the file(s) to make lists of plottable quantities.  If you change the name filters below, press this button to bring up new name selection widgets." -width ""
    APSButton .fscan -parent .userFrame.fileops.frame -text "FAST SCAN" -command "ScanFile fast" \
      -contextHelp "Like SCAN FILE(s), but only scans the first and last file.  Much faster for larger numbers of files, but may miss data names in some files." -width ""
    if {[file exists /home/helios/oagData/dataLoggerConfig/timeSeries.sdds]} {
        APSCheckButtonFrame .cbf1 -parent .userFrame.fileops.frame \
            -label "" \
            -buttonList {"Display Related Control Names"} \
            -variableList {showControlNames} \
            -packOption "-side left"
    }
}


APSFrame .plotops -parent .userFrame -packOption "-fill x -side top"

APSButton .plot -parent .userFrame.plotops.frame -text "PLOT" -command MakePlots \
  -contextHelp "Makes the plots you have asked for."  -width ""
APSCheckButtonFrame .tksddsplot -parent .userFrame.plotops.frame -label "" \
  -orientation horizontal -buttonList {"Use tksddsplot (beta)"} \
  -variableList useTksddsplot -packOption "-side left"
APSButton .saveplot -parent .userFrame.plotops.frame -text "SAVE COMMAND..." \
  -command SavePlotCommand \
  -contextHelp "Saves the present plot command into a file for reuse later."  -width ""
APSButton .useplot -parent .userFrame.plotops.frame -text "LOAD COMMAND..." \
  -command LoadPlotCommand \
  -contextHelp "Allows use of saved plot commands on the present data." -width ""
APSButton .showComm -parent .userFrame.plotops.frame -text "SHOW COMMAND..." \
  -command "wm deiconify .execLog; setActionButtons 0" -width ""
APSButton .sddsexport -parent .userFrame.plotops.frame -text "EXPORT..." \
  -command LaunchsddsExportData  -width "" \
  -contextHelp "Launches sddsExportData with the selected data as input, allowing you to make spreadsheet or text data."
setActionButtons 0
set useTksddsplot 0
set pngFile ""
ToggleHistogramMode
if {$plotNow} {
    .userFrame.plotops.frame.plot.button invoke
}
