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

# $Log: not supported by cvs2svn $
# Revision 1.155  2009/07/22 18:35:00  soliday
# Updated to gray out the data loggers that have been migrated to the
# new one-pv-per-file logger. The status message explains that these have been
# moved and that the old data can still be plotted from this application.
#
# Revision 1.154  2009/07/21 17:56:50  soliday
# Updated to fix 'global' commands that tried to globalize an array element
# instead of the array. This was causing error messages with the new Tcl/Tk version.
#
# Revision 1.153  2006/08/23 15:23:42  jiaox
# Added the feature that preprocesses the data input files to save only used columns to temporary files. This could speed up the "improved zoom" feature of sddsplot.
#
# Revision 1.152  2006/03/06 21:27:37  soliday
# Forced it so that if the SR BPMs tab is found it puts it at the end of
# the list instead of the front of the list.
#
# Revision 1.151  2005/11/18 21:03:45  soliday
# Updated so that the preset plot screen can be resized.
#
# Revision 1.150  2005/08/23 20:18:53  soliday
# Added APSRenameExecToAPSBGExec.
#
# Revision 1.149  2005/02/09 16:49:56  soliday
# Fixed problem with whitespace at the end of a glitch logger file when
# only one file was found.
#
# Revision 1.148  2005/02/03 23:02:24  soliday
# Expanded the tab frame because the last row was not visable.
#
# Revision 1.147  2005/01/13 22:08:46  soliday
# Fixed issue with the PrepareVirtualLoggersFiles procedure when an input file
# has more than one page.
#
# Revision 1.146  2005/01/12 21:50:08  soliday
# Prior to using quickSDDSplot or sddsExportData the virtual data logger files
# are combined, interpreted, and xrefed into one file using the
# PrepareVirtualLoggerFiles procedure. This procedure also strips the files
# of unwanted columns based on the virtual data logger .mon file.
#
# Revision 1.145  2005/01/12 17:12:09  soliday
# Added the ability to work with virtual data loggers. Where a virtual data logger
# is a subset of real data loggers.
#
# Revision 1.144  2004/12/22 16:32:01  soliday
# Fixed issue with SR rf Fast.
#
# Revision 1.143  2004/12/01 19:29:26  soliday
# Changed the ordering of the tabs. They are now reverse alphanumeric order.
# Prior to this they were setup based on where they appeared in the
# timeSeries.config file.
#
# Revision 1.142  2004/11/23 19:21:58  shang
# replaced set MonDataDirRoot $OAGGlobal(OAGDataDirectory)/monitoring by
# set MonDataDirRoot $OAGGlobal(OAGDataDirectory)
#
# Revision 1.141  2004/11/23 19:11:56  shang
# modified Michael's change on eliminating some APS-specific items
#
# Revision 1.140  2004/11/16 20:19:37  soliday
# Added the ability to plot preset contour plots. It looks for the IsContour
# column in the preset plot file.
#
# Revision 1.139  2004/07/23 16:16:27  shang
# removed the hard-coded loggers, and read them from configuration files instead.
# separated the Main logger interface into SR, Booster, Par, Linac and Misc tab
# frames; added autoscale option for glitch logger plots.
#
# Revision 1.138  2004/06/07 19:33:06  soliday
# Added the Liquid Nitrogen Distribution System data logger.
#
# Revision 1.137  2004/03/12 16:44:48  soliday
# Added SR Source Parameters datalogger.
#
# Revision 1.136  2003/11/18 17:37:03  soliday
# Added the tksddsplot option to the preset plots.
#
# Revision 1.135  2003/11/03 16:26:44  soliday
# It now launches quickSDDSplot with the option to display the related controlnames.
#
# Revision 1.134  2003/10/09 20:27:00  soliday
# Fixed problem with separate option when plotting multiple days.
#
# Revision 1.133  2003/10/09 16:06:08  soliday
# Added the separate button on the preset plot dialog.
#
# Revision 1.132  2003/09/18 18:08:10  soliday
# Fixed typo.
#
# Revision 1.131  2003/09/18 18:06:23  soliday
# Added linacWater
#
# Revision 1.130  2003/09/03 17:06:50  soliday
# Moved dp_atexit command below APSApplication.
#
# Revision 1.129  2003/07/17 20:28:51  soliday
# Added the PSS_DIW glitch logger.
#
# Revision 1.128  2003/07/17 14:24:42  soliday
# Added the CA Diagnostics data logger.
#
# Revision 1.127  2003/06/10 18:05:34  soliday
# Added sol computer to OPI data group.
#
# Revision 1.126  2003/06/08 16:59:43  borland
# Added ravel, debussy, and chopin to OPIs for review.
#
# Revision 1.125  2003/03/03 20:19:13  soliday
# Added srBPLD data logger.
#
# Revision 1.124  2003/02/27 17:14:11  soliday
# Fixed problem with plotting SRrfFast with non-integer hours
#
# Revision 1.123  2003/01/31 16:12:22  soliday
# Modifed the name of the Frontend & PSS category
#
# Revision 1.122  2003/01/15 23:03:45  soliday
# Removed Frontend & Beamline Water and Shutters because the Frontend & Beamline
# category replaces these.
#
# Revision 1.121  2003/01/15 21:07:43  soliday
# Added the Frontend & Beamlines
#
# Revision 1.120  2002/10/24 19:31:06  soliday
# Added the LTP BESOCM glitch logger.
#
# Revision 1.119  2002/10/16 19:06:07  soliday
# Changed the wording on my last change
#
# Revision 1.118  2002/10/16 15:04:45  soliday
# Added the Frontend Beamline Water category.
#
# Revision 1.117  2002/08/27 20:26:05  soliday
# Removed status updated that took too much time with large numbers of files.
#
# Revision 1.116  2002/07/29 19:03:49  soliday
# Added the Controllaw Glitch mode.
#
# Revision 1.115  2002/06/18 01:38:14  borland
# Made rf glitch logger labels more clear.
#
# Revision 1.114  2002/04/09 20:04:48  shang
# modified MonDataFindFiles for SRrfFast
#
# Revision 1.113  2002/04/08 20:07:08  shang
# fixed the mismatching problem between the end dates in glicth mode
#
# Revision 1.112  2002/03/27 23:03:35  shang
# corrected the time filter feature
#
# Revision 1.111  2002/03/26 17:56:26  borland
# Disabled start-time checks for all loggers except SRrfFast.
#
# Revision 1.110  2002/03/26 16:57:31  shang
# added time filters (that is, only the files whose StartTime falls in the
# range between start hour and end hour will be choosed) and removed redundant
# work.
#
# Revision 1.109  2002/03/08 15:20:37  borland
# Added run control group.
#
# Revision 1.108  2002/03/01 19:40:16  soliday
# Added the Linac Test Stand.
#
# Revision 1.107  2001/11/28 17:31:53  borland
# Improved function of filtering and view options for glitch logs.
#
# Revision 1.106  2001/11/27 18:10:29  borland
# Added rfgun glitch logger.
#
# Revision 1.105  2001/10/22 14:42:10  borland
# Added Top-Up events to glitch review.
#
# Revision 1.104  2001/06/26 18:56:43  soliday
# Added SearchDataLoggers button.
#
# Revision 1.103  2001/03/19 15:26:59  borland
# Added linac top-up loggers to the normal logger list.
#
# Revision 1.102  2001/02/07 15:29:38  borland
# Added 100Hz SR DCPS loggers to standard data review group.
#
# Revision 1.101  2000/11/28 14:26:30  borland
# Added RadMonitors to gtlich group.
#
# Revision 1.100  2000/11/27 19:55:42  borland
# Added RadMonitors group.
#
# Revision 1.99  2000/06/17 19:59:54  borland
# Added brahms to list of OPI groups.
#
# Revision 1.98  2000/05/03 15:50:12  borland
# Added linacDiag group to data review groups.
#
# Revision 1.97  2000/01/14 15:49:45  borland
# Per D. Blachowicz: no longer puts multiple time filters on preset plots.
#
# Revision 1.96  1999/11/14 03:15:41  borland
# Added line to ensure removal of temporary file used in glitch mode.
#
# Revision 1.95  1999/07/28 22:44:10  borland
# Added repeat-plot feature.
#
# Revision 1.94  1999/06/22 16:22:17  borland
# Added button to display trigger events for glitch mode.
#
# Revision 1.93  1999/06/10 01:38:36  borland
# Now looks for and uses FixedTimeScale column from preset plots files.
# If present, value must be nonzero to get time scale exactly equal to
# user's input.
#
# Revision 1.92  1999/05/24 19:49:21  borland
# Changed labelsize option values to conform to new version of sddsplot.
#
# Revision 1.91  1999/03/09 22:34:14  borland
# Added Mobile MV200 Vid3.
#
# Revision 1.90  1999/02/23 14:45:43  borland
# Added checks for the existence of preset plot button widgets prior to
# enabling and disabling them.
#
# Revision 1.89  1999/02/03 18:44:39  borland
# Added linacRF to the glitch log group.  For glitch log preset plots,
# don't include the time limit argument to sddsplot.
#
# Revision 1.88  1998/11/17 22:31:56  borland
# Added SRThermocouples to main group.
#
# Revision 1.87  1998/10/12 14:49:37  borland
# Preset plots now have filter options and a way to view the plot command
# and error printouts.  Changes by D. Blachowicz.
#
# Revision 1.85  1998/09/28 21:38:47  borland
# Now allows preset-plot type files to be used as custom plot files, provided
# a parameter called PresetPlotFile is present and has value 1. (R. Soliday)
#
# Revision 1.84  1998/09/02 22:50:21  borland
# Added MobileMV200 to the main group.
#
# Revision 1.83  1998/07/23 22:27:45  borland
# Added powerSystem group.
#
# Revision 1.82  1998/07/20 21:24:28  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.81  1998/06/27 14:29:49  borland
# Now have different limits on the number of data selection radio buttons per
# row for different groups.
#
# Revision 1.80  1998/06/24 20:44:10  borland
# Changed rootname for SRDCPS-HVD and SRDCPS-QS to SRDCPS-HVDE and SRDCPS-QSE,
# respectively.
#
# Revision 1.79  1998/06/17 20:06:38  borland
# Now uses IsTimePlot column from preset plot files to determine whether it
# should set the scales to the time range chosen by the user, or allow
# autoscaling on horizontal.
#
# Revision 1.78  1998/06/16 21:59:53  borland
# Added SRDCPS-HVD-Extensive and SRDCPS-QS-Extensive logs to main group.
#
# Revision 1.77  1998/03/18 21:39:34  borland
# Removed SRDCPS (old) from default group.
#
# Revision 1.76  1998/03/16 23:59:40  borland
# Added SRDCPS HVD and QS groups.
#
# Revision 1.75  1998/01/16 18:05:11  borland
# Changed name of Process Water logger entry to "Process Water/Air Temps".
#
# Revision 1.74  1997/11/17 16:47:41  borland
# Added SRChamberTemp to main group.
#
# Revision 1.73  1997/11/15 00:56:49  borland
# For glitch analysis/plots, now passes a string showing which timestamped
# glitches are being analyzed.
#
# Revision 1.72  1997/11/06 14:48:13  borland
# Passes -indexFileTemplate option to quickSDDSplot to make use of column
# indices generated for some loggers.
#
# Revision 1.71  1997/11/05 15:21:32  borland
# Removed SRH2OPSMag and SRFastH2OPSMag.  Added SRPSMagH2O.
#
# Revision 1.70  1997/10/20 21:57:53  borland
# Moved location of preset plot files for glitch logs.
#
# Revision 1.69  1997/10/17 01:22:24  emery
# Added data group SRH20PSMag
#
# Revision 1.68  1997/10/16 12:58:22  emery
# Added data group SRFastH20PSMag
#
# Revision 1.67  1997/09/30 17:59:52  borland
# Modified the presentation of the list of trigger causes for Glitch mode
# to accomodate different types of names for alarm triggers.
#
# Revision 1.66  1997/09/18 16:32:36  borland
# Added Booster pulsed power supplies to main group.
#
# Revision 1.65  1997/09/09 15:52:57  borland
# Added SR dipole glitches to glitch mode selections.
#
# Revision 1.64  1997/08/18 23:20:56  borland
# Added linac switch gear to main group.
#
# Revision 1.63  1997/07/16 14:22:51  borland
# Added RTFB systems to main group.  Now uses limitPerRow feature of
# APSRadioButtonFrame rather than doing same by hand.
#
# Revision 1.62  1997/05/02 20:12:35  borland
# Added hydrostatic leveling system to main group.
#
# Revision 1.61  1997/05/01 18:51:15  borland
# Added BTSPS to main group.
#
# Revision 1.60  1997/04/30 19:27:07  borland
# Added SRSynchLightMon data to main group.
#
# Revision 1.59  1997/04/28 18:27:13  borland
# Added a "Working..." status message for glitch data analysis.
#
# Revision 1.58  1997/04/22 13:28:29  borland
# Added boosterRampGlitch to Glitch group.
#
# Revision 1.57  1997/04/15 20:31:06  borland
# Added SR switch gear to default group.
#
# Revision 1.56  1997/04/12 19:23:55  borland
# Added default time filter on 1,1e10 to avoid bad plots from data with
# invalid time values.
#
# Revision 1.55  1997/04/09 15:30:40  borland
# Added BInjection to default group.
#
# Revision 1.54  1997/04/09 00:14:04  borland
# Glitch analysis scripts now use multipage data.
#
# Revision 1.53  1997/04/02 16:38:46  borland
# Added SRInjection to standard group.
#
# Revision 1.52  1997/04/02 02:23:12  borland
# Added EXPORT button to launch sddsExportData.
#
# Revision 1.51  1997/03/10 19:42:15  borland
# Now only makes a one-wide frame grid in non-glitch mode.
#
# Revision 1.50  1997/03/07 21:50:32  borland
# Same as last time.
#
# Revision 1.49  1997/03/07 21:48:30  borland
# Fixed bug in IsProc arm for glitch analysis scripts
#
# Revision 1.48  1997/03/07 21:42:41  borland
# Now passes time filter info to quickSDDSplot.
#
# Revision 1.47  1997/02/28 01:44:04  borland
# Added SROrbit to glitch group.
#
# Revision 1.46  1997/02/27 22:55:36  borland
# Now puts workstation name on plot for OPI group.
#
# Revision 1.45  1997/02/11 19:50:18  borland
# Removed a debugging statement.
#
# Revision 1.44  1997/02/11 19:48:52  borland
# Added ability to filter glitch data on glitch/trigger cause, if such
# data is available.
#
# Revision 1.43  1997/01/14 16:56:22  borland
# Added rfgun entry to main group.
#
# Revision 1.42  1996/12/17 20:44:14  borland
# Now properly handles multiple files in glitch mode.
#
# Revision 1.41  1996/12/16 15:01:23  borland
# Added extra options entry for preset plots.
#
# Revision 1.40  1996/12/11 21:54:15  borland
# Changed labels for date entry in glitch mode.
#
# Revision 1.39  1996/12/11 21:23:01  borland
# Added -glitchMode option and capability to plot glitch data.
#
# Revision 1.38  1996/12/07 03:13:28  borland
# Added SRPulsed group.
#
# Revision 1.37  1996/10/17 17:46:11  borland
# Added logging of plotting using logMessage.
#
# Revision 1.36  1996/10/08 17:22:40  borland
# Added SRFastLog1 group.
#
# Revision 1.35  1996/09/30 18:08:44  borland
# Added ability to take H:M:S format for times.  Also added y offset mode
# check button.
#
# Revision 1.34  1996/09/21 23:44:08  borland
# Added srBPMAve and BM groups.
#
# Revision 1.33  1996/09/19 21:50:54  borland
# Changed from using "exec wish" to "exec oagwish".
#
# Revision 1.32  1996/09/11 16:29:18  borland
# Added item for SR DCPS review.
#
# Revision 1.31  1996/08/09 22:42:35  borland
# Added code to force re-search for data files after 10 minutes have elapsed.
#
# Revision 1.30  1996/07/19 22:30:39  borland
# Added more entries for OPI group.  Changed limit for
# switch to two-column group listing from 15 to 10 items.
#
# Revision 1.29  1996/07/18 15:53:40  borland
# Removed debugging statements.
#
# Revision 1.28  1996/07/18 15:51:20  borland
# Resolved problems with merged versions from oxygen and helios.
#
# Revision 1.27  1996/07/18 15:36:16  borland
# Added -group commandline option, which allows specifying
# different sets of data logs to access.  Current selections
# are Main and OPI.  Main is the default, while OPI gives
# stats for MCR OPIs.
#
# Revision 1.26  1996/07/06  17:02:35  borland
# Changed location referenced for preset plots to
# /home/helios/oagData/monitoring/MonitorDataReviewFiles.
#
# Revision 1.25  1996/07/05  22:04:51  borland
# Added PLET DCPS selection.
#
# Revision 1.24  1996/06/28  23:09:41  borland
# Added srBPMs selection.
#
# Revision 1.23  1996/06/28  13:30:40  borland
# Added key bindings for date entry boxes to force refinding of files when
# date entries are changed by hand.
#
# Revision 1.22  1996/06/27  19:06:24  borland
# Added "shutter" group, for beamline shutter status plots.
#
# Revision 1.21  1996/06/15  14:45:30  borland
# Added splitting of data group list into left and right
# halves to reduce height of screen.  Added selections for
# injIOC and srIOC groups.
#
# Revision 1.20  1996/06/06  15:16:57  borland
# Changed window title to MonitorDataReview.
#
# Revision 1.19  1996/06/05  18:13:50  borland
# Eliminated need for FIND FILES button.
#
# Revision 1.18  1996/05/31  19:08:51  borland
# Added IDs data logger entry.
#
# Revision 1.17  1996/03/26  00:30:43  borland
# Now using new -presparse option.
#
# Revision 1.16  1996/03/25  20:16:11  borland
# Added option override to custom/preset plots.
#
# Revision 1.15  1996/03/25  19:43:47  borland
# Added custom plots in addition to preset plots.
#
# Revision 1.14  1996/03/20  20:55:04  borland
# Added linac selections.  Renamed "Custom plots" to "Preset plots".  Removed
# SR DCPS for now.
#
# Revision 1.13  1996/03/16  22:50:43  borland
# Added booster RF.
#
# Revision 1.12  1996/03/07  23:12:38  borland
# Added process water entry.  Also added control of size of label characters.
#
# Revision 1.11  1996/03/07  03:30:07  borland
# Added support for start and end hour fields in time/date entry.
#
# Revision 1.10  1996/03/06  23:21:43  borland
# Added boosterRampParam data logger entries.
#
# Revision 1.9  1996/03/04  19:55:08  saunders
# Added revision/author to Version menu.
#
# Revision 1.8  1996/03/04 15:41:06  borland
# Added plot control widgets to custom plots pop-ups.
#
# Revision 1.7  1996/03/02  20:26:44  borland
# Now supports multiple choices from custom plot menus.
#
# Revision 1.6  1996/03/02  03:18:33  borland
# Added PRF1, PRF12, and SRvac data group choices.  Added list forming routine
# to make future expansion easier.
#
# Revision 1.5  1996/02/26  15:08:18  borland
# Removed Close button from custom plots listbox.  Changed Accept button
# to "Plot choice" and added "Done" button.  Added more informational
# messages.
#
# Revision 1.4  1996/02/26  00:27:48  borland
# Modified custom plot lauching procedure to use a temporary file instead
# of a csh on a pipe.  The latter didn't work from the ASDOPS account.
#
# Revision 1.3  1996/02/25  23:15:27  borland
# Added support for custom plot selections.
#
# Revision 1.2  1996/02/22  21:59:41  borland
# Moved procedure APSFindFilesBetweenDates to tcltklib area.
#
# Revision 1.1  1996/02/22  18:04:32  borland
# First version of this program.
#
#

