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

#
# $Log: not supported by cvs2svn $
# Revision 1.43  2012/02/27 15:26:02  shang
# corrected the SR revolution frequency calculation, and added chaning the center frequency after measurement to avoid NASA signal leak.
#
# Revision 1.42  2012/02/23 21:58:46  shang
# modified to read the SR rf frequency directly from pv instead of from CY's executable command.
#
# Revision 1.41  2012/02/03 19:58:53  shang
# now it turns of RF power when disable drive is selected.
#
# Revision 1.40  2012/01/27 21:08:22  shang
# updated due to pv names change.
#
# Revision 1.39  2011/10/24 19:33:30  shang
# commented out setting soft trigger for collecting turns data because it is not needed.
#
# Revision 1.38  2011/09/29 20:44:37  shang
# updated due to mux pvs name change.
#
# Revision 1.37  2011/09/28 17:49:27  shang
# updated by CY.
#
# Revision 1.36  2011/03/03 17:12:29  shang
# removed setting attenatuator and mixer delay PVs per CY's request, because it would affect P0 feedback.
#
# Revision 1.35  2011/03/03 16:27:35  shang
# created a config file to store the default values of those parameters, they are loaded when the application starts.
# And added feature of automatically updating the low/high limits of tune frequency whent the center frequency is changed.
#
# Revision 1.34  2011/03/01 22:20:31  shang
# committing CY's changes.
#
# Committing Shang's new version.
#
# Revision 1.32  2010/07/01 14:11:27  shang
# changed by CY
#
# Revision 1.31  2009/12/18 15:41:25  shang
# changes are made by CY; 1)Using an external process: /home/helios/PAR/bin/reprocessTune to
# process tune, which only process the tunes around tune sweep line in
# tune-time plane. 2)Center frequency input now reads in tune unit, which is converted
# into real freq when setting up NASA. 3) changed some parameters' default values.
#
# Revision 1.30  2009/07/20 21:13:39  shang
# CY's changes on .tune files
#
# Revision 1.29  2009/06/30 20:43:29  shang
# added collecting and review turns waveform data.
#
# Revision 1.28  2009/06/19 18:24:56  shang
# split the "set chirper buckets" button into two buttons -- "clear and set" and "set only" button; and modified the data taking procedure to not setting the chirper buckets which should be setting up before taking data, and modified to read and recored the used acquisition buckets from current values of chirper bucket PVs.
#
# Revision 1.27  2009/06/18 20:52:09  shang
# fixed a typo where chirpPlotOption should be chirperPlotOption
#
# Revision 1.26  2009/06/18 14:35:49  shang
# added user customer plot option for chirper data and added "review" button for chirper data.
#
# Revision 1.25  2009/06/17 15:37:38  shang
# added recording the bunch current for each bucket to chirper data and displaying the plot after taking data.
#
# Revision 1.24  2009/06/10 14:42:42  shang
# CY's changes on waiting time after arm chirper
#
# Revision 1.23  2009/06/09 23:29:35  shang
# fixed bugs during testings, added chirp buckets setting to the output file parameters, and changed the waiting time after arm depending on the acquistion waveform points.
#
# Revision 1.22  2009/06/09 16:38:57  shang
# added option of enable/disable NASA when using NASA source.
#
# Revision 1.21  2009/06/09 15:41:50  shang
# made extensive changes: 1)now the source is being selected by the tab selection and the output directory is updated automatically.
# 2)added more chirper paramaters setup 3)added set up chirper DAC and acquisition buckets.
#
# Revision 1.20  2009/05/22 14:11:36  shang
# merged CY's changes.
#
# Revision 1.19  2009/04/15 21:45:32  shang
# added ring bucket selection to be able to select the desired bucket for measuring tune.
#
# Revision 1.18  2009/04/13 19:54:01  shang
# merged CY's changes.
#
# Revision 1.17  2009/04/01 16:07:43  shang
# merged CY's changes
#
# Revision 1.16  2009/03/26 22:22:10  shang
# added setting the drive stripline cables to SL for start tune measurement and Gnd (ground) after tune measurement to avoid exciting striplines by mistake.
#
# Revision 1.15  2009/03/11 20:08:23  shang
# added "both" to channel selection so that one can collect both x and y plane data with one button click, and added message displaying for "scan clock phase".
#
# Revision 1.14  2009/03/06 22:35:15  shang
# added restoring NASA frequency span after collecting data
#
# Revision 1.13  2009/03/06 17:50:26  shang
# changed the B P0 phase default to 180
#
# Revision 1.12  2009/03/06 17:11:07  shang
# changed default values for clock phase.
#
# Revision 1.11  2009/03/05 16:03:51  shang
# made more changes:1)update the scalars file 2)modified the file list window to only show the original file 3) modified the review button to also plot the tune archive and save the tune archive file in the same directory as the original data 4)added "reprocess tune" button 5)added "initialize pinger pattern waveform PV" at the application startup 6)added setting span for NASA setup.
#
# Revision 1.10  2009/03/03 15:26:33  shang
# corrected setting NASA points per CY's request
#
# Revision 1.9  2009/03/02 22:59:00  shang
# fixed bugs in "scan clock phase" button, and improved the tune calculation using sddssmooth filter out the spikes and then find the maximum position as tune.
#
# Revision 1.8  2009/03/02 20:19:27  shang
# added entries for input and change NASA powerlevel, set points and center frequencies, and added filter for computing x/y tunes. Modified the "review tune archive" button to be able to reprocess and store the tune to the original file.
#
# Revision 1.7  2009/02/25 15:55:27  shang
# modified the review button to use the sddsplot/sddscontour command directly instead of calling from another script.
#
# Revision 1.6  2009/02/25 03:43:03  shang
# fixed another bug that defines the tune parameter before it is being calculated.
#
# Revision 1.5  2009/02/25 03:20:59  shang
# moved the tune calculation after data-processing and fixed the problem that SrTune column does not exist
#
# Revision 1.4  2009/02/24 18:52:57  shang
# fixed a typo
#
# Revision 1.3  2009/02/24 17:52:25  shang
# removed the radio button for change plane, but added changing plan to x (for channel A) or y (for channel B) inside the measurement, and restore the normal operation after measurement is done.
#
# Revision 1.2  2009/02/24 16:01:30  shang
# added tune computation in processing data and save it as parameter in the measurement file.
#
# Revision 1.1  2009/02/23 19:52:13  shang
# merged CY's scripts and added more buttons
#


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

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

