#!/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)]

set applicationName SRTunesVsCurrentScan
APSApplication . -name $applicationName -version 1 \
    -overview {This application scrapes down current using scraper, measures tunes using VSA, \
                   and performs postprocessing. By V. Sajaev}

set status ""
APSScrolledStatus .status -parent .userFrame -textVariable status -width 80 -height 10

set scraper S37T
set SCRposition 1
set xTune 0.17
set yTune 0.23
set scraperPositionList "4.65 4.0"
set waitForScraper 1

APSRadioButtonFrame .scraper -parent .userFrame -label "Select scaper position:" -orientation horizontal -buttonList {S37T S40} \
	-variable scraper -valueList {S37T S40} -commandList "UpdateScaperParameters UpdateScaperParameters"
APSRadioButtonFrame .wait -parent .userFrame -label "Wait for scraper to reach out  position before measurement?" \
    -variable waitForScraper -buttonList {Yes No} -valueList {1 0} -orientation horizontal

proc UpdateScaperParameters {args} {
    global SCRposition scraper xTune yTune scraperPositionList
    switch $scraper {
	S37T {
	    set SCRposition 1
	    set scraperPositionList "4.65 4.0"
	    set xTune 0.17
	    set yTune 0.23
	}
	S40 {
	    set SCRposition 2
	    set xTune 0.17
	    set yTune 0.23
	    set scraperPositionList "4.44 4.0"
	}
    }
}

#------------------------------------------------------------------------------------------------------------

proc ScanCurrentAndMeasureTunes {args} {
    global abortRun scraper SCRposition
    APSParseArguments {rootname simulate currentStep xTune yTune scraperPositionList minCurrent nBunches measPlane}
    
    if {[string length $rootname] == 0} {
        return -code error "No rootname given."
    }
    if {[file exists $rootname-x.sdds] || [file exists $rootname-y.sdds]} {
        return -code error "Error: Measurement $rootname already exists."
    }
    return -code error "Error: S-DCCT:LifetimeStdesSourceM no longer exists"

    #--- Get initial scraper position:
    if !$simulate {set initialScraperPos [exec cavget -list=${scraper}:SCR${SCRposition}:SM:sm -cavput]}
    set fileListX ""
    set fileListY ""
    set position0 [lindex $scraperPositionList 0]
    set position1 [lindex $scraperPositionList 1]
    if {$position0 > $position1} {
        set positionIn  $position0
        set positionOut $position1
    } else {
        set positionIn  $position1
        set positionOut $position0
    }
    if $abortRun {
        set abortRun 0
        return -code error "Measurement aborted."
    }
    
    set counter 0
    if [catch {DoMeasurements -rootname ${rootname}-$counter -xTune $xTune -yTune $yTune \
                 -simulate $simulate -measPlane $measPlane} result] {
        return -code error "DoMeasurements: $result"
    }
    if {$measPlane != 1} {lappend fileListX ${rootname}-$counter-x.sdds}
    if {$measPlane != 0} {lappend fileListY ${rootname}-$counter-y.sdds}
    if [catch {exec cavget -list=S-DCCT:LifetimeStdesSourceM -pend=30 -printErrors} presentCurrent] {
	return -code error "Error in reading present current: $presentCurrent."
    }
    set overshoot 0.3
    set Loop 1
    while $Loop {
        if $abortRun { break }
        if {$presentCurrent < $minCurrent} { break }
        set targetCurrent [expr $presentCurrent - $currentStep + $overshoot]
        if [catch {ScrapeCurrent -simulate $simulate -positionIn $positionIn -positionOut $positionOut \
                     -current $targetCurrent} result] {
            return -code error "InsertScraper: $result"
        }
        
        incr counter
        after 3000
        if [catch {DoMeasurements -rootname ${rootname}-$counter -xTune $xTune -yTune $yTune \
                     -simulate $simulate -measPlane $measPlane} result] {
            return -code error "DoMeasurements: $result"
            exit
        }
        if {$measPlane != 1} {lappend fileListX ${rootname}-$counter-x.sdds}
        if {$measPlane != 0} {lappend fileListY ${rootname}-$counter-y.sdds}
	if [catch {exec cavget -list=S-DCCT:LifetimeStdesSourceM -pend=30 -printErrors} presentCurrent] {
	    return -code error "Error in reading present current: $presentCurrent."
	}
        set overshoot [expr $targetCurrent - $presentCurrent]
    }
    APSSetVarAndUpdate status "Returning scraper to the initial position..."
    if !$simulate {
        exec cavput -list=$initialScraperPos -pend=5
    }
    
    if {$measPlane != 1} {eval exec sddscombine $fileListX -pipe=out \
			      | sddsprocess -pipe=in ${rootname}-x.sdds -redef=para,Nbunches,$nBunches}
    if {$measPlane != 0} {eval exec sddscombine $fileListY -pipe=out \
			      | sddsprocess -pipe=in ${rootname}-y.sdds -redef=para,Nbunches,$nBunches}
    if $abortRun {
        set abortRun 0
        return -code error "Measurement aborted. Existing files are combined."
    }
}

