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


set auto_path [linsert $auto_path 0  /usr/local/oag/apps/lib/$env(HOST_ARCH)]
set auto_path [linsert $auto_path 0 /usr/local/oag/lib_patch/$env(HOST_ARCH)]
APSDebugPath

set CVSRevisionAuthor "\$Revision: 1.0 $ \$Author: shang $"

APSApplication . -name quickDaqPVGroup -version $CVSRevisionAuthor \
  -overview {This is the quickDaqMonitor utility.  It provides a simple interface to the PvAggregator  program, which allows logging EPICS data to an SDDS file base on changes of pv values including traditional CA pvs and new EPIC7 pva channels.  The data can be plotted after it is collected, or during collection.  You can also manipulate and display the data offline using the SDDS toolkit programs.}

set monitors 0
set monitorLines 0

set mainStatus "Press ADD to enter more PV names for monitoring"

proc SetMainStatus {text} {
    global mainStatus
    set mainStatus "[exec date]: $text"
    update
}



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

frame .userFrame.lines  -bd 4  -relief raised
pack .userFrame.lines -side top -fill x

set pvScroll [APSScroll .sw -parent .userFrame.lines -name "PV List"]
set pvScrollFrame .userFrame.lines.sw

#APSButton .pvScrollAdd -parent .userFrame.lines -text ADD -command \
#  "MakeNewMonitorLine $pvScroll" \
# -contextHelp "Press to add PV name entry slots."
APSButton .pvScrollAdd -parent .userFrame.lines -text ADD -command "addNewPV"

set inputConfig ""
set runTime 60
set outputDir [APSGoToDailyDirectory -subdirectory daqMon]

set rootname DAQtest-000
APSLabeledEntry .config -parent .userFrame -label "Input config for PVs:" -width 70 -fileSelectButton 1 \
    -textVariable inputConfig -contextHelp "input config file for list of PVs, must have ControlName column, ReadbackName column is optional."
APSButton .load -parent .userFrame.config -packOption "-side right" -text "load" -command LoadInputParameters
APSLabeledEntry .dir -parent .userFrame -label "Output Directory: " \
  -textVariable outputDir -width 70 \
  -contextHelp "Enter a name for the output directory to hold the data. "
APSButton .pick -parent .userFrame.dir \
  -text F -packOption  "-side right" \
  -command "findDir -dirVariable outputDir" \
  -contextHelp "Bring up a directory selection dialog box to choose the directory."
APSButton .daily -parent .userFrame.dir \
  -text Daily -packOption "-side right"  \
  -command "set outputDir  [APSGoToDailyDirectory -subdirectory daqMon]"

APSLabeledEntry .rootname -parent .userFrame -label "Rootname:" \
  -textVariable rootname -width 70 -contextHelp "enter a rootname for the input and output file."
APSFrameGrid .grid -parent .userFrame -xList {x1 x2}

set w1 .userFrame.grid.x1
set w2 .userFrame.grid.x2
set width 20
set chanName PVAname
set updatePeriod 1
set runTime 60
set logOutput 0
set nworkers 1
set setValue 0
set setStepSize 0.5
set totalSetValue 0
set setFile ""
set readIndex 0
set deltaMode 1

APSLabeledEntry .name -parent $w1 -label "PVA channel name:" -textVariable chanName -width $width \
  -contextHelp "provide the group PVA channel name, which will be the single PV data object for the provided channels."
APSLabeledEntry .update -parent $w2 -label "Group update period (seconds):" \
    -textVariable updatePeriod -width $width \
    -contextHelp "group update period in seconds. default 10 seconds."
APSLabeledEntry .time -parent $w1 -label "Run time (seconds):" -textVariable runTime -width $width \
    -contextHelp "group channel run time, 0 indicates inifinite time; default 60.0 second."
APSLabeledEntry .works -parent $w2 -label "Number of CA workers:" -textVariable nworkers -width $width \
    -contextHelp "number of CA workers fro setting PV values (default: 10)"