set archiveDir /home/helios/oagData/sr/tuneArchive/FPGAdata

set env(EPICS_CA_MAX_ARRAY_BYTES) "3000000"

proc SetStatus {text} {
    global status fftLength
    set status $text
    update
}

set channel Both
set archive 0
set source NASA
set topIndex -1
set enableNASA 0
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 outputDir rootname fftLength clockShift adcDelay P0Select archiveDir archive
    global endDay endMonth endYear reprocess xySpan defaultSpan source topIndex enableNASA
    set reprocess 0
    # 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: "
    
    APSLabeledEntry .dir -parent $w -label "Output Directory:" -textVariable outputDir \
      -width 70
    APSButton .archive -parent $w.dir -packOption "-side right" -text "archive" -command "SetOutputDir -option archive" -size small
    APSButton .daily -parent $w.dir -packOption "-side right" -text "daily" -size small -command "SetOutputDir -option daily"
    APSLabeledEntry .filename -parent $w -label "Rootname:" -textVariable rootname \
      -width 70
    global comment 
    set comment "no comment"
    
    APSLabeledEntry .comment -parent $w -label "Comment:" -textVariable comment \
      -width 90

#    APSRadioButtonFrame .source -parent $w -label "Enable/Disable NASA:          " -buttonList {Enable Disable} \
#      -valueList {1 0} \
#      -variable enableNASA  -orientation horizontal
    
    APSFrameGrid .grid -parent $w -xList {x1 x2}
    global RingBucket
  #  APSLabeledEntry .bucket -parent $w.grid.x2 -label "    Select ring bucket number:" -textVariable RingBucket -width 20
  #  APSButton .add -parent $w.grid.x2.bucket -packOption "-side right" -text "->" -command "SelectBucket -add 1"
  #  APSButton .reduce -parent $w.grid.x2.bucket -packOption "-side right" -text "<-" -command "SelectBucket -add 0"
  #  bind $w.grid.x2.bucket.entry <Return> "SelectBucket -update 1"
    APSLabeledEntry .clockShiftA -parent $w.grid.x1 -label "clockShiftA:" \
      -textVariable clockShiftA -width 20
    APSLabeledEntry .clockShiftB -parent $w.grid.x2 -label "clockShiftB:" \
      -textVariable clockShiftB -width 20
    APSLabeledEntry .adcDelayA -parent $w.grid.x1 -label "adcDelayA:" \
      -textVariable adcDelayA -width 20
    APSLabeledEntry .adcDelayA -parent $w.grid.x2 -label "adcDelayB:" \
      -textVariable adcDelayB -width 20
    APSLabeledEntry .p0SelectA -parent $w.grid.x1 -label "P0PhaseA(0/180):" \
      -textVariable P0SelectA -width 20
    APSLabeledEntry .p0SelectB -parent $w.grid.x2 -label "P0PhaseB(0/180):" \
      -textVariable P0SelectB -width 20
   
    set w1 $w.grid.x1
    set w2 $w.grid.x2
    
    global scanRangeBuckets adcAcqDelay scanStartBucket xStartA \
      xStopA zRangeA xStartB xStopB zRangeB xPowerLevel xPoints xCenterFreq \
      xTuneLow xTuneHigh yPowerLevel yPoints yCenterFreq yTuneLow yTuneHigh
