#!/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.108 $ \$Author: sajaev $"

APSStandardSetup

set mainStatus Ready.
APSApplication . -name SRDispChromMeas -version $CVSRevisionAuthor -overview {Measure orbit and tune spectra at different rf frequencies, and computes the dispersions and chromaticities. Use of HP VSA is recommended.}

APSScrolledStatus .status -parent .userFrame -textVariable mainStatus -width 70 \
  -height 4

set output dispChrom01
set extraMonFile ""
set start -100
set stop 100
set points 5
set pauseNASA 15
set offset 0
set review 0
set finished 0

set args $argv
APSParseArguments {output start stop points pauseNASA}

set mainDir /home/helios/oagData/sr/dispChrom
set getChromatic 1
set instrument1 MXA
set instrument VSA
set MXA 1
set useS35Vid 1
set rfFrequency [exec cavget -list=A014-IETS:BTC:SRSetFreqM -floatFormat=%.1f -pendIoTime=5]
set harmonic 1296
set revFrequency [expr $rfFrequency / 1296]
set measHarmonic 1315
set measHarmonic 1390
set xchrom 6
set ychrom 4

set sideband -1
#obtain default parameters
set varNames [exec sdds2stream -col=VarName /home/helios/oagData/sr/tuneArchive/NASA/defaultParameters.sdds]
set values [exec sdds2stream -col=Value /home/helios/oagData/sr/tuneArchive/NASA/defaultParameters.sdds]
foreach var $varNames val $values {
    set $var [format %.2f $val]
}
set expectedXtune $xTune
set xFreq [format %.1f [expr $revFrequency * ($measHarmonic + $expectedXtune * $sideband)]]
set expectedYtune $yTune
set yFreq [format %.1f [expr $revFrequency * ($measHarmonic + $expectedYtune * $sideband)]]
set dividingLine [format %.3f [expr ($xTune + $yTune)/2.0]]
set HPVSATracesToAve 20
set chromProcMode peakfind
set measToAve 1
set chromBadPointList ""
set vsaSpan 10000
set nasaSpan 40000
set getDispersion 1
set npSmooth 11
set nPasses 3
set P0ReducedGain 2.0
proc SetStatus {text} {
    global mainStatus
    set mainStatus "$text"
    update
}

proc EnableDisableP0Widget {args} {
    global p0GainWidget
    if [catch {$p0GainWidget cget -state} state] {
	return -code error "Error in geting p0 widget state: $state"
    }
    set enable 0
    if [string compare $state disabled]==0 {
	set enable 1
    }
    if $enable {
        APSEnableWidget $p0GainWidget
    } else {
        APSDisableWidget $p0GainWidget
    }
}

set xPower 6
set yPower 3
proc SelectInstrument {args} {
    global instrument instrument1 MXA xPower yPower
    set MXA 0
    switch $instrument1 {
        MXA -
        VSA {
            set instrument VSA
            APSSetTuneMultiplexer -mode VSA
            set xPower 0
            set yPower 0
        }
        NASA {
            set instrument NASA
            APSSetTuneMultiplexer -mode NASA
            set xPower 10.0
            set yPower 6.0
        }
    }
    if {$instrument1=="MXA"} {
        set MXA 1
    }
}

proc RestoreVSA {args} {
    SetStatus "Restoring VSA (wait 25 seconds)..."
    if [catch {exec hpVecRestore -filename /home/helios/oagData/sr/hp89441A/states/MXA-TUNE.sta -unit sr} result] {
        return -code"Error restoring VSA: $result"
        
    }
    SetStatus "done."
}
proc makeLabeledEntriesAndRbFrame {widget args} {
    set parent .userFrame

    APSParseArguments {parent}

    global output outputDir start stop points extraMonFile instrument1 instrument reverseWaveform latticeDir
    global xFreq yFreq pauseNASA chromBadPointList vsaSpan nasaSpan getDispersion xrange yrange xchrom ychrom

    APSFrame $widget -parent $parent -relief flat
    set w $parent$widget.frame
    set outputDir .


    APSLabeledEntry .outputDir -parent $w \
      -label "Output directory:" \
      -textVariable outputDir \
      -contextHelp "Enter a name for the output file directory." \
      -width 55
    APSButton .daily -parent $w.outputDir -packOption "-anchor e" \
     -text "daily" -size small \
     -command {set outputDir [APSGoToDailyDirectory -subdirectory dispChrom]}
    APSLabeledEntry .output -parent $w \
      -label "Output file:" -textVariable output \
      -contextHelp "Enter a name for the output file." \
      -width 55
    APSLabeledEntry .extra -parent $w -width 55 \
      -label "Extra monitor file:" \
      -textVariable extraMonFile \
      -contextHelp "Enter the name of an sddsmonitor \
           input file. The PVs listed in this \
           file will be collected along with \
           the rest of the data."
    APSLabeledEntry .start -parent $w \
      -label "Start:" -textVariable start \
      -contextHelp "Enter a value to start with." \
      -width 10
    APSLabeledEntry .stop -parent $w \
      -label "Stop:" -textVariable stop \
      -contextHelp "Enter a value to stop at." \
      -width 10
    APSLabeledEntry .points -parent $w \
      -label "Points:" -textVariable points \
      -contextHelp "Enter the number of points to use." \
      -width 10
    APSLabeledEntry .measToAve -parent $w -width 10 \
      -label "Measurements to average: " \
      -textVariable measToAve \
      -contextHelp "Enter the number of measurements \
                                             of the PVs to average. Sample \
                                             interval is 0.5s."
    APSLabeledEntry .pauseNASA -parent $w \
      -label "Pause (s):" -textVariable pauseNASA \
      -contextHelp "Enter the number of seconds to wait for the NA/SA" \
      -width 10
    APSLabeledOutput .lattice -parent $w \
      -label "Lattice Name:" -textVariable latticeName \
      -contextHelp "lattice linked by $latticeDir. If default lattice is changed, then re-start the GUI." \
      -width 55
    APSLabeledEntry .momcompaction -parent $w \
      -label "Momentum Compaction Factor :" -textVariable momentumCompactionFactor \
      -contextHelp "Initially read from above lattice. Enter the momentum compaction factor (used for dispersion processing only)" \
      -width 10
    APSLabeledEntry .momcompaction2 -parent $w \
      -label "2nd-order Momentum Compaction Factor :" -textVariable  momentumCompactionFactor2 \
      -contextHelp "Initially read from above lattice. Enter the second-order momentum compaction factor (used for correcting relation between frequency and momentum error)" \
      -width 10
   
    
    APSRadioButtonFrame .chromRb -parent $w -label "Get chromatic data: " \
      -variable getChromatic \
      -buttonList {Yes No} -valueList {1 0} \
      -orientation horizontal
    APSRadioButtonFrame .disp -parent $w -label "Get dispersion data?" -variable getDispersion \
      -buttonList {Yes No} -valueList {1 0} \
      -orientation horizontal 
    APSRadioButtonFrame .vsaRB -parent $w -label "Use MXA (MXA-VSA) or NASA: " -variable instrument1 \
      -buttonList {MXA NASA} -valueList {MXA NASA} \
      -orientation horizontal \
      -commandList {SelectInstrument SelectInstrument}
    APSRadioButtonFrame .s35RB -parent $w -label "Include S35 video data: " -variable useS35Vid \
      -buttonList {Yes No} -valueList {1 0} \
      -orientation horizontal 
   
    set width 15
    APSFrame .hpvsa -parent $w -label "VSA/NASA parameters" 
    set w1 $w.hpvsa.frame
    APSFrame .f -parent $w1
    $w1.f.frame configure -bd 0
    APSButton .measureTunes -parent $w1.f.frame -text "FIND CENTER FREQUENCIES" \
      -command {MeasureInitialTunes \
                  -mainStatus SetStatus} \
      -contextHelp "Finds the center frequencies \
                                          for x and y tune measurement."
    APSButton .restorvsa -parent $w1.f.frame -text "RESTORE VSA" \
      -command "RestoreVSA" -contextHelp "restor the VSA setup for MXA-VSA tune measurment"
    APSFrameGrid .grid -parent $w1 -xList {x1 x2}
    APSLabeledOutput .xfreq -parent $w1.grid.x1 -width $width\
      -label "x frequency center (Hz): " \
      -textVariable xFreq  \
      -contextHelp "This quantity will NOT be used for calculating the center frequency of the range of the HPVSA. It is updated from the x-tune after the measurement has started."
    APSLabeledEntry .xtune -parent $w1.grid.x1 -width $width\
      -label "fractional x tune: " -textVariable xTune \
      -contextHelp "This quantity will be used for calculating the center frequency of the range of the HPVSA"
    bind $w1.grid.x1.xtune.entry <Leave> {set xFreq [ComputeFrequencyFromTune -tune $xTune];UpdateDividingLine}
    APSLabeledOutput .yfreq -parent $w1.grid.x2 -width $width \
	-label "y frequency center (Hz): " \
	-textVariable yFreq  \
	-contextHelp "This quantity will NOT be used for calculating the center frequency of the range of the HPVSA. It is updated from the x-tune after the measurement has started."
    APSLabeledEntry .ytune -parent $w1.grid.x2 -width $width \
	-label "fractional y tune: " -textVariable yTune \
	-contextHelp "This quantity will be used for calculating the center frequecny go the range of the HPVSA"
    bind $w1.grid.x2.ytune.entry <Leave> {set yFreq [ComputeFrequencyFromTune -tune $yTune];UpdateDividingLine}
    APSLabeledEntry .xspan -parent $w1.grid.x1 -width $width\
        -label "rf freq span for VSA:" \
        -textVariable vsaSpan \
        -contextHelp "this sets the rf frequency span for measuring x plane tune."
    APSLabeledEntry .ySpan -parent $w1.grid.x2 -width $width\
        -label "rf freq span for NASA:" \
        -textVariable nasaSpan \
        -contextHelp "this sets the value of NASA rf power for measuring y plane tune."

    APSLabeledEntry .xpower -parent $w1.grid.x1 -width $width\
        -label "rf power (x tune):" \
        -textVariable xPower \
        -contextHelp "this sets the value of NASA rf power for taking x plane tune."
    APSLabeledEntry .ypower -parent $w1.grid.x2 -width $width \
        -label "rf power (y tune):" \
        -textVariable yPower \
        -contextHelp "this sets the value of NASA rf power for taking y plane tune."
    APSLabeledEntry .mxarangex -parent $w1.grid.x1 \
      -label "MXA range (dBm) x plane: " -textVariable xrange -contextHelp \
      "enter the range value for MXA, normally, it should be 10 - 12 for hybrid, others 2-4." -width $width
    APSLabeledEntry .mxarangey -parent $w1.grid.x2 \
      -label "MXA range (dBm) for y plane: " -textVariable yrange -contextHelp \
      "enter the range value for MXA, normally, it should be 10 - 12 for hybrid, others 2-4." -width $width
    APSLabeledEntry .chromx -parent $w1.grid.x1 \
      -label "x est. chromaticity: " -textVariable xchrom -contextHelp \
      "estimated x chromaticity" -width $width
    APSLabeledEntry .chromy -parent $w1.grid.x2 \
      -label "y est. chromaticity: " -textVariable ychrom -contextHelp \
      "estimated y chromaticity." -width $width

    APSLabeledEntry .pause -parent $w1.grid.x1 -width $width\
      -label "Traces to average: " \
      -textVariable HPVSATracesToAve \
       -contextHelp "This quantity will be sent to the HPVSA before the experiment starts."
    APSLabeledEntry .div -parent $w1.grid.x2 -width $width \
      -label "Dividing line: " \
      -textVariable dividingLine \
       -contextHelp "This quantity will be separate the NASA spectrum in two parts"
    APSLabeledEntry .smooth -parent $w1.grid.x1 -width $width\
      -label "Points for smoothing: " \
      -textVariable npSmooth \
       -contextHelp "-points parameter for sddsmooth for waveform processing."
    APSLabeledEntry .pass -parent $w1.grid.x2 -width $width \
      -label "Passes for smoothing: " \
      -textVariable nPasses \
       -contextHelp "-passes parameter for sddsmooth for waveform processing."
    global P0ReducedGain p0GainWidget
    APSLabeledEntry .p0gain -parent $w -label "Reduced P0 feedback gain:" -textVariable P0ReducedGain -width 50 \
	-contextHelp "enter the value of P0 feedback gain for reducing P0 feedback to obtain good data."
    set p0GainWidget  $w.p0gain.entry
    #APSButton .enable -parent $w.p0gain -text "" -size small -command "EnableDisableP0Widget"
    checkbutton $w.p0gain.enable -relief flat -command "EnableDisableP0Widget"
    pack $w.p0gain.enable -side left
    APSDisableWidget $w.p0gain.entry

    APSRadioButtonFrame .chromProcMode -parent $w \
      -label "Tune change processing mode: " \
      -variable chromProcMode \
      -buttonList {Smooth+Peakfind \
                     Convolution Integral} \
      -valueList {peakfind convolve integrate} \
      -orientation horizontal 
    APSLabeledEntry .elimPoints -parent $w \
      -label "List of bad point numbers (space separated): " -width 30 \
      -textVariable chromBadPointList -contextHelp \
      "Enter a list of point numbers for points to be removed from fit.  Point numbers start from 1."
    APSRadioButtonFrame .reverse -parent $w \
      -label "Reverse tune waveform: " \
      -variable reverseWaveform \
      -buttonList {"Do not reverse" Reverse } \
      -valueList {1 -1} \
      -orientation horizontal 
    $w.chromRb.frame.button1 invoke
}

    global dx0r dy0r dx0s dy0s dx1r dy1r dx1s dy1s xfit yfit
    
    set dx0r 0
    set dy0r 0
    set dx0s 0
    set dy0s 0
    set dx1r 1
    set dy1r 1
    set dx1s 0
    set dy1s 0
    set xfit 1
    set yfit 1