APSRadioButtonFrame .log -parent $w1 -label "Log data to output file?" -buttonList {Yes No} \
    -valueList {1 0} -variable logOutput -orientation horizontal

APSLabeledEntry .index -parent $w2 -label "Read value file index:" -width 20 -textVariable readIndex
APSLabeledEntry .step1 -parent $w1 -label "Set step size" -width 20 -textVariable setStepSize
APSLabeledEntry .step -parent $w2 -label "Set value:" -textVariable setValue -width 20
APSButton .add -parent $w2.step -packOption "-side right" -text "->" -command "IncrementDelta -add 1" -highlight 1 -size small
APSButton .minus -parent $w2.step -packOption "-side right" -text "<-" -command "IncrementDelta -add 0" -highlight 1 -size small
APSButton .set -parent $w2.step -packOption "-side right" -text "set"  -command SetPVGroup  -highlight 1 -size small]
set mode add
APSRadioButtonFrame .add -parent $w1 -label "Set value  mode?" -buttonList {add absolute set multiply} -valueList {add absolute set multiply} \
    -variable mode -orientation horizontal

APSLabeledEntry .setfile -parent .userFrame -textVariable setFile -width 70 -label "Set values file:" \
    -fileSelectButton 1
APSButton .set -parent .userFrame.setfile -packOption "-side right" -size small -text "Set" -highlight 1 -command "SetPVGroup -file 1" \
    -contextHelp "set pv values by file"
APSButton .edit -parent .userFrame.setfile -packOption "-side right" -size small -text "Edit" -highlight 1 -command "EditSetFile"  \
    -contextHelp "edit set file."

APSButton .run -parent .userFrame -text CREAT -command RunPVGroup \
  -contextHelp "Launches a monitoring subprocess for the PVA group channel."
#APSButton .set -parent .userFrame -text SET -command SetPVGroup \
#    -contextHelp "set PV values."
APSButton .read -parent .userFrame -text READ -command ReadPVGroup \
    -contextHelp "Read PV values."

APSButton .new -parent .userFrame -text "NEW..." -command "exec quickDaqPVGroup &" \
  -contextHelp "Launches a new instance of the quickDaqPVGroup screen"
APSButton .clear -parent .userFrame -text "CLEAR ALL" -command "ClearAllSettings $pvScroll" \
  -contextHelp "Clears all of the settings, including PV names and filenames."
APSButton .save -parent .userFrame -text "SAVE CONFIG..." -command SaveMonitorList \
  -contextHelp "Allows you to save the configuration, which includes the list of PVs, the interval, and the number of steps"
APSButton .load -parent .userFrame -text "LOAD CONFIG..." -command LoadExistingInput \
  -contextHelp "Loads PV names and run parameters from a previously saved configuration file." 
APSButton .namecap -parent .userFrame -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..."

#APSButton .plot -parent .userFrame -text "Plot..." -command PlotFileChoice
frame .userFrame.review -bd 4 -relief raised
pack .userFrame.review -side top -fill x

#APSFrame .set1 -parent .userFrame -packOption "-side top"
#set f1 .userFrame.set1.frame
#APSLabeledEntry .delta -parent $f1 -width 20 -label "Set delta:" -textVariable setDelta
#APSButton .add -parent $f1.delta -packOption "-side right" -text "->" -command "SetDelta -add 1"
#APSButton .minus -parent $f1.delta -packOption "-side right" -text "<-" -command "SetDelta -add 0"


set fileSelListDir $env(HOME)

proc LoadInputParameters {args} {
    global inputConfig
    if {![string length $inputConfig] || ![file exist $inputConfig]} {
	SetMainStatus "input config not exist!"
	return
    }
    set pars [exec sddsquery -par $inputConfig]
    foreach par $pars {
	global $par
	set $par [exec sdds2stream -par=$par $inputConfig]
	if [catch {expr [set $par]/2.0} result] {
	    #SetMainStatus "$par $result"
	    #string, do nothing
	} else {
	    set $par [format %0.2f [set $par]]
	}
    }
    update
}

