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

#measure booster tunes and chromaticity, modified from SRDispChromMeas
set CVSRevisionAuthor "\$Revision: 1.9 $ \$Author: emery $"

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

#source /home/helios/EMERY/oag/apps/src/mplib/sr/HPVSATunes.tcl
#APSStandardSetup
set args $argv
set rootname ""
set outputDir ""
APSParseArguments {rootname outputDir}

set mainStatus Ready.
APSApplication . -name BoosterChromMeasurement -version "\$Revision: 1.0 $ \$Author: shang $" \
  -overview {measer boosters tunes and chromaticity}

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

if ![string length $rootname] {
    set output chrom-01
} else {
    set output $rootname
}
set extraMonFile ""
set start -1000
set stop 1000
set points 3
set pause 15
set offset 0
set review 0
set finished 0
set xChromTarget 3.5
set yChromTarget 2.0
set xChromTarget 5
set yChromTarget 0.5
#set tuneAve 50
#set tuneAVe 20
set tuneAve 10
set gain 0.25
set cycles 5
set numOfPages 100
set freqFinalValue -10000.0

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

set mainDir /home/helios/oagData/booster/dispChrom/inputFiles
set getChromatic 1
set useVSA 1
set results [exec cavget -list=Mt:BoosterRampTurnsAO,A014-IETS:BTC:BInjectionCycleM,A014-IETS:BTC:BExtractionCycleM,A014-IETS:BTC:SRSetFreqM -pend=5 -floatformat=%lf]
set srExtractionTurns [lindex $results 0]
set bInjectionCycle [lindex $results 1]
set bExtractionCycle [lindex $results 2]
set srFreq [lindex $results 3]
set rfFrequency [expr 432 * $srFreq * 3 * $srExtractionTurns / ($bExtractionCycle - $bInjectionCycle)]

set harmonic 432
set revFrequency [expr $rfFrequency / 432]
set measHarmonic 432
set sideband 1
set expectedXtune 0.742
set xFreq [format %.1f [expr $revFrequency * ($measHarmonic + $expectedXtune * $sideband)]]
set expectedYtune 0.670
set yFreq [format %.1f [expr $revFrequency * ($measHarmonic + $expectedYtune * $sideband)]]
set HPVSATracesToAve 10
set chromProcMode peakfind
set measToAve 1
set chromBadPointList ""

proc SetStatus {text} {
    global mainStatus
    set mainStatus "$text"
    update
}

proc makeLabeledEntriesAndRbFrame {widget args} {
    set parent .userFrame

    APSParseArguments {parent}

    global output outputDir start stop points 
    global pause chromBadPointList xChromTarget yChromTarget tuneAve gain

    APSFrame $widget -parent $parent -relief flat
    set w $parent$widget.frame
    if ![string length $outputDir] {
	set outputDir  [APSGoToDailyDirectory -subdirectory booChromMeas]
    }
   
    APSLabeledEntry .outputDir -parent $w \
      -label "Output directory:" \
      -textVariable outputDir \
      -contextHelp "Enter a name for the output file directory." \
      -width 55
    APSButton .daily -parent $w.outputDir -packOption "-anchor e" \
     -text "daily" -size small \
     -command {set outputDir [APSGoToDailyDirectory -subdirectory booChromCorr]}
    APSLabeledEntry .output -parent $w \
      -label "Output file:" -textVariable output \
      -contextHelp "Enter a name for the output file." \
      -width 55
    
 
   APSLabeledEntry .stop -parent $w \
     -label "Total RF frequency change (Hz):" -textVariable freqFinalValue \
      -contextHelp "Enter a value to stop at." \
      -width 10
    APSLabeledEntry .cycles -parent $w \
	-label "Cycles:" -textVariable cycles -width 10 \
	-contextHelp "Number of cycles for experiment (interleaving)"

    APSLabeledEntry .points -parent $w \
      -label "Points:" -textVariable points \
      -contextHelp "Enter the number of points to use." \
      -width 10
    APSLabeledEntry .measToAve -parent $w -width 10 \
      -label "Measurements to average: " \
      -textVariable measToAve \
      -contextHelp "Enter the number of measurements \
                                             of the PVs to average. Sample \
                                             interval is 0.5s."
    APSLabeledEntry .tuneAve -parent $w -width 10 \
      -label "Tune waveform average: " -textVariable tuneAve \
      -contextHelp "Enter the number of tune waveform average."
    APSLabeledEntry .pauseNASA -parent $w \
      -label "Pause (s):" -textVariable pause \
      -contextHelp "Enter the number of seconds to wait for the NA/SA" \
      -width 10
    
   

    global tuneFilter tuneLimit tuneNeighbor
    set tuneFitler 0
    set tuneLimit 0.005
    set tuneNeighbor 3
    
    APSLabeledEntryFrame .tune -parent $w -variableList {tuneLimit tuneNeighbor} \
      -orientation horizontal -width 15 \
      -label "Tune process filter, outleir absStd limit/neighbor:" \
      -contextHelp "filter noice for tune waveform with sddsoutlier absDev"
    #APSCheckButton .check -parent $w.tune -packOption "-side right" -variableList tuneFilter -label ""
    checkbutton  $w.tune.frame.check -variable tuneFilter -text ""
    pack $w.tune.frame.check -side right
    
    APSLabeledEntry .nump -parent $w -label "Number of pages to be processed:" -textVariable numOfPages -width 25
}