set auto_path [linsert $auto_path 0 /usr/local/oag/apps/lib/$env(HOST_ARCH)]
set auto_path [linsert $auto_path 0 /usr/local/oag/lib_patch/$env(HOST_ARCH)]
APSDebugPath
APSRenameExecToAPSBGExec
set CVSRevisionAuthor "\$Revision: 1.156 $ \$Author: soliday $"

set originalDir [pwd]

APSStandardSetup

set args $argv
set group Main
APSStrictParseArguments {group}

set MonDataReviewVersion 1.0
proc MonDataReviewOverview {} {
        return "This tool allows reviewing data collected by continuous monitoring processes.\
For the storage ring rf systems, a custom tool is available under the storage ring menu.\n\
Note that the hour entry fields in the date/time widgets are presently ignored."
        }

set APSExecIDList ""
proc KillAPSExecLogs {} {
    global APSExecIDList
    forech id $APSExecIDList {
        APSExecLogAbort -id $id -destroy 1
    }
}

APSSetOAGGlobal
#set MonDataDirRoot $OAGGlobal(OAGDataDirectory)/monitoring
set MonDataDirRoot $OAGGlobal(OAGDataDirectory)
set MonDataPresetPlotDir $MonDataDirRoot/monitoring/MonitorDataReviewFiles
set TimeSeriesConfigDir $OAGGlobal(OAGDataDirectory)/dataLoggerConfig