proc PlotFileChoice {args} {
    global outputDir rootname selectFile
    cd $outputDir
    set files1 [glob -nocomplain *.sdds]
    set files2 [glob -nocomplain *.wf]
    set files [concat $files1 $files2]
    if ![llength $files] {
        SetMainStatus "No files found for plot"
        return
    }
    set selectFile ""
     APSScrolledListWindow .scrollFile -name "Select A File" \
      -label "Select fields" -itemList $files -selectionVar selectFile 
    tkwait variable selectFile
    if ![string length $selectFile] {
        return
    }
    foreach file $selectFile {
        PlotFile -file $file
    }
}

proc PlotFile {args} {
    set file ""
    global outputDir
    APSParseArguments {file}
    if ![file exist $outputDir/$file] {
        SetMainStatus "$outputDir/$file does not exist"
        return
    }
    if [string match *.sdds $file] {
        exec sddsplot $outputDir/$file -grap=line,vary  -col=Time,* -yexclude=Time,OnjectId $outputDir/$file &

    } elseif [string match *.wf $file] {
        if ![file exist $outputDir/$file.proc] {
            exec sddsprocess $outputDir/$file $outputDir/$file.proc -define=col,Index,i_row,type=long 
              
        }
        set col [exec sddsquery -col $outputDir/$file]
        exec sddsplot -grap=line,vary -split=page -col=Index,$col $outputDir/$file.proc &
    }
}


proc LoadExistingInput {args} {
    set filename ""
    if {[APSStrictParseArguments {filename}]} {
        return -code error "LoadExistingInput: invalid arguments"
    }
    global pvScroll fileSelListDir
    global monitorLines PVname Steps Interval
    if ![string length $filename] {
        set filename [APSFileSelectDialog .chooseInputFile \
                        -listDir $fileSelListDir]
        if {$filename==""} { 
            return 
        }
    }
    set fileSelListDir [file dirname $filename]
    if {![APSCheckSDDSFile -fileName $filename]} {
        SetMainStatus "$filename is not an SDDS file."
        return
    }
    set names [APSGetSDDSNames -fileName $filename -class column]
    if {[llength $names]<1} {
        SetMainStatus "$filename is not a valid sddsmonitor input file."
        return 
    }
    if {[lsearch -exact $names "ControlName"]!=-1} {
        set columnName ControlName
    } elseif {[lsearch -exact $names "Device"]!=-1} {
        set columnName Device
    } else {
        SetMainStatus "$filename is not a valid input file."
        return
    }
    if {[lsearch -exact $names "ReadbackName"]!=-1} {
         set columnNameRB ReadbackName
    } else {
         set columnNameRB $columnName
    }
    
    set names [APSGetSDDSColumn -fileName $filename -column $columnName -page 0]
    set namesRB [APSGetSDDSColumn -fileName $filename -column $columnNameRB -page 0]
    
    if {[llength $names]==0} {
        SetMainStatus "$filename has no process variable names."
        return
    }
    if {$monitorLines==1 && [string length $PVname(0.PV)]==0} {
        incr monitorLines -1
    }
    set i 0
    foreach namePV $names nameRB $namesRB {
        MakeNewMonitorLine $pvScroll -pvNamePV $namePV -pvNameRB $nameRB 
        incr i
        update
    }
    set pars [exec sddsquery -par $filename]
    foreach par $pars {
        global $par
        set $par [exec sdds2stream -par=$par $filename]
	if [catch {expr [set $par]/1.0} result] {
	} else {
	    set $par [format %0.3f [set $par]]
	}
    }
    set nworkers [format %.0f $nworkers]
    set logOutput [format %.0f $logOutput]
    
    SetMainStatus "Loaded configuration from file $filename"
}


