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

#
# $Log: not supported by cvs2svn $
# Revision 1.19  2005/12/07 20:38:21  shang
# fixed the bug that experiment bombs if user supplied comment has commas through replacing
#  APSMakeSafeQualifierString by APSMakeSafeQualifierStringForEval.
#
# Revision 1.18  2004/08/22 21:44:08  borland
# Tabified the interface.
#
# Revision 1.17  2004/08/22 20:31:27  bosrland
# Added command button for output file.
#
# Revision 1.16  2002/12/11 17:42:21  shang
# replace the private version of sddsexperiment by official version
#
# Revision 1.15  2002/12/11 17:41:01  shang
# added comment feature
#
# Revision 1.14  2001/04/20 16:04:08  emery
# Added "Add copy" buttons to add new entries by copying the last entry.
#
# Revision 1.13  2001/01/30 17:20:24  borland
# If user changes parameters and has a private (non-temporary) input file,
# script now detects changes and asks user if he wants to overwrite the
# input file or use it without change.
#
# Revision 1.12  1996/09/23 19:34:20  borland
# Now somewhat smarter about user-supplied input file names.  Won't try
# to overwrite user-entered input file, but will just use it.
#
# Revision 1.11  1996/09/19 21:51:32  borland
# Changed from using "exec wish" to "exec oagwish".
#
# Revision 1.10  1996/06/05 21:00:19  borland
# Added button to bring up name capture utility.
#
# Revision 1.9  1996/05/05  09:47:35  emery
# Added default values for variable and measurement parameters equal
# to the last value of the corresponding lists.
#
# Revision 1.8  1996/03/15  03:18:00  borland
# Fixed problem with configuration file write-out.  Wasn't compatible with
# direct use with sddsexperiment.
#
# Revision 1.7  1996/03/04  20:14:19  saunders
# Added revision/author to Version menu.
#
# Revision 1.6  1996/02/28 22:27:46  borland
# Added check for too few averages for standard-deviation or sigma calc by
# sddsexperiment.
#
# Revision 1.5  1996/02/28  17:24:27  borland
# Modified font for DELETE and CLEAR buttons.  Changed some labels for PV
# name entry.  Trying to make screen narrower.
#
# Revision 1.4  1996/02/28  00:00:54  borland
# Improved context help.  Uncommented statement to make new temporary input
# filename after sddsexperiment is launched.
#
# Revision 1.3  1996/01/18  21:04:02  saunders
# Modified so that variables and measurement entries are put in
# APSScroll box.
#
# Revision 1.2  1996/01/17  16:59:32  saunders
# Added /usr/local/oag/lib_patch to front to auto_path.
#
# Revision 1.1  1996/01/16  21:12:08  saunders
# Fixed log entry problem, so now comments and version numbers
# appear properly. Also, renames X.tcl files to just X.
#
#

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 CVSRevisionAuthor "\$Revision: 1.20 $ \$Author: flood $"

APSApplication . -name quickExperiment -version $CVSRevisionAuthor \
  -overview {This is the quickExperiment utility.  It provides a simple interface to the sddsexperiment program, which allows varying and measuring EPICS data, and logging the results and some statistical analysis to an SDDS file.  The data can be plotted after it is collected. You can also manipulate and display the data offline using the SDDS toolkit programs.}


set Measurements 0
set MeasurementLines 1

set Variables 0
set VariableLines 1

set mainStatus "Press ADD to enter more PV names for measurements and variables"

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

APSScrolledStatus .status -parent .userFrame -textVariable mainStatus -width 80

set tabList [APSTabFrame .main -parent .userFrame -label "" \
    -labelList [list "Measurements" "Variables" "Parameters"] \
    -width 900 -height 400]

set measWidget [lindex $tabList 0]
set varWidget [lindex $tabList 1]
set paramWidget [lindex $tabList 2]

set Steps 5

APSLabeledEntry .steps -parent $varWidget -label \
  "Steps: " -textVariable Steps -width 60 -contextHelp "Enter the number of steps (or samples) in this field."
APSLabeledEntry .postChangePause -parent $varWidget -label "Post change pause (s): " \
  -textVariable PostChangePause -width 60 \
  -contextHelp "Enter the time in seconds to wait after a variable change and before measurements are taken."