#-----------------------------------------------------------------------------------------------

proc MoveScraper {args} {
    global scraper SCRposition
    APSParseArguments {simulate position}
    if $simulate {
        APSSetVarAndUpdate status "caput ${scraper}:SCR${SCRposition}:SM:sm $position"
    } else {
        if [catch {exec cavput -list=${scraper}:SCR${SCRposition}:SM:sm=$position -pend=30 } result] {
	    return -code error "Error in move scraper: $result"
	}
    }
}

#-----------------------------------------------------------------------------------------------

proc DoMeasurements {args} {
    APSParseArguments {rootname simulate xTune yTune measPlane}
    #--- The one I used in 2006
    set tuneMeasExecutable /home/helios/SR/daily/0612/20/1/TuneSlope/getxytunes
    #--- New one for linux
    set tuneMeasExecutable /usr/local/oag/apps/bin/linux-x86_64/getxytunes.00003
    return -code error "Error: S-DCCT:LifetimeStdesSourceM no longer exists"
    if [catch {exec cavget -list=S-DCCT:LifetimeStdesSourceM -pend=30 -printErrors} current] {
        return -code error "Error in reading present current: $current."
    }
    switch -exact $measPlane {
	0 {set onlyString " -only x "; set waitFile $rootname-x.sdds}
	1 {set onlyString " -only y "; set waitFile $rootname-y.sdds}
	2 {set onlyString ""; set waitFile $rootname-y.sdds}
    }
    
    APSSetVarAndUpdate status "Doing current $current..."
    APSSetVarAndUpdate status "$tuneMeasExecutable -root $rootname -description \"$current\" \
                               -xTune $xTune -yTune $yTune -plotTunes 0 $onlyString"
    if !$simulate {
        eval exec $tuneMeasExecutable -root $rootname -description \"$current\" \
          -xTune $xTune -yTune $yTune -plotTunes 0 $onlyString &
	set counter 0
	set waitLimit 200
	while {[file exists $waitFile] == 0} {
	    after 1000
	    update
	    incr counter
	    if {$counter > $waitLimit} {
		return -code error "Error: Waiting for $tuneMeasExecutable takes too long. Find and manually kill the executable."
	    }
	}
    }
}

#-----------------------------------------------------------------------------------------------