proc ScanClockPhase {args} {
    global clockPhase diagresponse acqDelay P0select clockShifts 
    ### switch to sum for scanning and set the extra delay to 200 ms.--CY
  
    SwitchInput S
    if [catch {exec cavput -list=B:tune:boosterInjTriggerEV.OUT -list=0,3,9 -list==0 -pend=10} result] {
        return -code error "Unable to disable booster triggers: $result"
    }
    if [catch {exec cavput -list=B:tune:storageInjTriggerEV.OUT -list=0,3,9 -list==1 -pend=10 } result] {
        return -code error "Unable to enable sr triggers: $result"
    }
    
    SetStatus "Start clock phase scan..."
    if [catch {exec cavput -list=B:tune:adc:gtr:numberPTE=200 -pend=20} result] {
        return -code error "Unable to start clock scan2: $result"
    }
    if [catch {exec  cavput -list=B:tune:ClockScanStartBO=1 -pend=20} result] {
        return -code error "Unable to start clock scan2: $result"
    }
    ### add 20 seconds waiting for the scanning to completed. 
    SetStatus "Wait for 20 seconds...."
    APSWaitWithUpdate -waitSeconds 20 -updateInterval 1
    if [catch {exec cavput -list=B:tune:boosterInjTriggerEV.OUT -list=0,3,9 -list==1 -pend=10} result] {
        return -code error "Unable to disable booster triggers: $result"
    }
    if [catch {exec cavput -list=B:tune:storageInjTriggerEV.OUT -list=0,3,9 -list==0 -pend=10 } result] {
        return -code error "Unable to enable sr triggers: $result"
    }
    SetStatus "done."

}
   
proc Review {args} {
    global outputDir
    cd $outputDir
    foreach plane {x y} {
        set files [glob -nocomplain *-$plane.chrom]
        if ![llength $files] {
            SetStatus "no files found for $plane plane."
        } else {
            catch {exec rm ${plane}chrom.png ${plane}chrom.eps}
            eval exec sddsplot3 ${plane}chrom \"-topline=$plane plane chromaticity"  -col=time,chrom -gra=sym,vary=sub,conn,scale=2,thick=2 $files -leg=file,edit=%/-${plane}.chrom// &
        }
    }
}