set varScroll [APSScroll .varScroll -parent $varWidget -packOption "-side top -fill both -expand true"]
set varScrollFrame $varWidget.varScroll

APSButton .addblank -parent $varWidget -text "Add Line" \
  -command "MakeNewVariableLine $varScroll" -contextHelp "Press to add another variable PV name entry line.\n\nDuring the experiment all variables will change together with the same number of steps with step size determined from their respective initial and final values."

APSButton .addcopy -parent $varWidget -text "Copy Line" \
  -command "MakeNewVariableLine $varScroll -addCopy 1" -contextHelp "Press to add another variable PV name entry line.\n\nDuring the experiment all variables will change together with the same number of steps with step size determined from their respective initial and final values."

APSButton .load -parent $varWidget -text "Load..." \
  -command LoadVariableData -contextHelp "Press to select a file from which to load PV names.  File may be a BURT request file, sddsmonitor input file, or a measurement configuration saved from this tool."

APSButton .save -parent $varWidget -text "Save..." \
  -command SaveVariableData -contextHelp "Press to save variable configuration data to a file.  Measurements can be reloaded later using LOAD NAMES..."


APSLabeledEntry .interMeasInterval -parent $measWidget \
  -label "Intermeasurement interval (s): " -packOption "-fill x" \
  -textVariable InterMeasInterval -width 60 \
  -contextHelp "Enter the time in seconds between measurements that are to be averaged."

set measScroll [APSScroll .measScroll -parent $measWidget -packOption "-side top -fill both -expand true" ]
set measScrollFrame $measWidget.measScroll

APSButton .add -parent $measWidget -text "Add Line" -command \
  "MakeNewMeasurementLine $measScroll" -contextHelp \
  "Press to add another measurement PV name entry line."

APSButton .addcopy -parent $measWidget -text "Copy Line" -command \
  "MakeNewMeasurementLine $measScroll -addCopy 1" -contextHelp \
  "Press to add another measurement PV name entry line using previous entry as starting point."

APSButton .load -parent $measWidget -text "Load..." \
  -command LoadMeasurementData -contextHelp "Press to select a file from which to load PV names.  File may be a BURT request file, sddsmonitor input file, or a measurement configuration saved from this tool."

APSButton .save -parent $measWidget -text "Save..." \
  -command SaveMeasurementData -contextHelp "Press to save measurement configuration data to a file.  Measurements can be reloaded later using LOAD NAMES..."

set InterMeasInterval 1
set PostChangePause 0
set inputFile /tmp/[APSTmpString]
set tmpInputFile 1
set outputFile ""
set comment ""

APSFrame .paramFrame -parent $paramWidget -label ""
APSLabeledEntry .input -parent $paramWidget.paramFrame.frame -label "Input file: " \
  -textVariable inputFile -width 80 \
  -contextHelp "Enter a name for the input file in this field, if you wish to.  Otherwise, a filename is generated for you. \
NOTE: This is the name of an input file to sddsexperiment that quickExperiment generates for you.  If the file you name \
exists already, it will be overwritten.  Use this field if you want quickExperiment to put the sddsexperiment input file \
in a place where you can retrieve it for later commandline use."
 
bind $paramWidget.paramFrame.frame.input.entry <Key> {set tmpInputFile 0}

APSLabeledEntry .output -parent $paramWidget.paramFrame.frame -label "Output file: " \
  -textVariable outputFile -width 78 -commandButton 1 -buttonsOnLeft 1 \
  -contextHelp "Enter a name for the output file to hold the data.  This file is not deleted by quickExperiment, so you can use the data for other purposes.  For example, you can use quickSDDSplot to plot the data."
APSLabeledEntry .comment -parent $paramWidget.paramFrame.frame -label "Comment: " \
  -textVariable comment -width 80 \
  -contextHelp "Enter the comment what you want to be saved as a parameter in the output file."

APSFrame .ops -parent $paramWidget \
  -contextHelp "Actions are started in this frame."
APSButton .ops.frame.run -parent $paramWidget -text RUN -command RunExperiment \
  -contextHelp "Launches a sddsexperiment subprocess to collect the data."