proc ClearAllSettings {widget0} {
    global monitorLines PVname outputFile logplot
    if {![APSYesNoPopUp "Really? Clear all settings?"]} { return }
    for {set i 0} {$i<$monitorLines} {incr i} {
        if {[winfo exists $widget0.m$i]} { destroy $widget0.m$i}
        set PVname($i.PV) ""
        set PVname($i.RB) ""
    }
    set monitorLines 0
    set outputFile ""
    set logplot 0
    SetMainStatus "Press ADD to enter PV names for monitoring"
}

proc CheckPVType {args} {
    set pvName ""
    APSParseArguments {pvName}
    
    set elementCount 1
    if [catch {exec cainfo $pvName} caResult] {
	return -code error "Error: only scalar CA pv is allowed!"
    }
}

proc MakeNewMonitorLine {widget0 args} {
    global pvScrollFrame
    global monitorLines PVname
    set pvNamePV ""
    set pvNameRB ""
    APSParseArguments {pvNamePV pvNameRB}

    
    for {set i 0} {$i<$monitorLines} {incr i} {
        if [string compare $pvNamePV $PVname($i.PV)]==0 {
            SetMainStatus "$pvNamePV already added."
            return
        }
    }
    
    set widget $widget0.m$monitorLines
    if ![winfo exists $widget] {
        frame $widget -bd 1
        pack $widget -fill x
        frame $widget.data
        frame $widget.op 
        frame $widget.op1
        pack $widget.data $widget.op $widget.op1 -side left

        APSButton .delete -parent $widget.op -text "DELETE" \
          -command "DeleteMonitorLine $widget0 $monitorLines" \
          -contextHelp "Press to delete the corresponding PV name entry line."
        $widget.op.delete configure -bd 0
        $widget.op.delete.button configure -font -adobe-courier-medium-r-normal-*-12-*-*-*-*-*-*-*
        APSButton .clear -parent $widget.op -text "CLEAR" \
          -command "ClearMonitorLine $widget0 $monitorLines" \
          -contextHelp "Press to clear the corresponding PV name entry line."
        
        $widget.op.clear configure -bd 0
        $widget.op.clear.button configure -font -adobe-courier-medium-r-normal-*-12-*-*-*-*-*-*-*
	set PVname($monitorLines.RB) $pvNameRB
        APSLabeledEntry .x -parent $widget.data -label " PV name:" \
          -textVariable PVname($monitorLines.PV) -width 30 -packOption "-side left" \
          -contextHelp "Enter the name of a process variable (PV) to be monitored in this field."
        bind $widget.data.x.entry <Return> "CheckPVType -number $monitorLines -widget $widget.data.x "
	APSLabeledEntry .x1 -parent $widget.data -label " readback:" \
	    -textVariable PVname($monitorLines.RB) -width 20 -packOption "-side left" \
	    -contextHelp "Enter the readback name of a process variable (PV) to be monitored in this field."
        
        
       # APSLabeledEntry .y -parent $widget.data -label " PV readback:" \
       #   -textVariable PVname($monitorLines.RB) -width 30 -packOption "-side right" \
       #   -contextHelp "Enter the name of the column in the output file for this PV.  Defaults to the PV name."
       
        
        
    }
    
    set PVname($monitorLines.PV) $pvNamePV
    if [string length $pvNameRB] {
        set PVname($monitorLines.RB) $pvNameRB
    } else { 
        set PVname($monitorLines.RB) $pvNamePV
    }
    
    incr monitorLines
    #tkwait visibility $widget.data.x
    APSScrollAdjust $pvScrollFrame -numVisible 10
    tkwait visibility $widget.data.x
}

