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

set usage "usage: APSMeasureTunes -ring {SR | PAR}"
set args $argv
set ring SR
if [APSStrictParseArguments {ring}] {
    puts stderr $usage
    exit 1
}
switch $ring {
    SR {
        set divisor 1296.0
        set archiveDir /home/helios/oagData/sr/tuneArchive/data
        set prefix SR
        set lowerTune x
        set upperTune y
        set dividingLine 0.21
        set freqPV A014-IETS:BTC:SRSetFreqM
    }
    PAR {
        set divisor [expr 1296.0*36]
        set archiveDir /home/helios/oagData/par/tuneArchive/data
        set prefix P
        set lowerTune x
        set upperTune y
        set dividingLine 0.20
        set freqPV A014-IETS:BTC:BInjSetFreqM
    }
    default {
        puts stderr $usage
        exit 1
    }
}
if [catch {exec cavget -list=$freqPV -printErrors  -floatFormat=%21.15e} refFreq] {
    puts stderr $refFreq
    exit 1
}
set revFrequency [expr $refFreq/$divisor]

APSApplication . -name $ring:MeasureTunes -version $CVSRevisionAuthor \
  -overview {Helps with tune measurement setup and data collection.}

set status Working...
APSScrolledStatus .status -parent .userFrame -textVariable status \
        -width 60 -height 6
update

proc MakeDriveWidget {widget args} {
    set parent ""
    APSStrictParseArguments {parent}

    APSFrame ${widget} -parent $parent \
      -label "Drive control" -contextHelp \
      "Controls over the drive configuration."
    APSButton .x -parent $parent${widget}.frame \
      -text "X only" \
      -command "ConfigureDrive -mode x"
    APSButton .y -parent $parent${widget}.frame \
      -text "Y only" \
      -command "ConfigureDrive -mode y"
    APSButton .xy -parent $parent${widget}.frame \
      -text "X/Y" \
      -command "ConfigureDrive -mode xy"
}

proc ConfigureDrive {args} {
    global ring revFrequency prefix
    set mode ""
    APSStrictParseArguments {mode}
    switch $mode {
        x {
            lappend phaseList -list=$prefix:TUNE:sig -list=1=0,3=0,2=180,4=180 -list=bo
            lappend sinkList  -list=$prefix:TUNE:sig -range=beg=5,end=8 -list=bo=SL
            set turnCommand -list=SR:TUNE:stripSELmbbo=0
        }
        y {
            lappend phaseList -list=$prefix:TUNE:sig -list=1=0,3=180,2=0,4=180 -list=bo
            lappend sinkList  -list=$prefix:TUNE:sig -range=beg=5,end=8 -list=bo=SL
            set turnCommand -list=SR:TUNE:stripSELmbbo=1
        }
        xy {
            lappend phaseList -list=$prefix:TUNE:sig -list=1=0,3=0,2=180,4=180 -list=bo
            lappend sinkList  -list=$prefix:TUNE:sig -list=5=SL,6=Gnd,7=Gnd,8=SL -list=bo
            set turnCommand -list=SR:TUNE:stripSELmbbo=2
        }
    }
    if {[catch {eval exec cavput $phaseList} result] || \
          [catch {eval exec cavput $sinkList} result] || \
          [catch {eval exec cavput $turnCommand -pend=15} result] } {
        APSSetVarAndUpdate status $result
    }
}
proc EnableDisableP0Widget {args} {
    set enable 0
    APSParseArguments {enable}
    global p0GainWidget
   
    if $enable {
        APSEnableWidget $p0GainWidget
    } else {
        APSDisableWidget $p0GainWidget
    }
}
proc MakeHarmonicWidget {widget args} {
    set parent ""
    APSStrictParseArguments {parent}
    global  measHarmonic
    APSFrame $widget -parent $parent \
      -label "Harmonic Control" -contextHelp \
      "Provides for shifting the harmonic around which the tune is viewed."
    APSLabeledEntry .harm -parent $parent$widget.frame  -width 20 -label "Harmonic number:" -textVariable measHarmonic
    bind $parent$widget.frame.harm.entry <Return> "GetFreqFromTune"
    set number 0
    foreach increment {-10 -5 -2 -1 +1 +2 +5 +10} {
        APSButton .b$number -parent $parent$widget.frame \
          -text $increment -command "IncrementHarmonic $increment" -fastClick 1
        incr number
    }
}

set measHarmonic 1390
proc GetFreqFromTune {args} {
    global xTune yTune xFreq yFreq measHarmonic dividingLine
    set rfFrequency [exec cavget -list=A014-IETS:BTC:SRSetFreqM -floatFormat=%.1f -pendIoTime=5]
    set revFrequency [expr $rfFrequency / 1296]
    set xFreq [format %.1f [expr $revFrequency * ($measHarmonic - $xTune)]]
    set yFreq [format %.1f [expr $revFrequency * ($measHarmonic - $yTune)]]
    set dividingLine [format %0.2f [expr ($xTune + $yTune)/2.0]]
    
}

proc MeasureInitialTune {args} {
    global xTune yTune xFreq yFreq xPower yPower  dividingLine
    
    set output /tmp/[APSTmpString]
    
    if [catch {APSMpMeasureTunes -ring SR -outputFile $output \
		   -xPower $xPower -yPower $yPower \
		   -xFreq $xFreq -yFreq $yFreq \
		   -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 dividingLine [expr ($xTune + $yTune)/2.0]
   # puts $xTune
    GetFreqFromTune
}
#obtain default parameter values
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]
}
if {$ring=="SR"} {
    set latticeFile /home/helios/oagData/sr/calibratedModels/lattices/default/aps.twi
    if ![file exist $latticeFile] {
        set latticeFile  $OAGGlobal(SRLatticesDirectory)/default/aps.twi
    }
    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)]]
}

#set xSourceLevel 3
#set ySourceLevel -27
proc GetFillPattern {args} {
    global fillPattern
    if [catch {exec cavget -list=SR:bunchPatternSO -pend=10 -printErrors} bunchPattern] {
        return -code error $bunchPattern
    }
    if [regexp {8x7} $bunchPattern] {
        set fillPattern hybrid
    } elseif [regexp {324} $bunchPattern] {
        set fillPattern 324singlets
    } elseif [regexp {24} $bunchPattern] {
        set fillPattern 24singlets
    } else {
        return -code error "invalid bunchpattern -- $bunchPattern"
    }
}
proc UpdateNASAParametersByFillPattern {args} {
    global fillPattern xPower yPower xDelay yDelay xRange yRange NASApar xSourceLevel ySourceLevel xDimtelReducedGain yDimtelReducedGain xDelay yDelay
    set refFile /home/helios/oagData/SCR/snapshots/SRNASA/SRNASA-${fillPattern}.gz
    foreach type {xPower yPower xRange yRange xSourceLevel ySourceLevel} {
        set $type $NASApar($fillPattern.$type)
    }
    set xDimtelReducedGain $NASApar($fillPattern.xDimtelGain)
    set yDimtelReducedGain $NASApar($fillPattern.yDimtelGain)
    if [catch {exec sddsprocess $refFile -match=col,ControlName=SR:tune:hpdl:x:SetDelay -pipe=out \
                 | sdds2stream -pipe -col=ValueString } xDelay] {
        return -code error "Error getting xDelay from $refFile: $xDelay"
    }
    set xDelay [format %.2f $xDelay]
    if [catch {exec sddsprocess $refFile -match=col,ControlName=SR:tune:hpdl:y:SetDelay -pipe=out \
                 | sdds2stream -pipe -col=ValueString } yDelay] {
        return -code error "Error getting yDelay from $refFile: $yDelay"
    }
    set yDelay [format %.2f $yDelay]
}