APSButton .ops.frame.new -parent $paramWidget -text "NEW..." -command "exec quickExperiment.tcl &" \
  -contextHelp "Launches a new instance of the quickExperiment screen"
APSButton .ops.frame.clear -parent $paramWidget -text "CLEAR ALL" \
  -command "ClearVarSettings $varScroll; ClearMeasSettings $measScroll; set outputFile \"\"; set logplot 0" \
  -contextHelp "Clears all of the settings for quickExperiment, including PV names and filenames."
APSButton .ops.frame.clearVar -parent $paramWidget -text "CLEAR MEAS" \
  -command "ClearMeasSettings $measScroll" \
  -contextHelp "Clears the measurement PV settings only."
APSButton .ops.frame.clearMeas -parent $paramWidget -text "CLEAR VARS" \
  -command "ClearVarSettings $varScroll" \
  -contextHelp "Clears the variable PV settings only."
APSButton .ops.frame.namecap -parent $paramWidget -text "NAME CAPTURE..." -command \
  "catch {exec namecapture &}" -contextHelp \
  "Launches an instance of the name capture utility, which is useful in making lists of process variable names for use with quickMonitor.  Use the center mouse button on any MEDM screen to get the process variable name of whatever you point at.  Hold the mouse button down and drag the name into the name capture window.  You can drop the name from there into a quickMonitor entry box, or have name capture put names in a file that you can load into quickMonitor using LOAD INPUT..."


proc LoadMeasurementData {} {
    global env measScroll 
    set filename [APSFileSelectDialog .chooseInputFile -listDir $env(HOME)]
    if [string length $filename]==0 { 
        return 
    }
    if [string first " " $filename]!=-1 {
        SetMainStatus "Filename may not have spaces in it."
        return
    }
    if {![APSCheckSDDSFile -fileName $filename]} {
        SetMainStatus "$filename is not an SDDS file."
        return
    }
    set colNames [APSGetSDDSNames -fileName $filename -class column]
    if {[llength $colNames]<1} {
        SetMainStatus "$filename doesn't contain any data columns from which to get PV names."
        return 
    }
    if {[lsearch -exact $colNames "ControlName"]!=-1} {
        set columnName ControlName
    } elseif {[lsearch -exact $colNames "Device"]!=-1} {
        set columnName Device
    } else {
        SetMainStatus "$filename doesn't contain any data columns from which to get PV names."
        return
    }
    set names [APSGetSDDSColumn -fileName $filename -column $columnName -page 0]
    if {[llength $names]==0} {
        SetMainStatus "$filename has no process variable names."
        return
    }
    set iyesno(y) 1
    set iyesno(n) 0
    if {[lsearch -exact $colNames NumberToAverage]!=-1 && [lsearch -exact $colNames IncludeStDev]!=-1 && \
          [lsearch -exact $colNames IncludeSigma]!=-1} {
        set nAverage [APSGetSDDSColumn -fileName $filename -column NumberToAverage -page 0]
        set stDev [APSGetSDDSColumn -fileName $filename -column IncludeStDev -page 0]
        set sigma [APSGetSDDSColumn -fileName $filename -column IncludeSigma -page 0]
	ClearMeasSettings $measScroll 0
        set index 0
        foreach name $names {
            MakeNewMeasurementLine $measScroll -pvName $name \
              -nAverage [lindex $nAverage $index] \
              -includeStDev $iyesno([lindex $stDev $index]) \
              -includeSigma $iyesno([lindex $sigma $index]) 
            incr index
        }
    } else {
	ClearMeasSettings $measScroll 0
        foreach name $names {
            MakeNewMeasurementLine $measScroll -pvName $name
        }
    }
    SetMainStatus "Measurement data loaded from $filename."
}