set MonDataName {}
set MonDataDirList {}
set MonDataRootnameList {}
set DataGroupCommandList {}
set DataGroupValueList {}
set MonDataDoRunList {}
set NumberOfDataGroups 0
set tkplot 0

proc AddToMonDataLists {name dir rootname args} {
    set tab ""
    APSParseArguments {tab virtualRootnames virtualSubdirectories doRun}
    global MonDataName MonDataDirList MonDataRootnameList
    global DataGroupCommandList DataGroupValueList NumberOfDataGroups 
    global MonDataVirtualRootnamesList MonDataVirtualSubdirectoriesList
    global MonDataDoRunList
    lappend MonDataName "$name"
    lappend MonDataDirList $dir
    lappend MonDataRootnameList $rootname
    lappend DataGroupCommandList ResetMonDataFileList
    lappend DataGroupValueList $NumberOfDataGroups
    lappend MonDataVirtualRootnamesList $virtualRootnames
    lappend MonDataVirtualSubdirectoriesList $virtualSubdirectories
    lappend MonDataDoRunList $doRun
    if [string length $tab] {
        global ${tab}MonDataName ${tab}DataGroupValueList ${tab}DataGroupCommandList ${tab}MonDataDoRunList
        lappend ${tab}MonDataName "$name"
        lappend ${tab}DataGroupValueList $NumberOfDataGroups
        lappend ${tab}DataGroupCommandList ResetMonDataFileList
        lappend ${tab}MonDataDoRunList $doRun
    }
    incr NumberOfDataGroups
}

set glitchMode 0
proc GetItemListFromConfig {args} {
    set group ""
    APSParseArguments {group}
    global glitchMode limitPerRow MonDataPresetPlotDir TimeSeriesConfigDir tabList
    set tmpRoot /tmp/[APSTmpString].config
    APSAddToTmpFileList -ID monitor -fileList "$tmpRoot.1 $tmpRoot.2 $tmpRoot"
    set doRunList ""
    switch $group {
        OPI {
            set limitPerRow 4
            set configFile $TimeSeriesConfigDir/OPI.config
        }
        ControllawGlitch {
            set configFile $TimeSeriesConfigDir/ControllawGlitch.config
            set glitchMode 2
	    set limitPerRow 8
            set MonDataPresetPlotDir $MonDataPresetPlotDir/controllaw     
        }
        Glitch {
            set glitchMode 1
            set limitPerRow 8
            set MonDataPresetPlotDir $MonDataPresetPlotDir/glitchLogs
            if [catch {exec sddsprocess $TimeSeriesConfigDir/timeSeries.config \
                         -match=col,MonitorGroup=Glitch  $tmpRoot.1 -nowarnings
                exec sddsprocess $TimeSeriesConfigDir/ExtraLogger.config \
                         -match=col,MonitorGroup=Glitch $tmpRoot.2 -nowarnings
                exec sddscombine $tmpRoot.1 $tmpRoot.2 $tmpRoot -merge } result] {
                return -code error $result
            }
            set configFile $tmpRoot
        }
        Main {
            if [catch {exec sddsprocess $TimeSeriesConfigDir/timeSeries.config \
                         -match=col,MonitorGroup=Main \
                         "-filter=col,doOnePvPerFileRun,-1,.5,doRun,.5,1.5,&" \
                         $tmpRoot.1 -nowarnings
                exec sddsprocess $TimeSeriesConfigDir/ExtraLogger.config \
                         -match=col,MonitorGroup=Main $tmpRoot.2 \
                         "-filter=col,doOnePvPerFileRun,-1,.5,doRun,.5,1.5,&" \
                         -nowarnings
                exec sddscombine $tmpRoot.1 $tmpRoot.2 -merge -pipe=out \
                     | sddssort -pipe=in $tmpRoot -col=GroupName } result] {
                return -code error $result
            }
            set configFile $tmpRoot

            set srRows [exec sddsprocess $tmpRoot -match=col,TabName=SR -pipe=out -nowarning \
                          | sdds2stream -pipe -rows=bar]
            set limitPerRow [format %.0f [expr $srRows/2.0 + 1]]
            if $limitPerRow<5 {
                set limitPerRow 5
            }
            set doRunList [exec sdds2stream $configFile -col=doRun]
        }
    }
    set columnNames [exec sddsquery $configFile -col]
    set rows [exec sdds2stream $configFile -rows=bare]
    set GroupNameList [exec sdds2stream $configFile -col=GroupName]
    set subDirectoryList [exec sdds2stream $configFile -col=subDirectory]
    set rootnameList [exec sdds2stream $configFile -col=rootname]
    set tabNameList [exec sdds2stream $configFile -col=TabName]
    if {[lsearch $columnNames VirtualRootnames] != -1} {
        set VirtualRootnamesList [exec sdds2stream $configFile -col=VirtualRootnames]
    } else {
        for {set i 0} {$i < $rows} {incr i} {
            lappend VirtualRootnamesList ""
        }
    }
    if {[lsearch $columnNames VirtualSubdirectories] != -1} {
        set VirtualSubdirectoriesList [exec sdds2stream $configFile -col=VirtualSubdirectories]
    } else {
        for {set i 0} {$i < $rows} {incr i} {
            lappend VirtualSubdirectoriesList ""
        }
    }
    set tabList ""
    foreach tab $tabNameList {
        if {[string length $tab] && [lsearch $tabList $tab]<0} {
            lappend tabList $tab
        }
    }
    set tabList [lsort -decreasing $tabList]
    set i [lsearch -exact $tabList "SR BPMs"]
    if {$i != -1} {
        set tabList "[lreplace $tabList $i $i] {SR BPMs}"
    }

    foreach groupname $GroupNameList dir $subDirectoryList root $rootnameList tab $tabNameList virtualRootnames $VirtualRootnamesList virtualSubdirectories $VirtualSubdirectoriesList doRun $doRunList {
        AddToMonDataLists "$groupname" $dir $root -tab $tab -virtualRootnames $virtualRootnames -virtualSubdirectories $virtualSubdirectories -doRun $doRun
    }
}

set MonDataGroupIndex 0

proc MakeDateTimeFrame {widget args} {
    set parent .
    set rootname ""
    set glitchMode 0
    APSStrictParseArguments {parent rootname glitchMode}
    if !$glitchMode {
        set label "Date/Time Range of Interest"
    } else {
        set label "Date of Interest"
    }
    APSFrame $widget -parent $parent -label $label
    set w $parent$widget.frame

    if !$glitchMode {
        APSDateTimeAdjEntry .startDate -parent $w \
          -yearVariable ${rootname}StartYear \
          -monthVariable ${rootname}StartMonth \
          -dayVariable ${rootname}StartDay \
          -hourVariable ${rootname}StartHour \
          -label "Starting date/time (year, month, day, hour): " -defaultHour 0 \
          -command ResetMonDataFileList
        APSDateTimeAdjEntry .endDate -parent $w \
          -yearVariable ${rootname}EndYear \
          -monthVariable ${rootname}EndMonth \
          -dayVariable ${rootname}EndDay \
          -hourVariable ${rootname}EndHour \
          -label "Ending date/time (year, month, day, hour):   " -defaultHour 24 \
          -command ResetMonDataFileList

    } else {
        APSDateTimeAdjEntry .startDate -parent $w \
          -yearVariable ${rootname}StartYear \
          -monthVariable ${rootname}StartMonth \
          -dayVariable ${rootname}StartDay \
          -label "Starting date/time (year, month, day): " \
          -command ResetMonDataFileList
    }
    SetDateTimeToToday -rootname ${rootname}Start -hour 0
    SetDateTimeToToday -rootname ${rootname}End  -hour 24
}

proc SetDateTimeToToday {args} {
    set rootname ""
    set hour 0
    ResetMonDataFileList
    APSStrictParseArguments {rootname hour}
    global todayMonth todayYear todayDay 
    global ${rootname}Month ${rootname}Year ${rootname}Day ${rootname}Hour
    
    APSDateBreakDown -dayVariable todayDay -yearVariable todayYear \
      -monthVariable todayMonth -twoDigitYear 0 -leadingZeros 0
    set ${rootname}Hour $hour
    set ${rootname}Month $todayMonth
    set ${rootname}Day $todayDay
    set ${rootname}Year $todayYear
}

    
set MonDataStatus Ready.
proc SetMonDataStatus {text} {
    global MonDataStatus
    set MonDataStatus $text
    update
}