proc MakeTuneWidget {widget args} {
    set parent ""
    APSParseArguments {parent}
    global xFreq yFreq xTune yTune xPower yPower  measHarmonic xDelay yDelay ring fillPattern xRange yRange xSourceLevel ySourceLevel
    
    APSFrame $widget -parent $parent -label "NASA parameters"
    set w1 $parent$widget.frame
    
   # APSButton .measureTunes -parent $w1 -text "FIND CENTER FREQUENCIES" \
   #   -command MeasureInitialTune \
    #  -packOption "-side top " \
     # -contextHelp "Finds the center frequencies for x and y tune measurement."
    APSFrameGrid .grid -parent $w1 -xList {x1 x2}
    set width 15
    MakeSlideWidget .slide -parent $w1.grid.x1 -plane x
    MakeSlideWidget .slide -parent $w1.grid.x2 -plane y
    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."
    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 .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 <Return> "GetFreqFromTune"
    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 <Return> "GetFreqFromTune"
    
    APSLabeledEntry .xpower -parent $w1.grid.x1 -width $width\
        -label "NASA rf power (for x tune):" \
        -textVariable xPower \
        -contextHelp "this sets the value of rf power for taking x plane tune."
    APSLabeledEntry .ypower -parent $w1.grid.x2 -width $width \
        -label "NASA rf power (for y tune):" \
        -textVariable yPower \
        -contextHelp "this sets the value of rf power for taking y plane tune."

    APSLabeledEntry .xpower1 -parent $w1.grid.x1 -width $width\
        -label "VSA source level (for x tune):" \
        -textVariable xSourceLevel \
        -contextHelp "this sets the value of rf power for taking x plane tune."
    
    APSLabeledEntry .ypower1 -parent $w1.grid.x2 -width $width \
        -label "VSA source level (for y tune):" \
        -textVariable ySourceLevel \
        -contextHelp "this sets the value of rf power for taking y plane tune."
    APSLabeledEntry .xrange -parent $w1.grid.x1 -width $width\
        -label "MXA range (dBm) for x tune:" \
        -textVariable xRange \
        -contextHelp "this sets the value of MXA range for taking x plane tune."
    APSLabeledEntry .yrange -parent $w1.grid.x2 -width $width \
        -label "MXA range for y tune:" \
        -textVariable yRange \
        -contextHelp "this sets the value of MXA range for taking y plane tune."
    APSLabeledEntryFrame .p0 -parent $w1.grid.x1 -width 7 -variableList {xP0ReducedGain yP0ReducedGain} \
      -orientation horizontal -label "P0 Reduced gain x/y:" 
    APSLabeledEntryFrame .dim -parent $w1.grid.x2 -width 7 -variableList {xDimtelReducedGain yDimtelReducedGain} \
      -orientation horizontal -label "Dimtel Reduced gain x/y:" 
    if {$ring=="SR"} {
        APSLabeledEntry .xdelay -parent $w1.grid.x1 -width $width \
          -label "SR x colby delay:" -textVariable xDelay \
          -contextHelp "this sets the value of SR tune x colby delay."
        APSLabeledEntry .ydelay -parent $w1.grid.x2 -width $width \
          -label "SR y colby delay:" -textVariable yDelay \
          -contextHelp "this sets the value of SR tune y colby delay."
        APSRadioButtonFrame .pattern -parent $w1 -label "Select Fill Pattern:       " \
          -buttonList {24singlets 324singlets hybrid} -orientation horizontal \
          -valueList {24singlets 324singlets hybrid} \
          -variable fillPattern -commandList {UpdateNASAParametersByFillPattern \
                                                UpdateNASAParametersByFillPattern \
                                                UpdateNASAParametersByFillPattern } \
          -contextHelp "this button updates the rf power and colby delay for each selected fill pattern."
    }
}

proc SaveFrequencySettings {} {
    global  ring prefix centerFreq0  freqSpan0
    
    if [catch {exec cavget -list=$prefix:TUNE:NASA:centerFreqAI -printErrors} centerFreq0] {
        APSSetVarAndUpdate status $centerFreq0
    }
    if [catch {exec cavget -list=$prefix:TUNE:NASA:freqSpanAI -printErrors} freqSpan0] {
        APSSetVarAndUpdate status $freqSpan0
    }
    
}
proc RestoreFrequency {} {
    global ring revFrequency prefix
    global centerFreq0 freqSpan0
    if [catch {APSSetTuneMultiplexer -mode NASA} result] {
        APSSetVarAndUpdate status $result
    }
    if [catch {exec cavput -list=$prefix:TUNE:NASA:centerFreqAO=$centerFreq0,$prefix:TUNE:NASA:freqSpanAO=$freqSpan0} result] {
        APSSetVarAndUpdate status $result
        return
    }
    APSSetVarAndUpdate status "Frequency and Span restored"
}

proc RestoreReferenceFile {} {
    global ring revFrequency prefix
    global centerFreq0 freqSpan0
    set refFile /home/helios/oagData/SCR/snapshots/${ring}NASA/${ring}NASA-Reference.gz
    if ![file exists $refFile] {
        APSSetVarAndUpdate status "Reference file ($refFile) not found--can't restore."
        return
    }
    set tmpFile /tmp/[APSTmpString]
    if [catch {exec sddsprocess $refFile $tmpFile "-match=col,ControlName=*center*FreqAO,ControlName=*SpanAO,|" } result] {
        APSSetVarAndUpdate status "$result"
        return
    }
    
    if [catch {exec sddscasr -restore $tmpFile
        exec rm $tmpFile
        APSSCRLogAction -file $refFile -action restore} result] {
        APSSetVarAndUpdate status "$result"
        return
    }
    
    APSSetVarAndUpdate status "Configuration restored."
}