proc SaveMeasurementData {} {
    global MeasurementLines MeasPVname doStd doSigma Average

    set PVcount 0
    for {set i 1} {$i<$MeasurementLines} {incr i} {
        if [string length $MeasPVname($i)]!=0 {
            incr PVcount
        }
    }

    if $PVcount==0 {
        SetMainStatus "No measurements specified--can't save."
        return
    }
    set filename [APSInfoDialog .[APSTmpString] -name "Measurement Save File Entry" \
                    -contextHelp "Enter the filename to save the measurement configuration to." \
                    -width 80 -infoMessage "Enter the filename to save the measurement configuration to."]
    if [string length $filename]==0 {
        return
    }
    if [string first " " $filename]!=-1 {
        SetMainStatus "Filename may not contain spaces--nothing saved."
        return
    }
    set fid [open $filename w]
    set yesno(0) n
    set yesno(1) y
    puts $fid "SDDS1"
    puts $fid "&column name=ControlName type=string &end"
    puts $fid "&column name=ReadbackName type=string &end"
    puts $fid "&column name=NumberToAverage type=long &end"
    puts $fid "&column name=IncludeStDev type=character &end"
    puts $fid "&column name=IncludeSigma type=character &end"
    puts $fid "&data mode=ascii no_row_counts=1 &end"
    for {set i 1} {$i<$MeasurementLines} {incr i} {
        if [string length $MeasPVname($i)]==0 continue
        puts $fid "$MeasPVname($i) $MeasPVname($i) $Average($i) $yesno($doStd($i)) $yesno($doSigma($i))"
    }
    close $fid
    SetMainStatus "Save completed to file $filename."
}

proc ClearMeasSettings {widget0 {popUp 1}} {
    global MeasurementLines MeasPVname doStd doSigma Average 

    if {$popUp} {
	if {![APSYesNoPopUp "Really? Clear measurement settings?"]} { return }
    }
    for {set i $MeasurementLines} {$i>0} {incr i -1} {
        if {[winfo exists $widget0.m$i]} { destroy $widget0.m$i}
        set MeasPVname($i) ""
        set doStd($i) 0
        set doSigma($i) 0
        set Average($i) 1
    }
    set MeasurementLines 1
    SetMainStatus "Press ADD to enter measurement or variable PV names for sddsexperiment"
}

proc ClearVarSettings {widget0 {popUp 1}} {
    global VariableLines VarPVname InitValue FinalValue Relative

    if {$popUp} {
	if {![APSYesNoPopUp "Really? Clear variable settings?"]} { return }
    }
    for {set i $VariableLines} {$i>0} {incr i -1} {
        if {[winfo exists $widget0.m$i]} { destroy $widget0.m$i}
        set VarPVname($i) ""
        set InitValue($i) 0
        set FinalValue($i) 0
        set Relative($i) 0
    }
    set VariableLines 1
    SetMainStatus "Press ADD to enter measurement or variable PV names for sddsexperiment"
}

proc MakeNewMeasurementLine {widget0 args} {
    global measScrollFrame
    global MeasurementLines MeasPVname 
    global doStd doSigma Average

    set addCopy 0
    APSParseArguments {addCopy}
    APSFrame .m$MeasurementLines -parent $widget0  -packOption "-anchor w"
    set widget $widget0.m$MeasurementLines.frame
    $widget configure -relief flat -bd 0

    APSFrame .op  -parent $widget -packOption "-side left" 
    $widget.op.frame configure -relief flat -bd 0 
    APSFrame .data  -parent $widget -height 1
    $widget.data.frame configure -relief flat -bd 0 

    if {!$addCopy} { 
        set pvName ""
        set nAverage 1
        set includeStDev 0
        set includeSigma 0
    } else {
        set lastMeas [expr $MeasurementLines - 1]
        set pvName $MeasPVname($lastMeas)
        set nAverage $Average($lastMeas)
        set includeStDev $doStd($lastMeas)
        set includeSigma $doSigma($lastMeas)
    }        
    APSParseArguments {pvName nAverage includeStDev includeSigma}
    
    APSButton .delete -parent $widget.op.frame -text "DELETE" \
      -command "DeleteMeasurementLine $widget0 $MeasurementLines" \
      -contextHelp "Press to delete the corresponding PV name entry line." 
    $widget.op.frame.delete configure -bd 0
    $widget.op.frame.delete.button configure -font -adobe-courier-medium-r-normal-*-12-*-*-*-*-*-*-*

    APSButton .clear -parent $widget.op.frame -text "CLEAR" \
      -command "ClearMeasurementLine $widget0 $MeasurementLines" \
      -contextHelp "Press to clear the corresponding PV name entry line." 
    $widget.op.frame.clear configure -bd 0
    $widget.op.frame.clear.button configure -font -adobe-courier-medium-r-normal-*-12-*-*-*-*-*-*-*
    
    set MeasPVname($MeasurementLines) $pvName
    APSLabeledEntry .x -parent $widget.data.frame -label "PV:" -textVariable \
      MeasPVname($MeasurementLines) -width 30 \
      -contextHelp "Enter the name of a readback process variable (PV) in this field." \
      -packOption "-side left -expand true"
    $widget.data.frame.x configure -bd 0
    set Average($MeasurementLines) $nAverage
    APSLabeledEntry .ave -parent $widget.data.frame -label "no. to average" -textVariable \
      Average($MeasurementLines) -width 5 \
      -contextHelp "Enter the number of PV readings to average in this field." \
      -packOption "-side left"
    set doStd($MeasurementLines) $includeStDev
    set doSigma($MeasurementLines) $includeSigma
    $widget.data.frame.ave configure -bd 0
    APSCheckButtonFrame .stats -parent $widget.data.frame -buttonList {stddev sigma} -label {} \
      -variableList "doStd($MeasurementLines) doSigma($MeasurementLines)" -orientation horizontal -allNone 0 \
      -contextHelp "Press these buttons to enable standard deviation or sigma calculation by sddsexperiment."
    $widget.data.frame.stats configure -bd 0
    
    incr MeasurementLines
    tkwait visibility $widget.data.frame.stats
    APSScrollAdjust $measScrollFrame -numVisible 5
}

