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

set tcl_precision 16

set ControlStatus "Ready.\nSynchrotron frequency measure mode selected (default)."
set CVSRevisionAuthor "\$Revision: 1.10 $ \$Author: soliday $"


#-----------------------------------------------------------
# Make the menu and status for the SR synchrotron freq msmt
#-----------------------------------------------------------

proc makeSRfreqSynchMenuAndStatus {args} {
    
    global ControlStatus CVSRevisionAuthor rfFreq

    APSApplication . -name "SR Longitudinal Beam Spectrum" \
      -version "$CVSRevisionAuthor (harkay)" \
      -overview "SR synchrotron frequency and advanced longitudinal beam\
	           spectrum measurements using hp VSA."

    APSScrolledStatus .status -parent .userFrame -textVariable ControlStatus \
      -width 78 -height 12 -packOption {-side top}

    SetStatus "rf source freq ${rfFreq} Hz"
}


#----------------------------------------------------------
# Start hp VSA display
#----------------------------------------------------------

proc makeVSAdisplay {args} {

    global ControlStatus hpvsa
    set parent ""
    APSParseArguments {parent}

    APSFrame .left -parent $parent -label "" \
      -packOption {-side left}

    APSFrame .vsaDisplay -parent $parent.left.frame  -label "VSA/beam display" \
      -packOption {-side top -ipady 3.} \
      -contextHelp "Select/open display/general setup of VSA and display\
		beam current"

    set w $parent.left.frame.vsaDisplay.frame

    APSRadioButtonFrame .vsaPick -parent $w -label "" \
      -variable vsa0 -buttonList {sr boo} \
      -valueList {sr boo} -orientation horizontal \
      -commandList {"vsaToggle sr -statusCallback SetStatus" "vsaToggle boo -statusCallback SetStatus"} \
      -packOption {-side top -padx 15.} \
      -contextHelp "Switches between VSA instruments: 89441A (hpvecsr) or\
		89440A (hpvecboo)." 

    APSButton .vsadisplay -parent $w \
      -text "open display" \
      -command {openVSAdisplay -statusCallback SetStatus} \
      -packOption {-side top} \
      -contextHelp "Opens VSA display"

    APSButton .vsadisplayRecall -parent $w \
      -text "recall state" \
      -command {exec hpSocketSend ${hpvsa} "mmem:load:stat 1,'nvram:fsynch'" } \
      -packOption {-side top} \
      -contextHelp "Recalls instrument state FSYNCH from nvram. Use this function if\
		many parameters have been changed on the instrument or if its state is\
		unknown. The setup VSA button only sets a limited number of parameters."

    APSButton .beamCurrent -parent $w \
      -text "beam current" \
      -command {exec medm -attach -x beam_new.adl &} \
      -packOption {-side top} \
      -contextHelp "Displays beam current (beam_new.adl)"

}


#-----------------------------------------------------------
# toggle between vector signal analyzers 89441A (sr) and 89440A (boo)
#-----------------------------------------------------------

proc vsaToggle {vsa args} {

    global ControlStatus vsaSwitch vsa0 hpvsa hptrac
    global revIndex revFreq rfIndex rfFreq startFreq centerFreqFS
    global rfstart nspan fsSpan 
    global commentDoY commentDoN
    set parent ""
    APSParseArguments {parent}

    set vsa0 ${vsa}
    if [string compare ${vsa} ${vsaSwitch}]==0 {
        return
    }
    switch ${vsa0} {
        sr {
            set hpvsa "hpvecsr.aps4.anl.gov"
            set hptrac "hpvecsr"
            SetStatus "Now using sr VSA 89441A"
            set rfIndex 7
            set startFreq [expr ${rfIndex} * ${rfFreq} + ${revIndex} * ${revFreq}]
            set centerFreqFS [expr ${startFreq} / 1e6 ]
            set rfstart 4
            set nspan 1
	    set ncbm 1296
        }
        boo {
            set hpvsa "hpvecboo.aps4.anl.gov"
            set hptrac "hpvecboo"
            SetStatus "Now using booster VSA 89440A"
            set rfIndex 5
            set startFreq [expr ${rfIndex} * ${rfFreq} + ${revIndex} * ${revFreq}]
            set centerFreqFS [expr ${startFreq} / 1e6 ]
            set rfstart 4
            set nspan 1
	    set ncbm 432
        }
    }

# next lines commented out because appl hangs up here when there are communication problems

#    catch {exec hpSocketSend ${hpvsa} "freq:cent?"} result1
#    set result2 [expr ${result1} / 1e6]
#    catch {exec hpSocketSend ${hpvsa} "freq:span?"} result3

    #    catch [winfo exists .userFrame.synchFreq] result

#    if {${result2} == ${centerFreqFS} && ${result3} == ${fsSpan} && ${commentDoY} != 1} {
#        SetStatus "   Nominal VSA setup for synch freq mode;\
#	    ready to archive or acquire ..."
#        set commentDoY 1
#    } elseif {${commentDoN} != 1} {
        SetStatus "   Choose archive or setup VSA (or verify desired state)\
	    to continue ..."
        set commentDoN 1
#    }

}


#---------------------------------------------------------
# Datalogger selection
#---------------------------------------------------------

proc makeDatalogger {args} {

    set parent ""
    APSParseArguments {parent}

    APSFrame .datalog -parent $parent.left.frame -label "data Logger" \
      -contextHelp "Setup of optional datalogger (sddsmonitor)"

    set w $parent.left.frame.datalog.frame

    APSLabeledEntry .secs -parent $w -width 3 \
      -textVariable secsLog \
      -label "interval (s):" \
      -contextHelp "Enter PV acquire interval in seconds"

    APSLabeledEntry .hours -parent $w -width 3 \
      -textVariable hoursLog \
      -label "time (hr):" \
      -contextHelp "Enter data-logging time in hours"

    APSButton .startDatalog -parent $w \
      -text "start" \
      -command {startDatalogger -statusCallback SetStatus} \
      -packOption {-side top} \
      -contextHelp "Starts EPICS data logging of beam/rf params using\
	    input file of select rf and beam parameters \
            (/home/helios/oagData/sr/synchTune/inputFiles/SRLongitudinalSpectrum.mon) \
	    or optionally launch quickMonitor."

}

#---------------------------------------------------------
# Start datalogger
#---------------------------------------------------------

proc startDatalogger {args} {

    global ControlStatus root noName secsLog hoursLog
    set parent ""
    APSParseArguments {parent}

    if [string compare ${root} ${noName}]==0 {
        SetStatus "*** please enter filename ***"
        return
    }

    set choice Overwrite
    if [file exists ${root}.mon] {
        if [catch {APSMultipleChoice [APSUniqueName .] -name "" \
                     -question "File exists. What do you want to do?" \
                     -labelList {Overwrite Cancel} \
                     -returnList  {Overwrite Cancel}} choice] {
            global errorInfo
            SetStatus "$errorInfo"
            return
        }
    }
    switch $choice {
        Overwrite {
            if [catch {APSMultipleChoice [APSUniqueName .] -name "" \
                         -question "Launching sddsmonitor job:\
			\n  ${root}.mon,\
			\n\n (input file SRLongitudinalSpectrum.mon)\
			\n\n  $secsLog-sec intervals,\
			\n  $hoursLog hours ...\
			\n\n What do you want to do?" \
                         -labelList {Continue QuickMonitor Abort} \
                         -returnList  {Continue QuickMonitor Abort}} choice2] {
                global errorInfo
                SetStatus "$errorInfo"
                return
            }
            switch $choice2 {
                Continue {
                    set timcalc2 "[eval exec date +%T]"
                    SetStatus "${timcalc2}  Data logger job ${root}.mon started."
                    exec sddsmonitor \
                      /home/helios/oagData/sr/synchTune/inputFiles/SRLongitudinalSpectrum.mon \
                      ${root}.mon -erase -interval=$secsLog,s -time=$hoursLog,h \
                      -getUnits=force &
                }
                QuickMonitor {
                    exec quickMonitor &
                    SetStatus "quickMonitor launched."
                    return 
                }
                Abort {
                    SetStatus "Data logger job aborted."
                    return 
                }
            }
        }
        Cancel {
            SetStatus "Data logger job aborted."
            return
        }
        default {
            puts "Unknown return value: $choice"
            return
        }
    }

}

#------------------------------------------------------------
# Make the hp vsa control frame and widgets for Measurement 
# Modes (per SRbpmConfig)
#------------------------------------------------------------
proc makeVSAControlFrameWidget {widget args} {

    set parent ""
    if [APSStrictParseArguments {parent}]==-1 {
        return
    } 
    set frameWidth 580
    set frameHeight 195
    APSFrame $widget -parent $parent
    set w $parent$widget.frame
    
    set topTabList [APSTabFrame .tab -parent $w -label "" -labelList "sychnFreq RFspan CBMscan"\
                      -packOption "-expand true -fill both" \
                      -width $frameWidth -height $frameHeight -commandList {"DescribeSection -index 0" "DescribeSection -index 1" "DescribeSection -index 2"} ] 

    
    makeSynchFreqFrame -parent [lindex $topTabList 0]
    makeRFspanFrame -parent [lindex $topTabList 1]
    makeCBMscanFrame -parent [lindex $topTabList 2]

}