proc IncrementTune {increment args} {
    set plane ""
    APSParseArguments {plane}

    global xFreq yFreq xTune yTune
    set ${plane}Tune [format %.2f [expr [set ${plane}Tune] + $increment]]
    GetFreqFromTune
}

proc IncrementHarmonic {increment} {
    global prefix revFrequency xFreq yFreq xTune yTune measHarmonic

    set measHarmonic [expr $measHarmonic + $increment]
    GetFreqFromTune
    return
    if [catch {APSSetTuneMultiplexer -mode NASA} result] {
        APSSetVarAndUpdate status $result
    }
    if [catch {exec cavget -list=$prefix:TUNE:NASA:centerFreqAI} freq] {
        APSSetVarAndUpdate status $freq
        return
    }
    set freq [expr $freq+$revFrequency*($increment)]
    if [catch {exec cavput -list=$prefix:TUNE:NASA:centerFreqAO=$freq} result] {
        APSSetVarAndUpdate status $freq
        return
    }
    APSSetVarAndUpdate status "Incremented harmonic by $increment to [expr $freq/$revFrequency]"
}

proc MakeSlideWidget {widget args} {
    set parent ""
    set plane ""
    APSStrictParseArguments {parent plane}
 
    APSFrame $widget -parent $parent \
      -label "Slide $plane Center Tune" -contextHelp \
      "Provides for shifting the center tune on the trace." 
    
    set number 0
    foreach increment {-0.01 +0.01} {
        APSButton .b$number -parent $parent$widget.frame\
          -text $increment -command "IncrementTune $increment -plane $plane" -fastClick 1
        incr number
    }
    
}

proc MakeWidthWidget {widget args} {
    set parent ""
    APSStrictParseArguments {parent}
 
    APSFrame $widget -parent $parent \
      -label "Change Tune Span" -contextHelp \
      "Provides for changing the tune span of the spectrum."
      set number 0
    foreach increment {-0.1 -0.05 -0.02 -0.01 +0.01 +0.02 +0.05 +0.10} {
        APSButton .b$number -parent $parent$widget.frame \
          -text $increment -command "IncrementSpan $increment" -fastClick 1
        incr number
    }
}

proc IncrementSpan {increment} {
    global prefix revFrequency
    if [catch {APSSetTuneMultiplexer -mode NASA} result] {
        APSSetVarAndUpdate status $result
    }
    if [catch {exec cavget -list=$prefix:TUNE:NASA:freqSpanAI} freqSpan] {
        APSSetVarAndUpdate status $freqSpan
    }
    set freqSpan [expr $freqSpan+$revFrequency*($increment)]
    if [catch {exec cavput -list=$prefix:TUNE:NASA:freqSpanAO=$freqSpan} result] {
        APSSetVarAndUpdate status $freq
        return
    }
    APSSetVarAndUpdate status "Incremented span by $increment"
}

set dataDirectory "."
set dataRootname tunes
set dataIndex 0
set measureXYtuneTogether 0
set recenterRange 0
set archiveMXATune 1
set xDimtelReducedGain 2
set yDimtelReducedGain 2
proc MakeSaveWidget {widget args} {
    set parent ""
    APSStrictParseArguments {parent}
    global dataDirectory dataRootname measureXYtuneTogether ring recenterRange xP0ReducedGain yP0ReducedGain
    global archiveFeedbackTune archiveMXATune xDimtelReducedGain yDimtelReducedGain
    
    APSFrame $widget -parent $parent \
      -label "Save Data" -contextHelp \
      "Provides for saving the tune spectrum to a file."
    set parent $parent$widget.frame
    APSLabeledEntry .directory -parent $parent -label "Directory: " \
      -textVariable dataDirectory -width 70
    APSButton .daily -parent $parent.directory -packOption "-anchor e" \
      -text "daily" -size small \
	-command {set dataDirectory [APSGoToDailyDirectory -subdirectory ${ring}Tune-NASA]}
    APSLabeledEntry .comment -parent $parent -label "Comment: " \
      -textVariable dataComment -width 70
    APSFrameGrid .grid -parent $parent -xList {x1 x2}
    set w1 $parent.grid.x1
    set w2 $parent.grid.x2
    set width 30
    APSLabeledEntry .rootname -parent $w1 -label "Rootname:" \
      -textVariable dataRootname -width $width
    APSLabeledEntry .index -parent $w2 -label "Index: " \
      -textVariable dataIndex -width $width
    
    APSLabeledEntry .dividingLine -parent $w1 -label "x/y boundary:" \
      -textVariable dividingLine -width $width -contextHelp \
      "Enter the tune value to divide x from y peaks."
   
   
    APSRadioButtonFrame .rec -parent $parent.grid.x1 -label "Re-center frequency range automatically?" \
        -buttonList {Yes No} -valueList {1 0} -variable recenterRange -orientation horizontal \
        -contextHelp "If Yes, after one measurement and processing, the \
        next measurement is prepared by using as center frequecny the previous \
        processed results."
    APSRadioButtonFrame .p0tune -parent $parent.grid.x2 -label "Archive Feedback Tune?"  \
      -buttonList {Yes No} -valueList {1 0} -variable archiveFeedbackTune -orientation horizontal
    APSRadioButtonFrame .mxatune -parent $parent.grid.x2 -label "Archive MXA/VSA Tune?   "  \
      -buttonList {Yes No} -valueList {1 0} -variable archiveMXATune -orientation horizontal
    if {0} {
    APSRadioButtonFrame .sep -parent $parent -label "Measure x/y tune separately?" \
        -variable measureXYtuneTogether -valueList {0 1} -buttonList {Yes No} \
        -orientation horizontal -contextHelp "If selected yes, x and y tune will be measured separated through switing stripline to X or Y plane; otherwise, they are measured together with stripline set to X/Y."
    }
   # APSLabeledEntryFrame .p0gain -parent $parent -label "Reduced P0 feedback gain:" \
   #   -variableList {xP0ReducedGain yP0ReducedGain} -width 20 -orientation horizontal \
   #   -contextHelp "enter the value of P0 feedback gain for reducing P0 feedback to obtain good data."
    
   # global p0GainWidget
  #  set p0GainWidget  $parent.p0gain.frame
   # APSButton .enable -parent $parent.p0gain -text "enable" -size small -command "EnableDisableP0Widget -enable 1"
   # APSButton .disable -parent $parent.p0gain -text "disable" -size small -command "EnableDisableP0Widget -enable 0"
   # APSDisableWidget $parent.p0gain.frame
    APSFrame .f1 -parent $parent
    APSFrame .f2 -parent $parent
    $parent.f1.frame configure -bd 0
    $parent.f2.frame configure -bd 0
    APSButton .save -parent $parent.f1.frame -text "Acquire, View, and Save" -command \
      saveData -contextHelp \
      "Saves tune data to the directory and file you've chosen."
    APSButton .view -parent $parent.f1.frame -text "Acquire and View Only" -command \
      "saveData -viewOnly 1" -contextHelp \
      "Acquires tune data and displays it."
   APSButton .proc -parent $parent.f1.frame -text "Reprocess" -command \
	ReprocessTuneData
    APSButton .scan -parent $parent.f2.frame -text "Scan Delay" -command ScanTuneDelay
    APSButton .p0 -parent $parent.f2.frame -text "Measure Tune with Feedback" -command MeasureTuneWithFeedback
    APSButton .p1 -parent $parent.f2.frame -text "Measure Tune with MXA/VSA" -command MeasureTuneWithMXA
}