proc ScrapeCurrent {args} {
    global scraper SCRposition waitForScraper abortRun
    APSParseArguments {positionIn positionOut simulate current}
    APSSetVarAndUpdate status "Move $scraper scraper to in position: $positionIn"
    if [catch {MoveScraper -simulate $simulate -position $positionIn} result] {
        return -code error "MoveScraper in: $result"
    }
    set Loop 1
    APSSetVarAndUpdate status "Waiting for current to reach $current..."
    return -code error "Error: S-DCCT:LifetimeStdesSourceM no longer exists"
    while $Loop {
	if [catch {APScavget -list=S-DCCT:LifetimeStdesSourceM -pend=20 -printErrors} currentNow] {
	    set answer [APSMultipleChoice .currentError -width 100 -type error -question "Error in reading current: ${currentNow}. Would you like to read it again or abort the experiment?" -labelList {"Read-Again" "Abort"} -returnList {ReadAgain Abort} -name "Error in reading current."]
	    switch $answer {
		ReadAgain {
		    continue
		}
		Abort {
		    return -code error "Error in reading current: $currentNow"
		}
	    }
	}
	if $abortRun {return -code error "aborted."}
        if $simulate { after 3000; break}
        if {$currentNow < $current} { break }
        after 500
    }
    APSSetVarAndUpdate status "Move $scraper scraper to out position: $positionOut"
    if [catch {MoveScraper -simulate $simulate -position $positionOut} result] {
        return -code error "MoveScraper out: $result"
    }
    if {$simulate || !$waitForScraper} {
	return
    }
    #waitfor scraper to get to the out position
    APSSetVarAndUpdate status "Wait for scraper move to the out position..."
    while {1} {
	if [catch {APScavget -list=${scraper}:SCR${SCRposition}:SM:sm.RBV -pend=10 -printErrors} pos] {
	    set answer [APSMultipleChoice .scraperError -width 100 -type error -question "Error in scraper position: ${pos}. Would you like to read it again or abort the experiment?" -labelList {"Read-Again" "Abort"} -returnList {ReadAgain Abort} -name "Error in reading scraper position."]
	    switch $answer {
		ReadAgain {
		    continue
		}
		Abort {
		    return -code error "Error in scraper position: $pos"
		}
	    }
	}
	if {[expr abs($pos - $positionOut)]<=0.03} {
	    break
	}
	if $abortRun {return -code error "aborted."}
	after 1000
    }
}

#------------------------------------------------------------------------------------------------------------

proc Processing {args} {
    APSParseArguments {inputRoot png procPlane peakExclusion nSigmaNoise staggerFraction}

    switch -regexp -- $procPlane {
        0 { set xExclude 0; set yExclude 1 }
        1 { set xExclude 1; set yExclude 0 }
        2 { set xExclude 0; set yExclude 0 }
    }

    foreach plane [list x y] {
        if !$${plane}Exclude {
            set fileroot $inputRoot-$plane
            #--- Subtracting floor and preparing parameters for filtering...
            exec sddssort $fileroot.sdds -pipe=out -para=S35DCCT \
              | sddsprocess -pipe \
              -process=Waveform,average,WaveformFloor1,fhead=0.05 \
              -process=Waveform,average,WaveformFloor2,ftail=0.05 \
              "-redef=para,WaveformFloor,WaveformFloor1 WaveformFloor2 + 2 /" \
              -process=WaveformPower,average,WaveformPowerFloor1,fhead=0.05 \
              -process=WaveformPower,average,WaveformPowerFloor2,ftail=0.05 \
              "-redef=para,WaveformPowerFloor,WaveformPowerFloor1 WaveformPowerFloor2 + 2 /" \
              "-redef=col,Waveform,Waveform WaveformFloor -" \
              "-redef=col,WaveformPower,WaveformPower WaveformPowerFloor -" \
              -process=Waveform,rms,WaveformNoise1,fhead=0.1 \
              -process=Waveform,rms,WaveformNoise2,ftail=0.1 \
              "-redef=para,WaveformNoise,WaveformNoise1 WaveformNoise2 + 2 /" \
              -process=WaveformPower,rms,WaveformPowerNoise1,fhead=0.1 \
              -process=WaveformPower,rms,WaveformPowerNoise2,ftail=0.1 \
              "-redef=para,WaveformPowerNoise,WaveformPowerNoise1 WaveformPowerNoise2 + 2 /" \
              "-redef=para,SingleBunchCurrent,S35DCCT Nbunches /" \
              -redef=col,BunchCurrent,SingleBunchCurrent \
              | sddsconvert -pipe -del=para,WaveformFloor?,WaveformPowerFloor?,WaveformNoise?,WaveformPowerNoise? \
              | tee $fileroot.proc \
              | sddssmooth -pipe -col=Waveform,WaveformPower -Savitzky=15,15,3 -passes=3 -despike \
              | sddsprocess -pipe=in $fileroot.proc.smoothed \
              -process=Waveform,maximum,WaveformMax \
              -process=WaveformPower,maximum,WaveformPowerMax \
              "-redef=para,WaveformMaxFraction,WaveformNoise $nSigmaNoise *" \
              "-redef=para,WaveformPowerMaxFraction,WaveformPowerNoise $nSigmaNoise *"
            exec sddspeakfind $fileroot.proc.smoothed $fileroot.peak \
              -col=Waveform -exclusion=$peakExclusion -threshold=@WaveformMaxFraction
            exec sddspeakfind $fileroot.proc.smoothed $fileroot.power.peak \
              -col=WaveformPower -exclusion=$peakExclusion -threshold=@WaveformPowerMaxFraction
            PlotEverything -fileroot $fileroot -plane $plane -column Waveform -png $png
            PlotEverything -fileroot $fileroot -plane $plane -column WaveformPower -png $png
        }
    }
    
}