proc DescribeSection {args} {
    set index -1
    APSParseArguments {index}
    switch $index {
        0 {
            SetStatus "synchFreq - high resolution, centered at rf harmonic; 10\
		averages, 6 kHz span, 10 Hz rbw; process option finds synch freq\
		and est. oscillation ampitude after a waveform is acquired;\
		quick calulation available of effective\
		rf gap voltage on entering a value for the synchrotron frequency\n"
        }
        1 {
            SetStatus "RFspan - low resolution, no\
		averaging; 351.927*n/h MHz span, 300*n/h kHz rbw, to study coupled-bunch\
		mode (n) spectrum (phas-mod) or bunch fill pattern spectrum (ampl-mod);\n"
        }
        2 {
            SetStatus "CBMscan - high\
		resolution, no averages; 20 kHz span, 30 Hz rbw, to study synchrotron\
		or betatron sidebands at rf and/or revolution harmonics, providing\
		scans at either \n (a) a single harmonic as a function of time, or\
		\n (b) N revolution harmonics \n"
        }
    }
}


#-----------------------------------------------------------
# Make frames and widgets for the 3 measurement mode options
#-----------------------------------------------------------

proc makeSynchFreqFrame {args} {

    global ControlStatus gapVolt fscalckHz
    set parent ""
    APSStrictParseArguments {parent noPack}

    APSFrame .synchFreq -parent $parent -label "synchrotron freq mode" \
      -height 30 -relief sunken 
    
    set fsynchw $parent.synchFreq.frame
    
    APSFrame .fs -parent $fsynchw \
      -height 30 -packOption {-pady 5}

    set w $fsynchw.fs.frame

    APSButton .archivefs -parent $w \
      -text "archive/review" \
      -command {Archive fsynch -statusCallback SetStatus} \
      -contextHelp "Allows archiving/reviewing of synchrotron frequency waveforms.\
		Automatically sets up VSA, and acquires, processes, and plots data.\
		Under review, file list appears in pop-up window; double-click to\
		select. Data can be reprocessed for any archived waveform by typing\
		in the name (incl dir) and selecting process/plot."

    APSButton .setvsafs -parent $w \
      -text "setup VSA" \
      -command {HPvsaSetup fsynch -statusCallback SetStatus} \
      -contextHelp "Sets center freq, rbw/span/etc for\
		synchrotron frequency measurements.\
		Any of the settings may be changed as desired prior to acquiring\
		waveform. This setup is limited; use the recall state button if\
		the instrument state is unknown."

    APSButton .acquireFsynch -parent $w \
      -text "acquire wfm" \
      -command {AcquireWaveform fsynch -statusCallback SetStatus} \
      -contextHelp "Acquires synchrotron frequency waveform \
		and several machine parameters, saving all in an sdds file."

    APSButton .processFsynch -parent $w \
      -text "process/plot wfm" \
      -command {processWaveform fsynch -statusCallback SetStatus} \
      -contextHelp "Processes synchrotron frequency waveform, \
		applying despike option under sddssmooth to reduce the 60/360 Hz\
		signals; results stored in root.despik. Plot panel 1 shows\
		despiked waveform only and location of fs,\
		and panel 2 shows waveform before/after despiking.\
		\n\nStatus window gives processing results for the synch freq; the\
		synch oscillation amplitude, del-t, is estimated using (gaussian model):\
		\n  ratio voltage (synch sideband/(p*frf)) =\
		\n                2/pi * (p*wrf) * del-t,\
		\nwhere p is the rf harmonic index and wrf = 2pi*frf,\
		whose signal amplitude before despiking is used."

    APSFrame .setfs -parent $fsynchw \
      -height 30 -packOption {-side left}

    set freqw $fsynchw.setfs.frame

    APSLabeledEntry .setfs -parent $freqw -width 12 \
      -textVariable centerFreqFS \
      -packOption {-ipadx 3.} \
      -label "center freq (MHz):" \
      -contextHelp "Enter center frequency for measurement. Note: this is not a readback.\
		Use <return> after entering a new value, or choose setup VSA.\
		\n\nBecause the envelope\
		of the synchrotron frequency sidebands peaks near the inverse of\
		the bunch length (~100 ps fwhm), it is suggested that this measurement\
		be made at as high an rf harmonic as possible. The default is the\
		7th rf harmonic for the sr hpVSA, and 5th rf harmonic for the boo hp VSA."

    bind $freqw.setfs.entry <Return> {setVSAcenterFreq fsynch -statusCallback SetStatus}

    APSLabeledOutput .gapvolt -parent $freqw -width 8 \
      -textVariable gapVolt \
      -packOption {-side top -ipadx 29.} \
      -label "RF gap volt (kV)" \
      -contextHelp "Total rf gap voltage calculated from sum of cavity probe powers"

    APSLabeledOutput .fscalc -parent $freqw -width 8 \
      -textVariable fscalckHz \
      -packOption {-ipadx 34.} \
      -label "fs (calc) (kHz)" \
      -contextHelp "Calculated synchrotron frequency for total gap voltage derived\
		from sum cavity probe power, using synchrotron radiation loss of\
		U=88.5 E^4/rho per turn (5.374 MeV at 7.0 GeV). \
                Total gap voltage < U returns fs = 0.\
		\n\n This calculation assumes that the inter-klystron station phase\
		is correct, and that the cavity probe power calibration is accurate."

    APSLabeledEntry .fsmsrd -parent $freqw -width 8 \
      -textVariable fsmsrdkHz \
      -packOption {-ipadx 29.} \
      -label "fs (msrd) (kHz):" \
      -contextHelp "Enter measured synchrotron frequency, fs, after acquiring or processing\
		waveform. Effective total gap voltage, V, is returned in status box,\
		assuming synchrotron radiation loss, U=88.5 E**4/rho (5.374 MeV at 7.0 GeV) \
                per turn (rho = 39.4079 m). \
		Note fs becomes detuned with beam intensity \
		(msr fs with < 40 mA for accurate rf Voltage calc.)\
		\n\nV(MV) = sqrt((fs(kHz))**4/Const + U**2)\
		\n where Const = frev**4 * (alpha_c*h/2pi(E/e))**2
		\n\nUpdated to read alpha_c from /home/helios/oagData/sr/lattices/default/api.twi
		\n\nBecause this sets up a new calculation,\
		use <return> after entering a new value."

    bind $freqw.fsmsrd.entry <Return> {calcGapVoltfsmsrd -statusCallback SetStatus}

    APSFrame .setproc -parent $fsynchw \
      -height 45 -packOption {-side top}

    set procw $fsynchw.setproc.frame

    APSLabeledEntry .beamE -parent $procw -width 4 \
      -textVariable beamEnerVal \
      -packOption {-ipadx 15.} \
      -label "beam energy (GeV):" \
      -contextHelp "Beam energy must be entered to calculate fsynch correctly."\

    bind $procw.beamE.entry <Return> {calcfs -statusCallback SetStatus}

    APSLabeledEntry .despik -parent $procw -width 3 \
      -textVariable despikVal \
      -packOption {-ipadx 3.} \
      -label "despike adjac datapts:" \
      -contextHelp "Applied during process wfm option: specifies number of\
		datapoint neighbors over which to average to effectively remove\
		the undesired 60/360 Hz spikes."

    APSLabeledEntry .pass -parent $procw -width 3 \
      -textVariable passVal \
      -packOption {-ipadx 25.} \
      -label "smoothing passes:" \
      -contextHelp "Applied during process wfm option: specifies number of\
		\smoothing passes."

}