set pvName ""
proc AddNewMonitor {args} {
    global pvScroll
    set pvNamePV ""
    set pvNameRB ""
    APSParseArguments {pvNamePV pvNameRB}
    
    if [catch {CheckPVType -pvName $pvNamePV} typeList] {
        SetMainStatus "Error checking pv type: $typeList; $pvNamePV was not added."
        return
    }
    
    set type [lindex $typeList 0]
    set count [lindex $typeList 1]
    
    if [string match "*.VAL" $pvNamePV] {
        set pvNamePV [file root $pvNamePV]
    }
    if ![string length $pvNameRB] {
	set pvNameRB $pvNamePV
    }
    
    MakeNewMonitorLine $pvScroll -pvNamePV $pvNamePV  -pvNameRB $pvNameRB
}

proc addNewPV {} {
    
    global pvName pvScroll pvReadback
    
    set okCommand {AddNewMonitor -pvNamePV $pvName -pvNameRB $pvReadback}
    APSDialogBox .pv -name "Add PV Box" -width 30 \
      -cancelCommand "" -okCommand $okCommand
   # APSDialogBoxAddButton .help -parent .pv -text "Help" -command "HelpDialog -box PVBox"
    APSDialogBoxAddButton .clear -parent .pv -text "Clear" \
      -contextHelp "clear the existing settings in this dialog." \
      -command {set pvName "";set pvReadback ""}
    APSLabeledEntry .addVar -parent .pv.userFrame \
      -label "PV name: " -textVariable pvName -width 30 \
      -contextHelp "Enter a PV name of your choice."
    APSLabeledEntry .addVar1 -parent .pv.userFrame \
      -label "Readback name: " -textVariable pvReadback -width 30 \
      -contextHelp "Enter a PV name of your choice."
    bind .pv.userFrame.addVar.entry <Return> "CheckPVType"
   
}



proc DeleteMonitorLine {widget0 number} {
    global monitorLines PVname 
    destroy $widget0.m$number
    set PVname($number.PV) ""
    set PVname($number.RB) ""
}

proc ClearMonitorLine {widget0 number} {
    global monitorLines PVname 
    set PVname($number.PV) ""
    set PVname($number.RB) ""
}

set outputListLength 0
proc SaveMonitorList {args} {
    set filename ""
    APSStrictParseArguments {filename}
    global monitorLines PVname add setStepSize deltaMode
    global outputDir
    global chanName updatePeriod runTime  rootname logOutput nworkers inputConfig
    
    #inputFile is the pv list provided by a file
    set count 0
    for {set i 0} {$i<$monitorLines} {incr i} {
        if {[string length $PVname($i.PV)]} {
            incr count
        }
    }
    if {!$count && ![string length $inputConfig] && ![file exist $inputConfig]} {
	return -code error "Neither list of PVs or input config file provided, can not create group-channel!"
    }
    
    set userMode 0
    while {![string length $filename]} {
        set userMode 1
        set filename [APSInfoDialog [APSUniqueName .] -name FileDialog \
                        -width 60 \
                        -infoMessage "Supply the name of a file to which to save the data." ]
        set filename [string trim $filename]
        if ![string length $filename] {
            return -code error "No filename given."
        }
        if {[file exists $filename] && \
              ![APSMultipleChoice [APSUniqueName .] -question "$filename exists.  Overwrite it?" \
                  -labelList {Yes No} -returnList {1 0}]} {
            set filename ""
        }
    }
    global plotList
    set plotList ""
    if {!$count} {
	if ![string length $inputConfig] {
	    return -code error "No PV names or input config file  provided."
	}
	if [file exist $inputConfig] {
	    set pvList [exec sdds2stream -col=ControlName $inputConfig]
	    foreach pv $pvList {
		if {[string length $plotList]==0} {
		    set plotList $pv
		} else {
		    set plotList "$plotList,$pv"
		}
	    }
	    exec cp $inputConfig $filename
	    return
	} else {
	    return -code error "input config file does not exist"
	}
    }
    set origNameList ""
    set readbackNameList ""
    
    for {set i 0} {$i<$monitorLines} {incr i} {
        if {[string length $PVname($i.PV)]} {
	    set origName [string trim $PVname($i.PV)]
            lappend origNameList $origName
            set readbackName $PVname($i.RB)
            lappend readbackNameList $readbackName
	    if {[string length $plotList]==0} {
		set plotList $readbackName
	    } else {
		set plotList "$plotList,$readbackName"
            }
        }
    }
    if {[string length $inputConfig] && [file exist $inputConfig]} {
	set file $filename.pv
    } else {
	set file $filename
    }
    if [catch {exec sddsmakedataset $file -col=ControlName,type=string -data=[join $origNameList ,] \
		   -col=ReadbackName,type=string -data=[join $readbackNameList ,] \
		   -par=chanName,type=string -data=$chanName \
		   -par=updatePeriod,type=double -data=$updatePeriod \
		   -par=runTime,type=double -data=$runTime \
		   -par=nworkers,type=long -data=$nworkers \
		   -par=setStepSize,type=double -data=$setStepSize \
		   -par=deltaMode,type=short -data=$deltaMode \
		   -par=logOutput,type=short -data=$logOutput \
		   -par=rootname,type=string -data=$rootname } result] {
        return -code error "Error saving config file: $result"
    }
    if {[string length $inputConfig] && [file exist $inputConfig]} {
	if [catch {exec sddscombine $file $inputConfig -merge -pipe=out \
		       | sddssort -pipe=in -unique -col=ControlName $filename } result] {
	    return -code error "Error combining PVs with input config: $result"
	}
    }
    
    if $userMode {
        SetMainStatus "Configuration saved to $filename"
    }
}