proc makeButtonRow {widget args} {

    global order
    global widgetPlottingButton
    
    set parent .userFrame
    set order 1

    APSParseArguments {parent}

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

    APSFrame .w2 -parent $parent -relief flat
    set w2 $parent.w2.frame
    
   
    APSButton .doExperiment -parent $w -text "DO \nEXPERIMENT" \
      -command doExperiment \
      -packOption "-side left" 
     
    APSButton .chromProcessing -parent $w -text "CHROMATIC \nPROCESSING" \
      -command PostProcessChrom \
      -packOption "-side left"
    
    
    APSButton .scan -parent $w -text "Scan Clock\n Phase" \
      -command "ScanClockPhase"
    
    APSButton .strip -parent $w2 -text "SD/SF Ramp\nStripTool" \
        -command "exec StripTool /home/helios/BOOSTER/StripToolConfig/BoosterXYChromMonConfig &" 
   
    APSButton .review -parent $w -text "Review" -command "Review"
    
   
    APSButton .inj1 -parent $w2 -text "Booster InjTune Controllaw Info" -command "exec medm -x -attach -macro RCPV=B:InjTune:ControllawRC ./sr/psApp/APSRunControlSingle.adl & "
    APSButton .inj2 -parent $w2 -text "Booster InjLong Controllaw Info" -command "exec medm -x -attach -macro RCPV=Booster:ControlLawLongRC ./sr/psApp/APSRunControlSingle.adl & "
}

set Xxdrive 134
set Xydrive 154
set Yxdrive 134
set Yydrive 0
set SUMxdrive 120
set SUMydrive 20
proc TurnOnOffTuneDrive {args} {
    set onoff ""
    set xdrive ""
    set ydrive ""
    APSParseArguments {onoff xdrive ydrive}
    global Xxdrive Xydrive Yxdrive Yydrive SUMxdrive SUMydrive
    SetStatus "turn $onoff tune drive ..." 
    if {(![string length $xdrive] || ![string length $ydrive]) && $onoff=="on"} {
        if [catch {exec cavget -list=B:TUNE:HP_1366A_P0_MBBO -pend=20} plane] {
            return -code error "Error turning on booster tune drive1: $plane"
        }
        if {$plane=="OFF" || $plane=="SPARE"} {
            SetStatus "drive is not being turned on.\nPlease select a plane X/Y/S on booster tune measurement multiplexer first before turn it on."
            return
        }
        set xdrive [set ${plane}xdrive]
        set ydrive [set ${plane}ydrive]
    }
    set onPVList [list B:DG1:aDelaySetAO=4.5e-7 \
                    B:DG1:bDelaySetAO=2.0e-6 \
                    B:DG1:cDelaySetAO=7.0e-7 \
                    B:DG1:dDelaySetAO=2.0e-6 \
                    B:DG1:trigModeSetMO=1 \
                    B:DG1:aOutputModeSetMO=0 \
                    B:DG1:cOutputModeSetMO=0 \
                    B:DG1:aOutputZSetBO=0 \
                    B:DG1:cOutputZSetBO=0 \
                    B:DG1:aOutputAmpSetAO=1 \
                    B:DG1:cOutputAmpSetAO=1 \
                    B:DG1:aOutputOffsetSetAO=0.0 \
                    B:DG1:cOutputOffsetSetAO=0.0 \
                    B:DG1:trigInputAmpSetAO=1.0 \
                    BOOTUNE:XAXIS:MATRE200SetVoltage=$xdrive \
                    BOOTUNE:YAXIS:MATRE200SetVoltage=$ydrive ]
    if {$onoff=="on"} {
        if [catch {exec cavput -pend=30 -list=[join $onPVList ,] } result] {
            return -code error "Error turning on booster tune drive: $result"
        }
    } else {
        if [catch {exec cavput -pend=30 \
                     -list=BOOTUNE:XAXIS:MATRE200SetVoltage=0,BOOTUNE:YAXIS:MATRE200SetVoltage=0 } result] {
            return -code error "Error turning off booster tune drive: $result"
        }
    }
    after 2000
    SetStatus "done."
}