### use 0/-6 for hybrids mode and -5/-12 for 24 singlets mode
    
    
  
    APSLabeledEntry .xStartA -parent $w1 -label "channel A xStart(0 to 0.1):" \
      -textVariable xStartA -width 20
    APSLabeledEntry .xStopA -parent $w1 -label "channel A xStopA(xStart to 0.5):" \
      -textVariable xStopA -width 20
    APSLabeledEntry .zRangeA -parent $w1 -label "channel A zRange (100 to 20000):" \
      -textVariable zRangeA -width 20
  
    APSLabeledEntry .freq -parent $w1 -label "x tune guess value (0.1-0.4):" -width 20 \
      -textVariable xCenterFreq
    bind $w1.freq.entry <Return> "UpdateXYFreqFilter"
    APSLabeledEntryFrame .range -parent $w1 -label "x tune filter (low/high):   " \
      -width 10 -variableList {xTuneLow xTuneHigh} -orientation horizontal 
    APSLabeledEntry .xStartB -parent $w2 -label "channel B xStart(0 to 0.1):" \
      -textVariable xStartB -width 20
    APSLabeledEntry .xStopB -parent $w2 -label "channel B xStop(xStart to 0.5):" \
      -textVariable xStopB -width 20
    APSLabeledEntry .zRangeB -parent $w2 -label "channel B zRange (100 to 20000):" \
      -textVariable zRangeB -width 20
    
    APSLabeledEntry .freq -parent $w2 -label "y tune guess value (0.1-0.4):" -width 20 \
      -textVariable yCenterFreq
    bind $w2.freq.entry <Return> "UpdateXYFreqFilter"
    APSLabeledEntryFrame .range1 -parent $w2 -label "y tune filter (low/high):    " \
      -width 10 -variableList {yTuneLow yTuneHigh} -orientation horizontal 
   
   
   

    APSFrame .ff2 -parent $w -packOption "-side top"
    $w.ff2.frame configure -bd 0
    set w $w.ff2.frame
    APSButton .scan -parent $w -packOption "-side top" -text "Scan Clock Phase" -command "scanClockPhase" -contextHelp \
      "set sample clock shifts."
    APSButton .view -parent $w -text "Acquire and View Only" -command "saveData -archive 0"
    APSButton .history -parent $w -text "Review Plots" -command \
        "ReviewPlots" -contextHelp \
        "Displays history of tune values between the dates given above."
}

proc DisableDrive {args} {
    global source
    
    if [catch {SetupNASATuneDrive -plane both } result] {
        return -code error "Error in disabling NASA: $result"
    }
    
    if [catch {exec cavput -list=S:tune:chirp:dacGainA=0,S:tune:chirp:dacGainB=0 } result] {
        return -code error "unable to disable chirper: $result"
    }
}
proc ReprocessTuneCurve {args} {
    
    global outputDir archiveDir fftLength xTuneLow xTuneHigh yTuneLow yTuneHigh reprocess fileSelection1
   
    set oldDir [pwd]
    cd $outputDir
    set fileList [lsort -unique -decreas [regsub -all {\.tune} [glob -nocomplain *] ""]]
    if ![llength $fileList] {
        SetStatus "No files found in $outputDir."
        return
    }
    cd $oldDir
    set fileSelection1 ""
    SetStatus "Selecting file..."
    APSScrolledListWindow .process -name "Select a file" \
      -label "Select a file" \
      -itemList $fileList -selectionVar fileSelection1
    tkwait variable fileSelection1
    if ![string length $fileSelection1] {
        SetStatus "No file chosen"
        return
    }
    
    if [catch {CalculateTune -filename $outputDir/$fileSelection1 -plot 1 } tune] {
        return -code error "$tune"
    }
    tkwait variable fileSelection1
    if [catch {CalculateTune -filename $outputDir/$fileSelection1 -plot 1 } tune] {
        return -code error "$tune"
    }
}