set archiveFeedbackTune 1
proc MeasureTuneWithFeedback {args} {
    global archiveFeedbackTune 
    APSExecLog .p0tune -width 70 -unixCommand "getP0FBTune -system TFB -statusCallback \"puts\" -plot 1 -archive $archiveFeedbackTune"

}

proc ScanTuneDelay {args} {
    global status
    set files ""
    if [catch {exec cavput -list=SR:tune:hpdl: -list=x,y -list=:SetDelay=3 -pend=20} delays] {
        return -code error "Error in reading current tune delays: $delays"
    }
    set xdelay0 3
    set ydelay0 3
    
    foreach degree {-90 90 0 180} {
        set deltaDelay [expr $degree * 2.6/360]
        set xdelay [format %.2f [expr $xdelay0 + $deltaDelay]]
        set ydelay [format %.2f [expr $ydelay0 + $deltaDelay]]
        set status "setting xdelay to $xdelay, ydelay to $ydelay"
        if [catch {exec cavput -list=SR:tune:hpdl:x:SetDelay=$xdelay,SR:tune:hpdl:y:SetDelay=$ydelay -pend=30} result] {
            return -code error "Error in changing x/y tune delays: $result"
        }
        #measure tune
        if [catch {saveData -archive 0 -popup 0} file] {
            return -code error "Error in measuring tune: $file"
        }
        if [catch {exec sddsprocess $file $file.tune \
                     "-print=par,xdelayLabel,xdelay=$xdelay ns" \
                     "-print=par,ydelayLabel,ydelay=$ydelay ns" \
                     -redefine=par,PageNumber,i_page \
                 } result] {
            return -code error "error in process $file: $result"
        }
        exec rm $file
        lappend files $file.tune
    }
    global setxdelay setydelay diagResp

    puts $files
    
    set setxdelay ""
    set setydelay ""
    set diagResp 0
    foreach plane {x y} page {1 2} {
        eval exec sddsplot  $files -split=page -sep=pageindex   -grap=line,vary -legend=par=${plane}delayLabel -col=Tune,*TUNE1 -groupby=pageindex \
          "-title=${plane}tune" -filter=par,PageNumber,$page,$page  &
        after 2000
        global setXdelay setYdelay diagResp
        set diagResp 0
        APSDialogBox .delay -name "set $plane delay to best value scanned" -width 30 \
          -cancelCommand {set diagResp cancel} -okCommand {set diagResp ok}
        APSLabeledEntry .$plane -parent .delay.userFrame -width 15 -textVariable set${plane}delay -label "$plane delay:" 
        tkwait window .delay
        
        if {$diagResp=="cancel"} {
            set status "changing delays was cancelled."
            return
        }
        set status "Changing $plane delay to [set set${plane}delay]"
        if [catch {exec cavput -list=SR:tune:hpdl:${plane}:SetDelay=[set set${plane}delay] -pend=10} result] {
            return -code error "Error in change $plane delay: $result"
        }
    }
    
}

proc ReprocessTuneData {args} {
    global dataDirectory selectFile ring dataRootname
    set oldDir [pwd]
    cd $dataDirectory
    set fileList [lsort -decreasing [glob -nocomplain ${dataRootname}*.sdds]]
    if ![llength $fileList] {
	APSSetVarAndUpdate status "No files found."
	cd $oldDir
        return
    }
    set selectFile ""
    APSScrolledListWindow .sel -name "Select a file" \
	-label "Select a file" -itemList $fileList -selectionVar selectFile
    tkwait variable selectFile
    if ![string length $selectFile] {
	APSSetVarAndUpdate status "No file selected."
	cd $oldDir
        return
    }
    global dividingLine
    if [catch {ReprocessTune -filename $selectFile -prefix $ring -dividingLine $dividingLine} result] {
	APSSetVarAndUpdate status "Error in reprocessing tune data for $selectFile: $result."
	cd $oldDir
        return
    }
    exec sddsplot -column=Tune,${ring}:TUNE1  $selectFile -split=page  \
	-graph=line,vary -topline=@TuneLabel -title=@BeamParamLabel &
    
    cd $oldDir
}