#----------------------------------------------------------------------
#
proc menuPlotting {} {
    global output order
    global dx0r dy0r dx0s dy0s dx1r dy1r dx1s dy1s xfit yfit
    global widgetPlottingButton

    APSEnableButton $widgetPlottingButton.plotDispersion.button

    set plotting [APSUniqueName .]
    if $order==1 {
        set dx1r 0
        set dy1r 0
        set dx1s 0
        set dy1s 0
    } elseif {$order==2} {
         set dx0r 0
        set dy0r 0
        set dx0s 0
        set dy0s 0
    }
    APSDialogBox $plotting -name Plotting -okCommand doPlotting -cancelCommand ""

    APSCheckButtonFrame .d0r -parent ${plotting}.userFrame \
                             -label "Dispersion1 over total ring:    " \
                             -variableList {dx0r dy0r} \
                             -buttonList {X Y} \
                             -orientation horizontal 
    
    APSCheckButtonFrame .dos -parent $plotting.userFrame \
                             -label "Dispersion1 by sectors: " \
                             -variableList {dx0s dy0s} \
                             -buttonList {X Y} \
                             -orientation horizontal

    APSCheckButtonFrame .d1r -parent $plotting.userFrame \
                             -label "Dispersion2 over total ring:    " \
                             -variableList {dx1r dy1r} \
                             -buttonList {X Y} \
                             -orientation horizontal
 
    APSCheckButtonFrame .d1s -parent $plotting.userFrame \
                             -label "Dispersion2 by sectors: " \
                             -variableList {dx1s dy1s} \
                             -buttonList {X Y} \
                             -orientation horizontal

    APSCheckButtonFrame .fit -parent $plotting.userFrame \
                             -label "Raw data with fit:          " \
                             -variableList {xfit yfit} \
                             -buttonList {X Y} \
                             -orientation horizontal

    APSButton .none -parent $plotting.userFrame \
                             -text "None" \
                             -size small -packOption "-side right" \
                             -command "allButtonOff $plotting.userFrame"

    APSButton .all -parent $plotting.userFrame \
                             -text "All" \
                             -size small -packOption "-side right" \
                             -command "allButtonOn $plotting.userFrame"

}

proc allButtonOn {w} {

    global dx0r dy0r dx0s dy0s dx1r dy1r dx1s dy1s xfit yfit
    
    set dx0r 1
    set dy0r 1
    set dx0s 1
    set dy0s 1
    set dx1r 1
    set dy1r 1
    set dx1s 1
    set dy1s 1
    set xfit 1
    set yfit 1
}

proc allButtonOff {w} {

    global dx0r dy0r dx0s dy0s dx1r dy1r dx1s dy1s xfit yfit
    
    set dx0r 0
    set dy0r 0
    set dx0s 0
    set dy0s 0
    set dx1r 0
    set dy1r 0
    set dx1s 0
    set dy1s 0
    set xfit 0
    set yfit 0
    
}

proc makeButtonRow {widget args} {

    global order
    global widgetPlottingButton
    
    set parent .userFrame
    set order 1

    APSParseArguments {parent}

    APSFrame $widget -parent $parent -relief flat
    set w $parent$widget.frame
    set widgetPlottingButton $w

   
    APSButton .doExperiment -parent $w -text "DO EXPERIMENT" \
      -command doExperiment \
      -packOption "-side left" 
     
    APSButton .chromProcessing -parent $w -text "CHROMATIC PROCESSING" \
      -command chromProcessing \
      -packOption "-side left"

    APSButton .calcDispersion -parent $w -text "CALCULATE\nDISPERSION" \
      -command calcDispersion \
      -packOption "-side left" \
      -contextHelp "Calculation of the first/second dispersion \
                   functions over x,y" 

    APSRadioButtonFrame .orderDispersion -parent $w -label "" \
                         -packOption "-side left" \
                         -variable order \
                         -buttonList {"order 1" "order 2"} \
                         -valueList {1 2} \
                         -orientation vertical \
                         -contextHelp "Choose the dispersion order to analyze with"
                         
    APSButton .plotDispersion -parent $w -text "PLOT 2nd ORDER\nDISPERSION" \
                              -packOption "-side right" \
                              -command menuPlotting \
                              -contextHelp "Plotting of the first/second \
                                        dispersion functions over x,y and \
                                        fitting figures" 
    APSFrameGrid .fg -parent $w -yList {y1 y2}  -packOption {-side left}
    APSButton .setupHplane -parent $w.fg.y1 \
      -text "SETUP H VSA" \
      -command {SetupHPVSAAndDrvStriplines -plane x -statusCallback SetStatus} \
      -packOption {-side left -fill x} \
      -contextHelp "This button recalls a state of the HP VSA which make the xtune appear and sets up tune measerement. The tunes are not measured."
    APSButton .setupVplane -parent $w.fg.y2 \
      -text "SETUP V VSA" \
      -command {SetupHPVSAAndDrvStriplines -plane y -statusCallback SetStatus} \
      -packOption {-side left -fill x} \
      -contextHelp "This button recalls a state of the HP VSA which make the ytune appear and sets up tune measerement. The tunes are not measured."
    APSDisableButton $widgetPlottingButton.plotDispersion.button
}

#----------------------------------------------------------------------
#
proc calcDispersion {} {

    global order output outputDir  
    
    if {$order == 2} {
       calcDispersion2
    } else {
       calcDispersion1
    }   
}

#----------------------------------------------------------------------
# Procedure measures and sets the initial tune values:  
# returns 1 when completed; returns 0 if the VSA is not selectedfre
#
proc MeasureInitialTunes {args} {
    
    global directory xFreq yFreq xTune yTune streamID hpvsaSelection instrument dividingLine P0ReducedGain
    global vsaSpan nasaSpan xPower yPower HPVSATracesToAve MXA instrument1 range xrange yrange
    
    APSParseArguments {mainStatus}
    
    if {$instrument=="NASA"} {
        if {$mainStatus!=""} {
            $mainStatus "Measure initial tune with NASA..."
        }
        set output /tmp/[APSTmpString]
        if [catch {APSMpMeasureTunes -ring SR -outputFile $output -xPower $xPower -yPower $yPower \
		       -span $nasaSpan  -xFreq $xFreq -yFreq $yFreq  -P0ReducedGain $P0ReducedGain  \
		       -useDividingLine 0 -measureXYtuneTogether 0} result] {
            return -codd error "MeasureInitialTunes(1): $result"
        }
        set xTune [lindex [exec sdds2stream -par=xTune $output] 0]
        set yTune [lindex [exec sdds2stream -par=yTune $output] 0]
        set xFreq [ComputeFrequencyFromTune -tune $xTune]
        set yFreq [ComputeFrequencyFromTune -tune $yTune]
        update
        if {$mainStatus!=""} {
            $mainStatus "done."
        }
        return 0
    }

    if {$mainStatus!=""} {
        $mainStatus "Measuring and setting the tune with $instrument1 ..."
    }
    if [catch {APSSetTuneMultiplexer -mode $instrument} result] {
        $mainStatus $result
        return
    }
    set tmpRoot /tmp/[APSTmpString]
    APSAddToTempFileList -ID dispchrom -fileList $tmpRoot
    if [catch {APSGetSRTunesVSA -output $tmpRoot -description "measure-SR-initial-tune-vsa" \
                 -xFrequency $xFreq -yFrequency $yFreq -MXA $MXA -xSourceLevel $xPower -ySourceLevel $yPower -xrange $xrange -yrange $yrange \
                 -dividingLine $dividingLine -average $HPVSATracesToAve -xP0ReducedGain $P0ReducedGain -yP0ReducedGain $P0ReducedGain} result] {
        $mainStatus $result
        return
    }
    exec hpSocketSend hpvecsr "OUTP OFF"
    set xTune [format %.4f [lindex [exec sdds2stream -par=xTune $tmpRoot] 0]]
    set yTune [format %.4f [lindex [exec sdds2stream -par=yTune $tmpRoot] 0]]
    set xFreq [ComputeFrequencyFromTune -tune $xTune]
    set yFreq [ComputeFrequencyFromTune -tune $yTune]
    update
    if {$mainStatus!=""} {
        $mainStatus "done."
    }
    return
    
}

# Procedure computes the tune by first acquiring the waveform then
# computing the tune via the integral method.  The procedure returns
# the tune computed from the acquired waveform.

proc DetermineTuneFromWaveform {} {
    
    global hpvsaSelection
    set waveformFile /tmp/waveform.sdds
    exec hpVecTrace -${hpvsaSelection} a $waveformFile
    set selectedTune [expr 1.0e6 * [exec sddssmooth -pipe=out $waveformFile \
                                      -col=Waveform -pass=0 \
                                      -despike=neighbors=5,average=5,passes=5 \
                                      | sddsprocess -pipe -process=Waveform,minimum,WvfMin \
                                      "-redefine=col,Waveform,Waveform WvfMin -" \
                                      | sddsinteg -pipe -integrate=Waveform -versus=Frequency \
                                      | sddsprocess -pipe -process=WaveformInteg,maximum,WvfMax \
                                      "-redefine=col,WaveformInteg,WaveformInteg WvfMax / 0.5 -" \
                                      -process=WaveformInteg,zerocrossing,TuneFreq,functionOf=Frequency \
                                      | sdds2stream -pipe=in -param=TuneFreq -ignore]]
    file delete $waveformFile
    set selectedTune [format %0.1f $selectedTune]
    return ${selectedTune}
}

# Procedure computes the tune from the specified tune frequency and returns the tune.
proc UpdateDividingLine {args} {
    global xTune yTune dividingLine
    set dividingLine [format %0.2f [expr ($xTune+$yTune)/2.0]]
}

proc ComputeTuneFromFrequency {args} {
    
    set tuneFreq ""
    APSStrictParseArguments {tuneFreq}
    
    set rfFrequency [exec cavget -list=A014-IETS:BTC:SRSetFreqM -floatFormat=%.1f -pendIoTime=25]
    set revFrequency [expr $rfFrequency / 1296.0]
    set tune [expr int($tuneFreq / $revFrequency) + 1.0 - ($tuneFreq / $revFrequency)]
    return [format %.5f $tune]
}

proc ComputeFrequencyFromTune {args} {
    global sideband measHarmonic
    set tune 0
    APSStrictParseArguments {tune}
    
    set rfFrequency [exec cavget -list=A014-IETS:BTC:SRSetFreqM -floatFormat=%.1f -pendIoTime=25]
    set revFrequency [expr $rfFrequency / 1296.0]
    set tuneFrequency [expr $revFrequency * ($measHarmonic + $tune * $sideband)]
    return [format %.1f $tuneFrequency]
}

# This procedure sets the HPVSA frequency to either one of the tune
# frequencies and the span to 5 kHz.  Returns 1 when completed.
# Returns 0 if $plane != Horizontal || Vertical.