#-------------------------------------------------------------------------------------------------------

proc PlotEverything {args} {
    global staggerFraction
    APSParseArguments {fileroot plane column png}
    
    if {[string compare $column WaveformPower] == 0} {
        set peakFile $fileroot.power.peak
        set plotIndex 2
    } else {
        set peakFile $fileroot.peak
        set plotIndex 1
    }
    set pngString ""
    set staggerTitle "$plane tune spectra"
    set spectrumTitle "$plane tune spectrum"
    set peakTitle "$plane tune peaks"
    set contourTitle "$plane tune scan"

    set max [exec sddsprocess $fileroot.proc -pipe=out -process=$column,maximum,Max \
               | sddscollapse -pipe \
               | sddsprocess -pipe -process=Max,average,MaxAver \
               | sdds2stream -pipe=in -para=MaxAver]
    set stagger [expr abs($max * $staggerFraction)]

    #--- Plotting contours...
    if $png { set pngString "-device=lpng,onwhite -output=$fileroot-contour-$plotIndex.png" }
    eval exec sddscontour -shade -waterfall=parameter=SingleBunchCurrent,indep=Tune,colorColumn=$column \
      $fileroot.proc "\"-topline=$contourTitle\"" $pngString &
    #--- Plotting peaks...
    if $png { set pngString "-device=lpng,onwhite -output=$fileroot-peaks-$plotIndex.png" }
    eval exec sddsplot $peakFile -col=BunchCurrent,Tune -graph=symbol,scale=2 "\"-topline=$peakTitle\"" \
      -title=$column $pngString &
    #--- Plotting spectra on separate plots
    exec sddsplot $fileroot.proc -col=Tune,$column -split=page -sep -legend=para=S35DCCTstring \
      -topline=$spectrumTitle &
    #--- Plotting spectra in stagger mode
    if $png { set pngString "-device=lpng,onwhite -output=$fileroot-stagger-$plotIndex.png" }
    eval exec sddsplot -thickness=2 -linetype=0,thickness=2 "\"-topline=$staggerTitle\"" $fileroot.proc \
      -col=Tune,$column -split=page -leg=para=S35DCCTstring -stagger=y=$stagger -graph=line,vary $pngString &
    
}

#-------------------------------------------------------------------------------------------------------