proc makeRFspanFrame {args} {

    global ControlStatus 
    set parent ""
    APSStrictParseArguments {parent noPack}

    APSFrame .rfspan -parent $parent -label "RF span mode" \
      -height 30 -relief sunken 

    set rfspanw $parent.rfspan.frame

    APSFrame .rf -parent $rfspanw \
      -height 30 -packOption {-pady 5}

    set w $rfspanw.rf.frame

    APSButton .setvsarf -parent $w \
      -text "setup VSA" \
      -command {HPvsaSetup rfspan -statusCallback SetStatus} \
      -contextHelp "Sets center freq, rbw/span/etc for\
		rf span or cbm measurements.\
		Any of the settings may be changed as desired prior to acquiring\
		waveform. This setup is limited; use the recall state button if\
		the instrument state is unknown."

    APSButton .acquireRFspan -parent $w \
      -text "acquire wfms" \
      -command {AcquireWaveform rfspan -statusCallback SetStatus} \
      -contextHelp "Acquires rf span or cbm waveforms over defined range, combining them,\
		and acquires several machine parameters, saving all in an sdds file."

    APSButton .processRFspan -parent $w \
      -text "plot wfm" \
      -command {processWaveform rfspan -statusCallback SetStatus} \
      -contextHelp "Plots rf span or cbm waveforms."

    APSFrame .setrf -parent $rfspanw \
      -height 45
    
    set w $rfspanw.setrf.frame

    APSLabeledEntry .setrfi -parent $w -width 3 \
      -textVariable rfstart \
      -packOption {-ipadx 80.} \
	-label "start rf harmonic:" \
      -contextHelp "Choose the rf harmonic (0 - 6) defining the beginning of\
		the desired range.\
		\n\nBecause this sends instructions to the VSA,\
		use <return> after entering a new value, or choose setup VSA."

    bind $w.setrfi.entry <Return> {setVSAcenterFreq rfspan -statusCallback SetStatus}

    APSLabeledEntry .setrff -parent $w -width 3 \
      -textVariable nspan \
      -packOption {-ipadx 100.} \
      -label "no. harmonics:" \
      -contextHelp "Choose the number of freq spans defining the end of\
		the desired range (units of rf or cbm span).  Do not exceed\
                2.65 GHz for hpvecsr or 1.8 GHz for hpvecboo."

    APSLabeledEntry .setcbm -parent $w -width 5 \
      -textVariable ncbm \
      -packOption {-ipadx 5.} \
      -label "no. bunches (cbms) (h = rf span):" \
      -contextHelp "To display cbm spectrum, enter number of bunches, else enter\
		1296 for rf span.\
		\n\nBecause this sends instructions to the VSA,\
		use <return> after entering a new value, or choose setup VSA."

    bind $w.setcbm.entry <Return> {HPvsaSetup rfspan -statusCallback SetStatus}
#    bind $w.setcbm.entry <Return> {setVSAcenterFreq rfspan -statusCallback SetStatus}

}


proc makeCBMscanFrame {args} {

    global ControlStatus aveOff aveOn
    set parent ""
    APSStrictParseArguments {parent noPack}

    APSFrame .cbmscan -parent $parent -label "coupled-bunch mode (CBM) scan mode" \
      -height 30 -relief sunken

    set cbmscanw $parent.cbmscan.frame

    APSFrame .cbm -parent $cbmscanw \
      -height 30 -packOption {-pady 5}

    set w $cbmscanw.cbm.frame

    APSButton .setvsarfZ -parent $w \
      -text "setup VSA: nus" \
      -command {HPvsaSetup cbmscanZ -statusCallback SetStatus} \
      -contextHelp "Sets center freq, rbw/span/etc for\
		coupled-bunch mode scan measurements\
		centered at synchrotron tune sidebands.\
		Any of the settings may be changed as desired prior to acquiring\
		waveform. This setup is limited; use the recall state button if\
		the instrument state is unknown."

    APSButton .setvsarfXY -parent $w \
      -text "setup VSA: nux/y" \
      -command {HPvsaSetup cbmscanXY -statusCallback SetStatus} \
      -contextHelp "Sets center freq, rbw/span/etc for\
		coupled-bunch mode scan measurements\
		centered at betatron tune sidebands.\
		Any of the settings may be changed as desired prior to acquiring\
		waveform. This setup is limited; use the recall state button if\
		the instrument state is unknown."

    APSButton .acquireCBMscan -parent $w \
      -text "acquire wfms" \
      -command {AcquireWaveform cbmscan -statusCallback SetStatus} \
      -contextHelp "Acquires cbm scan waveforms, optionally\
		including several beam parameters (standard),\
	        saving all in an sdds file."

    APSButton .processCBMscan -parent $w \
      -text "plot wfms" \
      -command {processWaveform cbmscan -statusCallback SetStatus} \
      -contextHelp "Plots cbm scan waveforms."

    APSFrame .setcbm -parent $cbmscanw \
      -height 30 -packOption {-side left}
    
    set w $cbmscanw.setcbm.frame

    APSLabeledEntry .setcbmrf -parent $w -width 3 \
      -textVariable rfIndex \
      -packOption {-ipadx 34.} \
      -label "start rf harmonic:" \
      -contextHelp "Choose the rf harmonic (max 7th on hpvecsr, max 5th on hpvecboo)\
		at which to begin the scan.\
		\n\nBecause this sends instructions to the VSA,\
		use <return> after entering a new value, or choose setup VSA."

    bind $w.setcbmrf.entry <Return> {setVSAcenterFreq cbmscan -statusCallback SetStatus}

    APSLabeledEntry .setcbmrev -parent $w -width 5 \
      -textVariable revIndex \
      -packOption {-ipadx 20.} \
      -label "start rev harmonic:" \
      -contextHelp "Choose the revolution harmonic (1 - 1296) at which to begin\
		the scan.\
		\n\nBecause this sends instructions to the VSA,\
		use <return> after entering a new value, or choose setup VSA."

    bind $w.setcbmrev.entry <Return> {setVSAcenterFreq cbmscan -statusCallback SetStatus}

    APSLabeledEntry .setbetatun -parent $w -width 5 \
      -textVariable betatun \
      -packOption {-ipadx 2.} \
      -label "betatron tune (H or V):" \
      -contextHelp "Enter the fractional betatron tune, horizontal or vertical,\
		as preferred.\
		\n\nBecause this sends instructions to the VSA,\
		use <return> after entering a new value, or choose setup VSA."

    bind $w.setbetatun.entry <Return> {setVSAcenterFreq cbmscanXY -statusCallback SetStatus}

    APSFrame .setscan -parent $cbmscanw \
      -height 30 -packOption {-side left}
    
    set w $cbmscanw.setscan.frame

    APSRadioButtonFrame .scanPick -parent $w -label "scan type:     " \
      -variable scan0 -buttonList {time cbm} \
      -valueList {time cbm} -orientation horizontal \
      -contextHelp "Switches between time scan of single cbm and cbm scan of many."

    APSRadioButtonFrame .scanInfo -parent $w -label "   " \
      -variable scanI -buttonList {std std/ave brief} \
      -valueList {std stdave brief} -orientation horizontal \
      -commandList {"exec hpSocketSend ${hpvsa} ${aveOff}" "exec hpSocketSend ${hpvsa} ${aveOn}" "exec hpSocketSend ${hpvsa} ${aveOff}"} \
      -contextHelp "Switches between standard and brief scans.\
	  \n\n  Standard: beam current, rf gap voltage, and\
	  x-ray pinhole signal fit results recorded with waveform.\
	  \n\n  Standard/Ave: same as above, +15 secs wait to allow wfm averaging.\
	  \n\n  Brief: no beam/machine params written to files."

    APSLabeledEntry .setscantime -parent $w -width 5 \
      -textVariable StepSize \
      -packOption {-ipadx 11.} \
      -label "step size (sec or n):" \
      -contextHelp "Choose step size in either # secs (time scan) or cbm # interval\
		(cbm scan)"

    APSLabeledEntry .setscancbm -parent $w -width 5 \
      -textVariable Steps \
      -packOption {-ipadx 70.} \
      -label "# steps:" \
      -contextHelp "Choose # steps, equalling total time (time scan) or total number\
		of cbms (cbm scan) acquired"

}


#-----------------------------------------------------------
# commands to open VSA display
#-----------------------------------------------------------

proc openVSAdisplay {args} {

    global ControlStatus hpvsa vsa0

    SetStatus "Opening VSA display ..."

    if [catch {exec hpVecDisplay -unit ${vsa0}} result] {
        SetStatus "$result"
        return
    }
    after 10000

    SetStatus "Done."
}


#------------------------------------------------------------
# commands to set basic VSA params
#------------------------------------------------------------

proc commonVSAparams {args} {

    global ControlStatus hpvsa 

    catch {exec hpSocketSend ${hpvsa} "inst?"} result1
    catch {exec hpSocketSend ${hpvsa} "swe:poin?"} result2
    catch {exec hpSocketSend ${hpvsa} "trig:sour?"} result3
    catch {exec hpSocketSend ${hpvsa} "disp:wind1:trac:y:rlev?"} result4
    catch {exec hpSocketSend ${hpvsa} "disp:wind1:trac:y:pdiv?"} result5

    if {${result1} != "SCAL"} {
        exec hpSocketSend ${hpvsa} "inst scal"
        after 3000
    }
    if {${result2} != 801} {
        exec hpSocketSend ${hpvsa} "swe:poin 801"
        after 3000
    }
    if {${result3} != "IMM"} {
        exec hpSocketSend ${hpvsa} "trig:sour imm"
        after 3000
    }
    if {${result4} != -15.} {
        exec hpSocketSend ${hpvsa} "disp:wind1:trac:y:rlev -15 dbm"
        after 3000
    }
    if {${result5} != 10.} {
        exec hpSocketSend ${hpvsa} "disp:wind1:trac:y:pdiv 10 db"
        after 3000
    }

}