proc MakeNewVariableLine {widget0 args} {
    global varScrollFrame
    global VariableLines VarPVname 
    global InitValue FinalValue Relative

    set addCopy 0
    APSParseArguments {addCopy}
    APSFrame .m$VariableLines -parent $widget0 -packOption "-anchor w -fill x"
    set widget $widget0.m$VariableLines.frame
    $widget configure -relief flat -bd 0
    APSFrame .op  -parent $widget -packOption "-side left" 
    $widget.op.frame configure -relief flat -bd 0
    APSFrame .data  -parent $widget -height 1
    $widget.data.frame configure -relief flat -bd 0

    if {!$addCopy} {
        set pvName ""
        set initVal 0
        set finalVal 0
        set relative 0
    } else {
        set lastVar [expr $VariableLines - 1]
        set pvName $VarPVname($lastVar)
        set initVal $InitValue($lastVar)
        set finalVal $FinalValue($lastVar)
        set relative $Relative($lastVar)
    }        
    APSParseArguments {pvName initVal finalVal relative}

    APSButton .delete -parent $widget.op.frame -text "DELETE" \
      -command "DeleteVariableLine $widget0 $VariableLines" \
      -contextHelp "Press to delete the corresponding PV name entry line." 
    $widget.op.frame.delete configure -bd 0
    $widget.op.frame.delete.button configure -font -adobe-courier-medium-r-normal-*-12-*-*-*-*-*-*-*

    APSButton .clear -parent $widget.op.frame -text "CLEAR" \
      -command "ClearVariableLine $widget0 $VariableLines" \
      -contextHelp "Press to clear the corresponding PV name entry line." 
    $widget.op.frame.clear configure -bd 0
    $widget.op.frame.clear.button configure -font -adobe-courier-medium-r-normal-*-12-*-*-*-*-*-*-*
    
    set VarPVname($VariableLines) $pvName
    APSLabeledEntry .x -parent $widget.data.frame -label "PV:" -textVariable \
      VarPVname($VariableLines) -width 30 \
      -contextHelp "Enter the name of a variable process variable (PV) in this field." \
      -packOption "-side left"
    $widget.data.frame.x configure -bd 0
    set InitValue($VariableLines) $initVal
    APSLabeledEntry .init -parent $widget.data.frame -label "Initial:" -textVariable \
      InitValue($VariableLines) -width 10 \
      -contextHelp "Enter the initial value for the variable process variable (PV) in this field." \
      -packOption "-side left"
    $widget.data.frame.init configure -bd 0
    set FinalValue($VariableLines) $finalVal
    APSLabeledEntry .final -parent $widget.data.frame -label "Final:" -textVariable \
      FinalValue($VariableLines) -width 10 \
      -contextHelp "Enter the final value for the variable process variable (PV) in this field." \
      -packOption "-side left"
    $widget.data.frame.final configure -bd 0
    set Relative($VariableLines) $relative
    APSCheckButtonFrame .rel -parent $widget.data.frame -label {} -buttonList {Relative} \
      -variableList Relative($VariableLines) -orientation horizontal \
      -contextHelp "If checked, then the variation range is defined relative to the PV's original value." \
      -packOption "-side left"
    $widget.data.frame.rel configure -bd 0
    
    incr VariableLines
    tkwait visibility $widget.data.frame.rel
    APSScrollAdjust $varScrollFrame -numVisible 5
}
#####