proc LoadSafety {args} {
    SetStatus "load SF and SD safety ramp..."
    if [catch {APSBoosterLoadSDUSafetyRamp -magnet SD-U} result] {
        return -code error "Error loading safety ramp for SD-U: $result"
    }
    if [catch {APSBoosterLoadSDUSafetyRamp -magnet SF-U} result] {
        return -code error "Error loading safety ramp for SF-U: $result"
    }
    SetStatus "done."
}

proc SwitchInput {args} {
    global Xxdrive Xydrive Yxdrive Yydrive Sxdrive Sydrive 
    set plane ""
    APSParseArguments {plane}
    
    SetStatus "Switching to $plane ..."
    global inputChannel
  
    set plane [string toupper $plane]
   
    set inputChannel $plane
    switch $plane {
        S {
            set plane SUM
            set xdrive 0
            set ydrive 0
            set onoff off
            
        }
        X {
            set xdrive $Xxdrive
            set ydrive $Xydrive
            set onoff on
        }
        Y {
            set xdrive $Yxdrive
            set ydrive $Yydrive
            set onoff on
        }
        default {
            set xdrive 0
            set ydrive 0
            set onoff off
        }
    }
    if [catch { TurnOnOffTuneDrive -xdrive $xdrive -ydrive $ydrive -onoff $onoff} result] {
        SetStatus "Error in turnOnOffTuneDrive: $result"
        return
    }
    if [catch {exec cavput -list=B:TUNE:HP_1366A_P0_MBBO=$plane,BOOTUNE:XAXIS:MATRE200SetVoltage=$xdrive,BOOTUNE:YAXIS:MATRE200SetVoltage=$ydrive } result] {
        SetStatus "Unable to switch to $plane plane: $result"
        return
    }
    if [catch {exec cavput -list=BOOTUNE:XAXIS:MATRE200SW=1,BOOTUNE:YAXIS:MATRE200SW=1 -pend=20} result] {
        SetStatus "Unable to set  BOOTUNE:XAXIS:MATRE200SW  and BOOTUNE:YAXIS:MATRE200SW to 1: $result"
        return
    }
    #load tune parameters
    if {$plane!="S"} {
	if [catch {exec sddscasr -restore \
		       /home/helios/oagData/booster/tuneArchive/inputFiles/tuneconfig.[string tolower $plane] -pend=30} result] {
	    SetStatus "Error in loading tune parameters for $plane plane: $result"
	    return 
	}
    }
    after 2000
    SetStatus "done"
}

set longConntrollaw 1
proc CheckControllaw {args} {
    global longControllaw
    #all other booster controllaw should be off
    SetStatus "check booster controllaws..."
    if [catch {exec cavget -list=B: -list=BM,QF,QD,SF,SD -list=bcontrollawRC.RUN -pend=10 -printError} runList] {
	return -code error "Error reading bcontrols: $runList"
    }
    foreach magnet {BM QF QD SF SD} running $runList {
	set ${magnet}bcontrol $running
    }
    if {!$BMbcontrol || !$QFbcontrol || !$QDbcontrol || !$SFbcontrol || !$SDbcontrol} {
	return -code error "Please check BM/QF/QD bcontrollaw and make sure they are running before start optimizer."
    }
    
    if [catch {exec cavget -list=B: -list=BM,QF,QD -list=:AutoCorrectionControlRC.RUN -pend=10 -printError } runList] {
	return -code error "Error reading booster ramp autocorrection: $runList"
    }
    set error 0
    set magList ""
    foreach mag {BM QF QD} running $runList {
	if !$running {
	    set error 1
	    lappend magList $mag
	}
    }
    if $error {
	return -code error "[join $magList ,] auto-ramp correction not running, please start them before start optimizer"
    }
    #check logitudial controllaw, suspend other booster controllaw
    if [catch {exec cavget -list=Booster:ControlLawLongRC.RUN -pend=10 -printErrors} running] {
	return -code error "Error reading booster longitudial controllaw: $running"
    }
    
    if !$running {	
	return -code error "Please start booster longitudial controllaw before start optimizer"
    }
    
    #suspend other booster controllaws
    if [catch {exec cavget -list=Booster:ControlLawXRC,Booster:ControlLawYRC,B:InjTune:ControllawRC -list=.RUN -pend=10 -printError} runList] {
	return -code error "Error reading booster x/y controllaw and injection tune controllaw: $runList"
    }
    foreach pv {Booster:ControlLawXRC Booster:ControlLawYRC B:InjTune:ControllawRC} running $runList {
	if $running {
	    SetStatus "suspending $pv controllaw..."
	    if [catch {exec cavput -list=$pv.SUSP=1 -pend=10} result] {
		return -code error "Error suspend $pv controllaw: $result"
	    }
	}
    }
    SetStatus "done"
}