proc AnalyzePeaks {args} {
    APSParseArguments {procPlane rootname fittingRange}

    switch -regexp -- $procPlane {
        0 { set xExclude 0; set yExclude 1 }
        1 { set xExclude 1; set yExclude 0 }
        2 { set xExclude 0; set yExclude 0 }
    }

    set peakStep 0.002
    foreach plane [list x y] {
        if !$${plane}Exclude {
            set fileroot $rootname-$plane.peak
            set nPages [exec sdds2stream $fileroot -npages=bare]
            
            #--- Sorting input
            exec sddssort $fileroot $fileroot.sorted -parameter=S35DCCT,decreasing
            
            #--- Filling first elements of the lists...
            set iPage $nPages
            set current [exec sdds2stream $fileroot.sorted -page=$iPage -para=SingleBunchCurrent]
            set peakList [exec sdds2stream $fileroot.sorted -page=$iPage -col=Tune]
            set K 0
            foreach peak $peakList {
                set mainPeakList$K $peak
                set peakCurrentList$K $current
                incr K
            }
            set numberOfPeaks $K
            
            #--- Running loop over pages...
            for {set iPage [expr $nPages - 1]} {$iPage > 0} {set iPage [expr $iPage - 1]} {
                set current [exec sdds2stream $fileroot.sorted -page=$iPage -para=SingleBunchCurrent]
                set peakList [exec sdds2stream $fileroot.sorted -page=$iPage -col=Tune]
                set peakUpdatedList ""
                for {set K 0} {$K < $numberOfPeaks} {incr K} {
                    lappend peakUpdatedList 0
                }
                foreach peak $peakList {
                    set peakFound 0
                    for {set K 0} {$K < $numberOfPeaks} {incr K} {
                        set distance [expr abs($peak - [lindex [set mainPeakList$K] end])]
                        if {$distance < $peakStep} {
                            set peakFound 1
                            set peakUpdatedList [lreplace $peakUpdatedList $K $K 1]
                            lappend mainPeakList$K $peak
                            lappend peakCurrentList$K $current
                            break
                        }
                    }
                    if !$peakFound {
                        incr numberOfPeaks
                        set mainPeakList[expr $numberOfPeaks - 1] $peak
                        set peakCurrentList[expr $numberOfPeaks - 1] $current
#                        lappend mainPeakList[expr $numberOfPeaks - 1] $peak
#                        lappend peakCurrentList[expr $numberOfPeaks - 1] $current
                        lappend peakUpdatedList 1
                    }
                }
                for {set K 0} {$K < $numberOfPeaks} {incr K} {
                    if ![lindex $peakUpdatedList $K] {
                        lappend mainPeakList$K 0
                    }
                }
            }
            
            set tmpRoot tmp
            set fileList ""
            for {set K 0} {$K < $numberOfPeaks} {incr K} {
                while {[lindex [set mainPeakList$K] end] == 0} {
                    set mainPeakList$K [lreplace [set mainPeakList$K] end end]
                }
                exec sddsmakedataset $tmpRoot.$K \
                  -col=Tune,type=double -data=[join [set mainPeakList$K] ,] \
                  -col=Current,type=double -data=[join [set peakCurrentList$K] ,] \
                  -para=PeakNumber,type=long -data=$K
                lappend fileList $tmpRoot.$K
            }
            
            eval exec sddscombine $fileList $fileroot.groupped -overWrite
            eval file delete $fileList $fileroot.sorted
            
            if ![string length $fittingRange] {
                exec sddspfit $fileroot.groupped -pipe=out -col=Current,Tune -terms=2 -generate \
                  | sddsxref -pipe=in $fileroot.groupped $fileroot.pfit -transfer=par,PeakNumber -leave=*
            } else {
                set limit1 [lindex $fittingRange 0]
                set limit2 [lindex $fittingRange 1]
                exec sddsprocess $fileroot.groupped -pipe=out -filter=col,Current,$limit1,$limit2 -nowarning \
                  | sddspfit -pipe -col=Current,Tune -terms=2 -generate \
                  | sddsxref -pipe=in $fileroot.groupped $fileroot.pfit -transfer=par,PeakNumber -leave=*
            }
            
            exec sddsplot -thickness=2 -linetype=0,thickness=2 -split=page "-topLine=$plane tune" \
              -col=Current,Tune -graph=symbol,vary=subtype $fileroot.pfit \
              -col=Current,TuneFit -graph=line,vary "-legend=para=PeakNumber,edit=a i%Peak %" $fileroot.pfit &
            
            exec sddsplot -thickness=2 -linetype=0,thickness=2 -split=page -groupby=page -sep=2 \
              -topLine=@sddspfitLabel "-title=@SlopeSigma,edit=i%Slope sigma %" \
              -col=Current,Tune -graph=symbol,vary=subtype $fileroot.pfit \
              -col=Current,TuneFit -graph=line,vary "-legend=para=PeakNumber,edit=a i%Peak %" $fileroot.pfit &
        }
    }
}