proc SearchPVName {args} {
     set pvnameList ""
     set useCA 0
     if [APSStrictParseArguments {pvnameList useCA}] {
         return -code error "SearchPVName: bad arguments"
     }
     if $useCA {
         if [catch {exec cavget -list=[join $pvnameList ,]} dataList] {
             return -code error "SearchPVName: $result"
         }
         set pvNotFoundList ""
         foreach pv $pvnameList value $dataList {
             if [string compare $value ?]==0 {
                 lappend pvNotFoundList $pv
             }
         }
         if [llength $pvNotFoundList] {
             return -code error "PVs not found: [join $pvNotFoundList]"
         }
     } else {
         set pvdata_path "/home/helios/iocinfo/pvdata"
         set origDir [pwd]
         if {[file isdirectory $pvdata_path] != 1} {
             return -code error "Cannot open or locate directory $pvdata_path"
         }

         cd $pvdata_path
         set pvdata_file_list [glob -nocomplain *]
         set findFlag 0
         foreach variable $pvnameList {
             set findFlag 0
             set variable [string trim $variable]
             set cmd "grep \"$variable\" $pvdata_file_list /dev/null"
             set catchlist [list open |$cmd r]
             catch $catchlist fp
             while {[gets $fp line] >= 1} {
                 set breakpoint [string first : $line]
                 set ematch [string range $line [expr $breakpoint+1] end]
                 
                 if {[string compare $ematch $variable] == 0} {
                     set findFlag 1
                     break
                 }
             }
             if !$findFlag {
                 cd $origDir
                 return -code error "Unable to find PV $variable."
             }
         }
         cd $origDir
     }
}