#---------------------------------------------------------
# Procedure to archive fsynch measurements.
#---------------------------------------------------------

# This procedure checks VSA setup, sets to standard if necessary, acquires and
# processes waveform in one step, saving in /home/helios/oagData/sr/synchTune

proc Archive {type args} {

    global ControlStatus hpvsa centerFreqFS fsSpan
    global root archDir

    set archDir /home/helios/oagData/sr/synchTune/data
    #    set archDir /home/helios/HARKAY/tcl
    set choice New

    if [catch {APSMultipleChoice [APSUniqueName .] -name "" \
                 -question "Archive new or review?" \
                 -labelList {New Review} \
                 -returnList  {New Review}} choice] {
        global errorInfo
        SetStatus "$errorInfo"
        return
    }

    switch $choice {
        New {
            SetStatus "\nArchiving ..."
        }
        Review {
            set archList [glob ${archDir}/fs*.despik]
            set shortList ""
            foreach elem $archList {
                set item ""
                if [catch {regexp "${archDir}/(.*)\.despik" $elem {} item}] {continue}
                lappend shortList $item
            }

            if [winfo exists .userFrame.dumpList] {
                destroy .userFrame.dumpList
            }

            APSScrolledList .dumpList -parent "" \
              -name "Archive Choices" \
              -itemList $shortList -packOption "-side bottom" \
              -callback ReviewArchive \
              -contextHelp "List of archived data. Double-click to review.\
		The numbers give the date and time in hours, minutes, and seconds."

            return
        }
    }

    if [string compare ${type} fsynch]==0 {

        set time "[eval exec date +%y%m%d-%H%M%S]"
        set root  ${archDir}/fs-${time}

        catch {exec hpSocketSend ${hpvsa} "freq:cent?"} result1
        set result2 [expr ${result1} / 1e6]
        catch {exec hpSocketSend ${hpvsa} "freq:span?"} result3
        catch {exec hpSocketSend ${hpvsa} "aver?"} result4

        if {${result2} != ${centerFreqFS} && ${result3} != ${fsSpan}\
              && ${result4} != 1} {
            HPvsaSetup fsynch -statusCallback SetStatus
        }

        AcquireWaveform fsynch -statusCallback SetStatus
        processWaveform fsynch -statusCallback SetStatus

    }

    SetStatus "Wrote ${root}.despik"

}

proc ReviewArchive {Item doubleClick} {
    global ControlStatus root archDir

    if !$doubleClick {
        return
    }

    catch {file rootname ${archDir}/${Item}.despik} root

    catch {exec sdds2stream ${root}.despik -param=SmoothPoints} despikVal
    catch {exec sdds2stream ${root}.despik -param=SmoothPasses} passVal
    catch {exec sdds2stream ${root}.despik -param=synchFreq} synchFreqFind

    SetStatus "\nReviewing ...\
       	\n   smooth despike value = ${despikVal}   \
       	 number of passes = ${passVal}"

    if {[string compare ${Item} fs-020226]==-1 || [string compare ${Item} fs-970000]==1} {
#   files archived prior to 2002 feb 27 (added up/dn sidebands)
        if [catch {exec sddsplot ${root}.despik \
                     -mod=y=log -fact=ymult=20 -offset=ychange=0.650515 \
                     -titl=@TimeStamp \
                     -file -scales=0,0,-135,-25 -lspac=0.75,0.9,0,0.95 \
                     -subtic=xdiv=5,ydiv=5 "-ylabel=Waveform (dBm)" \
                     -col=FreqOffset,Waveform \
                     -string=@synchFreqString,p=0.1,q=0.92 \
                     -string=@synchOscAmplString,p=0.05,q=0.86 \
                     -drawLine=x0val=$synchFreqFind,x1val=$synchFreqFind,y0val=-130,y1val=-45 \
                     -endpanel -sep=2 \
                     -col=Frequency,Waveform ${root}.sdds -grap=line=typ=0 \
                     "-legend=spec=raw" \
                     -col=Frequency,Waveform ${root}.despik -grap=line,typ=1 \
                     -string=@synchFreqString,p=0.1,q=0.92 \
                     -string=@synchOscAmplString,p=0.05,q=0.86 \
                     "-legend=spec=despiked" &} result] {
            SetStatus "Error: ${result}"
        }
    } else {
        catch {exec sdds2stream ${root}.despik -param=synchFreq} synchFreqUp
        catch {exec sdds2stream ${root}.despik -param=synchFreq} synchFreqDn
        catch {exec sdds2stream ${root}.despik -param=synchFreqAmplUp} synchFreqAmplUp
        catch {exec sdds2stream ${root}.despik -param=synchFreqAmplDn} synchFreqAmplDn
        if [catch {exec sddsplot ${root}.despik \
                     -mod=y=log -fact=ymult=20 -offset=ychange=0.650515 \
                     -titl=@TimeStamp \
                     -file -scales=0,0,-125,-25 -lspac=0.75,0.9,0,0.95 \
                     -subtic=xdiv=5,ydiv=5 "-ylabel=Waveform (dBm)" \
                     -col=FreqOffset,Waveform -grap=line \
                     -param=synchFreqUp,synchFreqAmplUp \
                     -grap=symb,subtyp=1,scale=3 \
                     -param=synchFreqDn,synchFreqAmplDn \
                     -grap=symb,subtyp=1,scale=3 \
                     -string=@synchFreqString,p=0.1,q=0.92 \
                     -string=@synchOscAmplString,p=0.05,q=0.86 \
                     -endpanel -sep=3 \
                     -col=Frequency,Waveform ${root}.sdds -grap=line=typ=0 \
                     "-legend=spec=raw" \
                     -col=Frequency,Waveform ${root}.despik -grap=line,typ=1 \
                     -string=@synchFreqString,p=0.1,q=0.92 \
                     -string=@synchOscAmplString,p=0.05,q=0.86 \
                     "-legend=spec=despiked" &} result] {
            SetStatus "Error: ${result}"
        }
    }
    
    SetStatus "Done."

}


#---------------------------------------------------------
# Procedure to setup VSA for measurements.  
#---------------------------------------------------------

proc HPvsaSetup {type args} {
    
    global ControlStatus hpvsa centerFreqFS rfFreq
    global rbwfsynch rbwrfspan rbwcbmscan scanxyz 
    global fsSpan ncbm

    commonVSAparams -statusCallback SetStatus

    if [string compare ${type} fsynch]==0 {
        SetStatus "\nSetting up VSA for synchrotron frequency msmnts, ave ON..."

        setVSAcenterFreq fsynch -statusCallback SetStatus
        SetStatus "Continuing setup, please wait ..."

        catch {exec hpSocketSend ${hpvsa} "freq:span?"} result1
        catch {exec hpSocketSend ${hpvsa} "band?"} result2
        catch {exec hpSocketSend ${hpvsa} "aver:coun?"} result3
        catch {exec hpSocketSend ${hpvsa} "swe:poin?"} result4

        if {${result1} != ${fsSpan}} {
            exec hpSocketSend ${hpvsa} "freq:span ${fsSpan} Hz"
            after 3000
        }
        if {${result2} != ${rbwfsynch}} {
            exec hpSocketSend ${hpvsa} "band ${rbwfsynch} Hz"
            after 3000
        }
        #	exec hpSocketSend ${hpvsa} "aver:type rms;tcon exp"
        exec hpSocketSend ${hpvsa} "aver on"
        after 3000
        if {${result3} != 10} {
            exec hpSocketSend ${hpvsa} "aver:coun 10"
            after 3000
        }
        if {${result4} != 801} {
            exec hpSocketSend ${hpvsa} "swe:poin 801"
            after 3000
        }

        SetStatus "Done."

    } elseif [string compare ${type} rfspan]==0 {
        SetStatus "\nSetting up VSA for RF span or cbm msmnts, ave OFF..."

        setVSAcenterFreq rfspan -statusCallback SetStatus
        SetStatus "Continuing setup, please wait ..."

        catch {exec hpSocketSend ${hpvsa} "freq:span?"} result1
        catch {exec hpSocketSend ${hpvsa} "band?"} result2
        catch {exec hpSocketSend ${hpvsa} "swe:poin?"} result3

        set StepSizeRF [expr ${rfFreq} * ${ncbm} / 1296.]
	set rbwnew [expr ${rbwrfspan} * ${ncbm} / 1296.]

        exec hpSocketSend ${hpvsa} "aver off"
        after 3000
        if {${result1} != ${StepSizeRF}} {
            exec hpSocketSend ${hpvsa} "freq:span ${StepSizeRF} Hz"
            after 3000
        }
        if {${result2} != ${rbwnew}} {
            exec hpSocketSend ${hpvsa} "band ${rbwnew} Hz"
            after 3000
        }
        if {${result3} != 1601} {
            exec hpSocketSend ${hpvsa} "swe:poin 1601"
            after 3000
        }

        SetStatus "Done."

    } elseif [string compare ${type} cbmscanZ]==0 {
        SetStatus "\nSetting up VSA for CBM scan msmnts; ave OFF..."

        set scanxyz "z"
        setVSAcenterFreq cbmscanZ -statusCallback SetStatus
        SetStatus "Continuing setup, please wait ..."

        catch {exec hpSocketSend ${hpvsa} "freq:span?"} result1
        catch {exec hpSocketSend ${hpvsa} "band?"} result2
        catch {exec hpSocketSend ${hpvsa} "swe:poin?"} result3

        exec hpSocketSend ${hpvsa} "aver off"
        after 3000
        if {${result1} != 20000} {
            exec hpSocketSend ${hpvsa} "freq:span 20000 Hz"
            after 3000
        }
        if {${result2} != ${rbwcbmscan}} {
            exec hpSocketSend ${hpvsa} "band ${rbwcbmscan} Hz"
            after 3000
        }
        if {${result3} != 801} {
            exec hpSocketSend ${hpvsa} "swe:poin 801"
            after 3000
        }

        SetStatus "Done."

    } elseif [string compare ${type} cbmscanXY]==0 {
        SetStatus "Setting up VSA for CBM scan msmnts; ave OFF..."

        set scanxyz "xy"
        setVSAcenterFreq cbmscanXY -statusCallback SetStatus
        SetStatus "Continuing setup, please wait ..."

        catch {exec hpSocketSend ${hpvsa} "freq:span?"} result1
        catch {exec hpSocketSend ${hpvsa} "band?"} result2
        catch {exec hpSocketSend ${hpvsa} "swe:poin?"} result3

        exec hpSocketSend ${hpvsa} "aver off"
        after 3000
        if {${result1} != 20000} {
            exec hpSocketSend ${hpvsa} "freq:span 20000 Hz"
            after 3000
        }
        if {${result2} != ${rbwcbmscan}} {
            exec hpSocketSend ${hpvsa} "band ${rbwcbmscan} Hz"
            after 3000
        }
        if {${result3} != 801} {
            exec hpSocketSend ${hpvsa} "swe:poin 801"
            after 3000
        }

        SetStatus "Done."

    }
}