#------------- Measurement frame ----------------------------------------------------------------------------

APSFrame .frameMeasure -parent .userFrame -label "Measurement" -width 700
set w .userFrame.frameMeasure.frame

APSLabeledEntry .rootname -parent $w \
  -label "Measurement rootname:" \
  -textVariable rootname -width 20 \
  -contextHelp "File rootname."
APSLabeledEntry .currentStep -parent $w \
  -label "Current step (mA):" \
  -textVariable currentStep -width 20 \
  -contextHelp "Step in current scan."
APSLabeledEntry .minCurrent -parent $w \
  -label "Minimum current (mA):" \
  -textVariable minCurrent -width 20 \
  -contextHelp "Current at with scan will be stopped."
APSLabeledEntry .bunches -parent $w \
  -label "Number of bunches:" \
  -textVariable nBunches -width 20 \
  -contextHelp "Number of bunches that are used during measurements."
APSLabeledEntry .xTune -parent $w \
  -label "Fractional X tune:" \
  -textVariable xTune -width 20 \
  -contextHelp "Approximate fractional part of X betatron tune."
APSLabeledEntry .yTune -parent $w \
  -label "Fractional Y tune:" \
  -textVariable yTune -width 20 \
  -contextHelp "Approximate fractional part of Y betatron tune."
APSLabeledEntry .scraper -parent $w \
  -label "Scraper position list (blank separated):              " \
  -textVariable scraperPositionList -width 20 \
  -contextHelp "Two positions of scraper corresponding to in and out positions. These has to be tested proir to running the scan (order is not important)."

APSRadioButtonFrame .measPlane -parent $w -label "Measurement plane:                                        " \
  -variable measPlane -valueList {2 0 1} \
  -buttonList {both x y} \
  -orientation horizontal \
  -commandList {{} {} {}} \
  -contextHelp "Choose plane for measurement by getxytunes."

APSRadioButtonFrame .simulate -parent $w -label "Simulate measurements:                                    " \
  -variable simulate -valueList {1 0} \
  -buttonList {simulate real} \
  -orientation horizontal \
  -commandList {{} {}} \
  -contextHelp "Use to check sequence - no real actions will be taken."

set measButton $w.measure.button
set abortButton $w.abort.button
APSButton .measure -parent $w -text "Do measurement" -command \
    {
        APSDisableButton $measButton
        APSEnableButton $abortButton
        APSSetVarAndUpdate status "Starting measurement..."
        if [catch {ScanCurrentAndMeasureTunes -rootname $rootname -simulate $simulate -currentStep $currentStep \
                     -xTune $xTune -yTune $yTune -scraperPositionList $scraperPositionList \
                     -minCurrent $minCurrent -nBunches $nBunches -measPlane $measPlane} result] {
            APSSetVarAndUpdate status "ScanCurrentAndMeasureTunes returned error: $result"
        } else {
            APSSetVarAndUpdate status "Measurement is done."
        }
        APSEnableButton $measButton
        APSDisableButton $abortButton
        
    } -contextHelp "Performs scan."