proc findDir {args} {
    # General purpose directory selection
    # args is passed to APSFileSelectDialog
    set dirVariable ""
    set trim 0
    APSParseArguments {dirVariable trim}
    global $dirVariable
     set choosedfile [APSFileSelectDialog .chooseInputFile -listDir ./  -selectDir 1]
    if [string length $choosedfile] {
        set $dirVariable $choosedfile
    }
    
}
proc RunPVGroup {} {
    global monitorLines outputDir rootname outputFile PVname monitorLines inputConfig
    global logplot
    global outputList plotComList plotLogScale outputListLength
    global plotList
    global chanName updatePeriod runTime nworkers logOutput
    
    if {[string length $rootname]==0} {
        SetMainStatus "Supply an output rootname."
        bell
        return
    }
    set opt ""
    
    set outputFile $outputDir/${rootname}.sdds
    if $logOutput {
	set outputFile $outputDir/${rootname}.sdds
	if {[file exists $outputFile]} {
	    bell
	    set ok [APSYesNoPopUp "Delete existing $outputFile?"]
	    if {!$ok} {
		SetMainStatus "Supply a new output rootname"
		return
	    }
	}
	append opt " --output-sdds-file ${rootname}.sdds --output-directory $outputDir"
    }
    if {![string length $inputConfig] || ![file exist $inputConfig]} {
	set inputFile $outputDir/${rootname}.mon
	if [catch {SaveMonitorList -filename $inputFile} result] {
	    bell
	    APSAlertBox [APSUniqueName .] -errorMessage $result
	    SetMainStatus "Searching is stopped."
	    return
	}
    } else {
	set inputFile $inputConfig
	set plotList ""
    }
    
    append opt " --input-sdds-file $inputFile"
    append opt " --group-channel $chanName"
    append opt " --group-update-period $updatePeriod"
    append opt " --runtime $runTime"
    append opt " --n-ca-workers $nworkers"
    
    
    SetMainStatus "running..."
    set outputList($outputListLength) $outputFile
    set plotComList($outputListLength) "sddsplot -ticks=xtime -column=Time,($plotList) -graph=line,vary -legend $outputFile"
   # puts "daq-pv-group create $opt"
    catch {APSExecLog .job$outputListLength -unixCommand "daq-pv-group create $opt" \
	-contextHelp "This window is running a quickDaqPVGroup subprocess."  \
	       -callback "SetMainStatus \"daq-pv-group terminated.\";AddPlotCommandToFile $outputFile $plotComList($outputListLength)" \
	       -cancelCallback "AbortPVGroup" \
	       -abortCallback "AbortPVGroup" } PID
    #puts $PID
    #if [llength $plotList] {
       # AddReplotButton .job$outputListLength $outputListLength
   # }
    
    puts $PID
    SetMainStatus "loading daq-pv-group config..."
    while {1} {
	if [catch {pvinfo $chanName} result] {
	    #not exist yet
	    after 1000
	    continue
	} else {
	    #load config
	    set tmpFile [APSTmpString]
	    APSAddToTmpFileList -ID pvgroup -fileList /tmp/$tmpFile
	    exec daq-pv-group configure --group-channel $chanName --input-sdds-file $inputConfig --output-directory /tmp/ --output-sdds-file $tmpFile
	    break
	}
    }
    incr outputListLength
}


proc AbortPVGroup {args} {
    global chanName
    #exec daq-pv-group destroy  --group-channel $chanName
    SetMainStatus "daq-pv-group aborted."
}

proc EditSetFile {args} {
    global setFile
    exec sddsedit $setFile &

}

proc AddPlotCommandToFile {outputFile args} {
    set command [APSMakeSafeQualifierString [join $args]]
    set tmpFile [file dirname $outputFile]/[APSTmpString]
    return
    exec sddsprocess $outputFile $tmpFile -nowarning \
      "-print=param,sddsplotCommand01,$command" 
    exec mv $tmpFile $outputFile
}

proc AddReplotButton {parent index} {
    global outputList plotComList plotLogScale plotSeparately plotSameScale
    set w $parent.rprow$index
    pack [frame $w -relief raised -bd 2] -side bottom

    set plotLogScale($index) 0
    set plotSeparately($index) 0
    set plotSameScale($index) 0
    APSButton .plot -parent $w \
      -text "Plot $outputList($index)" \
      -command "ReplotData $index" \
      -contextHelp "This button replots the data in file $outputList($index)"
    checkbutton $w.log -text "Log plot" \
      -variable plotLogScale($index) -relief ridge
    checkbutton $w.separ -text "Separate plots" \
      -variable plotSeparately($index) -relief ridge
    checkbutton $w.same -text "Same scale" \
      -variable plotSameScale($index) -relief ridge
    pack $w.log  $w.separ $w.same -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 &"
    }                
}