set first 1
proc saveData {args} {
    set archive 0
    set viewOnly 0
    set popup 1
    APSStrictParseArguments {archive viewOnly popup}

    global ring dataRootname dataDirectory dataIndex status dataComment xRange yRange
    global lowerTune upperTune dividingLine env measureXYtuneTogether centerFreqA0 xDelay yDelay
    global xFreq yFreq xPower yPower xTune yTune first recenterRange xP0ReducedGain yP0ReducedGain
    global xDimtelReducedGain yDimtelReducedGain

    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"} {
        APSSetVarAndUpdate status "The NASA analyzer mode is not on Network, you have to switch it to Network for tune measurement."
        return
    }
    GetFreqFromTune
    if [catch {APSSetTuneMultiplexer -mode NASA} result] {
        APSSetVarAndUpdate status $result
    }
    if [catch {exec cavget -list=SR:TUNE:stripSELmbbo -pend=30} turnArchive] {
        APSAlertBox [APSUniqueName .] -errorMessage $turnArchive
        return
    }
    if {$ring!="SR" || $measureXYtuneTogether} {
        if {[string compare $turnArchive "X/Y"]!=0 } {
            if [catch {exec cavput -list=SR:TUNE:stripSELmbbo=2 -pend=30} result] {
                return -code error $result
            }
            after 8000
        }
    }
    if {$archive} {
        if {[string compare $env(USER) asdops]!=0 && [string compare $env(USER) sr]!=0} {
            set message "Archiving of tune data may only be done by ASDOPS or SR account.\n\Please put your studies data in a private directory."
            APSAlertBox [APSUniqueName .] -errorMessage $message 
            return
        }
        if {[string compare $ring SR]==0} {
            if [catch {exec  cavget -list=S:DesiredMode -noquote} srMode] {
                APSAlertBox [APSUniqueName .] -errorMessage "Can not read S:DesiredMode: $srMode"
                return
            }
            if {$srMode!="SUPLEMENTAL TIME" && $srMode!="USER OPERATIONS"} {
                set message "Archiving of SR tune data may only be done when in user operations mode.\nPlease put your studies data in a private directory."
                APSAlertBox [APSUniqueName .] -errorMessage $message 
                return
            }
        }
    }
    if $viewOnly {
        set file /tmp/[APSTmpString]
    } else {
        if !$archive {
	    if $first {
		set files [lsort -decreasing [glob -nocomplain $dataDirectory/${dataRootname}*.sdds]]
		if ![llength $files] {
		    set dataIndex 0
		} else {
		    set lastFile [file tail [lindex $files 0]]
		    set dataIndex [scan $lastFile ${dataRootname}-%ld]
		    incr dataIndex
		}
		set first 0
	    }
            set file [format $dataDirectory/$dataRootname-%03ld.sdds $dataIndex]
            incr dataIndex
            APSSetVarAndUpdate status "Putting tune data in file $file"
        } else {
            set tag [APSOffsetDateInfo -today 1 -offset 0 -dateFormat Y-J-MD]
            set timeStamp [exec date +%H%M%S]
            global archiveDir
            set file $archiveDir/$tag.$timeStamp
            APSSetVarAndUpdate status "Putting tune data into archive area."
        }
    }
    switch $ring {
        PAR {
            if [catch {APSMpPARMeasureTunes -outputFile $file -measureXYtuneTogether $measureXYtuneTogether \
                         -lowerTune $lowerTune -upperTune $upperTune -dividingLine $dividingLine \
                         -useExistingData 1 -comment "$dataComment" \
                         -xDimtelReducedGain $xDimtelReducedGain -yDimtelReducedGain $yDimtelReducedGain \
                         -xP0ReducedGain $xP0ReducedGain -yP0ReducedGain $yP0ReducedGain} result] {
                APSSetVarAndUpdate status "PAR Tune: $result"
            }
            set prefix P
        }
        SR {
            if [catch {APSMpSRMeasureTunes -outputFile $file -xFreq $xFreq -yFreq $yFreq -xPower $xPower -yPower $yPower \
                         -xDelay $xDelay -yDelay $yDelay \
                         -measureXYtuneTogether $measureXYtuneTogether \
                         -lowerTune $lowerTune -upperTune $upperTune \
                         -dividingLine $dividingLine -useDividingLine 1 \
                         -useExistingData 1 -comment "$dataComment" \
                         -xDimtelReducedGain $xDimtelReducedGain -yDimtelReducedGain $yDimtelReducedGain \
                         -xP0ReducedGain $xP0ReducedGain -yP0ReducedGain $yP0ReducedGain } result] {
                APSSetVarAndUpdate status "SR tune: $result"
            }
            set prefix SR
        }
        default {
            APSSetVarAndUpdate status "Invalid ring: $ring"
        }
    }
    
    APSSetVarAndUpdate status "Checking data."
    if [catch {exec sddsprocess $file -pipe=out \
		   -process=$prefix:TUNE1,rms,%sRMS -process=$prefix:TUNE1,stand,%sStDev \
		   -process=$prefix:TUNE1,mad,%sMAD \
		   "-define=parameter,$prefix:TUNE1Ratio,$prefix:TUNE1StDev $prefix:TUNE1MAD /" \
		   | sdds2stream -pipe -parameter=$prefix:TUNE1Ratio,$prefix:TUNE1RMS,xTune,yTune} data] {
	APSSetVarAndUpdate status "$data"
	APSSetVarAndUpdate status "Data removed."
	catch {exec rm $file}
	return
    }
    if {[expr [lindex $data 0]<1.7] || [expr [lindex $data 1]<1.8e-6] || \
	    [expr [lindex $data 2]==0] || [expr [lindex $data 3]==0]} {
	#Automatic analysis indicates this data may be invalid. 
	# sleep a little while to make sure the plot has come up
	if !$viewOnly {
	    after 2000
            if $popup {
                if [APSMultipleChoice [APSUniqueName .] -labelList {Remove Keep} \
                      -returnList {1 0} -question \
                      "Automatic analysis indicates this data may be invalid.  If you don't see a clean spectrum on the plot, please remove the data by pressing Remove."] {
                    APSSetVarAndUpdate status "Data looks invalid---removed."
                    catch {exec rm $file}
                    return
                }
            }
	    if $recenterRange {
		set xTune [format %.2f [lindex [exec sdds2stream -par=xTune $file] 0]]
		set yTune [format %.2f [lindex [exec sdds2stream -par=yTune $file] 0]]
		GetFreqFromTune
	    }
	    # catch {APSSendEMail -address borland@aps.anl.gov  -message "Tune problem with $file\nStDev/MAD=[format %g [lindex $data 0]]  RMS=[format %g [lindex $data 1]]  xTune=[format %g [lindex $data 2]]  yTune=[format %g [lindex $data 3]]"}
	}
    } else {
	if $recenterRange {
	    set xTune [format %.2f [lindex [exec sdds2stream -par=xTune $file] 0]]
	    set yTune [format %.2f [lindex [exec sdds2stream -par=yTune $file] 0]]
	    GetFreqFromTune
	}
    }
    if !$viewOnly {
	APSSetVarAndUpdate status "Data looks valid---saved."	
    }
    return $file
}