APSButton .abort -parent $w -text "Abort measurement" -command \
    {
        APSSetVarAndUpdate status "Aborting measurement..."
        set abortRun 1
        APSEnableButton $measButton
        APSDisableButton $abortButton
    } -contextHelp "Aborts scan and retracts scraper."
APSDisableButton $abortButton

#------------- Processing frame ----------------------------------------------------------------------------

APSFrame .frameProcess -parent .userFrame -label "Processing" -width 700
set w .userFrame.frameProcess.frame

APSRadioButtonFrame .procPlane -parent $w -label "Process plane:                                            " \
  -variable procPlane -valueList {2 0 1} \
  -buttonList {both x y} \
  -orientation horizontal \
  -commandList {{} {} {}} \
  -contextHelp "Choose plane for processing."

APSRadioButtonFrame .png -parent $w -label "Generate png plots?                                       " \
  -variable png -valueList {0 1} \
  -buttonList {no yes} \
  -orientation horizontal \
  -commandList {{} {}} \
  -contextHelp "Clear enough."

APSLabeledEntry .peakExclusion -parent $w \
  -label "Peak exclusion (distance from the main peak):             " \
  -textVariable peakExclusion -width 20 \
  -contextHelp "This variable is for exclusion of peaks that are too close to the main peak (in units of total range)."
APSLabeledEntry .nSignaNoise -parent $w \
  -label "Noise level in rms for peak exclusion:" \
  -textVariable nSigmaNoise -width 20 \
  -contextHelp "This variable is for exclusion of peaks that are below this number of noise rms."
APSLabeledEntry .staggerFraction -parent $w \
  -label "Stagger fraction:" \
  -textVariable staggerFraction -width 20 \
  -contextHelp "Fraction of average maximum for stagger plots."
APSLabeledEntry .fittingRange -parent $w \
  -label "Slope fitting range:" \
  -textVariable fittingRange -width 20 \
  -contextHelp "Range of slope fitting, 2 numbers space separated (in mA). If empty, all data will be used."

APSButton .processPlot -parent $w -text "Process and Plot" -command \
    {
        APSSetVarAndUpdate status "Processing..."
        if [catch {Processing -inputRoot $rootname -png $png -procPlane $procPlane -peakExclusion $peakExclusion \
                     -nSigmaNoise $nSigmaNoise -staggerFraction $staggerFraction -plotOnly 0} result] {
            APSSetVarAndUpdate status "Processing: $result"
        } else {
            APSSetVarAndUpdate status "Done processing."
        }
    } -contextHelp "Processes and plots chosen planes."

APSButton .plotOnly -parent $w -text "Plot only" -command \
    {
        APSSetVarAndUpdate status "Plotting..."
        if [catch {Processing -inputRoot $rootname -png $png -procPlane $procPlane -peakExclusion $peakExclusion \
                     -nSigmaNoise $nSigmaNoise -staggerFraction $staggerFraction -plotOnly 1} result] {
            APSSetVarAndUpdate status "Error: $result"
        } else {
            APSSetVarAndUpdate status "Done processing."
        }
    } -contextHelp "Plots already processed data for chosen planes."

APSButton .analyzePeaks -parent $w -text "Analyze peaks" -command \
    {
        APSSetVarAndUpdate status "Analyzing..."
        if [catch {AnalyzePeaks -procPlane $procPlane -rootname $rootname -fittingRange $fittingRange} result] {
            APSSetVarAndUpdate status "Error: $result"
        } else {
            APSSetVarAndUpdate status "Done processing."
        }
    } -contextHelp "Groups peaks and fits straight lines for groups of peaks."

set currentStep 5.0
set minCurrent 10.0
set simulate 1
set abortRun 0

set procPlane 2
set measPlane 2
set png 0
set nBunches 24
set peakExclusion 0.05
set nSigmaNoise 5.0
set staggerFraction 0.4
set fittingRange ""