proc SelectBucket {args} {
    set add 0
    set update 0
    APSParseArguments {add update}
    global  BucketOffset adcDelayA adcDelayB RingBucket
    if $update {
        set adcDelayA [expr $BucketOffset + $RingBucket]
        set adcDelayB $adcDelayA
    } else {
        if $add {
            set RingBucket [expr $RingBucket+3]
            set adcDelayA [expr $adcDelayA+3]
            set adcDelayB [expr $adcDelayB+3]
        } else {
            set RingBucket [expr $RingBucket - 3]
            set adcDelayA [expr $adcDelayA - 3]
            set adcDelayB [expr $adcDelayB -3]
        }
        if $RingBucket>=0 {
            set RingBucket [expr $RingBucket%1296]
        } else {
            set RingBucket [expr $RingBucket + 1296]
        }
    }
}

proc scanClockPhase {args} {
    global clockShiftA adcDelayA P0SelectA clockShiftB adcDelayB BucketOffset SRBucket
    global P0SelectB diagresponse adcAcqDelay scanStartBucket scanRangeBuckets  
    set att_x [lindex [exec caget C0:P0FB:SumAttSet.A] 1]
    set att_y [lindex [exec caget C1:P0FB:SumAttSet.A] 1]
#### set fixed att value for timing scan
    exec caput C0:P0FB:SumAttSet.A [expr $att_x + 0] 
    exec caput C1:P0FB:SumAttSet.A [expr $att_y + 0] 
    set diagresponse 0
    SetStatus "Scan clock phase, please waiting ..."
    exec caput S:tune:scanPllFirstBucket $scanStartBucket 
    exec caput S:tune:scanPllBucketCount $scanRangeBuckets 
    foreach channel { "A" "B" } index {0 1} {  
        #    puts "$channel $index"
        exec caput S:tune:scanPllAdcSelect $index 
        after 1000
        exec caput S:tune:ClockScanStartBO 1
        after 10000
        set P0Select${channel} [exec caget -t S:tune:pinger:P0select]
        set adcDelay${channel} [exec caget -t S:tune:pinger:acqDelay]
        set clockShift${channel} [exec caget -t S:tune:adcClockShift]
    }
    set BucketOffset adcDelayA
    set SRBucket 0
#### restore attenuator values.
    exec caput C0:P0FB:SumAttSet.A $att_x
    exec caput C1:P0FB:SumAttSet.A $att_y
    SetStatus "done."
    update
}


proc Measure {args} {
#    global adcAcqDelay 
    set outputFile ""
    set commandline 0
    set channel ""
    set source ""
    set maxWaitMs [expr int(1024 * 15.07328) + 3000] 
    APSParseArguments {outputFile commandline channel source}
    
    global clockShiftA adcDelayA P0SelectA clockShiftB adcDelayB P0SelectB 
    
    if !$commandline {
	SetStatus "1. set clockShift (Stune:pinger:clockShift)"
        if {$channel=="A"} {
	    if [catch { exec /home/helios/PAR/bin/setSRClockShift \
			    $clockShiftA $adcDelayA  $P0SelectA } result] {
		return -code error $result
            }
        }
	if {$channel=="B"} {
	    if [catch { exec /home/helios/PAR/bin/setSRClockShift \
			    $clockShiftB $adcDelayB $P0SelectB } result] {
		return -code error $result
	    }
	}
   }
    if !$commandline {
        SetStatus "2. disable both pingers on tuneAcquisition.adl (S:tune:pinger:Yenable)"
    }
    switch $channel {
        A {
            set plane x
            set index 0
            set waveformPV S:tune:fftAvg:gtr:waveform0
        } 
        B {
            set plane y
            set index 1
            set waveformPV S:tune:fftAvg:gtr:waveform1
        }
    }
    #do not enable drive
    DisableDrive 
    if [catch {exec cavput -list=S:tune:fftAvg:gtr:arm=0} result] {
        return -code error $result
    }
    after 500
    if !$commandline {
        SetStatus "4. set auto restart to no on tunePlots.adl (S:tune:fftAvg:gtr:autoRestart) "
        if [catch {exec cavput -list=S:tune:fftAvg:gtr:autoRestart=0} result] {
            return -code error $result
        }
    }
    after 500
    if !$commandline {
        SetStatus "5. disarm and arm the acquisition the FftWaterfallPlots.adl (S:tune:fftAvg:gtr:arm)"
        
        if [catch {exec cavput -list=S:tune:fftAvg:gtr:arm=1} result] {
            return -code error $result
        }
        after 3000
    }
    if !$commandline {
        SetStatus "7. take data..."
    }
    global env xDim yDim fftLength 
    set env(EPICS_CA_MAX_ARRAY_BYTES) 3000000
    set tuneInterval [expr 1.0 / 2048.0]
    set scalars /home/helios/oagData/sr/tuneArchive/inputFiles/tuneScalars.mon 
    set timeStr [clock format [clock seconds] -format %Y-%j-%m%d:%H%M%S].$plane
   
    if [catch {exec sddswmonitor -erase -pvnames=$waveformPV  \
                 -xparameter=name=x,dimension=$xDim,interval=1,minimum=0 \
                 -yparameter=name=y,dimension=$yDim,interval=$tuneInterval,minimum=0 \
                 -scalars=$scalars \
                 $outputFile } result] {
        return -code error $result
    }
    
    if [catch {SetupNASATuneDrive -plane x/y } result] {
        return -code error $result
    }
    if !$commandline {
        set plot 1
    } else {
        set plot 0
    }
    if [catch {ProcessData -filename $outputFile -plot $plot -channel $channel -source $source} result] {
        return -code error $result
    }
    if !$commandline {
        SetStatus "done."
    }
    return $timeStr
}