#--------------------------------------------------------------
# Set the VSA center frequency
#--------------------------------------------------------------

proc setVSAcenterFreq {type args} {

    global ControlStatus hpvsa 
    global centerFreqFS rfFreq revFreq rfstart nspan ncbm
    global centerFreqCBM rfIndex revIndex betatun
    global scanxyz StepSize scan0


    if [string compare ${type} cbmscan]==0 {
        if [string compare ${scanxyz} z]==0 {
            set type cbmscanZ
        } elseif [string compare ${scanxyz} xy]==0 {
            set type cbmscanXY
        }
    }

    if [string compare ${type} fsynch]==0 {

        SetStatus "Working ..."
        exec hpSocketSend ${hpvsa} "freq:cent ${centerFreqFS} MHz"
        after 4000
        #	exec hpSocketSend ${hpvsa} "calc1:mark:max"
        #	after 4000
        #	exec hpSocketSend ${hpvsa} "freq:cent (calc1:mark:x?)" &

    } elseif [string compare ${type} rfspan]==0 {

        SetStatus "Working ..."
        set StepSizeRF [expr ${rfFreq} * ${ncbm} / 1296.]
        set centerFreqRF [expr ${rfFreq} * ${rfstart} +  ${StepSizeRF} / 2.]
        exec hpSocketSend ${hpvsa} "freq:cent ${centerFreqRF} Hz"
        after 4000

    } elseif [string compare ${type} cbmscanZ]==0 {

        SetStatus "Working ..."
        if [string compare ${scan0} cbm]==0 {
            SetStatus "Now selecting CBM scans at nus,\
		intervals of ${StepSize} frev"
        } elseif [string compare ${scan0} time]==0 {
            SetStatus "Now selecting CBM scans at nus,\
		intervals of ${StepSize} secs"
        }
        set startFreq [expr ${rfIndex} * ${rfFreq} + ${revIndex} * ${revFreq}]
        set centerFreqCBM ${startFreq}
        exec hpSocketSend ${hpvsa} "freq:cent ${centerFreqCBM} Hz"
        after 4000

    } elseif [string compare ${type} cbmscanXY]==0 {

        if [string compare ${scanxyz} z]==0 {
            SetStatus "Entry only valid for CBM scans at nux/nuy."
            return 1
        }
        SetStatus "Working ..."
        if [string compare ${scan0} cbm]==0 {
            SetStatus "Now selecting CBM scans at nux/nuy,\
		intervals of ${StepSize} frev"
        } elseif [string compare ${scan0} time]==0 {
            SetStatus "Now selecting CBM scans at nux/nuy,\
		intervals of ${StepSize} secs"
        }
        set startFreq [expr ${rfIndex} * ${rfFreq} + ${revIndex} * ${revFreq} \
                         + ${betatun} * ${revFreq}]
        set centerFreqCBM ${startFreq}
        exec hpSocketSend ${hpvsa} "freq:cent ${centerFreqCBM} Hz"
        after 4000
        
    }
    SetStatus "New center frequency."
    return 1
}


#--------------------------------------------------------------
# Make frames for data acquisition
#--------------------------------------------------------------

proc makeAcquireFrame {args} {
    
    global ControlStatus dirSR root
    set parent ""
    APSParseArguments {parent}
    set noName ""

    APSFrame .acquire -parent $parent -label "" \
      -height 30 \
      -packOption {-side bottom} \
      -contextHelp "Select directory and file root name for acquired/saved\
	    waveforms or datalogger file."

    set w $parent.acquire.frame

    APSLabeledEntry .fnam -parent $w -width 59 \
      -textVariable root \
      -label "file root name:" \
      -contextHelp "Sets directory and file root name for acquired/saved waveforms\
	    (.sdds) or datalogger (.mon) file."

}


#--------------------------------------------------------
# Acquiring single or multiple waveforms according to measure mode
#--------------------------------------------------------