proc SaveVariableData {} {
    global VariableLines VarPVname InitValue FinalValue Relative

    set PVcount 0
    for {set i 1} {$i<$VariableLines} {incr i} {
        if [string length $VarPVname($i)]!=0 {
            incr PVcount
        }
    }

    if $PVcount==0 {
        SetMainStatus "No variables specified--can't save."
        return
    }
    set filename [APSInfoDialog .[APSTmpString] -name "Variable Save File Entry" \
                    -contextHelp "Enter the filename to save the variable configuration to." \
                    -width 80 -infoMessage "Enter the filename to save the variable configuration to."]
    if [string length $filename]==0 {
        return
    }
    if [string first " " $filename]!=-1 {
        SetMainStatus "Filename may not contain spaces--nothing saved."
        return
    }
    set vfid [open $filename w]
    set yesno(0) n
    set yesno(1) y
    puts $vfid "SDDS1"
    puts $vfid "&column name=ControlName type=string &end"
    puts $vfid "&column name=ReadbackName type=string &end"
    puts $vfid "&column name=Initial type=string &end"
    puts $vfid "&column name=Final type=string &end"
    puts $vfid "&column name=Relative type=character &end"
    puts $vfid "&data mode=ascii no_row_counts=1 &end"
    for {set i 1} {$i<$VariableLines} {incr i} {
        if [string length $VarPVname($i)]==0 continue
        puts $vfid "$VarPVname($i) $VarPVname($i) $InitValue($i) $FinalValue($i) $Relative($i)"
    }
    close $vfid
    SetMainStatus "Save completed to file $filename."
}




proc DeleteMeasurementLine {widget0 number} {
    global MeasurementLines MeasPVname 
    if {$number} {
        destroy $widget0.m$number
        set MeasPVname($number) ""
    } else {
        bell
    }
}

proc ClearMeasurementLine {widget0 number} {
    global MeasurementLines MeasPVname
    global doStd doSigma Average

    set MeasPVname($number) ""
    set doStd($number) 0
    set doSigma($number) 0
    set Average($number) 1
}

proc DeleteVariableLine {widget0 number} {
    global VariableLines VarPVname 
    if {$number} {
        destroy $widget0.m$number
        set VarPVname($number) ""
    } else {
        bell
    }
}

proc ClearVariableLine {widget0 number} {
    global VariableLines VarPVname 
    global InitValue FinalValue Relative

    set VarPVname($number) ""
    set InitValue($number) 0
    set FinalValue($number) 0
    set Relative($number) 0
}

###Add load variable procedure

proc LoadVariableData {} {
    global env varScroll 
    set filename [APSFileSelectDialog .chooseInputFile -listDir $env(HOME)]
    if [string length $filename]==0 { 
        return 
    }
    if {![APSCheckSDDSFile -fileName $filename]} {
        SetMainStatus "$filename is not an SDDS file."
        return
    }
    set colNames [APSGetSDDSNames -fileName $filename -class column]
    if {[llength $colNames]<1} {
        SetMainStatus "$filename doesn't contain any data columns from which to get PV names."
        return 
    }
    if {[lsearch -exact $colNames "ControlName"]!=-1} {
        set columnName ControlName
    }  else {
        SetMainStatus "$filename doesn't contain any data columns from which to get PV names."
        return
    }
    set names [APSGetSDDSColumn -fileName $filename -column $columnName -page 0]
    if {[llength $names]==0} {
        SetMainStatus "$filename has no process variable names."
        return
    }
    set iyesno(y) 1
    set iyesno(n) 0
    set InitValue [APSGetSDDSColumn -fileName $filename -column Initial -page 0]
    set FinalValue [APSGetSDDSColumn -fileName $filename -column Final -page 0]
    set Relative [APSGetSDDSColumn -fileName $filename -column Relative -page 0]
    ClearVarSettings $varScroll 0
    set index 0
       foreach name $names init $InitValue final $FinalValue \
	relative $Relative {
  MakeNewVariableLine $varScroll -pvName $name -initVal $init \
	-finalVal $final -relative $relative
       }

    

    SetMainStatus "Variable data loaded from $filename."
}
###