# This procedure will need editing since telnet stream is no longer supported by RHEL8.
proc SetHPVSAHVRange {plane index} {

    global xTune xFreq newxFreq yTune yFreq newyFreq streamID

    if {$index==0} {
        set xFreq [ComputeFrequencyFromTune -tune $xTune]
        set yFreq [ComputeFrequencyFromTune -tune $yTune]
        set newxFreq $xFreq
        set newyFreq $yFreq
    }
    # Ensure that averaging is normal, i.e. not repeating.
    if [catch {APSWriteToTelnetStream -command "OUTP ON" -streamID $streamID \
             } result ] {
        return -code error "SetHPVSAHVRange: unable to turn on VSA scope: $result"
    }
    APSWriteToTelnetStream -command "AVER:TCON NORM" -streamID $streamID
    if {[string match $plane Horizontal]} {
        if [catch {exec cavput -list=SR:TUNE:HP_1366A_C0P1_MBBO,SR:TUNE:Mux4Sw1BO -list==X \
                     -pend=20} result] {
            return -code error "SetHPVSAHVRange: $result"
        }
    
    
       # if [catch {exec cavput -list=SR:TUNE:stripSELmbbo=X,SR:TUNE:HP_1366A_P0_MBBO=1 \
       #          } result ] {
       #     return -code error "SetHPVSAHVRange: $result"
       # }
        APSWriteToTelnetStream -command "PAUSE" -streamID $streamID
        APSWriteToTelnetStream -command "FREQ:CENT ${newxFreq} Hz" -streamID $streamID
        APSWriteToTelnetStream -command "BAND 300 Hz" -streamID $streamID
        APSWriteToTelnetStream -command "ABOR;*WAI" -streamID $streamID
        update
        after 2000
        set operationCondition 256
        while {$operationCondition & 256} {
            after 1000
            set operationCondition [APSWriteToTelnetStream -command "STAT:OPER:COND?" -streamID $streamID]
        }
        APSWriteToTelnetStream -command "PAUSE" -streamID $streamID
        set newxFreq [APSWriteToTelnetStream -command "CALC:MARK:X?" -streamID $streamID]
        APSWriteToTelnetStream -command "BAND 25 Hz" -streamID $streamID
        APSWriteToTelnetStream -command "FREQ:CENT $newxFreq Hz" -streamID $streamID
        APSWriteToTelnetStream -command "PAUSE" -streamID $streamID
        APSWriteToTelnetStream -command "DISP:WIND1:TRAC:Y:AUTO ONCE" -streamID $streamID
        APSWriteToTelnetStream -command "ABOR;*WAI" -streamID $streamID
        update
        after 2000
        set operationCondition 256
        while {$operationCondition & 256} {
            after 1000
            set operationCondition [APSWriteToTelnetStream -command "STAT:OPER:COND?" -streamID $streamID]
        }
        return 1
    } elseif {[string match $plane Vertical]} {
         if [catch {exec cavput -list=SR:TUNE:HP_1366A_C0P1_MBBO,SR:TUNE:Mux4Sw1BO -list==Y \
                     -pend=20} result] {
            return -code error "SetHPVSAHVRange: $result"
        }
        #if [catch {exec cavput -list=SR:TUNE:stripSELmbbo=Y,SR:TUNE:HP_1366A_P0_MBBO=2 \
        #         } result ] {
         #   return -code error "SetHPVSAHVRange: $result"
        #}
        APSWriteToTelnetStream -command "PAUSE" -streamID $streamID
        APSWriteToTelnetStream -command "FREQ:CENT ${newyFreq} Hz" -streamID $streamID
        APSWriteToTelnetStream -command "BAND 300 Hz" -streamID $streamID
        APSWriteToTelnetStream -command "ABOR;*WAI" -streamID $streamID
        update
        after 2000
        set operationCondition 256
        while {$operationCondition & 256} {
            after 1000
            set operationCondition [APSWriteToTelnetStream -command "STAT:OPER:COND?" -streamID $streamID]
        }
        APSWriteToTelnetStream -command "PAUSE" -streamID $streamID
        set newyFreq [APSWriteToTelnetStream -command "CALC:MARK:X?" -streamID $streamID]
        APSWriteToTelnetStream -command "BAND 25 Hz" -streamID $streamID
        APSWriteToTelnetStream -command "FREQ:CENT $newyFreq Hz" -streamID $streamID
        APSWriteToTelnetStream -command "PAUSE" -streamID $streamID
        APSWriteToTelnetStream -command "DISP:WIND1:TRAC:Y:AUTO ONCE" -streamID $streamID
        APSWriteToTelnetStream -command "ABOR;*WAI" -streamID $streamID
        update
        after 2000
        set operationCondition 256
        while {$operationCondition & 256} {
            after 1000
            set operationCondition [APSWriteToTelnetStream -command "STAT:OPER:COND?" -streamID $streamID]
        }
        return 1
    } else {
        return 0
    }
}

proc doExperiment {} {
    global output outputDir start stop points offset review getChromatic cancel mainDir extraMonFile instrument
    global xTune xFreq yTune yFreq HPVSATracesToAve pauseNASA measToAve dividingLine range xrange yrange xchrom ychrom
    global momentumCompactionFactor rfFrequency0 span xPower yPower vsaSpan nasaSpan getDispersion P0ReducedGain measHarmonic
    global useS35Vid MXA deltaFreq sideband points

    set cancel 0
    checkIfFilesExist
    if $cancel {return}
    set xFreq [expr $xFreq + $sideband * $start * $xchrom / $momentumCompactionFactor / 1296.0]
    set yFreq [expr $yFreq + $sideband * $start * $ychrom / $momentumCompactionFactor / 1296.0]

    set deltaFreq [expr ($stop - $start)/($points - 1.0)]
    if {$instrument=="NASA"} {
        if [catch {exec cavget -list=SR:TUNE:NASA:analyzerModeBO -pend=10 -printErrors} mode] {
            return -code error "Unable to read NASA analyzer mode: $mode"
        }
        if {$mode!="Network"} {
            SetStatus "The NASA analyzer mode is not on Network, you have to switch it to Network for chromaticity measurement."
            return
        }
    }
    if !$review {
        cd $outputDir

        set xFreq [ComputeFrequencyFromTune -tune $xTune]
        set yFreq [ComputeFrequencyFromTune -tune $yTune]

        SetStatus "Acquiring data." 

        if $getChromatic {
            if [catch {APSSetTuneMultiplexer -mode $instrument} result] {
                SetStatus $result
                return
            }
            if {[string match $instrument NASA]} {
                #Determine sweep time and average
                if [catch {exec cavget -list=SR:TUNE:NASA:sweepTimeAI,SR:TUNE:NA:CH1:avgFactorAI} dataList] {
                    SetStatus "$dataList"
                    return
                }
            }
        }
        
        set expFile /tmp/[APSTmpString].exp
        set monFile /tmp/[APSTmpString].mon
        APSAddToTempFileList $expFile $monFile
        if $useS35Vid { 
            exec cp $mainDir/inputFiles/dispersion.mon $monFile
        } else {
            if [catch {exec sddsprocess $mainDir/inputFiles/dispersion.mon $monFile \
                         -match=column,ControlName=S:VID?:*,!} result] {
                return -code error "$result"
            }
        }

        if [string length $extraMonFile] {
            set extraExpFile /tmp/[APSTmpString].exp
            set extraMonFile1 /tmp/[APSTmpString].mon
            APSAddToTempFileList $extraMonFile $extraMonFile1
            if [catch {exec sddsselect $extraMonFile $monFile \
                         -match=ControlName -nowarning -invert -pipe=out \
                         | sddsconvert -pipe=in $extraMonFile1 \
                         -retain=column,ControlName,ReadbackName,ReadbackUnits
                exec sdds2stream -rows $extraMonFile1 | token -n=1} rows] {
                SetStatus "Preparing extra PV monitor file: $rows"
                return
            }
            if [lsearch -exact [exec sddsquery -column $extraMonFile1] ReadbackName]!=-1 {
                if [catch {exec sddsselect $extraMonFile1  $monFile $extraMonFile1.1 \
                             -match=ReadbackName -nowarning -invert
                    exec sdds2stream -rows $extraMonFile1.1 | token -n=1} rows] {
                    SetStatus "Preparing extra PV monitor file: $rows"
                    return
                }
                file delete -force $extraMonFile1
                file copy -force $extraMonFile1.1 $extraMonFile1
            }
            if $rows {
                set fid [open $extraExpFile w]
                puts $fid "&measurement_file filename = $extraMonFile1, number_to_average=$measToAve &end"
                close $fid
            } else {
                set extraExpFile ""
            }
        } else {
            set extraExpFile ""
        }

        if {$getChromatic} {
            set template SdispchromTemplate.exp
            set pause 15
            switch $instrument {
                NASA {
                    set pause $pauseNASA
                    if $getDispersion {
                        set template SdispchromTemplateNASA.exp
                    } else {
                        set template SchromTemplateNASA.exp
                    }
                    set span $nasaSpan
                }
                VSA {
                    if $getDispersion {
                        set template SdispchromTemplateVSA.exp
                        set pause [expr 15-2*(0.060*$HPVSATracesToAve)]
                    } else {
                        set template SchromTemplateVSA.exp
                        set pause 3
                    }
                    set span $vsaSpan
                }
            }
	    
            if $pause<0 {
                set pause 0
            }
            exec replaceText $mainDir/inputFiles/$template $expFile \
              -orig=<limit1>,<limit2>,<points>,<mainFile>,<xFreq>,<yFreq>,<pause>,<tracesToAve>,<measToAve>,<monFile>,<dividingLine>,<span>,<xPower>,<yPower>,<P0ReducedGain>,<MXA>,<xrange>,<yrange>,<xchrom>,<ychrom>,<deltaFreq>,<alpha_c>,<measHarmonic>,<steps>,<monFile> \
              -repl=$start,$stop,$points,$output,$xFreq,$yFreq,$pause,$HPVSATracesToAve,$measToAve,$monFile,$dividingLine,$span,$xPower,$yPower,$P0ReducedGain,$MXA,$xrange,$yrange,$xchrom,$ychrom,$deltaFreq,$momentumCompactionFactor,$measHarmonic,$points,$monFile
        } else {
            exec replaceText $mainDir/inputFiles/SdispersionTemplate.exp $expFile \
              -orig=<limit1>,<limit2>,<points>,<measToAve>,<monFile> \
              -repl=$start,$stop,$points,$measToAve,$monFile
        }		    

        if [string length $extraExpFile] {
            exec cat $extraExpFile $expFile > $expFile.1
            file rename -force $expFile.1 $expFile
        }

        # do experiment
        global apsSRDispChromExpDone
        set apsSRDispChromExpDone 0
        set rcList {S:RC:OrbitControlLawXC S:RC:OrbitControlLawYC S:rfFreqControlLawRC DP:S:OrbitControlLawXSDDS DP:S:OrbitControlLawYSDDS}
        if [catch {exec cavget -list=[join $rcList ,] -list=.SUSP -cavputForm} controllawMode] {
            SetStatus "Problem getting orbit controllaw status: $controllawMode"
            return
        }
        if [catch {exec cavput -list=[join $rcList ,] -list=.SUSP=1} result] {
            SetStatus "Problem suspending controllaw: $result"
            return
        }
        set statusDir /home/helios/oagData/sr/BPMStatus
        set NBIOCList [exec sddsprocess $statusDir/config.sdds -pipe=out \
                         -match=col,ElectronicsType=Narrowband -nowarnings\
                         -filter=col,NonexistentH,0,0,NonexistentV,0,0,& \
                         -scan=col,Sector,DeviceName,S%ld,type=long \
                         "-define=col,Sector1,Sector 2 mod" \
                         | sddsprocess -pipe -filter=col,Sector1,0.5,1 \
                         | sddssort -pipe -col=Sector -unique \
                         | sdds2stream -pipe -col=Sector]
        if [catch {exec cavget -cavputForm -pend=10 \
                     -list=S:bpm \
                     -list=[join $NBIOCList ,] \
                     -list=P0: \
                     -list=msAve:Num2AveAO,mswAve:CoeffAO} NBBPMSetup1] {
            SetStatus "Problem saving BPM setup: $NBBPMSetup1"
            return
        }
        if [catch {APSSRSetIOCAveraging -num2Ave 128 -filterCoeff 1 -enable 1 \
                 } result] {
            SetStatus "Problem setting BPM averaging: $result"
            catch {exec cavput -list=$controllawMode}
            return
        }
        
        #modify RTFB regulator, set the filter to higher high-pass 
        SetStatus "Change the high-pass filter of RTFB regulator..."
        if [catch {APSMpSRSetFBfilters -ramp 0 -hFactor 10 -vFactor 15 } result] {
            SetStatus "Problem modifying RTFB regulator filter, $result"
            return
        }
        SetStatus "Done with change the high-pass filter of RTFB regulator..."
         # make sure source is on for VSA
        if $getChromatic {
            SetStatus "cavput -list=SR:TUNE:stripSELmbbo=X,SR:TUNE:Mux4Sw2BO=0"
            if [catch {exec cavput -list=SR:TUNE:stripSELmbbo=X,SR:TUNE:Mux4Sw2BO=0 \
                     } result ] {
                return -code error "doExperiment: unable to setup striplines for NASA: $result"
            }
            SetStatus "APSSetTuneMultiplexer -mode $instrument"
            if [catch {APSSetTuneMultiplexer -mode $instrument} result] {
                return -code error "doExperiment(a): unable to setup tune multiplexer: $result"
            }
            
            switch $instrument {
                VSA {
                    if [catch {exec hpSocketSend hpvecsr "OUTP ON"} result] {
                        return -code error "Error in turning off VSA source: $result"
                    }
                }
                NASA {
                    if [catch {exec cavput -list=SR:TUNE:NASA:rfPowerBO=1} result ] {
                        puts stderr $result
                        exit 1
                    }      
                }
            }
        }
        
        # record present rf frequency for saving in data file
        SetStatus "read rf frequency ..."
        set rfFrequency0 [exec cavget -list=A014-IETS:BTC:SRSetFreqM -float=%13.10g]

        SetStatus "Launching exec log ..."
        APSExecLog .expExec -name "Experiment log" \
          -cancelCallback "APSSRCleanUpDispChrom -datafile $output" \
          -abortCallback "APSSRCleanUpDispChrom -datafile $output" \
          -unixCommand "sddsexperiment $expFile $output -verbose" \
          -callback "APSSRCleanUpDispChrom -datafile $output"  -width 80
        tkwait variable apsSRDispChromExpDone

        # turn off the source
        if $getChromatic {
            switch $instrument {
                VSA {
                    #replace following telnet command, since turn off source does not work, 6/27/2014
                    if [catch {exec hpSocketSend hpvecsr "OUTP OFF"} result] {
                        return -code error "Error in turning off VSA source: $result"
                    }
                }
                NASA {
                  #  if [catch {exec cavput -list=SR:TUNE:NASA:rfPowerBO=0} result ] {
                  #      puts stderr $result
                  #      exit 1
                  #  }      
                }
            }
            #turn off stripline and NASA rf power after experiment
            if [catch {APSSetupStriplineDrive -plane X/Y -stripline 0 -rf 0} result] {
                puts stderr $result
                exit 1
            }
        }

        SetStatus "Restore the RTFB regulator filter..."
        if [catch {APSMpSRSetFBfilters -ramp 1 -steps 5 -interval 1 -restore 1 \
                 } result] {
            SetStatus "Problem restoring RTFB regulator filter, $result"
            return
        }
        #SetStatus "Data acquired. Restoring BPM setup..."
        #if [catch {exec cavput -list=$BPMSetup1 
        #    exec cavput -list=$NBBPMSetup1 \
        #         } result] {
        #    SetStatus "Problem restoring BPM averaging setup: $result"
        #} else {
        #    SetStatus "BPM averaging setup restored."
        #}
        if {[string length $controllawMode] && \
              [catch {exec cavput -list=$controllawMode} result]} {
            SetStatus "Problem setting orbit controllaw mode: $result"
        } else {
            SetStatus "Orbit/rf freq controllaws restored."
        }

        if [catch {exec sddsprocess $output -nowarning  -pipe=out \
                       "-reprint=parameter,Instrument,$instrument" \
                       "-redefine=parameter,useS35Vid,$useS35Vid,type=long" \
                       "-redefine=parameter,sddsexperimentUsed,1,type=long" \
                       "-redefine=para,alpha,$momentumCompactionFactor" \
                       | sddssortcolumn -pipe=in $output.1 -bpmOrder 
            file delete ${output}~} result] {
            SetStatus "Problem post-processing file: $result"
        } else {
            exec mv $output.1 $output
        }
    }
}