proc MeasureTuneWithMXA {args} {
    global archiveMXATune env xPower yPower xRange yRange prefix
    global ring dataRootname dataDirectory dataIndex status dataComment
    global lowerTune upperTune dividingLine env measureXYtuneTogether centerFreqA0 xDelay yDelay
    global xFreq yFreq xPower yPower xTune yTune first recenterRange xP0ReducedGain yP0ReducedGain xSourceLevel ySourceLevel
    global xDimtelReducedGain yDimtelReducedGain
    
    if {$ring!="SR"} {
        return -code error "MXA tune measurent is only available for SR tune."
    }
    if {$archiveMXATune} {
        if {[string compare $env(USER) asdops]!=0 && [string compare $env(USER) sr]!=0} {
            set message "Archiving of tune data may only be done by ASDOPS or SR account.\n\Please put your studies data in a private directory."
            APSAlertBox [APSUniqueName .] -errorMessage $message 
            return
        }
        if [catch {exec  cavget -list=S:DesiredMode -noquote} srMode] {
            APSAlertBox [APSUniqueName .] -errorMessage "Can not read S:DesiredMode: $srMode"
            return
        }
        if {$srMode!="SUPLEMENTAL TIME" && $srMode!="USER OPERATIONS"} {
            set message "Archiving of SR tune data may only be done when in user operations mode.\nPlease put your studies data in a private directory."
            APSAlertBox [APSUniqueName .] -errorMessage $message 
            return
        }
    }
    if !$archiveMXATune {
        set file /tmp/[APSTmpString]
        set viewOnly 1
    } else {
        set viewOnly 0
        set tag [APSOffsetDateInfo -today 1 -offset 0 -dateFormat Y-J-MD]
        set timeStamp [exec date +%H%M%S]
        global archiveDir
        set file /home/helios/oagData/sr/tuneArchive/MXAdata/$tag.$timeStamp
        APSSetVarAndUpdate status "Putting tune data into archive area."
    }
    if [catch {APSGetSRTunesVSA -output $file -description "$dataComment" \
                 -xFrequency $xFreq -yFrequency $yFreq -MXA 1 \
                 -xSourceLevel $xSourceLevel -ySourceLevel $ySourceLevel \
                 -xrange $xRange -yrange $yRange \
                 -dividingLine $dividingLine -average 20 \
                 -xDimtelReducedGain $xDimtelReducedGain -yDimtelReducedGain $yDimtelReducedGain \
                 -xP0ReducedGain $xP0ReducedGain -yP0ReducedGain $yP0ReducedGain} result] {
        APSSetVarAndUpdate status $result
        return
    }
    exec hpSocketSend hpvecsr "OUTP OFF"
    if [catch {exec sddsprocess $file -nowarnings \
                 "-print=par,filename,[file tail $file]" \
                 "-print=par,TuneLabel,\\\$gn\\\$r\\\$bx\\\$n = %.4f  \\\$gn\\\$r\\\$by\\\$n = %.4f,xTune,yTune" } result] {
        APSSetVarAndUpdate status $result
        catch {exec rm ${file}* }
        return
    }
    APSSetVarAndUpdate status "Checking data."
    
    if [catch {exec  sddsprocess $file -pipe=out  \
                 -process=xWaveform,rms,xTuneRMS -process=xWaveform,stand,xTuneStDev \
                 -process=xWaveform,mad,xTuneMAD \
                 -process=yWaveform,rms,yTuneRMS -process=yWaveform,stand,yTuneStDev \
                 -process=yWaveform,mad,yTuneMAD \
                 "-define=par,xTuneRatio,xTuneStDev xTuneMAD /" \
                 "-define=par,yTuneRatio,yTuneStDev yTuneMAD /"  \
                 | sdds2stream -pipe -parameter=xTuneRatio,xTuneRMS,xTune,yTuneRatio,yTuneRMS,yTune} data] {
	APSSetVarAndUpdate status "$data"
	APSSetVarAndUpdate status "Data removed."
	#catch {exec rm $file}
	return
    }
    catch {exec rm ${file}.x~ ${file}.y~ }
    catch {exec rm ${file}~ }
    set xTuneRatio [lindex $data 0]
    set xTuneRMS [lindex $data 1]
    set xTune [format %.4f [lindex $data 2]]
    set yTuneRatio [lindex $data 3]
    set yTuneRMS [lindex $data 4]
    set yTune [format %.4f [lindex $data 5]]
    exec sddsplot -grap=line,vary  "-topline=@TuneLabel" -samescale=x -mode=y=normalize  \
      -col=xTune,xWaveform -leg=spec=xTune $file -col=yTune,yWaveform -leg=spec=yTune  $file &
   
    if {$xTuneRatio<1.7 || $xTuneRMS<1.8e-6 || $yTuneRatio<1.7 || $yTuneRMS<1.8e-6 || \
          $xTune==0 || $yTune==0} {
	#Automatic analysis indicates this data may be invalid. 
	# sleep a little while to make sure the plot has come up
	if !$viewOnly {
	    after 2000
            if [APSMultipleChoice [APSUniqueName .] -labelList {Remove Keep} \
                  -returnList {1 0} -question \
                  "Automatic analysis indicates this data may be invalid.  If you don't see a clean spectrum on the plot, please remove the data by pressing Remove."] {
                APSSetVarAndUpdate status "Data looks invalid---removed."
                catch {exec rm $file}
                return
            }
            
	    if $recenterRange {
		#set xTune [format %.2f [lindex [exec sdds2stream -par=xTune $file] 0]]
		#set yTune [format %.2f [lindex [exec sdds2stream -par=yTune $file] 0]]
		GetFreqFromTune
	    }
	}
    } else {
	if $recenterRange {
	    #set xTune [format %.2f [lindex [exec sdds2stream -par=xTune $file] 0]]
	    #set yTune [format %.2f [lindex [exec sdds2stream -par=yTune $file] 0]]
	    GetFreqFromTune
	}
    }
    if !$viewOnly {
	APSSetVarAndUpdate status "Data looks valid---saved."	
    }
    APSSetVarAndUpdate status "done."
    return $file
   
}
proc MakeArchiveWidget {widget args} {
    set parent ""
    APSStrictParseArguments {parent}
    APSFrame $widget -parent $parent -label "Archive" \
      -contextHelp "Controls archiving and review of archived tune data."

    set w $parent$widget.frame

    global startDay startMonth startYear
    global endDay endMonth endYear
    APSDateTimeAdjEntry .date0 -parent $w \
      -dayVariable startDay -monthVariable startMonth -yearVariable startYear \
      -label "Start Y/M/D: "
    APSDateTimeAdjEntry .date1 -parent $w \
      -dayVariable endDay -monthVariable endMonth -yearVariable endYear \
      -label "End   Y/M/D: "
    
    APSButton .archive -parent $w -text Archive -command \
      "saveData -archive 1" -contextHelp \
      "Saves tune data to the archive area."
    APSButton .review -parent $w -text "Review spectra" -command \
      "reviewArchivedData -mode spectra" -contextHelp \
      "Reviews archived tune data between the dates given above."
    APSButton .reprocess -parent $w -text "Reprocess Tune" -command \
        "reviewArchivedData -mode spectra -reprocess 1" -contextHelp \
      "Reprocess archived tune data between the dates given above."
    APSButton .history -parent $w -text "Show tune history" -command \
      "reviewArchivedData -mode history" -contextHelp \
      "Displays history of tune values between the dates given above."
    APSButton .ampHistory -parent $w -text "Show amplitude history" -command \
      "reviewArchivedData -mode ampHistory" -contextHelp \
      "Displays history of tune peak amplitude values between the dates given above."
    APSButton .p0history -parent $w -text "Review P0tune spectra" -command \
      "reviewP0TuneArchivedData -mode spectra" \
      -contextHelp  "Reviews archived P0 feedback tune data between the dates given above."
    APSButton .mxahistory -parent $w -text "Review MXA spectra" -command \
      "reviewP0TuneArchivedData -mode spectra -MXA 1" \
      -contextHelp  "Reviews archived MXA/VSA tune data between the dates given above."
}