proc CalculateTune {args} {
    set filename ""
    set plot 0
    APSParseArguments {filename plot}
    
    global xTuneLow xTuneHigh yTuneLow yTuneHigh xCenterFreq yCenterFreq 
    global xStartA xStartB xStopA xStopB 
    global srRevFreq
    SetStatus "Calculating tune..."

    if [catch {exec sdds2stream -par=channel $filename} channel] {
        set channel A
    } 
    if [catch {exec sdds2stream -par=SR:TUNE:NASA:centerFreqAI $filename} centerFreqHz] {
    return -code error "centerFreqHz parameter not found"
    } 
    switch $channel {
        A {
            set low $xTuneLow
            set high $xTuneHigh
            set plane x
	    set xStart $xStartA
	    set xStop $xStopA
        }
        B {
            set low $yTuneLow
            set high $yTuneHigh
            set plane y
	    set xStart $xStartB
	    set xStop $xStopB
        }
    }
    if [catch { set centerFreqTune [expr fmod ($centerFreqHz / $srRevFreq, 1)]} result ] {
    return -code error "$result centerFreqTune: $centerFreqTune"
    }
    if { $centerFreqTune > 0.5 } {
	set centerFreqTune [expr 1.0 - $centerFreqTune]
    }
    if [catch {exec sddsprocess $filename \
		   "-redefine=col,tune,Index 1024 mod 2048 /" -pipe=out \
		   | sddssort -col=tune -pipe \
		   | sddsbreak -change=tune -pipe \
		   | sddsprocess -process=SrTune,max,SrTune \
		   -process=tune,first,tune -pipe \
		   | sddscollapse  -pipe \
		   | sddsprocess -filter=col,SrTune,100,1e9 -pipe \
		   | sddssmooth -col=SrTune -pipe \
		   | sddsxref -pipe=in $filename -leave=* -transfer=par,* $filename.tune } result] {
	return -code error "Error in processing tune: $result"
    }
    if [catch {exec sddsprocess $filename.tune -pipe=out \
                 -process=SrTune,max,tune,functionOf=tune,position,lowerLimit=$low,upperLimit=$high \
                 | sdds2stream -pipe -par=tune} tune] {
        return -code error $tune
    }
    if [catch {exec sddsprocess $filename $filename.1 -redefine=par,nu,$tune} result] {
        return -code error $result
    }
    if [catch {exec sddsprocess $filename.tune $filename.tune.1 -redefine=par,nu,$tune} result] {
        return -code error $result
    }
    exec mv $filename.1 $filename
    exec mv $filename.tune.1 $filename.tune
    if $plot {
        exec sddsplot -col=tune,SrTune -graph=line $filename.tune \
	"-title=$filename" "-topline=$plane tune\\=[format %.4f $tune]" \
	-filter=col,tune,$low,$high &
    }
    SetStatus "calculating tune done."
    return $tune
}

proc saveData {args} {
    set archive 0
    APSParseArguments {archive}
    
    global archiveDir outputDir rootname fftLength channel source
    
    switch $channel {
        A {
            set planeList x
            set channelList A
        }
        B {
            set planeList y
            set channelList B
        }
        Both {
            set planeList {x y}
            set channelList {A B}
        }
    }
    foreach chan $channelList plane $planeList {
        set filename ${rootname}.${plane}-0000
        set newfilename [APSNextGenerationedName -name $filename -separator "-" -directory $outputDir -newFile 1] 
        
        if [catch {Measure -outputFile $outputDir/$newfilename -channel $chan -source $source} timeStr] {
            return -code error $timeStr
        }
        if $archive {
            if [APSYesNoPopUp "Would you like to archive this data?"] {
                exec cp $outputDir/$filename $archiveDir/$timeStr
                exec cp $outputDir/$filename.tune $archiveDir/$timeStr.tune
            }
        }
    }
}