# Procedure is called after sddsexperiment and at the start of processing and re-processing
proc APSSRCleanUpDispChrom {args} {
    global momentumCompactionFactor momentumCompactionFactor2 rfFrequency0 latticeName
    set datafile ""
    APSStrictParseArguments {datafile}

    global apsSRDispChromExpDone
    set apsSRDispChromExpDone 1

    set parameterList [APSGetSDDSNames -class parameter -fileName $datafile]
    if {[lsearch -exact $parameterList rfFrequency0] != -1} return

    # This post-processing is supposed to be done only once, after sddsexperiment.
    SetStatus "Postprocessing $datafile"
    if [catch {exec sddsprocess $datafile -nowarning \
                   -print=para,Lattice,$latticeName \
                   -def=para,rfFrequency0,$rfFrequency0,units=Hz \
                   "-redefine=column,delta,rfFrequency rfFrequency0 - rfFrequency0 / $momentumCompactionFactor / chs  sto deltaFirstOrder = sqr $momentumCompactionFactor2 * $momentumCompactionFactor * +" } result] {
        SetStatus "$result"
    }
}

proc chromProcessing {} {
    global output outputDir start stop points offset review getChromatic chromProcMode dividingLine
    global momentumCompactionFactor momentumCompactionFactor2 chromBadPointList order
    set oldDir [pwd]
    cd $outputDir
    set root [file rootname $output]
    SetStatus "Performing chromatic processing for $output."
    APSSRCleanUpDispChrom -datafile $output

    if [catch {exec sddsquery $output -parameter} parameterList] {
        cd $oldDir
        SetStatus "$parameterList"
        return
    }
    if [lsearch -exact $parameterList Instrument]!=-1 {
        if [catch {exec sdds2stream -parameter=Instrument $output} instrument] {
            cd $oldDir
            SetStatus "$instrument"
            return
        }
    }
    set foundAlphaFromFile 0
    if [lsearch -exact $parameterList alpha]!=-1 {
        set foundAlphaFromFile 1
        if [catch {exec sdds2stream -parameter=alpha $output} alphaFromFile] {
            cd $oldDir
            SetStatus "$alphaFromFile"
            return
        }
    }
    # compare alpha_c from file with alpha_c from tcl entry box
    if {$foundAlphaFromFile} {
        if {[expr abs($alphaFromFile - $momentumCompactionFactor) < \
             1e-4 *$momentumCompactionFactor] } {
            # agreement between entry box and file
        } else {
            # ask for change in momentumCompactionFactor value in box
            if [APSYesNoPopUp  "Detected a different value of momentum compaction factor in the data file. Do you want the value in the file ($alphaFromFile) to overwrite the value in the box ($momentumCompactionFactor)?"] {
                set momentumCompactionFactor $alphaFromFile
            }
        }
    }
    

    set badPointList ""
    if [string length $chromBadPointList] {
        set badPointList0 [split $chromBadPointList " ,"]
        foreach item0 $badPointList0 {
            if [scan $item0 %ld item]==1 {
                lappend badPointList $item
            }
        }
        set chromBadPointList [join $badPointList]
    }
    set newNASA 0
    set tuneFileList0 [lsort [glob -nocomplain ${root}Tunes-\[0-9\]\[0-9\]\[0-9\]]]
    set parameters [exec sddsquery -par [lindex $tuneFileList0 0]]
    if {$instrument=="NASA" && [lsearch -exact $parameters "plane"]>=0} {
        set newNASA 1
    }
                       
    if !$review {
        if [llength $badPointList] {
            foreach file $tuneFileList0 {
                set isbad 0
                foreach item $badPointList {
                    incr item -1
                    if [string compare $file [format ${root}Tunes-%03ld $item]]==0 {
                        set isbad 1
                        break
                    }
                }
                if !$isbad {
                    lappend tuneFileList $file
                }
            }
        } else {
            set tuneFileList $tuneFileList0
        }
        set tuneFiles [llength $tuneFileList]
        if !$tuneFiles {
            SetStatus "No data matches ${root}Tunes-\[0-9\]\[0-9\]\[0-9\]"
            cd $oldDir
            return
        }
        
        SetStatus "Processing $tuneFiles files"
        switch $chromProcMode {
            peakfind -
            integrate {
                set fitColumnRoot Tune    
            }
            convolve {
                set fitColumnRoot TuneChange
            }
        }
        if $newNASA {
            #new nasa tune data has two pages, one page for x plane and one page for y plane
            if [catch {ProcessNewNASATuneData -root $root -tuneFileList $tuneFileList \
                         -chromProcMode $chromProcMode} result] {
                cd $oldDir
                return -code error "Error in processing new NASA tune data: $result"
            }
        } else {
            switch $chromProcMode {
                peakfind {
                    if [catch {eval exec sddscombine $tuneFileList \
                                 ${root}traces.sdds -overwrite \
                             } result] {
                        SetStatus $result
                        cd $oldDir
                        return
                    }	
                    switch $instrument {
                        NASA {
                            # removed despiking since there is no real spikes 
                            # in the NASA data and despiking reduces good peaks
                            # at the expense of weaker ones.
                            #      -despike=neighbors=5,average=3,passes=10 
                            if [catch {exec sddssmooth ${root}traces.sdds -pipe=out \
                                         -column=SR:TUNE1 \
                                         | tee ${root}traces.sdds.smo \
                                         | sddspeakfind -pipe -column=SR:TUNE1 -exclusionZone=0.2 \
                                         | sddssort -pipe -column=SR:TUNE1,decr \
                                         | sddsprocess -pipe -clip=2,0,invert \
                                         | sddsconvert -pip -dele=para,xTune,yTune \
                                         | sddssort -pipe=in ${root}peaks.sdds \
                                         -column=Tune,incr  \
                                     } result] {
                                SetStatus "NASA Error1 (peakfind): $result"
                                cd $oldDir
                                return
                            }
                            set whichTune first
                            set clip 0,1
                            foreach plane {x y} {
                                if [catch {exec sddsprocess ${root}peaks.sdds -pipe=out -clip=$clip \
                                             -process=SR:TUNE1,$whichTune,SR:TUNE1$plane \
                                             -process=Tune,$whichTune,${plane}Tune \
                                             | tee ${root}${plane}peaks.sdds \
                                             | sddscollapse -pipe=in ${root}${plane}tune.sdds  \
                                         } result] {
                                    SetStatus "NANA error2 (peakfind) processing $plane data: $result"
                                    cd $oldDir
                                    return
                                }
                                set whichTune last
                                set clip 1,0
                            }
                            
                            if [catch {exec sddsxref ${root}xtune.sdds ${root}ytune.sdds -pipe=out \
                                         | sddsxref -pipe ${root} -transfer=par,rf* -leave=* \
                                         | sddsprocess -pipe=in ${root}tune.sdds \
                                         -define=param,alpha,$momentumCompactionFactor \
                                         -define=param,alpha2,$momentumCompactionFactor2 \
                                         -nowarning \
                                         "-redefine=col,delta,rfFreq rfFrequency0 - rfFrequency0 / alpha / chs sto deltaFirstOrder = sqr alpha2 * alpha * +,symbol=\$gd\$r" \
                                     } result] {
                            cd $oldDir
                                SetStatus "NANA error3 (peakfind) combining tune data: $result"
                                return
                            }
                            
                            catch {file delete ${root}xtune.sdds ${root}ytune.sdds}
                            set fitColumnRoot Tune
                        }
                        VSA {
                            # HPVSA data
                            if [catch {exec sddscollapse ${root}traces.sdds -pipe=out \
                                         | sddsxref -pipe ${root} -transfer=par,rf*  -leave=* \
                                         | sddsprocess -pipe=in ${root}tune.sdds \
                                         -define=param,alpha,$momentumCompactionFactor \
                                         -define=param,alpha2,$momentumCompactionFactor2 \
                                         "-define=column,delta,rfFrequency rfFrequency0 1.0e6 / - rfFrequency0 1.0e6 / / alpha / chs sto deltaFirstOrder = sqr alpha2 * alpha * +,symbol=\$gd\$r" \
                                     } result] {
                                cd $oldDir
                                SetStatus "VSA error1 (peakfind): $result"
                                return
                            }
                            set fitColumnRoot Tune
                        }
                        default {
                            SetStatus "Can't determine instrument from file."   
                        }
                    }
                }
                convolve {
                    set referenceFile [lindex $tuneFileList [expr int($tuneFiles/2)]]
                    SetStatus "Reference tune file: $referenceFile"
                    set tmpRoot /tmp/[APSTmpString]
                    APSAddToTempFileList $tmpRoot.traces $tmpRoot.params $tmpRoot.ref
                    switch $instrument {
                        NASA {
                            if [catch {eval exec sddscombine $tuneFileList -pipe=out \
                                         | sddssort -pipe=in -column=Tune,incr $tmpRoot.traces 
                                exec sddscollapse $tmpRoot.traces $tmpRoot.params
                                eval exec sddscombine [APSReplicateItem -item $referenceFile -number $tuneFiles] \
                                         -pipe=out \
                                         | sddssort -pipe=in -column=Tune,incr $tmpRoot.ref} result] {
                                SetStatus "NASA convolve error: $result"
                                cd $oldDir
                                return
                            }
                            set filter -filter=column,Tune,0,$dividingLine 
                            foreach plane {x y} {
                                APSAddToTempFileList $tmpRoot.traces.$plane $tmpRoot.ref.$plane $tmpRoot.plane
                                if [catch {exec sddsprocess $tmpRoot.traces $tmpRoot.traces.$plane \
                                             $filter \
                                             -process=SR:TUNE1,spread,WSpread -process=SR:TUNE1,min,WMin \
                                             -process=Tune,ave,Tune0 \
                                             "-define=column,W,SR:TUNE1 WMin - WSpread /" \
                                             "-define=column,dTune,Tune Tune0 -"
                                    exec sddsprocess $tmpRoot.ref $tmpRoot.ref.$plane \
                                             $filter \
                                             -process=SR:TUNE1,spread,WSpread -process=SR:TUNE1,min,WMin \
                                             -process=Tune,ave,Tune0 \
                                             "-define=column,W,SR:TUNE1 WMin - WSpread /" \
                                             "-define=column,dTune,Tune Tune0 -"
                                    eval exec sddsconvolve -correlate \
                                             -signal=dTune,W $tmpRoot.traces.$plane \
                                             -response=dTune,W $tmpRoot.ref.$plane \
                                             -output=dTune,WW -pipe=out \
                                             | tee convolve.$plane \
                                             | sddsprocess -pipe \
                                             -process=WW,max,${plane}TuneChange,function=dTune,position \
                                             | sddscollapse -pipe=in $tmpRoot.$plane \
                                         } result] {
                                    SetStatus "NASA cpnvolve error2: $result"
                                    cd $oldDir
                                    return
                                }	
                                set filter -filter=column,Tune,$dividingLine,1
                            }
                            if [catch {exec sddsxref $tmpRoot.x $tmpRoot.y -pipe=out \
                                         | sddsxref -pipe $tmpRoot.params \
                                         | sddsxref -pipe ${root} -transfer=par,rf* -leave=* \
                                         | sddsprocess -pipe=in ${root}tune.sdds \
                                         -define=param,alpha,$momentumCompactionFactor \
                                         -define=param,alpha2,$momentumCompactionFactor2 \
                                         "-define=col,delta,rfFreq rfFreqency0 - rfFreqency0  / alpha / chs sto deltaFirstOrder = sqr alpha2 * alpha * +,symbol=\$gd\$r" \
                                     } result] {
                                cd $oldDir
                                SetStatus "NASA convolve error3: $result"
                                return
                            }
                        }
                        VSA {
                            if [catch {eval exec sddscombine $tuneFileList -pipe=out \
                                         | sddsprocess -pipe \
                                         "-process=?Waveform,min,%sMin" \
                                         "-process=?Waveform,spread,%sSpread" \
                                         {"-define=column,%sNorm,%s %sMin - %sSpread /,select=?Waveform"} \
                                         | sddssort -pipe=in -column=xTune,incr $tmpRoot.traces 
                                exec sddscollapse $tmpRoot.traces $tmpRoot.params
                                eval exec sddscombine [APSReplicateItem -item $referenceFile -number $tuneFiles] \
                                         -pipe=out \
                                         | sddsprocess -pipe \
                                         "-process=?Waveform,min,%sMin" \
                                         "-process=?Waveform,spread,%sSpread" \
                                         {"-define=column,%sNorm,%s %sMin - %sSpread /,select=?Waveform"} \
                                         | sddssort -pipe=in -column=xTune,incr $tmpRoot.ref} result] {
                                SetStatus "VSA convolve error1: $result"
                                cd $oldDir
                                return
                            }
                            foreach plane {x y} {
                               if [catch { exec sddsconvolve -correlate \
                                  -signal=${plane}Tune,${plane}WaveformNorm $tmpRoot.traces \
                                  -response=${plane}Tune,${plane}WaveformNorm $tmpRoot.ref \
                                  -output=${plane}Tune,WW -pipe=out \
                                  | sddsconvert -pipe -delete=parameter,* \
                                  | sddsprocess -pipe \
                                  -process=WW,max,${plane}TuneChange,function=${plane}Tune,position \
                                  | sddscollapse -pipe=in $tmpRoot.$plane } result] {
                                   SetStatus "VSA convolve error2 for $plane: $result"
                                   cd $oldDir
                                   return
                               }
                            }
                            if [catch {exec sddsxref $tmpRoot.x $tmpRoot.y -pipe=out \
                                         | sddsxref -pipe $tmpRoot.params -nowarning \
                                         | sddsxref -pipe $root -transfer=par,rf* -leave=* \
                                         | sddsprocess -pipe=in ${root}tune.sdds \
                                         -define=param,alpha,$momentumCompactionFactor \
                                         -define=param,alpha2,$momentumCompactionFactor2 \
                                         "-define=col,delta,rfFrequency rfFrequency0 1.0e6 / - rfFrequency0 1.0e6 / / alpha / chs sto deltaFirstOrder = sqr alpha2 * alpha * +,symbol=\$gd\$r" \
                                     } result] {
                                cd $oldDir 
                                SetStatus "VSA convolve error3: $result"
                                return
                            }
                        }
                        default {
                            SetStatus "Can't determine instrument from file."   
                        }
                    }
                    
                    file delete [glob -nocomplain $tmpRoot.*]
                    set fitColumnRoot TuneChange
                }
                integrate {
                    # there seems to be only applicable to NASA
                    set tmpRoot /tmp/[APSTmpString]
                    APSAddToTempFileList $tmpRoot.params $tmpRoot.x $tmpRoot.y
                    if [catch {eval exec sddscombine $tuneFileList \
                                 -pipe=out \
                                 | sddssort -pipe -column=Tune,incr \
                                 | tee ${root}traces.sdds \
                                 | sddscollapse -pipe \
                                 | sddsconvert -pipe=in -delete=column,?Tune $tmpRoot.params } result] {
                        SetStatus "Integrate error1: $result"
                        cd $oldDir
                        return
                    }	
                    set filter -filter=column,Tune,0,$dividingLine
                    foreach plane {x y} {
                        if [catch {exec sddsprocess ${root}traces.sdds -pipe=out $filter \
                                     -delete=param,?Tune \
                                     | sddsinteg -versus=Tune -integrate=SR:TUNE1 -pipe \
                                     | sddsprocess -pipe \
                                     -process=SR:TUNE1Integ,min,SR:TUNE1IntegMin \
                                     -process=SR:TUNE1Integ,spread,SR:TUNE1IntegSpread \
                                     "-define=column,W,SR:TUNE1Integ SR:TUNE1IntegMin - SR:TUNE1IntegSpread /" \
                                     -process=W,zero,${plane}Tune,functionOf=Tune,offset=-0.5 \
                                     | sddscollapse -pipe=in $tmpRoot.$plane} result] {
                            SetStatus "Integrate error2: $result"
                            cd $oldDir
                            return
                        }
                        set filter -filter=column,Tune,$dividingLine,1
                    }
                    if [catch {exec sddsxref $tmpRoot.x $tmpRoot.y -pipe=out \
                                 | sddsxref -pipe $root -transfer=par,rf* -leave=* \
                                 | sddsprocess -pipe=in ${root}tune.sdds \
                                 -define=param,alpha,$momentumCompactionFactor \
                                 -define=param,alpha2,$momentumCompactionFactor2 \
                                 "-define=col,delta,rfFreq rfFrequency0 - rfFrequency0 / alpha / chs sto deltaFirstOrder = sqr alpha2 * alpha * +,symbol=\$gd\$r" \
                             } result] {
                        cd $oldDir
                        SetStatus "Integrate error3: $result"
                        return
                    }
                    
                    file delete [glob -nocomplain $tmpRoot.*]
                    set fitColumnRoot Tune
                }
            }
        }
        
        if {$order == 1} {set terms 2} else {set terms 3}
        foreach plane {x y} {
            if [catch {exec sddspfit ${root}tune.sdds -pipe=out -col=delta,${plane}${fitColumnRoot} -terms=$terms \
                         | sddsoutlier -pipe -column=${plane}${fitColumnRoot}Residual -stDevLimit=2 \
                         | sddspfit -pipe -col=delta,${plane}${fitColumnRoot} -terms=$terms -generate \
                         | sddsconvert -pipe \
                         -rename=param,Slope=${plane}Chromaticity,SlopeSigma=${plane}ChromaticitySigma \
                         -nowarning  \
                         | sddsprocess -pipe=in ${root}${plane}Tune.fit \
                         "-redefine=parameter,FitPoints,n_rows,type=long" \
                         "-reprint=param,${plane}FitLabel,${plane}: RMS Residual=%.2g N=%ld,RmsResidual,FitPoints" \
                         "-reprint=param,${plane}ChromLabel,${plane} = %.2f\$sa\$e%.2f,${plane}Chromaticity,${plane}ChromaticitySigma" \
                     } result] {
                if {$tuneFiles==2} {
                    SetStatus "ignore sddspfit error for 2 data points."
                } else {
                    SetStatus "sddspfit error: $result"
                    cd $oldDir
                    return
                }
            }
            
            if {$tuneFiles<=2} {
                if [catch {exec sddsprocess ${root}${plane}Tune.fit \
                             -redefine=par,${plane}ChromaticitySigma,0 \
                             "-reprint=param,${plane}FitLabel,${plane}: RMS Residual=%.2g N=%ld,RmsResidual,FitPoints" \
                             "-reprint=param,${plane}ChromLabel,${plane} = %.2f,${plane}Chromaticity" -nowarnings} result] {
                    SetStatus "Error redefine fit error for 2 points data: $result"
                    cd $oldDir
                    return
                }
                
            }
        }
        if {$order == 2} {
            set xChrom2 [format %10.2e [expr [exec sdds2stream ${root}xTune.fit -para=Curvature] * 2]]
            set yChrom2 [format %10.2e [expr [exec sdds2stream ${root}yTune.fit -para=Curvature] * 2]]
            SetStatus "Second order chromaticity: X: $xChrom2; Y: $yChrom2."
        }
        if {[catch {exec sddsxref -nowarning ${root}tune.sdds -pipe=out \
                      ${root}yTune.fit -leave=* -transfer=param,yChrom*,yFitLabel \
                      | sddsxref -pipe -nowarning ${root}xTune.fit \
                      -leave=* -transfer=param,xChrom*,xFitLabel \
                      | sddsprocess -pipe=in ${root}tune.sdds1  \
                      "-reprint=param,FitLabel,%s  %s,xFitLabel,yFitLabel" \
                      "-reprint=param,ChromLabel,Chromaticities: %s %s,xChromLabel,yChromLabel" 
            exec mv ${root}tune.sdds1 ${root}tune.sdds } result]}  {
            SetStatus "Error combining tune data: $result"
            cd $oldDir
            return
        }
        
        catch {rm ${root}*~}
    }
    if [catch {exec sddsplot \
                 -col=delta,?$fitColumnRoot -graph=sym,vary=subtype,scale=2 \
                 -legend=scale=2 ${root}tune.sdds \
                 -title=@FitLabel -topline=@ChromLabel \
                 -col=delta,x${fitColumnRoot}Fit ${root}xTune.fit -grap=line,type=0 \
                 -col=delta,y${fitColumnRoot}Fit ${root}yTune.fit -grap=line,type=1 "-ylabel=Tune value" &  \
             } result] {
        cd $oldDir
        SetStatus $result
        return
    }

    switch $instrument {
        NASA {
            if $newNASA {
                if [catch {exec sddsplot -split=page -sep=page -groupby=page -same -grap=line,vary \
                             -col=Tune,SR:TUNE1 ${root}traces.sdds.x ${root}traces.sdds.x.smo -topline=xtune \
                             -col=Tune,SR:TUNE1 ${root}xpeaks.sdds -graph=sym,scale=2,subtype=3 -endp \
                             -col=Tune,SR:TUNE1 ${root}traces.sdds.y ${root}traces.sdds.y.smo -topline=ytune \
                             -col=Tune,SR:TUNE1 ${root}ypeaks.sdds -graph=sym,scale=2,subtype=4 -endp & \
                         } result] {
                    cd $oldDir
                    SetStatus $result
                    return
                }
            } else {
                if [catch {exec sddsplot -split=page -sep=page -groupby=page -same -grap=line,vary \
                             -col=Tune,SR:TUNE1 ${root}traces.sdds ${root}traces.sdds.smo \
                             -col=Tune,SR:TUNE1 ${root}xpeaks.sdds -graph=sym,scale=2,subtype=3 \
                             -col=Tune,SR:TUNE1 ${root}ypeaks.sdds -graph=sym,scale=2,subtype=4 & \
                         } result] {
                    cd $oldDir
                    SetStatus $result
                    return
                }
            }
        }
        VSA {
            if [catch {exec sddsplot -split=page -separate=page -groupby=page -same \
                         "-ylabel=Waveform" "-xlabel=Tune" -mode=y=log,y=special \
                         -legend=yname,edit=%/Waveform// -graph=line,vary \
                         -column=xTune,xWaveform \
                         ${root}traces.sdds \
                         -column=xTune,xWaveform \
                         ${root}traces.sdds \
                         -column=yTune,yWaveform \
                         ${root}traces.sdds \
                         -column=yTune,yWaveform \
                         ${root}traces.sdds \
                         -parameter=xTune,xWaveformPeak -graph=sym,scale=3,subtype=5 \
                         ${root}traces.sdds -legend=spec= \
                         -parameter=yTune,yWaveformPeak -graph=sym,scale=3,subtype=5 \
                         ${root}traces.sdds -legend=spec= & } result] {
                cd $oldDir
                SetStatus $result
                return
            }
        }
        default {
            SetStatus "Can't determine instrument from file."   
        }
    }
    cd $oldDir
    APSDeleteTempFiles
    SetStatus Done.
}