#set MonDataFileList {}
set DataDir ""
set MonDataFileListIsOld 0
set MonDataFileListUpdateTime 0
set glitchDataFile ""
set MonDataFileListExist 0
proc MonDataFindFiles {} {
    global MonDataStartMonth MonDataStartYear MonDataStartDay MonDataStartHour
    global MonDataEndMonth MonDataEndYear MonDataEndDay MonDataEndHour
    global MonDataDirRoot MonDataGroupIndex MonDataDirList MonDataRootnameList 
    global MonDataFileList DataDir MonDataGroupIndex glitchMode MonDataFileListExist
    global MonDataFileStartTime MonDataFileUpdateList todayYear todayMonth todayDay

    global MonDataVirtualRootnamesList MonDataVirtualSubdirectoriesList
    set VirtualRootnamesList [lindex $MonDataVirtualRootnamesList $MonDataGroupIndex]
    set VirtualSubdirectoriesList [lindex $MonDataVirtualSubdirectoriesList $MonDataGroupIndex]
    if {[llength $VirtualRootnamesList]} {
        set RootnameList $VirtualRootnamesList
	foreach dd $VirtualSubdirectoriesList {
            lappend DataDirList $MonDataDirRoot/$dd
        }
        set virtual 1
    } else {
        set RootnameList [lindex $MonDataRootnameList $MonDataGroupIndex]
        set DataDirList $MonDataDirRoot/[lindex $MonDataDirList $MonDataGroupIndex]
        set virtual 0
    }

    set fileOptions ""
    if $glitchMode {
        foreach elem {Year Month Day} {
            set MonDataEnd$elem [subst \$MonDataStart$elem]
        }
	if {$glitchMode == 2} {
	    set fileOptions {-filter "-????" -extensionList ".glog"}
        }
    }
    set name1 {sm sy sd st em ey ed et}
    set name2 {MonDataStartMonth MonDataStartYear MonDataStartDay MonDataStartHour \
                 MonDataEndMonth MonDataEndYear MonDataEndDay MonDataEndHour}
    foreach nm1 $name1 nm2 $name2 {
        set $nm1 [set $nm2]
    }
    set filesfound 0
    foreach Rootname $RootnameList DataDir $DataDirList {
        set FileList ""
        set nm $Rootname-$sy-$sm-$sd-$st-$ey-$em-$ed-$et
        global MonDataFileList
        
        set fileList  \
          [eval APSFindFilesBetweenDates -tailsOnly 1 \
             -rootname ${Rootname}- \
             -directory $DataDir $fileOptions \
             -startDateList {[APSFormatDate -year $MonDataStartYear -month $MonDataStartMonth \
                                -day $MonDataStartDay -dateFormat list]} \
             -endDateList {[APSFormatDate -year $MonDataEndYear -month $MonDataEndMonth \
                              -day $MonDataEndDay -dateFormat list]} ]
        
        if [lsearch -exact [list SRrfFast] $Rootname]==-1 {
            if {$virtual} {
                foreach fl $fileList {
                    lappend FileList $DataDir/$fl
                }
            } else {
                set FileList $fileList
            }
        } else {
            if {[string is double $MonDataStartHour]} {
                if {($MonDataStartHour < 0)} {
                    set MonDataStartHour 0
                } elseif {($MonDataStartHour >= 24)} {
                    set MonDataStartHour 23.9999
                }
                set h [expr {int($MonDataStartHour)}]
                set m [expr {int(fmod($MonDataStartHour,1) * 60)}]
                set s [expr {round(fmod(fmod($MonDataStartHour,1) * 60,1) * 60)}]
                if {$s == 60} {set s 59}
                set MonDataStartHour ${h}:${m}:${s}
                update
            }
            if {[string is double $MonDataEndHour]} {
                if {($MonDataEndHour < 0)} {
                    set MonDataEndHour 0
                } elseif {($MonDataEndHour >= 24)} {
                    set MonDataEndHour 23.9999
                }
                set h [expr {int($MonDataEndHour)}]
                set m [expr {int(fmod($MonDataEndHour,1) * 60)}]
                set s [expr {round(fmod(fmod($MonDataEndHour,1) * 60,1) * 60)}]
                if {$s == 60} {set s 59}
                set MonDataEndHour ${h}:${m}:${s}
                update
            }
            set oldDir [pwd]
            cd $DataDir
            set fileList [glob *.??:??:??]
            cd $oldDir
            set FileList ""
            set pre(file) ""
            set pre(time) 0
            foreach file $fileList {
                if {[info exist MonDataFileList($file.startTime)]} {
                    set hour $MonDataStartHour
                    set startTime [clock scan "$MonDataStartMonth/$MonDataStartDay/$MonDataStartYear $hour"]
                    set hour $MonDataEndHour
                    set endTime [clock scan "$MonDataEndMonth/$MonDataEndDay/$MonDataEndYear $hour"]
                    if {$MonDataFileList($file.startTime) >= $startTime &&
                        $MonDataFileList($file.startTime) <= $endTime } {
                        lappend FileList $DataDir/$file
                    } 
                } else {
                    if [regexp {([^.]*):(.+)} $file hour] {
                        if ![regexp {([^.]*)} $file date] {
                            SetMonDataStatus "Unknown file format,it should be rootname-YYYY-JDD-MMDD.HH:MM:SS"
                            continue
                        }
                        set date [split $date -]
                        set year [lindex $date 1]
                        set monthday [lindex $date 3]
                        set month [string range $monthday 0 1]
                        set day [string range $monthday 2 3]
                        set startTime [clock scan "$month/$day/$year $hour"]
                        # SetMonDataStatus "$file, $month/$day/$year $hour"
                    } else {
                        set startTime [APSGetSDDSParameter -fileName $DataDir/$file -parameter StartTime \
                                         -page 1]
                    }
                    set MonDataFileList($file.startTime) $startTime
                    set hour $MonDataStartHour
                    set startTime [clock scan "$MonDataStartMonth/$MonDataStartDay/$MonDataStartYear $hour"]
                    set hour $MonDataEndHour
                    set endTime [clock scan "$MonDataEndMonth/$MonDataEndDay/$MonDataEndYear $hour"]
                    if {$MonDataFileList($file.startTime) >= $startTime &&
                        $MonDataFileList($file.startTime) <= $endTime } {
                        lappend FileList $DataDir/$file
                    } elseif {($MonDataFileList($file.startTime) < $startTime) &&
                              ($MonDataFileList($file.startTime) > $pre(time))} {
                        set pre(file) $DataDir/$file
                        set pre(time) $MonDataFileList($file.startTime)
                    }
                }
            }
            if {$pre(time) > 0} {
                set FileList [linsert $FileList 0 $pre(file)]
            }
        }
        set MonDataFileList($nm) $FileList
        incr filesfound [llength $FileList]
    }
    #SetMonDataStatus "$MonDataStartHour $MonDataEndHour MonDataFileList($nm) $FileList"
    SetMonDataStatus "$filesfound files found."
}

proc CheckFileListExistence {} {
    global MonDataStartMonth MonDataStartYear MonDataStartDay MonDataStartHour
    global MonDataEndMonth MonDataEndYear MonDataEndDay MonDataEndHour
    global MonDataDirRoot MonDataGroupIndex MonDataDirList MonDataRootnameList 
    global MonDataFileList DataDir MonDataGroupIndex glitchMode MonDataFileListExist
    global MonDataFileUpDateList todayYear todayMonth todayDay needUpDate MonDataFileExist

    global MonDataVirtualRootnamesList MonDataVirtualSubdirectoriesList
    set VirtualRootnamesList [lindex $MonDataVirtualRootnamesList $MonDataGroupIndex]
    set VirtualSubdirectoriesList [lindex $MonDataVirtualSubdirectoriesList $MonDataGroupIndex]
    if {[llength $VirtualRootnamesList]} {
        set RootnameList $VirtualRootnamesList
        foreach dd $VirtualSubdirectoriesList {
            lappend DataDirList $MonDataDirRoot/$dd
        }
    } else {
        set RootnameList [lindex $MonDataRootnameList $MonDataGroupIndex]
        set DataDirList $MonDataDirRoot/[lindex $MonDataDirList $MonDataGroupIndex]
    }

    if $glitchMode {
        foreach elem {Year Month Day} {
            set MonDataEnd$elem [subst \$MonDataStart$elem]
        }
    }
    set name1 {sm sy sd st em ey ed et}
    set name2 {MonDataStartMonth MonDataStartYear MonDataStartDay MonDataStartHour \
                 MonDataEndMonth MonDataEndYear MonDataEndDay MonDataEndHour}
    foreach nm1 $name1 nm2 $name2 {
        set $nm1 [set $nm2]
    }
    set MonDataFileExist 0
    set results ""
    foreach Rootname $RootnameList DataDir $DataDirList {
        set nm $Rootname-$sy-$sm-$sd-$st-$ey-$em-$ed-$et
        set nmU $Rootname-$sy-$sm-$sd-$todayYear-$todayMonth-$todayDay
        set needUpDate 0 
        if {$MonDataEndMonth == $todayMonth && 
            $MonDataEndYear == $todayYear &&
            $MonDataEndDay == $todayDay} {        
            if {![info exist MonDataFileOneDayList($nmU)] ||
                ![llength $MonDataFileUpdateList($nmU)] } {
                set MonDataFileOneDayList($nmU) \
                  [APSFindFilesBetweenDates -tailsOnly 1 \
                     -rootname ${Rootname}- \
                     -directory $DataDir \
                     -startDateList [APSFormatDate -year $MonDataStartYear \
                                       -month $MonDataStartMonth \
                                       -day $MonDataStartDay -dateFormat list] \
                     -endDateList [APSFormatDate -year $todayYear -month $todayMonth \
                                     -day $todayDay -dateFormat list] ]
                set needUpDate 1
            } else {
                set fileList1 \
                  [APSFindFilesBetweenDates -tailsOnly 1 \
                     -rootname ${Rootname}- \
                     -directory $DataDir \
                     -startDateList [APSFormatDate -year $MonDataStartYear \
                                       -month $MonDataStartMonth \
                                       -day $MonDataStartDay -dateFormat list] \
                     -endDateList [APSFormatDate -year $todayYear -month $todayMonth \
                                     -day $todayDay -dateFormat list] ]
                if {[llength $fileList]> [llength $MonDataFileUpdateList($nmU)]} {
                    set needUpDate 1
                    set MonDataFileUpdateList($nmU) $fileList
                }
            }
        }
        global MonDataFileList
        if {[info exists MonDataFileList($nm)] && [llength $MonDataFileList($nm)] } {
            set MonDataFileExist 1
        }
        append results "MonDataFileList($Rootname-$sy-$sm-$sd-$st-$ey-$em-$ed-$et) "
    }
    return [string trim $results]
}
proc ResetMonDataFileList {} {
    global MonDataFileList MonDataFileListIsOld
    global MonDataGroupIndex
    global glitchChoice

    #set MonDataFileList {}
    #if [info exist MonDataFileList] {
    #    unset MonDataFileList 
    #}
    set MonDataFileListIsOld 1
    set glitchChoice ""
}