set outputListLength 0
proc RunExperiment {} {
    global MeasurementLines MeasPVname doStd doSigma Average comment
    global VariableLines VarPVname InitValue FinalValue Relative
    global outputFile inputFile tmpInputFile
    global PostChangePause InterMeasInterval Steps logplot
    global outputList plotComList plotLogScale outputListLength

    if {[string length $inputFile]==0} {
        set tmpInputFile 1
        set inputFile /tmp/[APSTmpString]
    }
    if {[string length $outputFile]==0} {
        SetMainStatus "Supply an output filename."
        bell
        return
    }
    if {[string first " " $outputFile]!=-1} {
        SetMainStatus "Spaces are not allowed in the filename"
        bell
        return
    }
    if {[file exists $outputFile]} {
        set ok [APSYesNoPopUp "Delete existing $outputFile?"]
        if {!$ok} {
            SetMainStatus "Supply a new output filename"
            return
        } else {
            exec rm $outputFile
        }
    }


    set plot ""
    # make a PV list for later sorting and finding duplicates
    set PVlist {}
    set count 0
    for {set i 1} {$i<$MeasurementLines} {incr i} {
        if {[string length $MeasPVname($i)]} {
            if {[string first " " $MeasPVname($i)]!=-1} {
                SetMainStatus "Space found in PV name:$MeasPVname($i)"
                bell
                return
            }
            if {($doStd($i) || $doSigma($i)) && $Average($i)<2} {
                SetMainStatus "Too few points for sigma/standard-deviationfor $MeasPVname($i)"
                bell
                return
            }
            set PVlist [linsert $PVlist 0 $MeasPVname($i)]
            incr count
        }
    }
    if {!$count} {
        SetMainStatus "No measurement PV names given."
        bell
        return
    }

    
    set count 0
    for {set i 1} {$i<$VariableLines} {incr i} {
        if {[string length $VarPVname($i)]} {
            if {[string first " " $VarPVname($i)]!=-1} {
                SetMainStatus "Space found in PV name:$VarPVname($i)"
                bell
                return
            }  
            set PVlist [linsert $PVlist 0 $VarPVname($i)]
            incr count
        }
    }
    if {!$count} {
        SetMainStatus "No variable PV names given."
        bell
        return
    }

    #check for duplicate PVs
    set FoundDuplicate 0
    set PVlist [lsort -ascii $PVlist]
    for {set i 1; set j 0} {$i<[llength $PVlist]} {incr i; incr j} {
        if {![string compare [set PV [lindex $PVlist $j]] [lindex $PVlist $i]] } {
            APSInfoWindow .info$i -name "Duplicate PV $PV" \
              -infoMessage "Found two PV of the same name ($PV). Check both lists of measurement and variable PVs.\n\nsddsexperiment not started."
            set FoundDuplicate 1
        }
    }
    if {$FoundDuplicate} {return}

    set tmpfile /tmp/[APSTmpString]
    set fid [open $tmpfile w]
    # create sddsexperiment input file here.
    set plot ""
    for {set i 1} {$i<$MeasurementLines} {incr i} {
        if {[string length $MeasPVname($i)]} {
            puts $fid "&measurement control_name=$MeasPVname($i), column_name=$MeasPVname($i),"
            puts $fid "        include_standard_deviation=$doStd($i), include_sigma=$doSigma($i),"
            puts $fid "        number_to_average=$Average($i), &end"
            if {[string length $plot]==0} {
                set plot $MeasPVname($i)
            } else {
                set plot "$plot,$MeasPVname($i)"
            }
        }
    }
    for {set i 1} {$i<$VariableLines} {incr i} {
        if {[string length $VarPVname($i)]} {
            puts $fid "&variable control_name=$VarPVname($i), column_name=$VarPVname($i),"
            puts $fid "        initial_value=$InitValue($i), final_value=$FinalValue($i),"
            puts $fid "        index_limit=$Steps, index_number=0,"
            puts $fid "        relative_to_original=$Relative($i), &end"
        }
    }
    puts $fid "&execute post_change_pause=$PostChangePause,"
    puts $fid "        intermeasurement_pause=$InterMeasInterval,"
    puts $fid "        &end"
    close $fid
    if {$tmpInputFile || ![file exists $inputFile]} {
        file copy -force $tmpfile $inputFile
        file delete -force $tmpfile
    } else {
        if {[catch {exec diff $inputFile $tmpfile | wc -l} result] || \
              [string length $result]} {
            set choice [APSMultipleChoice [APSUniqueName .] \
                          -question "Parameters are inconsistent with $inputFile.  What do you want to do?" \
                          -labelList "Abort \"Use $inputFile\" \"Replace $inputFile\"" \
                          -returnList {Abort Use Replace}]
            switch $choice {
                Abort {
                    return
                }
                Replace {
                    file copy -force $inputFile ${inputFile}~
                    file copy -force $tmpfile $inputFile
                }
            }
        }
    }

    set date [exec date]
    SetMainStatus "Running.... (started $date)."
    set outputList($outputListLength) $outputFile
    if [string length $plot] {
        set plotComList($outputListLength) "sddsplot -column=$VarPVname(1),($plot) -graph=line,vary -legend $outputFile"
    } else {
        set plotComList($outputListLength) ""
    }
    set comCmd ""
    if [string length $comment] {
	set com [APSMakeSafeQualifierStringForEval $comment]
	set comCmd \"-comment=$com\"
    }
    APSExecLog .job$outputListLength -unixCommand "sddsexperiment $inputFile $outputFile -verb -summ $comCmd" \
      -contextHelp "This window is running a quickExperiment subprocess." -width 80 \
      -callback "AddPlotCommandToFile $outputFile $plotComList($outputListLength)"
    .job$outputListLength.userFrame.text.text configure  -width 80
    if $tmpInputFile {
        set inputFile /tmp/[APSTmpString]
    }
    if [string length $plot] {
        AddReplotButton .job$outputListLength $outputListLength
    }
    incr outputListLength
}