proc doExperiment {} {
    global output outputDir start stop points offset review getChromatic cancel mainDir cycles
    global HPVSATracesToAve pause measToAve  mainDir tuneAve gain freqFinalValue
    set cancel 0
    
    if [catch {exec sddscasr -save /home/helios/oagData/par/dispChrom/inputFiles/freqRampInjTimingPVList $outputDir/RFfreq.ref } result] {
	return -code error "Error reading RF freq reference: $result"
    }
    
    #check if it user operation, do not do it during user operation
    if [catch {exec cavget -list=S:DesiredMode -num -pend=10} srMode] {
        return -code error "Error reading SR mode: $srMode"
    }
    if {$srMode==1 || $srMode==2} {
        bell
        SetStatus "Chaning RF frequency is not allowed during user operation!"
        return
    }
    
    checkIfFilesExist
    if $cancel {return}
    
    
    cd $outputDir
    SetStatus "Acquiring data." 
    
    set expFile ${output}.exp
    set template $mainDir/BoosterChromCorrTemplate.exp
    if $pause<0 {
        set pause 2
    }
    global  apsSRDispChromExpDone
    
    if [catch {CheckControllaw} result] {
	return -code error "Error checking controllaw: $result"
    }
    foreach plane {x y} {
       
       # SetStatus "switching to $plane plane ..."
        
        set rootname ${output}-$plane
        if [file exist $rootname] {
            if ![APSYesNoPopUp "$rootname already exist, overwrite it?"] {
                continue
            }
            set files [glob ${rootname}*]
            eval file delete -force $files
        }
        if [catch {SwitchInput -plane $plane} result] {
            return -code error "Error switching plane: $result"
        }
        if ![APSYesNoPopUp "Measure $plane chromaticity now?"] {
            continue
        }
	#total frequency change is -10000.0, steps=points-1
	set deltaFreq [expr $freqFinalValue/(($points-1.0)*1.0)]
	exec replace $template $expFile \
	    -orig=<outputDir>,<limit1>,<limit2>,<points>,<mainFile>,<pause>,<measToAve>,<waveAve>,<cycles>,<outputDIr>,<final_value> \
	    -repl=$outputDir,$start,$stop,$points,$rootname,$pause,$measToAve,$tuneAve,$cycles,$outputDir,$freqFinalValue
        # do experiment
        set apsSRDispChromExpDone 0
        #turn on booster extraction kicker
        if [catch {TogglePulsedMagnetEnables -location GuntoBoosterExt} result] {
            return -code error "Error turn on booster extraction: $result"
        }
        APSExecLog .expExec -name "Experiment log" \
          -cancelCallback "set  apsSRDispChromExpDone aborted" \
          -abortCallback "set  apsSRDispChromExpDone aborted" \
          -unixCommand "sddsexperiment $expFile $rootname -verbose" \
          -callback "set apsSRDispChromExpDone done;ProcessChrom -datafile $rootname"  -width 80
        tkwait variable apsSRDispChromExpDone
	exec parTimingFeedforward -outputDir $outputDir
        if {$apsSRDispChromExpDone=="aborted"} {
	    
            SetStatus "$plane chromaticity measurement was aborted."
        }
    }
    
    SetStatus "resuming booster injection longitudial and tune controllaw..."
    if [catch {exec cavput -list=B:InjTune:ControllawRC,Booster:ControlLawLongRC -list=.SUSP=0 -pend=30} result] {
        return -code error "Error suspending booster injection tune controllaw: $result"
    }
    APSInfoWindow .info1 -modal 1 -name "Restore PAR timing" -infoMessage "Experiment done, Please restore PAR timing from SCR."	
    SetStatus "experiment done."
}