proc PlotFile {args} {
    set filename ""
    APSParseArguments {filename}
    global xTuneLow xTuneHigh yTuneLow yTuneHigh xCenterFreq yCenterFreq 
    global adcAcqDelay xStartA xStopA zRangeA xStartB xStopB zRangeB
    SetStatus "plotting..."
    if [catch {exec sdds2stream -par=channel $filename} channel] {
        set channel A
    }
    if [catch {exec sdds2stream -par=nu $filename} tune] {
        set description [exec sdds2stream -par=Description $filename]
    } else {
        set description "tune = [format %.4f $tune]"
    }
    
    switch $channel {
        A {
            set plane x
	    set low $xTuneLow
	    set high $xTuneHigh
            if {$zRangeA==0} {
                exec sddscontour $filename  -quantity=SrTune -swapxy \
                  -shade=100\
                  -topline=file -date \
                  "-title=$description" \
                  "-yLabel=${plane} tune" -xLabel=Traces \
                  -scales=$xStartA,$xStopA,0,0  &
            } else {
                exec sddscontour $filename  -quantity=SrTune -swapxy \
                  -shade=100,0,$zRangeA \
                  -topline=file -date \
                  "-title=$description" \
                  "-yLabel=${plane} tune" -xLabel=Traces \
                  -scales=$xStartA,$xStopA,0,0 &
            }
        }
        B {
            set plane y
	    set low $yTuneLow
	    set high $yTuneHigh
            if {$zRangeB==0} {
                exec sddscontour $filename  -quantity=SrTune -swapxy \
                  -shade=100\
                  -topline=file -date \
                  "-title=$description" \
                  -yLabel=${plane}\ tune -xLabel=Traces  \
                  -scales=$xStartB,$xStopB,0,0  &
            } else {
                exec sddscontour $filename  -quantity=SrTune -swapxy \
                  -shade=100,0,$zRangeB \
                  -topline=file -date \
                  "-title=$description" \
                  -yLabel=${plane}\ tune -xLabel=Traces \
                  -scales=$xStartB,$xStopB,0,0 &
            }
        }
    }
    if [file exist $filename.tune] {
        set tune [exec sdds2stream -par=nu $filename.tune]
        exec sddsplot -col=tune,SrTune -graph=line $filename.tune \
	"-title=$filename" "-topline=$plane tune\\=[format %.4f $tune]" \
	-scales=$low,$high,0,0 &
    }
}

proc UpdateXYFreqFilter {args} {
    global xCenterFreq yCenterFreq xTuneLow xTuneHigh yTuneLow yTuneHigh
    set xTuneLow [format %.2f [expr $xCenterFreq - 0.05]]
    set xTuneHigh [format %.2f [expr $xCenterFreq + 0.05]]
    set yTuneLow [format %.2f [expr $yCenterFreq - 0.05]]
    set yTuneHigh [format %.2f [expr $yCenterFreq + 0.05]]
}

proc ReviewPlots {args} {
    set archive 0
    APSParseArguments {archive}
    
    
    global outputDir archiveDir fftLength channel fileSelection
    set oldDir [pwd]
    
    if $archive {
        set dir $archiveDir
    } else {
        set dir $outputDir
    }
    cd $dir
    set fileList [lsort -unique -decreas [regsub -all {\.tune} [glob -nocomplain *] ""]]
    if ![llength $fileList] {
        SetStatus "No files found in $dir."
        return
    }
    SetStatus "listing files..."
    set fileSelection ""
    APSScrolledListWindow .process1 -name "Select a file" \
      -label "Select a file" \
      -itemList $fileList -selectionVar fileSelection
    tkwait variable fileSelection
    if ![string length $fileSelection] {
        SetStatus "No file chosen"
        return
    }
    PlotFile -filename $dir/$fileSelection
    tkwait variable fileSelection
    PlotFile -filename $dir/$fileSelection
}