proc FilterTriggerTimes {timeListWidget} {
    global triggerSourceList glitchDataFile
    set filter ""
    if [llength $triggerSourceList] {
        set first 1
        foreach elem $triggerSourceList {
            if $first {
                lappend filter "${elem},1,1"
                set first 0
            } else {
                lappend filter "${elem},1,1,|"
            }
        }
        set filter -filter=column,[join $filter ,]
    }
    set timeFile /tmp/[APSTmpString]
    APSAddToTempFileList $timeFile
    if [catch {eval exec sddscollapse -pipe=out $glitchDataFile \
                 | sddsprocess -pipe $filter -nowarning \
                 | tee $timeFile \
                 | sdds2stream -rows -pipe} result] {
        SetMonDataStatus "Error filtering records: $result"
        return
    }
    if [string compare $result "0 rows"]==0 {
        SetMonDataStatus "No match for selected triggers."
        bell
        return
    }
    if [catch {APSGetSDDSColumn -fileName $timeFile -column PageTimeStamp} glitchList] {
        SetMonDataStatus "Error: $glitchList"
        return
    }
    $timeListWidget.userFrame.sl.listbox delete 0 end
    eval $timeListWidget.userFrame.sl.listbox insert 0 $glitchList
    SetMonDataStatus "Filtering done: [llength $glitchList] matches."
    bell
}

proc ViewTriggerTimes {} {
    global triggerSourceList glitchDataFile triggerList
    set tmpFile /tmp/[APSTmpString]
    if ![llength $triggerList]  {
        return -code error "No trigger data."
    }
    foreach item $triggerList {
        lappend optList -parameter=$item
    }
    if [catch {eval exec sddsprintout -width=120 $glitchDataFile \
                -parameter=PageTimeStamp,end $optList $tmpFile} result] {
        SetMonDataStatus "Error: $result"
        return
    }
    APSFileDisplayWindow [APSUniqueName .] -width 120 -deleteOnClose 1 \
      -fileName $tmpFile -comment "Filter channels for each event"
}

proc UpdateMonDataFileList {} {
    global MonDataStartYear MonDataStartMonth MonDataStartDay  MonDataStartHour
    global MonDataEndYear MonDataEndMonth MonDataEndDay MonDataEndHour
    global MonDataRootnameList MonDataGroupIndex needUpDate
    global MonDataFileListIsOld MonDataFileList MonDataFileListUpdateTime
    global timeNow glitchFile DataDir glitchDataFile glitchMode MonDataFileExist

    if $glitchMode {
        foreach elem {Year Month Day} {
            set MonDataEnd$elem [subst \$MonDataStart$elem]
        }
    }
    set fileList {}
    set FileList ""
    set FileList [CheckFileListExistence]
    if ![string length $FileList] {
        tkwait variable FileList
    }
    if {$needUpDate || !$MonDataFileExist} {
        MonDataFindFiles
       # puts stderr "ffind.."
    }
    #set MonDataFileListIsOld 0
    if $glitchMode {
        foreach fl $FileList {
            append fileList "[set $fl] "
        }
        SetMonDataStatus "Working..."
        if [llength $fileList]>1 {
            set glitchDataFile /tmp/[APSTmpString]
            set oldDir [pwd]
            APSAddToTempFileList $glitchDataFile
            cd $DataDir
            if [catch {eval exec sddscombine $fileList $glitchDataFile} result] {
                cd $oldDir
                return 0
            }
            cd $oldDir
        } else {
            set glitchDataFile [string trim $DataDir/$fileList]
        }
    }
    #return the list name
    return $FileList
}

proc PrepareVirtualLoggerFiles {args} {
    set monfile ""
    set fileList ""
    APSStrictParseArguments {monfile fileList}
    SetMonDataStatus "Preparing virtual data logger files. One moment please..."
    if {[catch {exec sdds2stream $monfile -col=ReadbackName} readbackName]} {
        return -code error "error: $readbackName"
    }
    set tmpFile /tmp/[APSTmpString]
    set i 0
    foreach f $fileList {
        incr i
        APSAddToTempFileList ${tmpFile}$i
        if {[catch {exec sddsconvert $f ${tmpFile}$i \
                      -retain=column,Time,[join $readbackName ,]} results]} {
            return -code error "error: $results"
        }
        lappend frootname([string range [file rootname [file tail $f]] 0 end-14]) ${tmpFile}$i
    }
    set groupfiles ""
    foreach rootname [lsort -dictionary [array names frootname]] {
        incr i
        APSAddToTempFileList ${tmpFile}$i
        if {[catch {eval exec sddscombine $frootname($rootname) \
                      ${tmpFile}$i -merge -overwrite} results]} {
            return -code error "error: $results"
        }
        lappend groupfiles ${tmpFile}$i
        eval file delete -force $frootname($rootname)
    }
    incr i
    APSAddToTempFileList ${tmpFile}$i
    if {[catch {eval exec sddscombine $groupfiles \
                  -pipe=out -retain=column,Time \
                  "-delete=array,*" "-delete=parameter,*" \
                  -merge -overwrite \
                  | sddssort -pipe=in ${tmpFile}$i \
                  -col=Time -unique} results]} {
        return -code error "error: $results"
    }
    set timefile ${tmpFile}$i
    
    set interpfiles ""
    foreach f $groupfiles {
        incr i
        APSAddToTempFileList ${tmpFile}$i
        if {[catch {exec sddsinterp $f ${tmpFile}$i "-col=Time,*" \
                      -fileValues=${timefile},column=Time} results]} {
            return -code error "error: $results"
        }
        lappend interpfiles ${tmpFile}$i
        file delete -force $f
    }
    file delete -force ${timefile}
    incr i
    APSAddToTempFileList ${tmpFile}$i
    if {[catch {eval exec sddsxref $interpfiles ${tmpFile}$i \
                  -leave=Time} results]} {
        return -code error "error: $results"
    }
    eval file delete -force $interpfiles
    return ${tmpFile}$i
}

proc LaunchQuickSDDSPlot {} {
    global MonDataFileList DataDir MonDataName MonDataGroupIndex OldMonDataFileList
    global MonDataStartYear MonDataStartMonth MonDataStartDay  MonDataStartHour
    global MonDataEndYear MonDataEndMonth MonDataEndDay MonDataEndHour
    global MonDataRootnameList MonDataGroupIndex MonDataDirRoot MonDataDirList
   
    global MonDataVirtualRootnamesList MonDataVirtualSubdirectoriesList
    set VirtualRootnamesList [lindex $MonDataVirtualRootnamesList $MonDataGroupIndex]
    if {[llength $VirtualRootnamesList]} {
	set virtual 1
    } else {
	set virtual 0
    }

    set fileList {}
    foreach FileList [UpdateMonDataFileList] {
        append fileList "[set $FileList] "
    }
    if ![llength $fileList] {
        SetMonDataStatus "No data selected or found."
        return
    }

    if {$virtual} {
	if {[catch {PrepareVirtualLoggerFiles -fileList $fileList -monfile $MonDataDirRoot/[lindex $MonDataDirList $MonDataGroupIndex]/[lindex $MonDataRootnameList $MonDataGroupIndex].mon} fileList]} {
	    SetMonDataStatus "$fileList"
	    return
	}
    }
    exec quickSDDSplot -dataDirectory $DataDir -timeFilterMode "day" \
        -timeFilterStart "$MonDataStartYear $MonDataStartMonth $MonDataStartDay $MonDataStartHour" \
        -timeFilterEnd "$MonDataEndYear $MonDataEndMonth $MonDataEndDay $MonDataEndHour" \
        -dataFileList $fileList -message "Data from [lindex $MonDataName $MonDataGroupIndex] logger." \
        -groupMessage [lindex $MonDataRootnameList $MonDataGroupIndex] \
        -indexFileTemplate "columnIndices/%s.index.gz" \
        -showControlNames 1 &
    if [catch {LogMonitorDataReviewAction -action quickSDDSplot} result] {
        SetMonDataStatus "$result"
    }
    SetMonDataStatus "quickSDDSplot launched with [llength $fileList] data files."
}

proc LaunchsddsExportData {} {
    global originalDir
    global MonDataFileList DataDir MonDataName MonDataGroupIndex OldMonDataFileList
    global MonDataStartYear MonDataStartMonth MonDataStartDay  MonDataStartHour
    global MonDataEndYear MonDataEndMonth MonDataEndDay MonDataEndHour
    global MonDataDirRoot MonDataDirList
    global MonDataRootnameList MonDataGroupIndex 
    global MonDataVirtualRootnamesList MonDataVirtualSubdirectoriesList
    set VirtualRootnamesList [lindex $MonDataVirtualRootnamesList $MonDataGroupIndex]
    if {[llength $VirtualRootnamesList]} {
	set virtual 1
    } else {
	set virtual 0
    }

    set fileList {}
    foreach FileList [UpdateMonDataFileList] {
        append fileList "[set $FileList] "
    }
    if ![llength $fileList] {
        SetMonDataStatus "No data selected or found."
        return
    }

    if {$virtual} {
	if {[catch {PrepareVirtualLoggerFiles -fileList $fileList -monfile $MonDataDirRoot/[lindex $MonDataDirList $MonDataGroupIndex]/[lindex $MonDataRootnameList $MonDataGroupIndex].mon} fileList]} {
	    SetMonDataStatus "$fileList"
	    return
	}
    }

    set oldDir [pwd]
    cd $originalDir
    exec sddsExportData -dataDirectory $DataDir -timeFilterMode "day" \
      -timeFilterStart "$MonDataStartYear $MonDataStartMonth $MonDataStartDay $MonDataStartHour" \
      -timeFilterEnd "$MonDataEndYear $MonDataEndMonth $MonDataEndDay $MonDataEndHour" \
      -dataFileList $fileList -message "Data from [lindex $MonDataName $MonDataGroupIndex] logger." &
    cd $oldDir
    if [catch {LogMonitorDataReviewAction -action sddsExportData} result] {
        SetMonDataStatus "$result"
    }
    SetMonDataStatus "sddsExportData launched with [llength $fileList] data files."
}