proc AcquireWaveform {type args} {

    global ControlStatus root noName hpvsa hptrac
    global centerFreqFS rfFreq rfstart nspan ncbm
    global rbwfsynch rbwrfspan rbwcbmscan StepSizeRF
    global centerFreqCBM scan0 scanI StepSize Steps revFreq rfIndex revIndex

    if [string compare ${root} ${noName}]==0 {
        SetStatus "*** please enter filename ***"
        return
    }

    set choice Cont
    catch {file dirname ${root}} dir
    if {![file exists $dir]} {
        if [catch {APSMultipleChoice [APSUniqueName .] -name "" \
                     -question "Directory does not exist. Create it?" \
                     -labelList {Create Cancel} \
                     -returnList  {Create Cancel}} choice] {
            global errorInfo
            SetStatus "$errorInfo"
            return
        }
    }
    switch $choice {
        Cont {
        }
        Create {
            SetStatus "Creating directory ..."
            exec mkdir -p $dir
        }
        Cancel {
            SetStatus "Directory not created. Acquire waveform aborted."
            return
        }
    }

    set choice Overwrite
    if {[file exists ${root}.sdds] || [file exists ${root}-000.sdds]} {
        if [catch {APSMultipleChoice [APSUniqueName .] -name "" \
                     -question "File exists. What do you want to do?" \
                     -labelList {Overwrite Cancel} \
                     -returnList  {Overwrite Cancel}} choice] {
            global errorInfo
            SetStatus "$errorInfo"
            return
        }
    }
    switch $choice {
        Overwrite {
        }
        Cancel {
            SetStatus "Acquire waveform aborted."
            return
        }
        default {
            SetStatus "Unknown return value: $choice"
            return
        }
    }

    if [string compare ${type} fsynch]==0 {

        SetStatus "Acquiring synchrotron frequency waveform ..."

        exec hpVecTrace -${hptrac} a ${root}.sdds

        if [catch {exec cavget -pend=8 \
                     -list=S-DCCT:CurrentM,SR:C:cavTotalGapVolt,S:VID1:x:fit:fwhmM,S:VID1:x:fit:centroidM,S:VID1:y:fit:fwhmM,S:VID1:y:fit:centroidM \
                     -repeat=num=5,pause=1,average} result] {
            SetStatus "Error: $result"
        } else {
            set current  [lindex $result 0]
            set gapVolt  [lindex $result 1]
            set xfwhm  [lindex $result 2]
            set xcent  [lindex $result 3]
            set yfwhm  [lindex $result 4]
            set ycent  [lindex $result 5]
            if [string compare ${xfwhm} ?]==0 {
                set xfwhm 0
                set xcent 0
                set yfwhm 0
                set ycent 0
            }
        }

        catch {exec hpSocketSend ${hpvsa} "freq:span?"} fsSpanGet

        if [catch {exec sddsprocess ${root}.sdds \
                     -define=param,CenterFreq,${centerFreqFS},units=Hz \
                     -define=param,RBW,${rbwfsynch},type=long,format_string=%ld,units=Hz \
                     -define=param,fsSpan,${fsSpanGet},units=Hz \
                     -define=param,BeamCurrent,${current},units=mA \
                     -define=param,TotGapVolt,${gapVolt},units=kV \
                     -define=param,PhotonMonXfwhm,${xfwhm},units=chan \
                     -define=param,PhotonMonXcent,${xcent},units=chan \
                     -define=param,PhotonMonYfwhm,${yfwhm},units=chan \
                     -define=param,PhotonMonYcent,${ycent},units=chan \
                     -nowarnings} result] {
            SetStatus "Error: $result"
        }

        SetStatus "Wrote datafile ${root}.sdds"
        file delete ${root}.sdds~
        
    } elseif [string compare ${type} rfspan]==0 {

        SetStatus "\nAcquiring rf span waveforms ...\
	    \n*** temporarily disabling auto calib and auto zero ***\
	    \n\n stopFreq (Hz)        beam current (mA)"

        exec hpSocketSend ${hpvsa} "cal:auto off"
        exec hpSocketSend ${hpvsa} "cal:zero:auto off"

        set StepSizeRF [expr ${rfFreq} * ${ncbm} / 1296.]
        set centerFreqRF [expr ${rfFreq} * ${rfstart} +  ${StepSizeRF} / 2.]
        set halfRf [expr ${StepSizeRF} / 2.]
        set StepsRF ${nspan}

        ## Main loop: step in centerFreq

        for {set index 0} {$index < ${StepsRF}} {incr index 1} {

            set Index [format %02ld ${index}]

            exec hpSocketSend ${hpvsa} "freq:cent ${centerFreqRF} Hz"
            after 5000
            exec hpVecTrace -${hptrac} a ${root}-${Index}.sdds

            set stopFreq [expr ${centerFreqRF} + ${halfRf}]

            if [catch {exec cavget -pend=8 \
                         -list=S-DCCT:CurrentM,SR:C:cavTotalGapVolt,S:VID1:x:fit:fwhmM,S:VID1:x:fit:centroidM,S:VID1:y:fit:fwhmM,S:VID1:y:fit:centroidM \
                         -repeat=num=5,pause=1,average} result] {
                SetStatus "Error: $result"
            } else {
                set current  [lindex $result 0]
                set xfwhm  [lindex $result 1]
                set xcent  [lindex $result 2]
                set yfwhm  [lindex $result 3]
                set ycent  [lindex $result 4]
                if [string compare ${xfwhm} ?]==0 {
                    set xfwhm 0
                    set xcent 0
                    set yfwhm 0
                    set ycent 0
                }
            }

            SetStatus "${stopFreq}\t\t${current}"

            set rbwnew [expr ${rbwrfspan} * ${ncbm} / 1296.]
            set StepSizeRF [expr ${rfFreq} * ${ncbm} / 1296.]

            if [catch {exec sddsprocess ${root}-${Index}.sdds \
                         -define=param,CenterFreq,${centerFreqRF},units=Hz \
                         -define=param,RBW,${rbwnew},type=long,format_string=%ld,units=Hz \
                         -define=param,BeamCurrent,${current},units=mA \
                         -define=param,PhotonMonXfwhm,${xfwhm},units=chan \
                         -define=param,PhotonMonXcent,${xcent},units=chan \
                         -define=param,PhotonMonYfwhm,${yfwhm},units=chan \
                         -define=param,PhotonMonYcent,${ycent},units=chan \
			 "-define=col,cbm,Frequency 0 &Frequency \[ - ${StepSizeRF} / 1.e+06 * ${ncbm} * " \
                         -nowarnings} result] {
                SetStatus "Error: $result"
            }

            file delete ${root}-${Index}.sdds~
            set centerFreqRF [expr ${centerFreqRF} + ${StepSizeRF}]

        }

        set dataFileList [glob ${root}-*.sdds]
        eval exec sddscombine -overWrite $dataFileList ${root}.sdds
        file delete $dataFileList
        exec hpSocketSend ${hpvsa} "cal:auto on"
        exec hpSocketSend ${hpvsa} "cal:zero:auto on"

        SetStatus "\n*** re-enabled auto calib and auto zero ***\nWrote\
	    datafile ${root}.sdds"


    } elseif [string compare ${type} cbmscan]==0 {

        if {${centerFreqCBM} == 0.} {
            setVSAcenterFreq cbmscan -statusCallback SetStatus
        }

        SetStatus "\nAcquiring cbm scan waveforms ...\
	    \n*** temporarily disabling auto calib and auto zero ***\n"

        exec hpSocketSend ${hpvsa} "cal:auto off"
        exec hpSocketSend ${hpvsa} "cal:zero:auto off"

        #### For cbm(n) scan, Steps = # freq steps; for cbm(t) scan, Steps = # time steps

        if {$StepSize == 0.} {
            SetStatus "  Error: step size = 0."
            exit
        }

        if [string compare ${scan0} cbm]==0 {
            SetStatus "  time       cbm index           center freq (Hz)"
        }

        if [string compare ${scan0} time]==0 {
            exec hpSocketSend ${hpvsa} "freq:cent ${centerFreqCBM} Hz"
            after 5000
            if [string compare ${scanI} stdave]==0 {
                after 15000
            }
            set timInterval ${StepSize}
            SetStatus " revIndex = ${revIndex}  \
		centerFreq = ${centerFreqCBM}    time interval = ${timInterval} sec\
		\n\n  time       del-t (s)       time index"
            set timeWait [expr 0]
            set timeAct [expr 0]
        }

        #### Main loop: step in centerFreq (scan cbm #) or time (scan cbm(t))

        for {set index 0} {$index < ${Steps}} {incr index 1} {

            set timcalc "[eval exec date +%T]"
            set timBegStd ${timcalc}
            set timBeg [exec timeconvert -breakdown=now]

            if [string compare ${scan0} cbm]==0 {
                set timIndex [expr 0]
                set Index [format %04ld ${revIndex}]
                SetStatus "${timBegStd}\t${Index}\t\t${centerFreqCBM}"
                exec hpSocketSend ${hpvsa} "freq:cent ${centerFreqCBM} Hz"
                after 6000
                if [string compare ${scanI} stdave]==0 {
                    after 15000
                }
            }

            if [string compare ${scan0} time]==0 {
                set timIndex [expr ${StepSize} * ${index}]
                set Index [format %04ld ${timIndex}]
                SetStatus "${timBegStd}\t${timeAct}\t\t${Index}"
            }

            exec hpVecTrace -${hptrac} a ${root}-${Index}.sdds

            if {[string compare ${scanI} std]==0 || [string compare ${scanI} stdave]==0} {
                if [catch {exec cavget -pend=8 \
                             -list=S-DCCT:CurrentM,SR:C:cavTotalGapVolt,S:VID1:x:fit:fwhmM,S:VID1:x:fit:centroidM,S:VID1:y:fit:fwhmM,S:VID1:y:fit:centroidM \
                             -repeat=num=5,pause=1,average} result] {
                    SetStatus "Error: $result"
                } else {
                    set current  [lindex $result 0]
                    set gapVolt  [lindex $result 1]
                    set xfwhm  [lindex $result 2]
                    set xcent  [lindex $result 3]
                    set yfwhm  [lindex $result 4]
                    set ycent  [lindex $result 5]
                    if [string compare ${xfwhm} ?]==0 {
                        set xfwhm 0
                        set xcent 0
                        set yfwhm 0
                        set ycent 0
                    }
                }
                if {${current} < 0.05} {
                    SetStatus "Beam lost, terminating measurement..."
                    break
                }
                if [catch {exec sddsprocess ${root}-${Index}.sdds \
                             -define=param,CenterFreq,${centerFreqCBM},units=Hz \
                             -define=param,RBW,30,type=long,format_string=%ld,units=Hz \
                             -define=param,Pindex,${rfIndex},type=long,format_string=%ld \
                             -define=param,Nindex,${revIndex},type=long,format_string=%ld \
                             -define=param,Tindex,${timIndex},type=long,format_string=%ld \
                             -define=param,BeamCurrent,${current},units=mA \
                             -define=param,PhotonMonXfwhm,${xfwhm},units=chan \
                             -define=param,PhotonMonXcent,${xcent},units=chan \
                             -define=param,PhotonMonYfwhm,${yfwhm},units=chan \
                             -define=param,PhotonMonYcent,${ycent},units=chan \
                             -define=param,TotGapVolt,${gapVolt},units=kV \
                             "-print=param,Legend,%.1f mA  xfwhm %.1f,BeamCurrent,PhotonMonXfwhm" \
                             -nowarnings} result] {
                    SetStatus "Error: $result"
                }

            } elseif [string compare ${scanI} brief]==0 {
                if [catch {exec sddsprocess ${root}-${Index}.sdds \
                             -define=param,CenterFreq,${centerFreqCBM},units=Hz \
                             -define=param,RBW,30,type=long,format_string=%ld,units=Hz \
                             -define=param,Pindex,${rfIndex},type=long,format_string=%ld \
                             -define=param,Nindex,${revIndex},type=long,format_string=%ld \
                             -define=param,Tindex,${timIndex},type=long,format_string=%ld \
                             "-print=param,Legend,(no beam params)" \
                             -nowarnings} result] {
                    SetStatus "Error: $result"
                }
            }

            file delete ${root}-${Index}.sdds~

            if [string compare ${scan0} cbm]==0 {
                set centerFreqCBM [expr ${centerFreqCBM} + ${revFreq} * ${StepSize}]
                set revIndex [expr ${revIndex} + ${StepSize}]
            }

            if [string compare ${scan0} time]==0 {
                set timEnd [exec timeconvert -breakdown=now]
                set timeWait [expr int(${timInterval} - (${timEnd} - ${timBeg}))*1000]
                if {${timeWait} < 0} {
                    set timeWait [expr 0]
                }
                set timeAct [expr int(${timEnd} - ${timBeg}) + (${timeWait}/1000)]
                after ${timeWait}
            }

        }

        set dataFileList [glob ${root}-*.sdds]
        eval exec sddscombine -overWrite $dataFileList ${root}.sdds
        eval file delete $dataFileList
        exec hpSocketSend ${hpvsa} "cal:auto on"
        exec hpSocketSend ${hpvsa} "cal:zero:auto on"
        
        SetStatus "\n*** re-enabled auto calib and auto zero ***\nWrote\
	    datafile ${root}.sdds"
        
    }
    return 1
}