#MakeNewMonitorLine $pvScroll

if [llength $argv] {
    set args $argv
    set fileName ""
    if {[APSStrictParseArguments {fileName}] || ![string length $fileName]} {
        return -code error {usage: quickMonitor [-fileName <string>]}
    }
    if ![file exists $fileName] {
        return -code error "not found: $fileName"
    }
    LoadExistingInput -filename $fileName
}

proc IncrementDelta {args} {
    set add 1
    APSParseArguments {add}
    global setValue setStepSize
    if $add {
	set setValue [format %.3f [expr $setValue + $setStepSize]]
    } else {
	set setValue [format %.3f [expr $setValue - $setStepSize]]
    }
    update
}

proc SetPVGroupWithFile {args} {
    global chanName setFile updatePeriod
    if [catch {exec pvinfo $chanName} result] {
	return -code error "Error: $chanName does not exist yet! click \"CREATE\" button to create it first!"
    }
    SetMainStatus "Reading current values..."
    ReadPVGroup
    SetMainStatus "change group pv to $setFile ..."
    if [catch {exec daq-pv-group set --group-channel $chanName --input-sdds-file $setFile } result] {
	return -code error "Error setting group pv by delta: $result"
    }
    after [format %.0f [expr $updatePeriod * 1000]]
    SetMainStatus "Read pv values after set..."
    ReadPVGroup
    SetMainStatus "change PV by file done."
}

proc SetPVGroup {args} {
    set file 0
    APSParseArguments {file}
    
    global chanName setValue setFile mode
    if [catch {exec pvinfo $chanName} result] {
	return -code error "Error: $chanName does not exist yet! click \"CREATE\" button to create it first!"
    }
    SetMainStatus "Read value before setting..."
    if [catch {exec pvaget -pvaName $chanName -label 1} result] {
	return -code error "Error reading $chanName: $result"
    }
    SetMainStatus "$result"
    SetMainStatus "Setting...."
    
    if $file {
	if [catch {exec pvaput -pvaName $chanName -inputFile $setFile -mode $mode } result] {
	    return -code error "Error set $chanName: $result"
	}
    } else {
	if [catch {exec pvaput -pvaName $chanName -value $setValue -mode $mode } result] {
	    return -code error "Error set $chanName: $result"
	}
    }
    after 1000
    if [catch {exec pvaget -pvaName $chanName -label 1} result] {
	return -code error "Error reading $chanName: $result"
    }
    SetMainStatus "Values after setting: $result"
    SetMainStatus "set done."
}


proc SetPVGroupWithDelta {args} {
    global chanName setDelta updatePeriod add
    if [catch {exec pvinfo $chanName} result] {
	return -code error "Error: $chanName does not exist yet! click \"CREATE\" button to create it first!"
    }
    SetMainStatus "Reading current values..."
    ReadPVGroup
    SetMainStatus "change group pv by $setDelta ..."
    if [catch {exec daq-pv-group set --group-channel $chanName --value $setDelta --mode add } result] {
	return -code error "Error setting group pv by delta: $result"
    }
    after [format %.0f [expr $updatePeriod * 1000]]
    SetMainStatus "Read pv values after set..."
    ReadPVGroup
    SetMainStatus "set pvs by file done."
}

proc ReadPVGroup {args} {
    global chanName outputDir rootname readIndex

    if [catch {exec pvinfo $chanName} result] {
	return -code error "Error: $chanName does not exist yet! click \"CREATE\" button to create it first!"
    }
    set filename $outputDir/${rootname}.read-[format %03d $readIndex]
    incr readIndex
    SetMainStatus "Reading $chanName..."
    if [catch {exec pvaget -pvaName $chanName -label 1 -outputFile $filename } result] {
	return -code errorr "Error reading $chanName: $result"
    }
    SetMainStatus "$result"
    SetMainStatus "read done."
    return
   
}