set customPlotsDir .
set triggerSourceList ""
proc BringUpPlotChoices {args} {
    set preset 1
    set glitchMode 0
    APSStrictParseArguments {preset glitchMode}
    global sparsingInterval plotDevice sameScaleY optionOverride layoutChoice printerName labelSizeOption separate
    global env customPlotsDir yOffsetMode presetLabel MonDataGroupIndex presetUserOptions glitchDataFile
    global triggerSourceList group MonDataPresetPlotDir IsTimePlot FixedTimeScale
    global repeatPlotMode

    set sparsingInterval 1
    set plotDevice motif
    set repeatPlotMode 0
    set sameScaleY 0
    set separate 0
    set yOffsetMode 0
    set optionOverride 0
    set layoutChoice -layout=1,1
    set labelSize -labelsize=0.03
    set presetUserOptions ""
    if [info exists env(PRINTER)] {
        set printerName $env(PRINTER)
    } else {
        set printerName mcr1
    }
    
    global MonDataFileList DataDir MonDataName MonDataGroupIndex MonDataPresetPlotDir
    global MonDataName MonDataRootnameList 
    global PresetPlotCommandList PresetPlotDescripList presetUserFilters scrollHeight
    global IsContour
    global MonDataStartYear MonDataStartMonth MonDataStartDay  MonDataStartHour
    global MonDataEndYear MonDataEndMonth MonDataEndDay MonDataEndHour
    global preprocessInput
    if $glitchMode {
        foreach elem {Year Month Day} {
            set MonDataEnd$elem [subst \$MonDataStart$elem]
        }
	set preprocessInput 0
    }
    set fileList {}
    foreach FileList [UpdateMonDataFileList] {
        append fileList "[set $FileList] "
    }
    if ![llength $fileList] {
        SetMonDataStatus "No data selected or found."
        return
    }

    if $preset {
        set presetPlotsFile $MonDataPresetPlotDir/[lindex $MonDataRootnameList $MonDataGroupIndex].sdds
        if ![file exists $presetPlotsFile] {
            SetMonDataStatus "No preset plots available for [lindex $MonDataName $MonDataGroupIndex]"
            return
        }
        set presetLabel Preset
	set preprocessInput 1
    } 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]} {
            SetMonDataStatus "$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 {
 		    SetMonDataStatus "$customPlotsFile is not a valid file: missing $elem."
 		    return
 		}
 	    }
 	} else {
 	    set presetPlotsFile $customPlotsFile
 	}
        set customPlotDir [file dirname $customPlotsFile]
        set presetLabel Custom
    }

    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 \
                 IsContour} IsContour] {
        set IsContour ""
    }
    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
    }

    if $glitchMode {
        set scrollHeight 14
	set timestamp "PageTimeStamp"
	if {$glitchMode == 2} {
	    set timestamp "TimeStamp"
	}
        if [catch {APSGetSDDSParameter -fileName $glitchDataFile -parameter $timestamp} glitchList] {
            SetMonDataStatus "Error reading from $glitchDataFile: $glitchList"
            destroy .presetPlots
            return
        }
        if [llength $glitchList]==0 {
            SetMonDataStatus "No glitches recorded for that system on that date."
            return
        }
        if [catch {APSGetSDDSNames -fileName $glitchDataFile -class parameter} parameterNames] {
            SetMonDataStatus "Error reading from $glitchDataFile: $parameterNames"
            destroy .presetPlots
            return
        }
    } else {
        set scrollHeight 20
    }

    if $glitchMode {
        set analysisFile $MonDataPresetPlotDir/[lindex $MonDataRootnameList \
                                                  $MonDataGroupIndex]-AnalysisScripts.sdds
        if [file exists $analysisFile] {
            APSFrameGrid .presetPlots -xList {one two three}
        } else {
            APSFrameGrid .presetPlots -xList {one two}
        }
    } else {
        APSFrameGrid .presetPlots -xList {one}
    }
    
    if $glitchMode {
        global glitchChoice triggerList
        APSScrolledListWindow .glitchList -parent .presetPlots.two -height $scrollHeight \
          -label "glitch times" -itemList $glitchList \
          -contextHelp "List of glitches.  Click on the one you are interested in prior to plotting." \
          -closeButton 0 -clearButton 0 -acceptButton 0 -autoAccept 1 \
          -selectionVar glitchChoice
        set triggerList {}
        foreach name $parameterNames {
            if [string match *AlarmTrigger* $name] {
                lappend triggerList $name
            } elseif [string match *Glitched* $name] {
                lappend triggerList $name
            } elseif [string match *Triggered* $name] {
                lappend triggerList $name
            }
        }
        if [llength $triggerList] {
            APSScrolledListWindow .triggerList -parent .presetPlots.two -height $scrollHeight \
              -label "trigger/glitch sources" -itemList $triggerList \
              -contextHelp "List of channels on which triggers or glitches may occur." \
              -closeButton 0 -clearButton 1 -acceptButton 0 \
              -selectionVar triggerSourceList -autoAccept 1
            APSButton .filter -parent .presetPlots.two.triggerList.buttonRow \
              -text "Filter" -command \
              {FilterTriggerTimes .presetPlots.two.glitchList} -contextHelp \
              "Filters trigger time list to contain only those records for which one of the selected trigger sources was a cause of the record being dumped."
            APSButton .view -parent .presetPlots.two.triggerList.buttonRow \
              -text "View" -command \
              ViewTriggerTimes -contextHelp \
              "Displays times at which different triggers fired."
        }
        global analysisScriptNameList analysisDescriptionList analysisExecTypeList
        if [file exists $analysisFile] {
            if {[catch {sdds open $analysisFile r} fid] ||  \
                  [catch {sdds getColumn $fid ScriptName} analysisScriptNameList] || \
                  [catch {sdds getColumn $fid ScriptDescription} analysisDescriptionList] || \
                  [catch {sdds getColumn $fid ExecType} analysisExecTypeList] || \
                  [catch {sdds close $fid} result]} {
                destroy .presetPlots
                SetMonDataStatus "Error reading from $analysisFile: $fid$analysisScriptNameList$analysisDescriptionList$result"
                return
            }
            
            APSScrolledListWindow .analysis -parent .presetPlots.three -height [expr $scrollHeight*2+2] \
              -label "Analysis options" -itemList $analysisDescriptionList \
              -contextHelp "List of analysis scripts that can be applied to the data." \
              -closeButton 0 -clearButton 0 -acceptButton 1 \
              -selectionVar analysisSelection -autoAccept 1 \
              -callback ExecuteGlitchAnalysisScript
            global autoscale
            set autoscale 0
            APSRadioButtonFrame .auto -parent .presetPlots.three.analysis -label "Auto scale:" \
              -variable autoscale -buttonList {Yes No} -valueList {1 0} -orientation horizontal \
              -contextHelp "choose yes for auto-scale options for all plots (only valid for orbit change plots) "
            .presetPlots.three.analysis.buttonRow.accept.button configure -text Execute
        }
    }

#    APSFrameGrid .options -parent .presetPlots.one \
#      -yList {y1 y2} -width 10 \
#      -xList {x1 x2 x3 x4}
        
    pack [frame .presetPlots.one.options] -fill x
    frame .presetPlots.one.options.x1
    frame .presetPlots.one.options.x2
    frame .presetPlots.one.options.x3
    frame .presetPlots.one.options.x4
    pack .presetPlots.one.options.x1 .presetPlots.one.options.x2 .presetPlots.one.options.x3 .presetPlots.one.options.x4 -side left -fill y
    APSRadioButtonFrame .layout -parent .presetPlots.one.options.x1 \
      -label Layout -orientation vertical \
      -variable layoutChoice \
      -buttonList {1x1 1x2 1x3 2x1 2x2 2x3 3x3 4x4 5x5} \
      -valueList {-layout=1,1 -layout=1,2 -layout=1,3 -layout=2,1 -layout=2,2 -layout=2,3 -layout=3,3 -layout=4,4 -layout=5,5} \
      -contextHelp {Choose the number of plot panels horizontally and vertical on each page.}
    APSRadioButtonFrame .sparse  -parent .presetPlots.one.options.x2 \
      -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."
    APSCheckButtonFrame .misc  -parent .presetPlots.one.options.x3 \
      -label Misc. -orientation vertical \
      -variableList {sameScaleY yOffsetMode optionOverride separate} \
      -buttonList {"Same y scales." "y offset mode" "Option override." "Separate"}  \
      -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 .labelsize -parent .presetPlots.one.options.x4 \
        -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."

    APSRadioButtonFrame .device  -parent .presetPlots.one.options.x3 \
      -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.x3 \
        -label "Printer: " -textVariable printerName -width 10 \
        -contextHelp "Enter the name of the printer for postscript output."
    APSCheckButtonFrame .tkplot  -parent .presetPlots.one.options.x3 \
      -label "" -orientation vertical \
      -variableList {tkplot} \
      -buttonList {"Use tksddsplot"}
    APSRadioButtonFrame .repeat -parent .presetPlots.one.options.x4 \
        -packOption "-anchor nw" \
        -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."

    APSFrame .extFrame -parent .presetPlots.one -packOption "-anchor nw"
    APSLabeledEntry .extra -parent .presetPlots.one.extFrame.frame \
      -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 [lindex $MonDataName $MonDataGroupIndex]" \
      -itemList $PresetPlotDescripList \
      -callback MakePresetPlot \
      -packOption "-fill both -expand true" \
      -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." 
  
    APSCheckButtonFrame .preprocess  -parent $g.x3.y1 \
      -label "" -orientation vertical \
      -variableList {preprocessInput} \
      -buttonList {"Preprocess Input"}
	
    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
    SetMonDataStatus "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 [lindex $MonDataName $MonDataGroupIndex]"
}