proc reviewP0TuneArchivedData {args} {
    set mode spectra
    set MXA 0
    APSStrictParseArguments {mode MXA}

    global startDay startMonth startYear dividingLine
    global endDay endMonth endYear
    if $MXA {
        set archiveDir /home/helios/oagData/sr/tuneArchive/MXAdata
    } else {
        set archiveDir /home/helios/oagData/sr/TFB/tuneArchive/data
    }
    set fileList \
      [APSFindFilesBetweenDates -tailsOnly 1 \
         -rootname "" -directory $archiveDir \
         -extensionList {.?????? .gz} \
         -startDateList [APSFormatDate -year $startYear \
                           -month $startMonth -day $startDay -dateFormat list] \
         -endDateList [APSFormatDate -year $endYear \
                           -month $endMonth -day $endDay -dateFormat list] \
        ]
    if [llength $fileList]==0 {
        APSSetVarAndUpdate status "No files found."
        return
    } else {
        APSSetVarAndUpdate status "[llength $fileList] files found."
    }
    set oldDir [pwd]
    cd $archiveDir
    
    switch $mode {
        spectra {
            if $MXA {
                eval exec sddsplot -grap=line,vary -samescale=x -mode=y=normalize -split=page  -title=@filename -topline=@TuneLabel \
                  -column=xTune,xWaveform -col=yTune,yWaveform -groupby=filestring \
                  -separate=filestring $fileList    &
            } else {
                eval exec sddsplot -samescale=x -mode=y=normalize -split=page  -title=@TuneLabel \
                  -column=Tune,SR:TUNE1 -graph=line,vary -groupby=filestring,namestring \
                  -separate=filestring $fileList \
                  {"-topline=@BeamParamLabel,edit=i/Archived tune data:  /"}   &
            }
        }
        history {
            eval exec sddsplot -ticks=xtime -graph=symbol -labelsize=0.024 -frompage=1 -topage=1 \
              -groupby=nameindex -separate=nameindex \
              -parameter=Time,(xTune,yTune) \
              $fileList {"-topline=Tune history for $ring"} -title= &
        }
        ampHistory {
            eval exec sddsplot -ticks=xtime -graph=symbol -labelsize=0.024 -frompage=1 -topage=1 \
              -mode=y=log,y=special -limit=ymax=1e300,ymin=0 \
              -groupby=nameindex -separate=nameindex \
              -parameter=Time,(xNormAmplitude,yNormAmplitude) \
              $fileList {"-topline=Tune peak amplitude history for $ring"} -title= &
        }
    }
    
    cd $oldDir
    APSSetVarAndUpdate status "Plot launched"
}

proc reviewArchivedData {args} {
    set mode spectra
    set reprocess 0
    APSStrictParseArguments {mode reprocess}

    global startDay startMonth startYear dividingLine
    global endDay endMonth endYear
    global archiveDir ring

    set fileList \
      [APSFindFilesBetweenDates -tailsOnly 1 \
         -rootname "" -directory $archiveDir \
         -extensionList {.?????? .gz} \
         -startDateList [APSFormatDate -year $startYear \
                           -month $startMonth -day $startDay -dateFormat list] \
         -endDateList [APSFormatDate -year $endYear \
                           -month $endMonth -day $endDay -dateFormat list] \
        ]
    if [llength $fileList]==0 {
        APSSetVarAndUpdate status "No files found."
        return
    } else {
        APSSetVarAndUpdate status "[llength $fileList] files found."
    }
    set oldDir [pwd]
    cd $archiveDir
    if $reprocess {
        foreach file $fileList {
            if [catch {ReprocessTune -filename $file -dividingLine $dividingLine -prefix $ring} result] {
                return -code error "Error in reprocessing tune: $result"
            }
        }
        eval exec sddsplot -samescale=x -mode=y=normalize -split=page  -title=@TuneLabel \
            -column=Tune,*TUNE1 -graph=line,vary -groupby=filestring,namestring \
            -separate=filestring $fileList \
            {"-topline=@BeamParamLabel,edit=i/Archived tune data:  /"}   &
        return
    }
    switch $mode {
        spectra {
            eval exec sddsplot -samescale=x -mode=y=normalize -split=page  -title=@TuneLabel \
              -column=Tune,*TUNE1 -graph=line,vary -groupby=filestring,namestring \
              -separate=filestring $fileList \
              {"-topline=@BeamParamLabel,edit=i/Archived tune data:  /"}   &
        }
        history {
            eval exec sddsplot -ticks=xtime -graph=symbol -labelsize=0.024 -frompage=1 -topage=1 \
              -groupby=nameindex -separate=nameindex \
              -parameter=Time,(xTune,yTune) \
              $fileList {"-topline=Tune history for $ring"} -title= &
        }
        ampHistory {
            eval exec sddsplot -ticks=xtime -graph=symbol -labelsize=0.024 -frompage=1 -topage=1 \
              -mode=y=log,y=special -limit=ymax=1e300,ymin=0 \
              -groupby=nameindex -separate=nameindex \
              -parameter=Time,(xNormAmplitude,yNormAmplitude) \
              $fileList {"-topline=Tune peak amplitude history for $ring"} -title= &
        }
    }
    
    cd $oldDir
    APSSetVarAndUpdate status "Plot launched"
}