proc AddPlotCommandToFile {outputFile args} {
    set command [APSMakeSafeQualifierString [join $args]]
    if ![string length $command] {
        return
    }
    exec sddsprocess $outputFile [set tmpfile /tmp/[APSTmpString]] -nowarning \
      "-print=param,sddsplotCommand01,$command" 
    exec cp $tmpfile $outputFile
    exec rm $tmpfile
}

proc AddReplotButton {parent index} {
    global outputList plotComList plotLogScale plotSeparately plotSameScale
    APSFrame .rprow -parent $parent
    set plotLogScale($index) 0
    set plotSeparately($index) 0
    set plotSameScale($index) 0
    APSButton .plot -parent $parent.rprow.frame \
      -text "Plot $outputList($index)" \
      -command "ReplotData $index" \
      -contextHelp "This button replots the data in file $outputList($index)"
    APSCheckButtonFrame .plotOptions -parent $parent.rprow.frame -label {} \
      -buttonList [list "Log plot" "Separate plots" "Same scale"] \
      -variableList [list plotLogScale($index) plotSeparately($index) plotSameScale($index)] \
      -contextHelp "Adds various options to the sddsplot command" \
      -orientation horizontal -packOption "-side left"
    
}

proc ReplotData {index} {
    global outputList plotComList plotLogScale plotSeparately plotSameScale
    SetMainStatus "Plotting  $outputList($index)"
    set extraArgs ""
    if $plotSameScale($index) {
        set extraArgs "$extraArgs -samescale=y"
    }
    if $plotSeparately($index) {
        set extraArgs "$extraArgs -separate"
    }
    if $plotLogScale($index) {
        eval exec "$plotComList($index)  -mode=y=log \"-ylabel=edit=i/Log\\\$b10\\\$n /\" $extraArgs &"
    } else {
        eval exec "$plotComList($index) $extraArgs &"
    }
}


MakeNewMeasurementLine $measScroll
MakeNewVariableLine $varScroll