# 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 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
     SetMonDataStatus "All preset plots are deselected for a plotting" 
}

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

set presetFilterList ""

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 updates a description scrolled list after button "Apply Filter" or
# "Remove Filter" was set to action.
proc updateScrolledList {scrolledList} {
     global scrollHeight presetLabel MonDataName MonDataGroupIndex 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 [lindex $MonDataName $MonDataGroupIndex]"

     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 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"
     SetMonDataStatus "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
}

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 MakePreprocessedInput {args} {
     global PresetPlotCommandList PresetPlotDescripList tmpInputFile
     global MonDataRootnameList  MonDataDirList MonDataDirRoot MonDataGroupIndex
     global MonDataVirtualRootnamesList MonDataVirtualSubdirectoriesList
     
     set fileList ""
     set descriptionList ""
     set commandList ""
     set command ""
     set col_token ""
     set cols ""
     APSStrictParseArguments {fileList descriptionList}
     
     set rootNames [lindex $MonDataRootnameList $MonDataGroupIndex]
     set dataDirs  $MonDataDirRoot/[lindex $MonDataDirList $MonDataGroupIndex]
     set foo [lindex $MonDataVirtualRootnamesList $MonDataGroupIndex]
    
     if { [llength $foo] } {
        set rootNames $foo
	set dataDirs ""
	set VirtualSubdirectoriesList [lindex $MonDataVirtualSubdirectoriesList $MonDataGroupIndex] 
	foreach dd $VirtualSubdirectoriesList {
            lappend dataDirs $MonDataDirRoot/$dd
        }
     }	
     
     set nameList ""
     set colList ""
     set tmpInputFile ""
     
     foreach dir $dataDirs rname $rootNames  {
        lappend inputFileList [lsearch  -all -inline $fileList *${rname}*]
        
	set file_use [lsearch  -inline $fileList *${rname}*]
	
	if { [ string match  ${dir}/${rname}*  $file_use ] == 0 } {
	    set file_use ${dir}/$file_use
	}    
	
        if [ catch {APSGetSDDSNames -fileName $file_use} result ]  {
	    SetMonDataStatus "Error: $result"
            return
	}
        lappend nameList [split $result]
	lappend colList ""
	lappend tmpInputFile /tmp/[APSTmpString].sdds
    }
    
    foreach description $descriptionList {
        set col_token ""
	set split_token ""
	set match_token ""
	set filter_token ""
	set timeFilter_token ""
	
        set command [lindex $PresetPlotCommandList [lsearch $PresetPlotDescripList $description]]
	
	foreach  element $command {
	   if [ string match -nocase "-col*=time,*" $element] {
	      lappend col_token $element
	   }
	   if [ string match -nocase "-split=co*" $element ] {
	      lappend split_token $element
	   }
	   if [ string match -nocase "-filter=co*" $element ] {
	      lappend filter_token $element
	   }
	   if [ string match -nocase "-timefilter=co*" $element ] {
	      lappend timeFilter_token $element
	   }
	   if [ string match -nocase "-match=co*" $element] {
	      lappend match_token $element
	   }
	   	      
	}    
	
	if {[ llength $col_token] } {	
	    foreach token $col_token {
	       set foo [string range  $token [expr [string first "=Time," $token]+6]       end]     
	       set foo [ string trim $foo "(" ]
	       set foo [ string trim $foo ")" ]
	       lappend cols $foo
	   }
	}
	if {[llength $split_token] } {
	   foreach token $split_token {
	      set i1 [string first "=" $token [expr [string first "=" $token 0]+1] ]
	      incr i1
	      set i2 [string first "," $token ]
	      incr i2 -1
	      set foo [string range $token $i1 $i2]
	      set foo [ string trim $foo "(" ]
	      set foo [ string trim $foo ")" ]
	      lappend cols $foo
	   }
	}
	if {[llength $timeFilter_token] } {
	   foreach token $timeFilter_token {
	      set i1 [string first "," $token ]
	      incr i1
	      set i2 [string first "," $token $i1 ]
	      incr i2 -1
	      set foo [string range $token $i1 $i2]
	      set foo [ string trim $foo "(" ]
	      set foo [ string trim $foo ")" ]
	      lappend cols $foo
	   }
	}
	if {[llength $filter_token] } {
	   foreach token $filter_token {
	      set i1 [string first "," $token ]
	      incr i1
	      set token_foo [split [string range  $token $i1 end ] ,]
	      foreach foo $token_foo {
	         if [string match -nocase {*[A-z]*} $foo ] {
	            lappend cols [string trim [string trim $foo "("] ")"]
	            lappend cols $foo
	         }
	      }	 
	   }
	}
	
	if {[llength $match_token] } {
	   foreach token $match_token {
	      set i1 [string first "," $token ]
	      incr i1
	      set token_foo [split [string range  $token $i1 end ] ,]
	      foreach foo $token_foo {
	         set i2 [string first = $foo ] 
		 if { $i2 != -1 } {
		    set foo2   [string range $foo [incr i2] end ]
	            lappend cols [string trim [string trim $foo2"("] ")"]
		 }   
	      }
	   }
	}
     }
     
     lappend cols "Time"
     
     set cols [lsort -unique $cols]
     set cols [split [join $cols ,] ,]
     foreach colname $cols {
        set n 0
	foreach nl $nameList {
	  
	   if { [ lsearch $nl $colname] != -1 } {
	      set colList [ lreplace $colList $n $n [join [list [lindex $colList $n ] $colname] ]]
	      if ![string match "Time" $colname ] {
	         break
              }		 
	  } 
	  incr n    
	}  
     }
          
     set cmd ""
     foreach out $tmpInputFile in $inputFileList  cname $colList {
          append cmd "sddscombine $in $out \"-retain=col,[join $cname ,]\" -overwrite\n"
     }
     
     return $cmd
      	 
}

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

    global PresetPlotCommandList PresetPlotDescripList IsTimePlot FixedTimeScale
    global MonDataStartMonth MonDataStartYear MonDataStartDay MonDataStartHour
    global MonDataEndMonth MonDataEndYear MonDataEndDay MonDataEndHour
    global presetLabel glitchMode glitchChoice glitchDataFile group
    global MonDataName MonDataGroupIndex newAcceptCommand confFlag IsContour
    if [winfo exists .execLog] {
        destroy .execLog
    }
    setActionButtons 0
    set confFlag 0
    
    
    
    if {[llength $IsContour]} {
        set contour -1
        foreach description $descriptionList {
            set index [lsearch $PresetPlotDescripList $description]
            set iscon [lindex $IsContour $index]
            if {$iscon == "y"} {
                if {$contour == 0} {
                    SetMonDataStatus "Unable to plot contour and non-contour plots together."
                    return
                }
                if {$contour == 1} {
                    SetMonDataStatus "Unable to plot more than one contour plots at the same time."
                    return
                }
                set contour 1
            } else {
                if {$contour == 1} {
                    SetMonDataStatus "Unable to plot contour and non-contour plots together."
                    return
                }
                set contour 0
            }
        }
    } else {
        set contour 0
    }
    
    
    set fileList {}
    
    foreach FileList [UpdateMonDataFileList] {
        append fileList "[set $FileList] "
    }
   
    set preprocessCmd ""
    if { $preprocessInput == 1  && !$contour } {
       set preprocessCmd [MakePreprocessedInput -descriptionList $descriptionList -fileList $fileList]
       set fileList $tmpInputFile
    }
    
    if ![llength $fileList] {
        SetMonDataStatus "No data selected or found."
        return
    }
    if [catch {APSConvertTimeToHours $MonDataStartHour} hour] {
        SetMonDataStatus "Invalid starting hour: $MonDataStartHour"
        return
    }
    set StartTime \
      [exec timeconvert \
         -breakDown=year=$MonDataStartYear,day=$MonDataStartDay,month=$MonDataStartMonth,hour=$hour]
    if [catch {APSConvertTimeToHours $MonDataEndHour} hour] {
        SetMonDataStatus "Invalid ending hour: $MonDataEndHour"
        return
    }
    set EndTime \
      [exec timeconvert \
         -breakDown=year=$MonDataEndYear,day=$MonDataEndDay,month=$MonDataEndMonth,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]
    puts $cshFID $preprocessCmd
    set timeFilterFlag 0
    if {$contour} {
        set preCommand "sddscombine $fileList -pipe=out -merge | sddsprocess -pipe -filter=column,Time,$StartTimePlot,$EndTimePlot | "
        set timeFilterFlag 1
        set extraOptions ""
    } else {
        if {$MonDataStartHour!=0 || $MonDataEndHour!=24} {
            set extraOptions -filter=column,Time,$StartTime,$EndTime
            set timeFilterFlag 1
        } else {
            set extraOptions ""
        }
    }
    if [string compare $group "OPI"]==0 {
        set extraOptions "$extraOptions -topline=[lindex $MonDataName $MonDataGroupIndex]"
    }

    if $glitchMode {
	set timestamp "PageTimeStamp"
	if {$glitchMode == 2} {
	    set timestamp "TimeStamp"
	}
        set extraOptions "$extraOptions -split=page '-match=parameter,${timestamp}=[lindex $glitchChoice 0]'"
    }
    if {$contour} {
        set extraOptions "$extraOptions -title= $layoutChoice"
    } else {
        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 {!$contour} {
        if $sameScaleY {
            set extraOptions "$extraOptions -same=x,y,global"
        } else {
            set extraOptions "$extraOptions -same=x,global"
        }
    }
    if $separate {
        set extraOptions "$extraOptions -separate=nameString -groupby=nameString"
    }
    if $yOffsetMode {
        set extraOptions "$extraOptions -mode=y=offset"
    }
    set dataFile $fileList
    if $glitchMode {
        set dataFile $glitchDataFile
    }
    global tkplot
    if {$contour} {
        set command "$preCommand sddscontour"
    } elseif {($tkplot) && ($repeatPlotMode == 0)} {
        set command tksddsplot
    } else {
        set command sddsplot
    }
    if $timeFilterFlag {
        puts $cshFID "$command \\"
    } else {
        puts $cshFID "$command -filter=column,Time,1,1e10 \\"
    }
    if $repeatPlotMode {
        puts $cshFID "-repeat \\"
    }
    if {$contour} {
        if !$optionOverride {
            puts $cshFID " $extraOptions $presetUserOptions -pipe \\"
        } else {
            puts $cshFID "-pipe $presetUserOptions \\"
        }
    } else {
        if !$optionOverride {
            puts $cshFID " $extraOptions $presetUserOptions $dataFile \\"
        } else {
            puts $cshFID "$fileList $presetUserOptions \\"
        }
    }
    set plotsFound 0

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

    foreach description $descriptionList {
        set index [lsearch $PresetPlotDescripList $description]
        if $index==-1 {
            SetMonDataStatus "Error: no match for description $description!"
        }
        SetMonDataStatus "Will plot $description"
        set plotsFound 1
        puts -nonewline $cshFID " [lindex $PresetPlotCommandList $index] "
        if {!$glitchMode && [llength $IsTimePlot] && [lindex $IsTimePlot $index]} {
            if {![llength $FixedTimeScale] || [lindex $FixedTimeScale $index]} {
                puts -nonewline $cshFID " -limit=xmin=$StartTimePlot,xmax=$EndTimePlot "
            }
        }
        if {$contour} {
            if !$optionOverride {
                puts $cshFID " \\"
            } else {
                puts $cshFID " $extraOptions \\"
            }
        } else {
            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 {SetMonDataStatus "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
        SetMonDataStatus "Plotting..."
     #   puts $cshFile
    }
    if [catch {LogMonitorDataReviewAction -action ${presetLabel}Plot} result] {
        SetMonDataStatus "$result"
    }
#    after 5000 "exec rm $cshFile"
     .presetPlots.one.plotlist.buttonRow.buttons.x1.y3.plot.button configure -command $newAcceptCommand
    cd $origDir
}

proc ExecuteGlitchAnalysisScript {descriptionList} {
    global MonDataFileList DataDir 
    global glitchMode glitchChoice glitchDataFile 
    global MonDataName MonDataGroupIndex presetUserOptions
    global analysisDescriptionList analysisScriptNameList analysisExecTypeList

    set fileList {}
    foreach FileList [UpdateMonDataFileList] {
        append fileList "[set $FileList] "
    }
    if ![llength $fileList] {
        SetMonDataStatus "No data selected or found."
        return
    }
    SetMonDataStatus "Working on [join $descriptionList ,]"
    set dataFile /tmp/[APSTmpString]
    APSAddToTempFileList $dataFile

    set first 1
    foreach item $glitchChoice {
        if $first {
            set matchOption "-match=parameter,PageTimeStamp=$item"
            set first 0
        } else {
            set matchOption "$matchOption,PageTimeStamp=$item,|"
        }
    }
    if [catch {exec sddsprocess $glitchDataFile $dataFile \
                 $matchOption -nowarning} result] {
        SetMonDataStatus "$result"
        return
    }
    foreach description $descriptionList {
        set index [lsearch $analysisDescriptionList $description]
        if $index==-1 {
            SetMonDataStatus "Error: no match for description $description!"
        }
        switch [lindex $analysisExecTypeList $index] {
            IsExec {
                catch {eval exec [lindex $analysisScriptNameList $index] \
                         -input $dataFile -selectionLabel "[join $glitchChoice +]" \
                         -title {$description} \
                         -deleteInput 1 &} 
            }
            IsAPSExecLog {
                APSExecLog [APSUniqueName .] \
                  -unixCommand \
                  "[lindex $analysisScriptNameList $index] -input $dataFile -title $description -deleteInput 1 -selectionLabel [join $glitchChoice +] "
            }
            IsProc {
                if {$description=="Orbit change plots"} {
                    global autoscale
                    eval [lindex $analysisScriptNameList $index] -input $dataFile -title \
                      {$description} -deleteInput 1 -selectionLabel {"[join $glitchChoice +]"} \
                      -autoscale $autoscale
                } else {
                    eval [lindex $analysisScriptNameList $index] -input $dataFile -title \
                      {$description} -deleteInput 1 -selectionLabel {"[join $glitchChoice +]"} 
                }
            }
        }
    }
    SetMonDataStatus "Analysis done."
}

proc MakeGroupSelectionFrame {widget args} {
    set parent ""
    set group ""
    APSParseArguments {parent group}
    
    global MonDataName DataGroupValueList MonDataGroupIndex
    global DataGroupCommandList  limitPerRow tabList MonDataDoRunList
    if {$group == "Main" } {
        set widgetList [APSTabFrame $widget -parent $parent -label "Data group" \
                          -width 830 -height 380 -labelList $tabList -packOption "-fill both -expand true"]
        for {set index 0} {$index<[llength $tabList]} {incr index} {
            set tab [lindex $tabList $index]
	    set parent [lindex $widgetList $index]
            global ${tab}MonDataName ${tab}DataGroupValueList ${tab}DataGroupCommandList ${tab}MonDataDoRunList
            APSRadioButtonFrame .srgroup -parent $parent -variable MonDataGroupIndex \
              -buttonList "[set ${tab}MonDataName]" -label "" \
              -valueList [set ${tab}DataGroupValueList] \
              -orientation vertical \
              -commandList [set ${tab}DataGroupCommandList] \
              -limitPerRow $limitPerRow \
              -contextHelp "Choose the data group that you want to view data from."
            set i 1
            foreach doRun [set ${tab}MonDataDoRunList] name [set ${tab}MonDataName] {
                if {$doRun == 0} {
                    if {$name != "ID Source Position and Tunnel Temperature"} {
                        $parent.srgroup.frame.button$i configure -fg "\#888888"
                    }
                }
                incr i
            }
        }
        #SetMonDataStatus "Grayed out loggers have been migrated to the \"new\" Monitor Data Review.\nOld data can still be plotted from this program."
    } else {
        APSRadioButtonFrame $widget -parent $parent -label "Data group" \
          -variable MonDataGroupIndex \
          -buttonList "$MonDataName" \
          -valueList $DataGroupValueList \
          -orientation vertical \
          -contextHelp "Choose the data group that you want to view data from." \
          -commandList $DataGroupCommandList \
          -limitPerRow $limitPerRow
    }
}


proc LogMonitorDataReviewAction {args} {
    global MonDataGroupIndex MonDataRootnameList
    global MonDataStartMonth MonDataStartYear MonDataStartDay MonDataStartHour
    global MonDataEndMonth MonDataEndYear MonDataEndDay MonDataEndHour
    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 $MonDataStartHour} hour] {
        SetMonDataStatus "Invalid starting hour: $MonDataStartHour"
        return
    }
    if [catch {exec timeconvert -breakdown=year=$MonDataStartYear,day=$MonDataStartDay,month=$MonDataStartMonth,hour=$hour} \
          startTime] {
        SetMonDataStatus "$startTime"
        return
    }

    if [catch {APSConvertTimeToHours $MonDataEndHour} hour] {
        SetMonDataStatus "Invalid ending hour: $MonDataEndHour"
        return
    }
    if [catch {exec timeconvert -breakdown=year=$MonDataEndYear,day=$MonDataEndDay,month=$MonDataEndMonth,hour=$hour} \
          endTime] {
        SetMonDataStatus "$endTime"
        return
    }

    if [catch {exec logMessage -sourceId=MonitorDataReview \
                 -tag=User $apsScriptUser \
                 -tag=Host $apsScriptHost \
                 -tag=Action $action \
                 -tag=Group [lindex $MonDataRootnameList $MonDataGroupIndex] \
                 -tag=dataStartTime $startTime \
                 -tag=dataEndTime $endTime \
                 -tag=Script $apsScriptCommand} result] {
        return -code error $result
    }
}
                 