proc PostProcessChrom {args} {
    global output outputDir gain
    set oldDir [pwd]
    cd $outputDir
    set xdone 0
    set ydone 0
    foreach plane {x y} {
        set file ${output}-$plane
        if [file exist $file] {
            SetStatus "Processing chromaticity for $file..."
            if [catch {ProcessChrom -datafile $file} result] {
                SetStatus "error processing $file: $result"
                return
            }
            SetStatus "done."
            set ${plane}done 1
        } else {
            SetStatus "$file does not exist, no data for $plane to process"
        }
    }
    
}

set xChromTarget 3.5
set yChromTarget 0.5
set gain 0.25
proc ProcessChrom {args} {
    global output outputDir start stop points offset review xChromTarget yChromTarget gain
    global tuneFilter tuneLimit tuneNeighbor numOfPages
    set datafile ""
    APSParseArguments {datafile}
    set oldDir [pwd]
    cd $outputDir
   
    set alpha 7.144e-3 
    set alpha 0.009702
    set tuneTimeOffset 13.33 
    set tuneStart 5
    set tuneEnd 126
    set numToAve 5
    
    SetStatus "Performing chromatic processing for $output."
    
    if [regexp "x" $datafile] {
        set plane x
    } elseif [regexp "y" $datafile] {
        set plane y
    } else {
        return -code error "Invalid datafile provided."
    }
    set target [set ${plane}ChromTarget]
    set files [glob -nocomplain ${datafile}Tunes-???]
    if ![llength $files] {
        SetStatus "No tunes files for $datafile found."
        return
    }
    set files [lsort $files]
    set rfFreqList [exec sdds2stream -col=rfFrequency $datafile]
    set tmpRoot /tmp/[APSTmpString]
    set step 0
    set fileList ""
    set steps [llength $files]
    if [catch {exec sddsconvert $datafile -keeppage=1 -pipe=out \
		   | sddsprocess -pipe -redefine=col,Step,i_row,type=long  \
		   | sddspfit -pipe -col=Step,rfFrequency \
		   | sdds2stream -pipe=in -par=Slope } slop] {
        return -code error "Error getting freq step ratio: $slop"
    }
    set freqStepRatio [expr $slop / 1000.0]
    if [catch {exec sddsconvert $datafile -pipe=out -keeppage=1 \
		   | sddsprocess -pipe -process=rfFrequency,ave,rfFreq  \
                 | sdds2stream -pipe=in -par=rfFreq } rfFreq] {
        return -code error "Error getting the rf frequency average: $rfFreq"
    }
    set rfFreq [expr $rfFreq / 1000.0]
    set fileList ""
    foreach file $files {
        if $tuneFilter {
            #remove noices in tune waveform
            if [catch {exec sddsprocess $file -pipe=out -filter=par,B:diag1:rms:A:region4,0.5,5 -nowarn \
			   | sddsconvert -pipe -frompage=1 -topage=$numOfPages \
			   |  sddsoutlier -pipe -col=B:tune:peak:gtr:waveform1 \
			   -absDev=$tuneLimit,n=$tuneNeighbor -replace=interp \
			   | tee $file.proc \
			   | sddsenvelope -pipe -mean=B:tune:peak:gtr:waveform1 -copy=Index \
			   -standardDeviation=B:tune:peak:gtr:waveform1 \
			   | sddsprocess -pipe \
			   -redefine=col,tuneMean,B:tune:peak:gtr:waveform1Mean \
			   -redefine=col,tuneStDev,B:tune:peak:gtr:waveform1StDev  \
			   | tee $file.env \
			   | sddsbreak -pipe  -rowlimits=$numToAve \
			   | sddsprocess -process=tuneMean,average,%s \
			   -process=tuneMean,StandardDeviation,tuneStDev -pipe \
			   -process=Index,first,%s \
			   | sddscollapse -pipe=in $file.env.coll } result] {
                return -code error "ChromProcess1: $result"
            }
        } else {
            if [catch {exec sddsprocess $file -pipe=out -filter=par,B:diag1:rms:A:region4,0.5,5 -nowarn \
			   | sddsconvert -pipe -frompage=1 -topage=$numOfPages \
			   | sddsenvelope -pipe -mean=B:tune:peak:gtr:waveform1 -copy=Index \
			   -standardDeviation=B:tune:peak:gtr:waveform1 \
			   | sddsprocess -pipe \
			   -redefine=col,tuneMean,B:tune:peak:gtr:waveform1Mean \
			   -redefine=col,tuneStDev,B:tune:peak:gtr:waveform1StDev  \
			   | tee $file.env \
			   | sddsbreak -pipe  -rowlimits=$numToAve \
			   | sddsprocess -process=tuneMean,average,%s \
			   -process=tuneMean,StandardDeviation,tuneStDev -pipe \
			   -process=Index,first,%s \
			   | sddscollapse -pipe=in $file.env.coll } result] {
                return -code error "ChromProcess1: $result"
            }
        }
        lappend fileList $file.env.coll
    }
    if [catch {eval exec sddscombine $fileList -pipe=out \
                 | sddsprocess -pipe \"-redefine=par,Step,i_page 1 -\" \
                 | sddsenvelope -slope=Step,tuneMean \
                 -standardDeviation=tuneStDev \
                 -copy=Index \
                 -pipe \
                 | sddsprocess \
                 "-filter=col,Index,$tuneStart,$tuneEnd" \
                 \"-redefine=col,chrom,tuneMeanSlope $alpha * $rfFreq * $freqStepRatio / \" \
                 \"-redefine=para,freqStepRatio,$freqStepRatio\" \
                 \"-redefine=para,alpha,$alpha\" \
                 \"-redefine=para,timePerPoint,1.8,units=ms\" \
                 \"-redefine=col,time,Index 5 - 1.8 *,units=ms\" \
                 \"-redefine=col,chromStdev,tuneStDevStDev $alpha * $rfFreq * $freqStepRatio /\" \
                 -pipe \
                 | tee $datafile.chrom \
                 | sddsenvelope -pipe -mean=chrom -copy=time,Index \
                 | sddsprocess -pipe -redefine=col,target,$target \
                 | sddsprocess -pipe=in $datafile.chromError \
                 \"-redefine=col,ChangeInChrom,chromMean target -\" } result] {
        return -code error "Error processing chromaticity: $result"
    }
    exec sddsplot -col=Index,chrom $datafile.chrom -grap=symbol,sub=2,connect=2,scale=2,fill \
      -filter=col,Index,0,115 \
      -factor=xMultiplier=1.80 \
      -xLabel=time\(ms\) "-topline=$plane plane chromaticity" &
    
    cd $oldDir
    SetStatus Done.
}


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

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

proc RestoreSafetyRamp {args} {
    global SFsafety SDsafety
    
    set rampDir /home/helios/oagData/booster/ramps/IRamp/safety     
    set oldDir [pwd]
    cd $rampDir
    exec rm SF-UIref.afg100
    exec ln -s $SFsafety SF-UIref.afg100
    exec rm SD-UIref.afg100
    exec ln -s $SDsafety SD-UIref.afg100
    cd $oldDir
    SetStatus "SF safety was restored to $SFsafety"
    SetStatus "SD safety was restored to $SDsafety"
}

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