proc ProcessNewNASATuneData {args} {
    set root ""
    set tuneFileList ""
    set chromProcMode ""
    APSParseArguments {root tuneFileList chromProcMode}

    global momentumCompactionFactor momentumCompactionFactor2 npSmooth nPasses reverseWaveform
    set tmpRoot /tmp/[APSTmpString]
    set xFileList ""
    set yFileList ""
    set index 0
   
    foreach file $tuneFileList {
        foreach plane {x y} {
            if [catch {exec sddsprocess $file $tmpRoot.$index.$plane -match=par,plane=$plane} result] {
                return -code error "No matching plane found in file $file: $result"
            }
            lappend ${plane}FileList $tmpRoot.$index.$plane
        }
        incr index
    }
   
    switch $chromProcMode {
        peakfind {
            foreach plane {x y} {
                if [catch {eval exec sddscombine [set ${plane}FileList] -pipe=out \
			     | sddsprocess -pipe \"-redef=col,SR:TUNE1,SR:TUNE1 $reverseWaveform *\" \
                             | tee ${root}traces.sdds.$plane \
                             | sddssmooth -pipe -column=SR:TUNE1 -despike=neighbors=3,average=3,passes=3 \
			     -points=$npSmooth -passes=$nPasses \
                             | tee ${root}traces.sdds.$plane.smo \
                             | sddspeakfind -pipe -column=SR:TUNE1 -exclusionZone=0.2 \
                             | sddssort -pipe -column=SR:TUNE1,decr \
                             | sddsprocess -pipe -clip=1,0,invert \
                             | sddsconvert -pip -dele=para,xTune,yTune \
                             | sddsprocess -pipe -process=SR:TUNE1,first,SR:TUNE1$plane \
                             -process=Tune,first,${plane}Tune \
                             |  tee ${root}${plane}peaks.sdds \
                             | sddscollapse -pipe=in ${root}${plane}tune.sdds } result] {
                    return -code error "Error in processing new NASA tune data(1): $result"
                }
            }
            if [catch {exec sddsxref ${root}xtune.sdds ${root}ytune.sdds -pipe=out \
                         | sddsxref -pipe ${root} -transfer=par,rf* -leave=* \
                         | sddsprocess -pipe=in ${root}tune.sdds \
                         -define=param,alpha,$momentumCompactionFactor \
                         -define=param,alpha2,$momentumCompactionFactor2 \
                         -nowarning \
                         "-redefine=col,delta,rfFreq rfFrequency0 - rfFrequency0 / alpha / chs sto deltaFirstOrder = sqr alpha2 * alpha * +,symbol=\$gd\$r" \
                     } result] {
                return -code error "Error in processing new NASA tune data(2): $result"
            }
                        
            catch {file delete ${root}xtune.sdds ${root}ytune.sdds}
        }
        convolve {
            if [catch {eval exec sddscombine $xFileList -pipe=out \
                         | sddscollapse -pipe=in $tmpRoot.params } result] {
                return -code error "Error in processing new NASA tune data(3): $result"
            }
          
            foreach plane {x y} {
                set tuneFiles [llength $tuneFileList]
                set referenceFile [lindex [set ${plane}FileList] [expr int($tuneFiles/2)]]
                if [catch {eval exec sddscombine [APSReplicateItem -item $referenceFile -number $tuneFiles] \
                             -pipe=out \
                             | sddssort -pipe -col=Tune,incr \
                             | sddsprocess -pipe=in $tmpRoot.ref.$plane \
                             -process=SR:TUNE1,spread,WSpread -process=SR:TUNE1,min,WMin \
                             -process=Tune,ave,Tune0 \
                             \"-define=column,W,SR:TUNE1 WMin - WSpread /\" \
                             \"-define=column,dTune,Tune Tune0 -\"} result] {
                    return -code error "Error in processing new NASA tune data(4): $result"
                } 
                
                if [catch {eval exec sddscombine [set ${plane}FileList] -pipe=out \
                             | sddssort -pipe=in -column=Tune,incr $tmpRoot.traces.$plane 
                    exec sddscollapse $tmpRoot.traces.$plane $tmpRoot.params  } result] {
                    return -code error "Error in processing new NASA tune data(5): $result"
                }
                APSAddToTempFileList $tmpRoot.traces.$plane $tmpRoot.ref.$plane $tmpRoot.plane
                if [catch {eval exec sddscombine [set ${plane}FileList] -pipe=out \
                             | sddssort -pipe -col=Tune,incr \
                             | sddsprocess -pipe=in $tmpRoot.traces.$plane \
                             -process=SR:TUNE1,spread,WSpread -process=SR:TUNE1,min,WMin \
                             -process=Tune,ave,Tune0 \
                             \"-define=column,W,SR:TUNE1 WMin - WSpread /\" \
                             \"-define=column,dTune,Tune Tune0 -\"
                    eval exec sddsconvolve -correlate \
                             -signal=dTune,W $tmpRoot.traces.$plane \
                             -response=dTune,W $tmpRoot.ref.$plane \
                             -output=dTune,WW -pipe=out \
                             | tee convolve.$plane \
                             | sddsprocess -pipe \
                             -process=WW,max,${plane}TuneChange,function=dTune,position \
                             | sddscollapse -pipe=in $tmpRoot.$plane \
                         } result] {
                    return -code error "Error in processing new NASA tune data(5): $result"
                }
            }
            if [catch {exec sddsxref $tmpRoot.x $tmpRoot.y -pipe=out \
                         | sddsxref -pipe ${root} -transfer=par,rf* -leave=* \
                         | sddsprocess -pipe=in  ${root}tune.sdds  \
                         -define=param,alpha,$momentumCompactionFactor \
                         -define=param,alpha2,$momentumCompactionFactor2 \
                         "-define=col,delta,rfFreq rfFrequency0 - rfFrequency0  / alpha / chs sto deltaFirstOrder = sqr alpha2 * alpha * +,symbol=\$gd\$r" \
                     } result] {
                return -code error "Error in processing new NASA tune data(7): $result"
                
            }
            file delete [glob -nocomplain $tmpRoot.*]
        }
        integrate {
            APSAddToTempFileList $tmpRoot.params $tmpRoot.x $tmpRoot.y
            if [catch {eval exec sddscombine $xFileList -pipe=out \
                         | sddscollapse -pipe \
                         | sddsconvert -pipe=in -delete=col,?Tune $tmpRoot.params} result] {
                return -code error "Error in processing new NASA tune data(8): $result"
            }
            foreach plane {x y} {
                if [catch {eval exec sddscombine [set ${plane}FileList] -pipe=out \
                             | sddsconvert -pipe -dele=par,?Tune \
                             | sddsinteg -versus=Tune -integrate=SR:TUNE1 -pipe \
                             | sddsprocess -pipe \
                             -process=SR:TUNE1Integ,min,SR:TUNE1IntegMin \
                             -process=SR:TUNE1Integ,spread,SR:TUNE1IntegSpread \
                             \"-define=column,W,SR:TUNE1Integ SR:TUNE1IntegMin - SR:TUNE1IntegSpread /\" \
                             -process=W,zero,${plane}Tune,functionOf=Tune,offset=-0.5 \
                             | sddscollapse -pipe=in $tmpRoot.$plane} result] {
                    return -code error "Error in processing new NASA tune data(9): $result"
                }
            }
            if [catch {exec sddsxref $tmpRoot.x $tmpRoot.y -pipe=out \
                         | sddsxref -pipe $root -transfer=par,rf* -leave=* \
                         | sddsprocess -pipe=in ${root}tune.sdds \
                         -define=param,alpha,$momentumCompactionFactor \
                         -define=param,alpha2,$momentumCompactionFactor2 \
                         "-define=col,delta,rfFreq rfFrequency0 - rfFrequency0 / alpha / chs sto deltaFirstOrder = sqr alpha2 * alpha * +,symbol=\$gd\$r" \
                     } result] {
                return -code error "Error in processing new NASA tune data(10): $result"
            }
            file delete [glob -nocomplain $tmpRoot.*]
        }
    }
    return
}

#-----------------------------------------------------------------------------
#
proc calcDispersion1 {} {
    #
    #-----------------------------------------------------------------------------
    global output outputDir start stop points offset review momentumCompactionFactor momentumCompactionFactor2 OAGGlobal
  
    #-----------------------------------------------------------------------------
    #
    set oldDir [pwd]
    SetStatus "Calculating the first order dispersion for $output."
    cd $outputDir
    APSSRCleanUpDispChrom -datafile $output
    #    
    #-----------------------------------------------------------------------------
    if [catch {exec sddsquery $output -parameter} parameterList] {
        cd $oldDir
        SetStatus "$parameterList"
        return
    }
    set useS35Vid 0
    if [lsearch -exact $parameterList useS35Vid]!=-1 {
        if [catch {exec sdds2stream -parameter=useS35Vid $output} useS35Vid] {
            cd $oldDir
            SetStatus "calcDispersion1 (Error1a): $useS35Vid"
            return
        }
    }
    set foundAlphaFromFile 0
    if [lsearch -exact $parameterList alpha]!=-1 {
        set foundAlphaFromFile 1
        if [catch {exec sdds2stream -parameter=alpha $output} alphaFromFile] {
            cd $oldDir
            SetStatus "calcDispersion1 (Error1): $alphaFromFile"
            return
        }
    }
    # compare alpha_c from file with alpha_c from tcl entry box
    if {$foundAlphaFromFile} {
        if {[expr abs($alphaFromFile - $momentumCompactionFactor) < \
             1e-4 *$momentumCompactionFactor] } {
            # agreement between entry box and file
        } else {
            # ask for change in momentumCompactionFactor value in box
            if [APSYesNoPopUp  "Detected a different value of momentum compaction factor in the data file. Do you want the value in the file ($alphaFromFile) to overwrite the value in the box ($momentumCompactionFactor)?"] {
                set momentumCompactionFactor $alphaFromFile
            }
        }
    }


    set firstCommand "cat $output"
    if [lsearch [APSGetSDDSNames -fileName $output -class parameter] sddsexperimentUsed]!=-1 {
        if [catch {APSGetSDDSParameter -fileName $output \
                     -parameter sddsexperimentUsed} result] {
            cd $oldDir
            SetStatus "calcDispersion1 (Error2): Problem getting value of sddsexperimentUsed \
                       parameter: $result"
            return
        }
        set sddsexperimentUsed [lindex $result 0]
        if $sddsexperimentUsed {
            set firstCommand "sddscollect $output -pipe=out \
                              -collect=suffix=:msAve:x \
                              -collect=suffix=:msAve:y "
        }
    } else {
        set sddsExperimentUsed 0
    }
    
    # take slopes. rfFrequency0 previously determined in real-time is not
    # available as a global variable, so we have to get it from the saved
    # data, which is probably better
    set rfFrequency0 [lindex [exec sdds2stream -para=rfFrequency0 $output] 0 ]
    if [catch {eval exec $firstCommand \
                 | sddsprocess -pipe -reprint=param,ActuatorName,rfFrequency \
                   \"-def=para,rfFrequencyDelta,rfFrequency $rfFrequency0 -\" \
                 -nowarning \
                 | sddsvslopes -pipe -indep=rfFrequencyDelta -sigma \
                 | sddsxref    -pipe -match=Rootname=BPMName -noWarning \
                 $OAGGlobal(SRLatticesDirectory)/scripts/SRBPMPosition.xref \
                 -take=s \
                 | sddssort    -pipe -col=s \
                 | sddsprocess -pipe -redefine=param,nBPMSectors,40,type=long \
                 | sddsprocess -pipe=in $output.slopes \
                 -redefine=column,Index,i_row,type=long \
                 -reprint=param,ActuatorName,rfFrequency \
                 -redefine=param,alpha,$momentumCompactionFactor \
                 -redefine=param,centerFrequency,$rfFrequency0,units=Hz \
                 {"-redefine=col,xDispersion,:msAve:xSlope \
              alpha * centerFrequency * chs,symbol=\$gc\$r\$a(1)\$bx\$n,units=mm"} \
                 {"-redefine=col,yDispersion,:msAve:ySlope \
              alpha * centerFrequency * chs,symbol=\$gc\$r\$a(1)\$by\$n,units=mm"} \
                 \
                 {"-redefine=col,xDispersionSigma,:msAve:xSlopeSigma \
              alpha * centerFrequency * chs,symbol=\$gc\$r\$a(1)\$bx\$n,units=mm"} \
                 {"-redefine=col,yDispersionSigma,:msAve:ySlopeSigma \
              alpha * centerFrequency * chs,symbol=\$gc\$r\$a(1)\$by\$n,units=mm"} \
             } result] {
        cd $oldDir
        SetStatus "calcDispersion1 (Error3): Problem taking slopes: $result"
        return
    }
    
    exec sddsplot $output.slopes -col=Index,?Dispersion \
      -graph=line,vary -uns=y -axes=x &
    
    #    exec sddsplot $output.slopes  \
        -uns=y -axes=x \
        -col=Index,xDispersion,xDispersionSigma -grap=errorbar,conn=0,sub=1 \
        -col=Index,yDispersion,yDispersionSigma -grap=errorbar,conn=0,sub=2 &
    
    exec sddsplot $output.slopes \
        -uns=y -axes=x \
        -split=column=s,width=55.2,start=0 \
        -sep=subpage -leg \
        -group=subpage -same=y \
        -col=Rootname,xDispersion,xDispersionSigma \
        -graph=errorbar,conn=1,sub=1 \
        -col=Rootname,yDispersion,yDispersionSigma \
        -graph=errorbar,conn=2,sub=2 &
    
#    exec sddsplot $output.slopes -col=Rootname,?Dispersion\
        -graph=errorbar,conn=sub,vary=sub \
        -uns=y -axes=x \
        -split=column=s,width=55.2,start=0 \
        -sep=subpage -leg \
        -group=subpage -same=y & 
    
    if $useS35Vid {
        if [catch {exec sddspfit  -terms=2 -column=delta,S35BMxCentroidFit \
                     $output -pipe=out \
                     | sdds2stream -pipe -parameter=Slope} result] {
            cd $oldDir
            SetStatus "Problem computing S35BM x-dispersion: $result."
            return
        }
        SetStatus "S35BM x dispersion is [expr $result*1e-6] m"
        if [catch {exec sddspfit  -terms=2 -column=delta,S35BMyCentroidFit \
                     $output -pipe=out \
                     | sdds2stream -pipe -parameter=Slope} result] {
            cd $oldDir
            SetStatus "Problem computing S35BM y-dispersion: $result."
            return
        }
        SetStatus "S35BM y dispersion is [expr $result*1e-6] m"
        set columnList [exec sddsquery -col $output]
        if [lsearch -exact $columnList S36AMxCentroidFit]!=-1 {
            if [catch {exec sddspfit -terms=2 -column=delta,S36AMxCentroidFit \
                         $output -pipe=out \
                         | sdds2stream -pipe -parameter=Slope} result] {
                cd $oldDir
                SetStatus "Problem computing S36AM dispersion: $result."
                return
            }
            SetStatus "S36AM x dispersion is [expr $result*1e-6] m"
        }
        if [lsearch -exact $columnList S35IDxCentroidFit]!=-1 {
            if [catch {exec sddspfit  -terms=2 -column=delta,S35IDxCentroidFit \
                         $output -pipe=out \
                         | sdds2stream -pipe -parameter=Slope} result] {
                cd $oldDir
                SetStatus "Problem computing S35ID dispersion: $result."
                return
            }
            SetStatus "S35ID x dispersion is [expr $result*1e-6] m"
        }
    }
   # menuPlotting
    global widgetPlottingButton 
    #APSEnableButton $widgetPlottingButton.plotDispersion.button
    
    SetStatus Done.
    cd $oldDir
}
    
#-----------------------------------------------------------------------------
#
proc calcDispersion2 {} {

    global output outputDir start stop points offset review OAGGlobal
    global dx0r dy0r dx0s dy0s dx1r dy1r dx1s dy1s xfit yfit
    global columnList rfFrequency0 momentumCompactionFactor momentumCompactionFactor2

    SetStatus "Calculating the second order dispersion for $output."
    set oldDir [pwd]
    cd $outputDir
    APSSRCleanUpDispChrom -datafile $output
    
    set help1 "[APSGetSDDSParameter -fileName $output -parameter rfFrequency0]"
    set help2 "[APSGetSDDSParameter -fileName $output -parameter sddsexperimentUsed]"
    set parameterList [APSGetSDDSNames -fileName $output -class parameter]
    #----------------------------------------------------------------------
    # Obtaining the value of rfFrequency0
    #
    if [lsearch $parameterList rfFrequency0]==-1 {
        cd $oldDir
        SetStatus "Problems with parameter rfFrequency0"
        return
    } else {
        set rfFrequency0 $help1
    }
    SetStatus "rfFrequency0 = $rfFrequency0"
    #----------------------------------------------------------------------
    # Obtaining the value of sddsexperimentUsed and it's checking
    #
    if [lsearch $parameterList sddsexperimentUsed]==-1 {
        cd $oldDir
        SetStatus "Parameter sddsexperimentUsed is unknown"
        return
    } else {set sddsexperimentUsed $help2}
    SetStatus "sddsexperimentUsed = $sddsexperimentUsed"
    if $sddsexperimentUsed==0 {
        cd $oldDir
        SetStatus "Calculation is impossible: parameter sddsexperimentUsed=0"
        return
    } 
    #----------------------------------------------------------------------
    # Obtaining the list of the all columns
    #
    if ![catch {eval exec sddsquery $output -columnList} columnList]==0 {
        cd $oldDir
        SetStatus "Problems: $columnList"
        return
    } 
    #----------------------------------------------------------------------
    # Obtaining the list of the BPM with measuring x,y-orbits
    #
    set bpmListHelp ""
    foreach columnName $columnList {
        if {![regexp :msAve:x $columnName]==0} {
            lappend bpmListHelp $columnName
        } else {
            if {![regexp :msAve:y $columnName]==0} {
                lappend bpmListHelp $columnName
            }
        }
    }
    #    SetStatus "bpmListHelp = $bpmListHelp"
    
    #----------------------------------------------------------------------
    # Preparation of dependent column names for mpfit-function
    #
    set bpmNames ""
    set index -1
    foreach columnName $bpmListHelp {
        if {[regexp :AdjustedCC $columnName]==0} {
            incr index
            if {$index == 0} {
                set bpmNames $columnName
            } else {
                set bpmNames $bpmNames,$columnName
            }
        }
    }
    #    SetStatus "bpmNames = $bpmNames"

    set xrefFile $OAGGlobal(SRLatticesDirectory)/scripts/SRBPMPosition.xref

    #----------------------------------------------------------------------
    #
    #                     DISPERSION of first and second orders
    #
    #----------------------------------------------------------------------
    # Fitting with polynomial of the second order
    # 
    # preparation of the file $output.frame with data of the dependence 
    # :msAve:x, :msAve:y, :msAve:xFit and :msAve:yFit on rfFrequency for each BPM
    #
    SetStatus "Start of the dispersions calculations." 
   # SetStatus "Wait approximately 40 seconds, please..."
    set dispExpr0x "xSlope alpha * centerFrequency * chs"
    set dispExpr1x "xCurvature alpha * alpha * centerFrequency * centerFrequency * xDispersion1 alpha2 * alpha / +" 
    set dispExpr0y "ySlope alpha * centerFrequency * chs"
    set dispExpr1y "yCurvature alpha * alpha * centerFrequency * centerFrequency * yDispersion1 alpha2 * alpha / +" 
    set dispParam0x "symbol=\$gc\$r\$a(1)\$r\$bx\$n,units=mm"
    set dispParam1x "symbol=\$gc\$r\$a(2)\$r\$bx\$n,units=mm"
    set dispParam0y "symbol=\$gc\$r\$a(1)\$r\$by\$n,units=mm"
    set dispParam1y "symbol=\$gc\$r\$a(2)\$r\$by\$n,units=mm"
    # need three terms in order to get a parabola (2nd order dispersion)
    if [catch {eval exec sddsmpfit $output -pipe=out \
                 -indep=rfFrequency \
                 -depend=$bpmNames \
                 -xOffset=$rfFrequency0 -term=3 \
                 | sddsconvert -pipe=in $output.frame \
                 -retain=column,rfFrequency \
                 -retain=column,*msAve:x \
                 -retain=column,*msAve:xFit \
                 -retain=column,*msAve:y \
                 -retain=column,*msAve:yFit \
                 -retain=parameter,*:msAve:xCurvature \
                 -retain=parameter,*:msAve:yCurvature \
                 -retain=parameter,*:msAve:xSlope\
                 -retain=parameter,*:msAve:ySlope \
                 -delete=parameter,rfFrequency* \
                 -delete=parameter,Basis \
                 -delete=parameter,Terms \
                 -delete=parameter,*:msAve:xRmsResidual \
                 -delete=parameter,*:msAve:xFitIsValid \
                 -delete=parameter,*:msAve:xSddspfitlabel \
                 -delete=parameter,*:msAve:xIntercept \
                 -delete=parameter,*:msAve:yRmsResidual \
                 -delete=parameter,*:msAve:yFitIsValid \
                 -delete=parameter,*:msAve:ySddspfitlabel \
                 -delete=parameter,*:msAve:yIntercept \
             } result] {
        cd $oldDir
        SetStatus "Problems: $result"
        APSAddToTempFileList $output.frame     
        return
    }
    SetStatus "File $output.frame is written"   
    APSAddToTempFileList $output.frame    

    #----------------------------------------------------------------------
    # obtaining for each BPM the values of slope and curvature coefficients
    # 
    if [catch {eval exec sddsconvert $output.frame -pipe=out \
                 -delete=column,* \
                 | sddscollapse -pipe \
                 | sddscollect -pipe -collect=suffix=:msAve:xCurvature \
                 -collect=suffix=:msAve:xSlope \
                 -collect=suffix=:msAve:xReducedChiSquared  \
                 -collect=suffix=:msAve:xSignificanceLevel  \
                 -collect=suffix=:msAve:yCurvature \
                 -collect=suffix=:msAve:ySlope \
                 -collect=suffix=:msAve:yReducedChiSquared  \
                 -collect=suffix=:msAve:ySignificanceLevel  \
                 | sddsconvert -pipe \
                 -rename=column,:msAve:xCurvature=xCurvature \
                 -rename=column,:msAve:xSlope=xSlope \
                 -rename=column,:msAve:xReducedChiSquared=xReducedChiSquared \
                 -rename=column,:msAve:xSignificanceLevel=xSignificanceLevel \
                 -rename=column,:msAve:yCurvature=yCurvature \
                 -rename=column,:msAve:ySlope=ySlope \
                 -rename=column,:msAve:yReducedChiSquared=yReducedChiSquared \
                 -rename=column,:msAve:ySignificanceLevel=ySignificanceLevel \
                 | sddsxref -pipe -match=Rootname=BPMName $xrefFile \
                 -take=s -noWarning \
                 | sddssort -pipe -col=s \
                 | sddsprocess -pipe \
                 -redefine=param,nBPMSectors,40,type=long \
                 | sddsprocess -pipe=in $output.mpfit \
                 -redefine=column,Index,i_row,type=long \
                 -redefine=param,alpha,$momentumCompactionFactor \
                 -redefine=param,alpha2,$momentumCompactionFactor2 \
                 -redefine=param,centerFrequency,$rfFrequency0,units=Hz \
                 {"-redefine=col,xDispersion1,$dispExpr0x,$dispParam0x"} \
                 {"-redefine=col,xDispersion2,$dispExpr1x,$dispParam1x"} \
                 {"-redefine=col,yDispersion1,$dispExpr0y,$dispParam0y"} \
                 {"-redefine=col,yDispersion2,$dispExpr1y,$dispParam1y"} \
             } result] {
        cd $oldDir
        SetStatus "Problems: $result"
        APSAddToTempFileList $output.mpfit    
        return
    }
    
    SetStatus "File $output.mpfit is written"   
    APSAddToTempFileList $output.mpfit    

    #----------------------------------------------------------------------
    # Printing result data (X)
    #
    if [catch {exec sddsprintout $output.mpfit $output.Xtable \
                 -column=Index \
                 -column=Rootname,format=%10s \
                 -column=xDispersion1,format=%12.5f \
                 -column=xDispersion2,format=%12.5f \
                 -column=xSlope,format=%12.5e \
                 -column=xCurvature,format=%12.5e \
                 -column=xReducedChiSquared,format=%12.5e \
                 -column=xSignificanceLevel,format=%12.5f} result] {
        cd $oldDir
        SetStatus "Problems for file $output.Xtable due to $result"
        APSAddToTempFileList $output.Xtable    
    }
    SetStatus "File $output.Xtable is written"   
    APSAddToTempFileList $output.Xtable    
    
    APSFileDisplayWindow [APSUniqueName .] -fileName $output.Xtable \
      -deleteOnClose 1 -width 120 
    #----------------------------------------------------------------------
    # Printing result data (Y)
    #
    if [catch {exec sddsprintout $output.mpfit $output.Ytable \
                 -column=Index \
                 -column=Rootname,format=%10s \
                 -column=yDispersion1,format=%12.5f \
                 -column=yDispersion2,format=%12.5f \
                 -column=ySlope,format=%12.5e \
                 -column=yCurvature,format=%12.5e \
                 -column=yReducedChiSquared,format=%12.5e \
                 -column=ySignificanceLevel,format=%12.5f} result] {
        cd $oldDir
        SetStatus "Problems for file $output.Ytable due to $result"
        APSAddToTempFileList $output.Ytable    
    }
    SetStatus "File $output.Ytable is written" 
    APSAddToTempFileList $output.Ytable    
    
    APSFileDisplayWindow [APSUniqueName .] -fileName $output.Ytable \
      -deleteOnClose 1 -width 120 
    #menuPlotting  
    global widgetPlottingButton 
    APSEnableButton $widgetPlottingButton.plotDispersion.button 
    cd $oldDir
}

#-----------------------------------------------------------------------------
#
#   Plotting of all results
#
proc doPlotting {} {

    global output outputDir
    global columnList rfFrequency0
    global dx0r dy0r dx0s dy0s dx1r dy1r dx1s dy1s xfit yfit

    #----------------------------------------------------------------------
    # Plotting result data for first order dispersions
    #
    #----------------------------------------------------------------------
    #  X over total ring:
    #
    set oldDir [pwd]
    cd $outputDir
    if {$dx0r == 1} {
       exec sddsplot $output.mpfit -col=Index,xDispersion1 \
                                   -graph=line,vary -uns=y -axes=x &
    }  
    
    #----------------------------------------------------------------------
    #  X over ring by separate pieces:
    #
    if {$dx0s == 1} {
       exec sddsplot $output.mpfit -col=Rootname,xDispersion1 \
                                   -graph=sym,conn=sub,vary=sub \
                                   -uns=y -axes=x \
                                   -split=column=Index,width=18 \
                                   -sep=subpage \
                                   -group=subpage -same=y &
    }

    #----------------------------------------------------------------------
    #  Y over total ring:
    #
    if {$dy0r == 1} {
       exec sddsplot $output.mpfit -col=Index,yDispersion1 \
                                   -graph=line,vary -uns=y -axes=x &
    }
    
    #----------------------------------------------------------------------
    #  Y over ring by separate pieces:
    #
    if {$dy0s == 1} {
       exec sddsplot $output.mpfit -col=Rootname,yDispersion1 \
                                   -graph=sym,conn=sub,vary=sub \
                                   -uns=y -axes=x \
                                   -split=column=Index,width=18 \
                                   -sep=subpage \
                                   -group=subpage -same=y &
    }
    
    #----------------------------------------------------------------------
    # Plotting result data for second order dispersions
    #
    #----------------------------------------------------------------------
    #  X over total ring:
    #
    if {$dx1r == 1} {
       exec sddsplot $output.mpfit -col=Index,xDispersion2 \
                                   -graph=line,vary \
                                   -uns=y -axes=x &
    }
    
    #----------------------------------------------------------------------
    #  X over ring by separate pieces:
    #
    if {$dx1s == 1} {
       exec sddsplot $output.mpfit -col=Rootname,xDispersion2 \
                                   -graph=sym,conn=sub,vary=sub \
                                   -uns=y -axes=x \
                                   -split=column=Index,width=18 \
                                   -sep=subpage \
                                   -group=subpage -same=y &
    }
    
    #----------------------------------------------------------------------
    #  Y over total ring:
    #
    if {$dy1r == 1} {
       exec sddsplot $output.mpfit -col=Index,yDispersion2 \
                                   -graph=line,vary \
                                   -uns=y -axes=x &
    }
    
    #----------------------------------------------------------------------
    #  Y over ring by separate pieces:
    #
    if {$dy1s == 1} {
       exec sddsplot $output.mpfit -col=Rootname,yDispersion2 \
                                   -graph=sym,conn=sub,vary=sub \
                                   -uns=y -axes=x \
                                   -split=column=Index,width=18 \
                                   -sep=subpage \
                                   -group=subpage -same=y &
    }
    
    #----------------------------------------------------------------------
    # Plotting result data for X-fitting
    #
    if {$xfit == 1} {
       set xoffset [expr -1*$rfFrequency0]
       set columnsPlotted "-layout=3,3 -group=nameindex -sep=nameindex \
                           -offset=xChange=$xoffset"
       set plotList1 ""
       set plotList2 "" 
       foreach columnName $columnList {
           if {[string match *:msAve:x $columnName]} { 
               lappend plotList1 $columnName
               lappend plotList2 ${columnName}Fit 
           }
       }
        
        eval exec sddsplot -ylabel=edit=%/:msAve:x//%/:msAve:x// \"-topline=Horizontal bpm vs. f\" $columnsPlotted \
                 -column=rfFrequency,([join $plotList1 ,]) -graph=symbol,scale=3,subtype=1 $output.frame \
                 -column=rfFrequency,([join $plotList2 ,]) -graph=line $output.frame &
    }
    
    #----------------------------------------------------------------------
    # Plotting result data for Y-fitting
    #
    if {$yfit == 1} {
       set xoffset [expr -1*$rfFrequency0]
       set columnsPlotted "-layout=3,3 -group=nameindex -sep=nameindex \
                           -offset=xChange=$xoffset"
       set plotList1 ""
       set plotList2 ""

       foreach columnName $columnList {
          if {[string match *:msAve:y $columnName]} {
             lappend plotList1 $columnName
             lappend plotList2 ${columnName}Fit
          }
       }

       eval exec sddsplot -ylabel=edit=%/:msAve:y//%/:msAve:y// \"-topline=Vertical bpm vs. f\" $columnsPlotted \
                 -column=rfFrequency,([join $plotList1 ,]) -graph=symbol,scale=3,subtype=1 $output.frame \
                 -column=rfFrequency,([join $plotList2 ,]) -graph=line $output.frame &
    }
    cd $oldDir
    SetStatus Done.

}
#-----------------------------------------------------------------------------

proc checkIfFilesExist {} {
    global output outputDir review cancel
    if ![file exists $outputDir] {
        return -code error "not found: $outputDir"
    }
    if ![file isdir $outputDir] {
        return -code error "not a directory: $outputDir"
    }
    cd $outputDir
    if {[file exists $output]} {
        toplevel .existsBox
        wm title .existsBox "Experiment Exists"
        message .existsBox.message -text "Experiment [file tail $output] exists:\nPress \"Overwrite\" to overwrite existing files\
		\nor \"Cancel\" to cancel experiment and change name." -width 14c
        pack .existsBox.message -in .existsBox
        APSFrame .buttonRow -relief flat -parent .existsBox
        set w .existsBox.buttonRow.frame
        APSButton .overwrite -parent $w -text "Overwrite" -command {destroy .existsBox; removeOldFiles; set review 0; set done 1} \
          -packOption "-side left -padx 5"
        APSButton .cancel -parent $w -text "Cancel" -command {destroy .existsBox; set cancel 1; set done 1} -packOption "-side left"
        tkwait variable done
    } else {
        set review 0
    }
}

proc removeOldFiles {} {
    global output outputDir
    cd $outputDir
    SetStatus "Removing old experiment files..."
    eval file delete [glob -nocomplain $output*]
    SetStatus "Done."
}

proc SetupHPVSAAndDrvStriplines {args} {
    set hpvsaSelection SR

    set plane x
    set statusCallback ""
    APSParseArguments {plane statusCallback}
    if {$statusCallback!=""} {
        $statusCallback "Setting up Driver striplines and $plane plane measurement..."
    }
    global  xFreq yFreq HPVSATracesToAve range
    switch $plane {
        x {
            set sourceLevel 9
        }
        y {
            set sourceLevel 6
        }
    }
    set output /tmp/[APSTmpString]
    set freq [set ${plane}Freq]
   # if [catch {exec hpVecRestore -unit sr -filename /home/helios/oagData/sr/hp89441A/states/MXA-TUNE.sta } result] {
   #     return -code error "Error in setup VSA for tune measurement: $result"
   # }
    if [catch {APSSetupSRVSAScope  -sourceLevel $sourceLevel -plane $plane -root $output \
                 -average $HPVSATracesToAve -freq $freq -range $range } streamID] {
        return -code error "APSGetSRTunesVSA1: $streamID"
    }
    #APSCloseTelnetStream -streamID $streamID
    if [catch {exec hpSocketSend hpvecsr "OUTP OFF"} result] {
	return -code error "Error in turning off VSA source: $result"
    }
    if {$statusCallback!=""} {
        $statusCallback "done."
    }
    return 1
}

if [catch {exec cavget -list=SR:bunchPatternSO -pend=30} bunchPattern] {
    return -code error "Error in reading SR:bunchPatternSO : $bunchPattern"
}
set range 10
set xrange 6
set yrange 10
set hpvsaSelection hpvecsr
set reverseWaveform 1
# Value for default User lattice.
set latticeDir $OAGGlobal(SRLatticesDirectory)/default
set latticeName [file link $latticeDir]
set momentumCompactionFactor [format %.3e [exec sdds2stream -para=alphac $latticeDir/aps.twi]]
set momentumCompactionFactor2 [format %.3e [exec sdds2stream -para=alphac2 $latticeDir/aps.twi]]

set latticeFile /home/helios/oagData/sr/calibratedModels/lattices/default/aps.twi
if ![file exist $latticeFile] {
    set latticeFile  $OAGGlobal(SRLatticesDirectory)/default/aps.twi
}
# tunes from calibrated file
set nux [exec sdds2stream -par=nux $latticeFile]
set nuy [exec sdds2stream -par=nuy $latticeFile]
set xTune [format %.2f [expr $nux - floor($nux)]]
set yTune [format %.2f [expr $nuy - floor($nuy)]]

makeLabeledEntriesAndRbFrame .entries -parent .userFrame
makeButtonRow .buttonRow -parent .userFrame