APSApplication . -name MonitorDataReview -version $CVSRevisionAuthor -overview [MonDataReviewOverview] 
dp_atexit append KillAPSExecLogs

APSScrolledStatus .status -parent .userFrame -textVariable MonDataStatus -width 60 -packOption "-fill x"

GetItemListFromConfig -group $group

MakeGroupSelectionFrame .group -parent .userFrame -group $group

MakeDateTimeFrame .datetime -parent .userFrame -rootname MonData -glitchMode $glitchMode

if 0 {
    APSButton .findfiles -parent .userFrame -text "FIND FILES" \
      -command MonDataFindFiles \
      -contextHelp "Searches for data files for the selected group between the selected dates.  Must be pressed prior to plotting whenever you change the group selection or the date interval."
}

APSButton .presetplots -parent .userFrame -text "PRESET PLOTS..." \
  -command "BringUpPlotChoices -preset 1 -glitchMode $glitchMode" \
  -contextHelp "Brings up choices for preset plotting for the data group selected."
APSButton .customplots -parent .userFrame -text "CUSTOM PLOTS..." \
  -command "BringUpPlotChoices -preset 0 -glitchMode $glitchMode" \
  -contextHelp "Brings up choices for custom plotting for the data group selected.  These are typically prepared using quickSDDSplot to save plot commands."
APSButton .sddsplot -parent .userFrame -text "quickSDDSplot..." \
  -command LaunchQuickSDDSPlot \
  -contextHelp "Launches quickSDDSplot with the selected data as input."
APSButton .sddsexport -parent .userFrame -text "EXPORT..." \
  -command LaunchsddsExportData \
  -contextHelp "Launches sddsExportData with the selected data as input, allowing you to make spreadsheet or text data."
APSButton .sddssearch -parent .userFrame -text "Search for PVs..." \
  -command "exec SearchDataLoggers &" \
  -contextHelp "Launches SearchDataLoggers."