proc ProcessData {args} {
    global xDim xDimMax yDim totalTimeMs fftLength comment
    global adcAcqDelay xStartA xStopA zRangeA  xStartB xStopB zRangeB
    ### added to check and apply the acquisition length PV
    set fftLength [exec caget S:tune:pinger:FFTsampleCount -t]
   
    set filename ""
    set plot 1
    set channel ""
    set source ""
    APSParseArguments {filename plot channel source}
    #### limit to 113 traces. 
  
    set cutoff [expr $xDim * $yDim - 1]
    set option ""
    set fftFormatLog [exec sdds2stream -para=S:tune:crosspointControl.B3 $filename] 
    global xTuneLow xTuneHigh yTuneLow yTuneHigh
    
    switch $channel {
        A {
            set index 0
            set low $xTuneLow
            set high $xTuneHigh
            set plane x
        }
        B {
            set index 1
            set low $yTuneLow
            set high $yTuneHigh
            set plane y
        }
    }
    
    if {$fftFormatLog == 0 } { 
        if [catch {eval exec sddsprocess $filename -pipe=out -filter=col,Index,0,$cutoff \
                     | sddsprocess -pipe=in $filename.1 -nowarnings \
                     \"-redefine=col,SrTune,S:tune:fftAvg:gtr:waveform$index \" \
                     \"-reprint=par,Description,[APSMakeSafeQualifierString $comment]\" \
                     "-reprint=par,channel,$channel" \
                     "-reprint=par,source,$source" \
                     -redefine=para,xDimension,$xDim,type=long \
                     -redefine=para,yDimension,$yDim,type=long } result] {
            return -code error $result
        }
    } else {
        if [catch {eval exec sddsprocess $filename -pipe=out -filter=col,Index,0,$cutoff \
                     | sddsprocess -pipe=in $filename.1 -nowarnings \
                     \"-redefine=col,SrTune,2 S:tune:fftAvg:gtr:waveform$index 1024.0 / pow \" \
                     \"-reprint=par,Description,[APSMakeSafeQualifierString $comment]\" \
                     "-reprint=par,channel,$channel" \
                     "-reprint=par,source,$source" \
                     -redefine=para,xDimension,$xDim,type=long \
                     -redefine=para,yDimension,$yDim,type=long } result] {
            return -code error $result
        }   
    }
    exec mv $filename.1 $filename
    if [catch {CalculateTune -filename $filename } tune] {
        return -code error "Error in computing tune: $tune"
    }
    
    if $plot {
        PlotFile  -filename $filename
    }
}

set centerFreq 357317200
if [catch {exec cavget -list=SR:TUNE:NASA:freqSpanAO -printErrors} origSpan] {
    return -code error $origSpan
}

proc SetupNASATuneDrive {args} {
    set plane x
    APSParseArguments {plane}
    global centerFreq  xPowerLevel xPoints xCenterFreq  yPowerLevel yPoints yCenterFreq \
    defaultSpan xySpan origSpan srRevFreq centerFreqA0
   
    if {$plane=="x" || $plane=="y"} {
        #disable the chirper
        if [catch {exec cavput -list=S:tune:chirp:dacGainA=0,S:tune:chirp:dacGainB=0 -pend=30} result] {
            return -code error "SetupNASATuneDrive: unable to disable chirper."
        }
    }
    
    switch $plane {
        x {
            set pointsVal [expr int ( log (($xPoints  )/50)/ log (2.0)) ]
            if [catch {exec caput SR:TUNE:HP_1366A_C0P1_MBBO  1
		exec caput SR:TUNE:Mux4Sw0BO 0
		exec caput SR:TUNE:HP_1366A_C0P0_MBBO 1
		exec caput SR:TUNE:HP_1366A_C0P1_MBBO 1
		exec caput SR:TUNE:HP_1366A_C2P0_MBBO 1
		exec caput SR:TUNE:NASA:centerFreqAO [expr (1390 - $xCenterFreq) * $srRevFreq] 
		exec caput SR:TUNE:NASA:freqSpanAO $xySpan
                exec caput SR:TUNE:NASA:sweepSelectMBBO  1
                exec caput SR:TUNE:NASA:ifBwMO 2 
                exec caput SR:TUNE:NA:setNumPointsMO $pointsVal
		### setting sweep time zero forces updating of sweep time from points and ifBW
                exec caput SR:TUNE:NASA:sweepTimeAO 0
                exec caput SR:TUNE:NASA:rfPowerAO $xPowerLevel
		after 2000
                exec caput SR:TUNE:NASA:trigModeBO 1
                exec caput SR:TUNE:NASA:rfPowerBO 1  # turn on power
		exec caput SR:TUNE:Mux4Sw2BO 1 #turn on nasa drive
	    } result] {
                return -code error "unable to setup NASA for x plane: $result"
            }
        }
        y {
            set pointsVal [expr int ( log (($yPoints  )/50)/ log (2.0)) ]
            if [catch {exec caput SR:TUNE:HP_1366A_C0P1_MBBO 2
	    	exec caput SR:TUNE:Mux4Sw2BO 1
		exec caput SR:TUNE:HP_1366A_C0P0_MBBO 1
		exec caput SR:TUNE:HP_1366A_C0P1_MBBO 2
		exec caput SR:TUNE:HP_1366A_C2P0_MBBO 4
                exec caput SR:TUNE:NASA:centerFreqAO [expr (1390 - $yCenterFreq) * $srRevFreq] 
                exec caput SR:TUNE:NASA:freqSpanAO $xySpan
                exec caput SR:TUNE:NASA:sweepSelectMBBO  1
                exec caput SR:TUNE:NASA:ifBwMO 2 
                exec caput SR:TUNE:NA:setNumPointsMO $pointsVal
                exec caput SR:TUNE:NASA:sweepTimeAO 0 
                exec caput SR:TUNE:NASA:rfPowerAO $yPowerLevel
		after 2000
                exec caput SR:TUNE:NASA:trigModeBO 1
                exec caput SR:TUNE:NASA:rfPowerBO 1  # turn on power
		exec caput SR:TUNE:Mux4Sw2BO 1 #turn on nasa drive
		} result] {
                return -code error "unable to setup NASA for y plane: $result"
            }
        }
        default {
	    if [catch {exec cavput -list=SR:TUNE:HP_1366A_C0P1_MBBO=0,SR:TUNE:NASA:freqSpanAO=$origSpan,SR:TUNE:NASA:trigModeBO=0,SR:TUNE:NASA:rfPowerAO=13,SR:TUNE:NA:setNumPointsMO=3,SR:TUNE:NASA:ifBwMO=2,SR:TUNE:NASA:sweepTimeAO=0,SR:TUNE:Mux4Sw2BO=0 -pend=30 
	    } result] {
                return -code error "unable to setup NASA for x/y plane: $result"
            }
	    after 1000
	    if [catch {exec cavput -list=SR:TUNE:NASA:sweepSelectMBBO=0,SR:TUNE:NASA:rfPowerBO=0 -pend=30} result] {
		return -code error "unable to setup NASA for x/y plane2: $result"
	    }
        }
    }
}


proc SetOutputDir {args} {
    set option ""
    APSParseArguments {option}
    global source outputDir archive 
    
    if {$source=="Disable"} {
        return
    }
    switch $option {
        daily {
            set archive 0
            set outputDir [APSGoToDailyDirectory -subdirectory SRTuneFPGA-$source]
        }
        archive {
            set archive 1
            set outputDir /home/helios/oagData/sr/tuneArchive/FPGAdata/$source
        }
    }
}
set outputDir [APSGoToDailyDirectory -subdirectory SRTuneFPGA-NASA]

set rootname SrTune
set outputFile ""
set args $argv 
APSParseArguments {outputFile channel}

set xDim 128 
set yDim 1024 
set xDimMax 128
set comment "no comment"
### revolution period
if [catch {exec cavget -list=A014-IETS:BTC:SRSetFreqM -pend=30 -printErrors} rfFreq] {
    puts stderr "Error in reading SR rf frequency (A014-IETS:BTC:SRSetFreqM): $rfFreq"
    exit 1
}
set P0Period [expr 1.0e3 / $rfFreq * 1296.0 ]
set srRevFreq [expr $rfFreq / 1296.0 ]
###  set up pinger pattern
exec /home/helios/PAR/SRTune/setPingerPattern 9.5 1075 SR

#[expr 1.0e3 / 351.95e6 * 1296.0]
### total valid data time in ms for the booster
set fftLength [exec caget S:tune:pinger:FFTsampleCount -t]
set configFile /home/helios/oagData/sr/tuneArchive/inputFiles/tuneconfig.sdds

set varList [exec sdds2stream -col=VariableName $configFile]
set valList [exec sdds2stream -col=DefaultValue $configFile]
foreach var $varList val $valList {
    set $var $val
}

UpdateXYFreqFilter
set SRBucket 0
set RingBucket 0
set BucketOffset $adcDelayA

if ![string length $outputFile] {
    APSApplication . -name SR-Tunes-FPGA -version $CVSRevisionAuthor \
        -overview {Helps with booster tune measurement setup and data collection.}
    
    set status Working...
    APSScrolledStatus .status -parent .userFrame -textVariable status \
        -width 60 -height 2
    update
    
    MakeArchiveWidget .data -parent .userFrame
} else {
    wm withdraw .
    if [catch {Measure -outputFile $outputFile -commandline 1 -channel $channel} result] {
        puts stderr $result
        exit 1
    } else {
        exit 0
    }
}