proc ReprocessTune {args} {
    set filename ""
    set dividingLine ""
    set prefix ""
    APSParseArguments {filename dividingLine prefix}

   
    switch $prefix {
        SR { 
            set prefix SR
            set harmonic 1296
            set beamInten S35DCCT
            set beamIntenUnits mA
            set beamParamOpt \
              "-print=parameter,BeamParamLabel,%.2lf mA   %.0lf bunches   %s,S35DCCT,BucketsFilled,TimeStamp"
        }
        PAR {
            set prefix P
            set harmonic 1
            set beamInten P1P1:sum
            set beamIntenUnits V
            set beamParamOpt "-print=parameter,BeamParamLabel,%.2lf V  %s,P1P1:sum,TimeStamp"
        }
    }
    APSSetVarAndUpdate status "Reprocessing $filename ..."
    set tmpRoot /tmp/[APSTmpString]
    set pars [exec sddsquery -par $filename]
    if [lsearch $pars plane]>=0 {
        set planeList [exec sdds2stream -par=plane $filename]
        set page 1
        foreach plane $planeList {
            if [catch {exec sddsprocess $filename -pipe=out -match=par,plane=$plane \
                         | sddsconvert -pipe -del=par,*Tune*,*Amp*,*Label* \
                         | tee $tmpRoot.${plane}.1 \
                         | sddsprocess -pipe -process=${prefix}:TUNE1,max,MaxPeak \
                         | sddsprocess -pipe "-redefine=col,NormalizedTrace,${prefix}:TUNE1 MaxPeak /" \
                         | sddspeakfind -pipe -col=NormalizedTrace -threshold=0.5 -exclusion=0.2 \
                         | sddssort -pipe=in -col=NormalizedTrace,decr $tmpRoot.$plane.tune} result] {
                return -code error $result
            }
            set ${plane}Tune [lindex [exec sdds2stream -col=Tune $tmpRoot.$plane.tune] 0]
            if [catch {eval exec sddsprocess $tmpRoot.${plane}.1 $tmpRoot.$plane.2 -nowarning \
                         -redefine=par,${plane}Tune,\[set ${plane}Tune\]  \
                         -process=${prefix}:TUNE1,max,${plane}Amplitude,func=Tune  \
                         \"-redefine=parameter,${plane}NormAmplitude,${plane}Amplitude $beamInten / 10 rfDrivePower 10 / pow /,units=V/$beamIntenUnits/mW\" \
                         \"-print=parameter,TuneLabel,\\\$gn\\\$r\\\$b${plane}\\\$n = %.4f,${plane}Tune\"
                exec sddsxref $tmpRoot.$plane.1 $tmpRoot.$plane.2 -pipe=out -leave=* \
                         -transfer=parameter,TuneLabel,${plane}Tune,*NormAmplitude \
                         | sddsprocess -pipe=in $tmpRoot.$plane  $beamParamOpt  } result] {
                APSMpReturn error "Error processing tune data (4): $result"
            }
            APSSetVarAndUpdate status "$plane tune is [set ${plane}Tune]."
            incr page
        }
        set xamp [exec sdds2stream -par=xNormAmplitude $tmpRoot.x]
        set yamp [exec sdds2stream -par=yNormAmplitude $tmpRoot.y]
        if [catch {exec sddscombine $tmpRoot.x $tmpRoot.y -pipe=out \
                     | sddsprocess -pipe \
                     -redefine=par,xTune,$xTune \
                     "-redefine=par,yTune,$yTune" \
                     "-redefine=par,xNormAmplitude,$xamp" \
                     "-redefine=par,yNormAmplitude,$yamp" \
                     | sddsprocess -pipe=in $filename.1 \
                     "-reprint=parameter,TuneLabel,\$gn\$r\$bx\$n = %.4f  \$gn\$r\$by\$n = %.4f,xTune,yTune" \
                 } result] {
            APSMpReturn error "Error processing tune data (5): $result"
        }
        exec mv $filename.1 $filename
    } else {
        foreach plane {x y} {
            switch $plane {
                x {
                    set lower 0
                    set upper $dividingLine
                } 
                y {
                    set lower $dividingLine
                    set upper 0.5
                }
            }
            if [catch {exec sddsprocess $filename -pipe=out -filter=col,Tune,$lower,$upper \
                         | sddsprocess -pipe -process=${prefix}:TUNE1,max,MaxPeak \
                         | sddsprocess -pipe "-redefine=col,${prefix}:TUNE1,${prefix}:TUNE1 MaxPeak /" \
                         | sddspeakfind -pipe -col=${prefix}:TUNE1 -threshold=0.5 -exclusion=0.2 \
                         | sddssort -pipe=in $tmpRoot.$plane -col=${prefix}:TUNE1,decr  } result] {
                return -code error $result
            }
            set tunes [lindex [exec sdds2stream -col=Tune $tmpRoot.$plane] 0]
            if [llength $tunes]!=1 {
                APSSetVarAndUpdate status "Invalid tunes found for $plane: [join $tunes]\nYou need change the dividing line to get correct tunes"
                return -code error "Invalid tunes found for $plane: $tunes\nYou need change the dividing line to get correct tunes"
            }
            if {$tunes<$upper && $tunes>$lower} {
                set ${plane}Tune $tunes
                APSSetVarAndUpdate status "$plane tune is $tunes."
            } else {
                APSSetVarAndUpdate status "Invalid tunes found for $plane: $tunes"
                return -code error "Invalid tunes found for $plane: $tunes"
            }
        }
        if [catch {exec sddsprocess $filename -pipe=out \
                       "-redefine=par,xTune,$xTune" "-redefine=par,yTune,$yTune" \
                       | sddsprocess -pipe=in $filename.1 "-reprint=par,TuneLabel,\$gn\$r\$bx\$n = %.4f  \$gn\$r\$by\$n = %.4f,xTune,yTune" } result] {
            return -code error $result
        }
        exec mv $filename.1 $filename
    }
}
APSFrameGrid .grid -parent .userFrame -xList {x1 x2}
MakeDriveWidget .drive -parent .userFrame.grid.x1
MakeHarmonicWidget .harm -parent .userFrame.grid.x2
#MakeSlideWidget .slide -parent .userFrame
MakeWidthWidget .width -parent .userFrame
APSFrame .restore -parent .userFrame
APSButton .save -parent .userFrame.restore.frame \
    -text "Save Frequency Settings" -command SaveFrequencySettings \
    -contextHelp "Save current frequency."
APSButton .restore -parent .userFrame.restore.frame \
  -text "Restore Frequency Settings" -command RestoreFrequency 
APSButton .restorefile -parent .userFrame.restore.frame \
  -text "Restore Freq from Reference File" -command RestoreReferenceFile
MakeTuneWidget .tune -parent .userFrame
MakeSaveWidget .save -parent .userFrame
MakeArchiveWidget .review -parent .userFrame

if [catch {APSSetTuneMultiplexer -mode NASA} result] {
    APSSetVarAndUpdate status $result
}
if [catch {exec cavget -list=$prefix:TUNE:NASA:centerFreqAI -printErrors} centerFreq0] {
    APSSetVarAndUpdate status $centerFreq0
}
if [catch {exec cavget -list=$prefix:TUNE:NASA:freqSpanAI -printErrors} freqSpan0] {
    APSSetVarAndUpdate status $freqSpan0
}

#read NASA parameters
set tuneConfigFile /home/helios/oagData/sr/tuneArchive/inputFiles/NASAtuneconfig.sdds
foreach col {BunchPattern xPower yPower xRange yRange xSourceLevel ySourceLevel xDimtelGain yDimtelGain} {
    set ${col}List [exec sdds2stream -col=$col $tuneConfigFile]
}
set rows [llength $BunchPatternList]
for {set i 0} {$i<$rows} {incr i} {
    set pattern [lindex $BunchPatternList $i]
    foreach type {xPower yPower xRange yRange xSourceLevel ySourceLevel xDimtelGain yDimtelGain} {
        set NASApar($pattern.$type) [format %.1f [lindex [set ${type}List] $i]]
    }
}


APSSetVarAndUpdate status Ready.
catch {GetFreqFromTune}
if [catch {GetFillPattern} result] {
    APSSetVarAndUpdate status "No valid fill pattern detected: $result - Setting to default value (324 singlets)"
    set fillPattern 324singlets
} 
if [catch {UpdateNASAParametersByFillPattern} result] {
    APSSetVarAndUpdate status "error in update NASA parameters by fill pattern: $result"    
}