#--------------------------------------------------------------
# Processing single or multiple waveforms according to measure mode
#--------------------------------------------------------------

proc processWaveform {type args} {

    global ControlStatus root noName hpvsa
    global centerFreqFS despikVal passVal
    global rfstart nspan alphac
    global rbwfsynch rbwrfspan rbwcbmscan 
    APSParseArguments {parent}

    if [string compare ${root} ${noName}]==0 {
        SetStatus "*** please enter filename ***"
        return
    }

    if [string compare ${type} fsynch]==0 {

        SetStatus "Processing synchrotron frequency waveform ...\
		\n   smooth despike value = ${despikVal}   \
		 number of passes = ${passVal}"

        catch {exec sdds2stream ${root}.sdds -param=fsSpan} fsSpanRead
        
        set fsHalfSpan [expr (${fsSpanRead}/2. - ${fsSpanRead}*0.007) / 1000.]
        set freqUp [expr ${centerFreqFS} + (${fsHalfSpan} / 1000.)]
        set freqDn [expr ${centerFreqFS} - (${fsHalfSpan} / 1000.)]

        set centerFreqNew [eval exec sddsprocess ${root}.sdds -pipe=out \
                             -filter=col,Frequency,${freqDn},${freqUp} \
                             -process=Waveform,max,centerFreqNew,functionOf=Frequency,position \
                             | sdds2stream -pipe=in -param=centerFreqNew]
        SetStatus "\nprocess results:\
	    \n         center freq (max) = ${centerFreqNew} kHz"
        set centerFreqAmpl [eval exec sddsprocess ${root}.sdds -pipe=out \
                              -process=Waveform,max,centerFreqAmpl \
                              | sdds2stream -pipe=in -param=centerFreqAmpl]

        if [catch {exec sddsprocess ${root}.sdds -pipe=out \
                     -define,param,centerFreqNew,${centerFreqNew} \
                     "-define=col,FreqOffset,Frequency ${centerFreqNew} - 1000. * ,units=kHz" \
                     -filter=col,FreqOffset,-${fsHalfSpan},${fsHalfSpan} \
                     | sddssmooth -pipe=in ${root}.despik -col=Waveform \
                     -despik=neighb=${despikVal} -pass=${passVal}} result] {
            SetStatus "Error: ${result}"
        }

        ####	return -code error "$result"   ##  error message displayed in pop-up window
        
        if [catch {set synchFreqFindUp [eval exec sddsprocess ${root}.despik \
                                        -pipe=out "-filter=col,FreqOffset,-10.0,1.1,!" \
                                        -process=Waveform,max,synchFreqFindUp,functionOf=FreqOffset,position \
                                        | sdds2stream -pipe=in -param=synchFreqFindUp ]} result] {
            SetStatus "Error: cannot find synchrotron freq for this waveform (up)"
            exec sddsplot -mod=y=log -fact=ymult=20 \
              -offset=ychange=0.650515 -titl=@TimeStamp \
              -file -subtic=xdiv=5,ydiv=5 "-ylabel=Waveform (dBm)" \
              -col=FreqOffset,Waveform ${root}.despik &
            return
        }
        if [catch {set synchFreqFindDn [eval exec sddsprocess ${root}.despik \
                                        -pipe=out "-filter=col,FreqOffset,-1.1,10.0,!" \
                                        -process=Waveform,max,synchFreqFindDn,functionOf=FreqOffset,position \
                                        | sdds2stream -pipe=in -param=synchFreqFindDn ]} result] {
            SetStatus "Error: cannot find synchrotron freq for this waveform (down)"
            exec sddsplot -mod=y=log -fact=ymult=20 -offset=ychange=0.650515 \
              -titl=@TimeStamp \
              -file -subtic=xdiv=5,ydiv=5 "-ylabel=Waveform (dBm)" \
              -col=FreqOffset,Waveform ${root}.despik &
            return
        }
#        set synchFreqPrint [format %.3f $synchFreqFind]
#        if {$synchFreqFind < 0.0} {
#            set synchFreqPrint [format %.3f [expr -$synchFreqFind]]
#        }
        set synchFreqPrint [format %.3f [expr (${synchFreqFindUp} - ${synchFreqFindDn})/2.0]]

        set synchFreqAmplUp [eval exec sddsprocess ${root}.despik -pipe=out \
                             "-filter=col,FreqOffset,-10.0,1.1,!" \
                             -process=Waveform,max,synchFreqAmplUp \
                             | sdds2stream -pipe=in -param=synchFreqAmplUp ]
        set synchFreqAmplDn [eval exec sddsprocess ${root}.despik -pipe=out \
                             "-filter=col,FreqOffset,-1.1,10.0,!" \
                             -process=Waveform,max,synchFreqAmplDn \
                             | sdds2stream -pipe=in -param=synchFreqAmplDn ]
	set synchFreqAmplAvg [expr (${synchFreqAmplUp} + ${synchFreqAmplDn})/2.0]
        set ratio [format %.3f [expr 20.*log10(${synchFreqAmplAvg}/${centerFreqAmpl})]]
        set synchOscAmpl [format %.3f [expr ${synchFreqAmplAvg}/${centerFreqAmpl}/4./${centerFreqNew}*1.e6]]
        SetStatus "  synch sideband vs rf pwr = ${ratio} dB\
                       \n                synch freq = ${synchFreqPrint} kHz\
                       \n avg synch oscil amplitude = ${synchOscAmpl} psec"

        if [catch {exec sddsprocess ${root}.despik \
                     -define,param,alpha_c,${alphac} \
                     -define,param,ratioPwrSynchSideb2rf,${ratio},units=dB \
                     -define,param,synchFreq,${synchFreqPrint},units=kHz \
                     -define,param,synchFreqUp,${synchFreqFindUp},units=kHz \
                     -define,param,synchFreqDn,${synchFreqFindDn},units=kHz \
                     -define,param,synchFreqAmplUp,${synchFreqAmplUp},units=V \
                     -define,param,synchFreqAmplDn,${synchFreqAmplDn},units=V \
                     -define,param,synchOscAmpl,${synchOscAmpl},units=psec \
                     "-print=param,synchFreqString,<fsynch> = %.3f kHz,synchFreq" \
                     "-print=param,synchOscAmplString,<osc ampl> = %.3f psec,synchOscAmpl" \
                     -nowarnings} result] {
            SetStatus "Error: ${result}"
        }

        file delete ${root}.despik~

        if [catch {exec sddsplot ${root}.despik \
                     -mod=y=log -fact=ymult=20 -offset=ychange=0.650515 \
                     -titl=@TimeStamp \
                     -file -scales=0,0,-125,-25 -lspac=0.75,0.9,0,0.95 \
                     -subtic=xdiv=5,ydiv=5 "-ylabel=Waveform (dBm)" \
                     -col=FreqOffset,Waveform -grap=line \
                     -param=synchFreqUp,synchFreqAmplUp \
                     -grap=symb,subtyp=1,scale=3 \
                     -param=synchFreqDn,synchFreqAmplDn \
                     -grap=symb,subtyp=1,scale=3 \
                     -string=@synchFreqString,p=0.1,q=0.92 \
                     -string=@synchOscAmplString,p=0.05,q=0.86 \
                     -endpanel -sep=3 \
                     -col=Frequency,Waveform ${root}.sdds -grap=line=typ=0 \
                     "-legend=spec=raw" \
                     -col=Frequency,Waveform ${root}.despik -grap=line,typ=1 \
                     -string=@synchFreqString,p=0.1,q=0.92 \
                     -string=@synchOscAmplString,p=0.05,q=0.86 \
                     "-legend=spec=despiked" &} result] {

#                     -drawLine=x0val=$synchFreqFind,x1val=$synchFreqFind,y0val=-115,y1val=-45 \

            SetStatus "Error: ${result}"
        }

        SetStatus "\nVerify results with plot;\
		adjust despike/passes as required."


    } elseif [string compare ${type} rfspan]==0 {

        SetStatus "Plotting rf span & cbm wfm..."
#        if [catch {exec sddsplot -mod=y=log -fact=ymult=20 \
#                     -offset=ychange=0.650515 \
#                     -file -titl=@TimeStamp \
#                     -subtic=xdiv=5,ydiv=5 "-ylabel=Waveform (dBm)" \
#                     -col=Frequency,Waveform ${root}.sdds &} result] {
#            SetStatus "Error: ${result}"
#        }
        if [catch {exec sddsplot -file -titl=@TimeStamp \
                     -subtic=xdiv=5,ydiv=5 -split=pages -sep=nameIndex -group=nameIndex \
                     -sever=xGap=2 -grap=line,vary \
                     -col=Frequency,WaveformPower -col=cbm,WaveformPower \
                     ${root}.sdds &} result] {
            SetStatus "Error: ${result}"
        }
        
        SetStatus "Done."
        
    } elseif [string compare ${type} cbmscan]==0 {

        SetStatus "Plotting cbm scan wfms..."

        if [file exists ${root}.postp]==0 {
            if [catch {exec sddsprocess ${root}.sdds ${root}.postp \
                         "-define=col,FreqOffset,Frequency 1.e6 * CenterFreq - 1000. / ,units=kHz" \
                         "-print=param,NindexString,%ld,Nindex" \
                         "-print=param,PindexString,%ld,Pindex" \
                         "-print=param,TindexString,%ld,Tindex" \
                         -nowarnings} result] {
                SetStatus "Error: ${result};\n***check if file is a cbm-scan file."
            }
        }

        set xdiv 1
        set ydiv 1
        if [catch {exec sddsplot ${root}.postp \
                     -mode=y=log -fact=ymult=20 -offset=ychange=0.650515 \
                     -titl=@TimeStamp \
                     -scales=0,0,-120,-25 -lspace=0.7,0.95,0.7,0.95 \
                     -layout=$xdiv,$ydiv \
                     -subtick=xdiv=5,ydiv=5 "-ylabel=Waveform (dBm)" \
                     -col=FreqOffset,Waveform \
                     "-string=@NindexString,edit=i/n (cbm) = /3f,p=0.15,q=1.05" \
                     "-string=@PindexString,edit=i/p (frf) = /1f,p=0.45,q=1.05" \
                     "-string=@TindexString,edit=i/t = /1f,p=0.75,q=1.05" \
                     -legend=param=Legend \
                     -split=pages -sep &} result] {
            SetStatus "Error: ${result};\n***check if file is a cbm-scan file."
        }

        #	    -scales=-10.001,10.001,-120,-25 -lspace=0.7,0.95,0.7,0.95 \
          #	    -tag=@Nindex \
          #	    -split=parameterChange=Nindex,width=1. \
          #	    -split=parameterChange=PhotonMonXfwhm,width=0.1 \
          #	    -sep=tag -grap=line,vary &

        SetStatus "Done."

    }
}


#-------------------------------------------------------
# calculating total gap voltage from input, measured synch freq
#-------------------------------------------------------

proc calcGapVoltfsmsrd {args} {

    global ControlStatus fsmsrdkHz bktConst beamEnerVal U0

    set U0 [expr 88.5 * pow(${beamEnerVal},4) / 39.4079 / 1000]

    set gapVoltfsMV [format %.3f [expr sqrt(pow(${fsmsrdkHz},4)/${bktConst} + pow(${U0},2))]]
    SetStatus "Total gap V calculated from fs msrd: ${gapVoltfsMV} MV"

}


#-------------------------------------------------------
# calculating fs from beam Energy
#-------------------------------------------------------

proc calcfs {args} {

    global ControlStatus fsmsrdkHz bktConst gapVoltMV beamEnerVal U0

    set U0 [expr 88.5 * ${beamEnerVal} * ${beamEnerVal} * ${beamEnerVal} * ${beamEnerVal} / 39.4079 / 1000]

    set fscalckHz [format %.3f [expr pow((${bktConst} * (pow(${gapVoltMV},2) - pow(${U0},2))),0.25)]]
    SetStatus "Synchrotron frequency calcd from new beam energy: ${fscalckHz} kHz"

}


#---------------------------------------------------------
# setting today's SR directory (per ~sr/bin/today)
#---------------------------------------------------------

#   alias today 'set args=(\!*); source /home/helios/SR/bin/today'

set base /home/helios/SR/daily
set date "[eval exec date +%y%m/%d]"
set hour "[eval exec date +%H.]"

if {$hour < 8} {
    set shift "1"
} elseif {$hour < 16} {
    set shift "2"
} else {
    set shift "3"
}

set root $base/$date/$shift/


#-----------------------------------------------------------
# Setting global procedure/variables
#-----------------------------------------------------------

proc SetStatus {text} {
    global ControlStatus alphac
    set ControlStatus $text
    update
}

set noName ${root}
set rbwfsynch 10
set rbwrfspan 300000
set rbwcbmscan 30
set fsSpan 6000

if [catch {exec cavget -pend=8 \
             -list=SR:C:cavTotalGapVolt \
             -repeat=num=5,pause=1,average} result] {
    puts stderr "Error: $result"
} else {
    set gapVolt [lindex $result 0]
}

set gapVoltMV [expr ${gapVolt} / 1000.]

# U0 in twiss file is wrong: 1.393477e+00 ???
#if [catch {exec sdds2stream -param=U0 \
#	    /home/helios/oagData/sr/lattices/default/aps.twi} result] {
#    puts stderr "Error: $result"
#} else {
#    set U0 [lindex $result 0]
#}

set beamEnerVal 7.0
set U0 [expr 88.5 * pow(${beamEnerVal},4) / 39.4079 / 1000]

set secsLog 5
set hoursLog 8

set scanxyz "z"
set betatun 0.3

#set rfFreq 351927036.
#set rfFreq 351926761.

if [catch {exec cavget -pend=3 \
             -list=A014-IETS:BTC:SRSetFreqM -float=%.1f} result] {
    puts stderr "Error: $result"
} else {
    set rfFreq [lindex $result 0]
}

set rfIndex 7
set revIndex 0
set revFreq [expr ${rfFreq} / 1296.]
set pi 3.14159654

if [catch {exec sdds2stream -param=alphac \
	    $OAGGlobal(SRLatticesDirectory)/default/aps.twi} result] {
    puts stderr "Error: $result"
} else {
    set alphac [lindex $result 0]
    set bktConst [expr pow((${alphac}*1296./(2.*${pi}*7000.)),2) * pow((${revFreq}/1000.),4)]
}

if {${gapVolt} < ${U0}} {
    set fscalckHz 0.0
} else {
    set fscalckHz [format %.3f [expr pow((${bktConst} * (pow(${gapVoltMV},2) - pow(${U0},2))),0.25)]]
}

set startFreq [expr ${rfIndex} * ${rfFreq} + ${revIndex} * ${revFreq}]
set centerFreqFS [expr ${startFreq} / 1e6 ]
set centerFreqCBM 0.
set despikVal 4
set passVal 5

set rfstart 4
set nspan 1
set ncbm 1296

set StepSize 10
set Steps 1

set aveOff "aver off"
set aveOn "aver on"

set commentDoY 0
set commentDoN 0

#-----------------------------------------------------
# Build Application
#-----------------------------------------------------

makeSRfreqSynchMenuAndStatus -statusCallback SetStatus
SetStatus "Select desired measure mode through the buttons on the left\
		side. Functions appearing under each mode allow setup of the VSA,\
		acquisition of the waveform(s) and selected machine parameters, and\
		processing/plotting of the saved waveform(s). A number of user-defined\
		options appear under each selection.\n"

makeVSAdisplay -parent .userFrame
makeDatalogger -parent .userFrame
makeAcquireFrame -parent .userFrame
makeVSAControlFrameWidget .vsaControl -parent .userFrame
set vsaSwitch ""
vsaToggle sr -statusCallback SetStatus
set scan0 "time"
set scanI "std"
