
#!/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

set args $argv
set rootname ""
set outputDir ""
APSParseArguments {rootname outputDir}

set mainStatus Ready.
APSApplication . -name BoosterDispMeasurement -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 disp-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 numToAve 10
set interval 1
set cycles 1
set numOfPages 100
set freqFinalValue -10000.0
set longControllaw 1

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

set mainDir /home/helios/oagData/booster/dispChrom/inputFiles

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 measToAve interval

    APSFrame $widget -parent $parent -relief flat
    set w $parent$widget.frame
    if ![string length $outputDir] {
	set outputDir  [APSGoToDailyDirectory -subdirectory booDispMeas]
    }
   
    set width 30
    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 $width
    APSLabeledEntry .cycles -parent $w \
	-label "Cycles:" -textVariable cycles -width $width \
	-contextHelp "Number of cycles for experiment (interleaving)"

    APSLabeledEntry .points -parent $w \
      -label "Points:" -textVariable points \
      -contextHelp "Enter the number of points to use." \
      -width $width
    APSLabeledEntry .measToAve -parent $w -width $width \
      -label "Measurements to average: " \
      -textVariable numToAve \
      -contextHelp "Enter the number of measurements \
                                             of the PVs to average. Sample \
                                             interval is 0.5s."
    
    APSLabeledEntry .interval -parent $w -width $width \
	-label "Interval (s) between readings:" -textVariable interval \
	-contextHelp "enter the waiting time between two reading."
    
    APSLabeledEntry .pauseNASA -parent $w \
      -label "Pause (s):" -textVariable pause \
      -contextHelp "Enter the number of seconds to wait for the NA/SA" \
      -width $width
    
    global longControllaw
    APSRadioButtonFrame .contr -parent $w -variable longControllaw -label "Turn on/off longitudial controllaw during experiment?" \
	-orientation horizontal -buttonList  {On Off} -valueList {1 0}
  
   # APSLabeledEntry .nump -parent $w -label "Number of pages to be processed:" -textVariable numOfPages -width $width \
\#	-contextHelp "
}


   
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

   
    APSButton .doExperiment -parent $w -text "DO \nEXPERIMENT" \
      -command doExperiment \
      -packOption "-side left" 
     
    APSButton .chromProcessing -parent $w -text "DISPERSION \nPROCESSING" \
      -command ProcessDisp \
      -packOption "-side left"
    
    	
    APSButton .review -parent $w -text "Review" -command "PlotDisp"
    APSButton .check -parent $w -text "Check Controllaw" -command CheckControllaw
    APSButton .switch -parent $w -text "Switch Booster BPM to Average Mode" -command "SwitchBoosterBPM"
    
}

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/SF/SD 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 $longControllaw {
	if !$running {
	    return -code error "Please start booster longitudial controllaw before start optimizer"
	}
    } else {
	if $running {
	    if [catch {exec cavput -list=Booster:ControlLawLongRC.SUSP=1 -pend=10} result] {
		return -code error "Error suspending longituadial controllaw: $result"
	    }
	}
    }
    #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 SwitchBoosterBPM {args} {
    SetStatus "switch booster BPM to average mode."
    if [catch { APSMpBoosterSwitchBPMConfig -bpmSelection AverageBPM } result] {
	return -code error "Error switching booster bpm to average mode: $result"
    }
    SetStatus "done."
}

proc doExperiment {} {
    global output outputDir start stop points offset review getChromatic cancel mainDir cycles
    global numToAve interval  mainDir freqFinalValue pause
    set cancel 0
    
    APSInfoWindow .info -modal 1 -name "Booster Disp Meas" -infoMessage "Please dump SR stored beam,\n turn off SR rf system\n and obtain rf source frequency change permission from SCR.\nSwitch booster BPM to average mode"
    
    if ![file exist $outputDir/RFfreq.ref] {
	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"
	}
    }
    set template $mainDir/BoosterDispTemplate.exp
    if $pause<0 {
        set pause 2
    }
    checkIfFilesExist
    if $cancel {return}
    set expFile ${output}.exp
    exec replace $template $expFile \
	-orig=<outputDir>,<points>,<pause>,<numToAve>,<interval>,<cycles>,<outputDIr>,<final_value> \
	-repl=$outputDir,$points,$pause,$numToAve,$interval,$cycles,$outputDir,$freqFinalValue
    
    
    #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
    }
    
   
    if [catch {CheckControllaw} result] {
	SetStatus "$result"
	return
    }
    
   
    cd $outputDir
    SetStatus "Acquiring data." 
    
    set expFile ${output}.exp
    
    #total frequency change is -10000.0, steps=points-1
    
    set apsBooDispExpDone 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  apsBooDispExpDone aborted" \
	-abortCallback "set apsBooDispExpDone aborted" \
	-unixCommand "sddsexperiment $expFile $outputDir/$output -verbose" \
	-callback "set apsSRDispChromExpDone done"  -width 80
    tkwait variable apsBooDispExpDone
    exec parTimingFeedforward -outputDir $outputDir
    if {$apsSRDispChromExpDone=="aborted"} {
	SetStatus "$plane chromaticity measurement was aborted."
    }
    if [catch {exec sddsprocess $outputDir/$output -redefine=col,Step,i_row,type=long -nowarn } result] {
	return -code error "Error define Step for output file: $result"
    }
    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 ProcessDisp {args} {
    global outputDir output
    cd $outputDir
    
    if ![file exist $output] {
	SetStatus "$output does not exist!"
	return
    }
    SetStatus "processing dispersion for $output..."
    set alpha  9.705275e-03
    set cols [join [exec sddsquery -col $output]]
    if [lsearch -exact $cols "RfFreqReadback"]>=0 {
	set freqCol RfFreqReadback
    }  else {
	set freqCol BRF:S:Hp8657RefFreqAO
    }
    if [catch {exec sddsenvelope $output -pipe=out \
		   -mean=*ErrorCC -copy=$freqCol \
		   | sddsconvert -pipe -edit=col,*,%/Mean// \
		   | tee $output.orbit.proc \
		   | sddsprocess -pipe -redefine=col,Step,i_row,type=long \
		   | sddsprocess -pipe -process=*region*ErrorCC,slope,%sSlope,functionOf=Step \
		   -process=$freqCol,first,RFFreq0 \
		   -process=$freqCol,last,RFFreq1 \
		   "-define=par,FreqStep,RFFreq0 RFFreq1 - n_rows 1 - /" \
		   | tee $output.orbit.proc1 \
		   | sddscollapse -pipe \
		   | tee ttt1 \
		   | sddscollect -pipe=in $output.orbit.proc2 \
		   -collect=suffix=:region0:x:ErrorCCSlope,column=Region0x \
		   -collect=suffix=:region0:y:ErrorCCSlope,column=Region0y \
		   -collect=suffix=:region1:x:ErrorCCSlope,column=Region1x \
		   -collect=suffix=:region1:y:ErrorCCSlope,column=Region1y \
		   -collect=suffix=:region2:x:ErrorCCSlope,column=Region2x \
		   -collect=suffix=:region2:y:ErrorCCSlope,column=Region2y \
		   -collect=suffix=:region3:x:ErrorCCSlope,column=Region3x \
		   -collect=suffix=:region3:y:ErrorCCSlope,column=Region3y \
		   -collect=suffix=:region4:x:ErrorCCSlope,column=Region4x \
		   -collect=suffix=:region4:y:ErrorCCSlope,column=Region4y \
		   -collect=suffix=:region5:x:ErrorCCSlope,column=Region5x \
		   -collect=suffix=:region5:y:ErrorCCSlope,column=Region5y \
		   -collect=suffix=:region6:x:ErrorCCSlope,column=Region6x \
		   -collect=suffix=:region6:y:ErrorCCSlope,column=Region6y \
		   -collect=suffix=:region7:x:ErrorCCSlope,column=Region7x \
		   -collect=suffix=:region7:y:ErrorCCSlope,column=Region7y \
		   -collect=suffix=:region8:x:ErrorCCSlope,column=Region8x \
		   -collect=suffix=:region8:y:ErrorCCSlope,column=Region8y \
		   -collect=suffix=:region9:x:ErrorCCSlope,column=Region9x \
		   -collect=suffix=:region9:y:ErrorCCSlope,column=Region9y } result] {
	return -code error "Error process disp1: $result"
    }
    if [catch {exec sddsxref $output.orbit.proc2 $output.orbit.proc1 -leave=* -transfer=par,FreqStep,RFFreq0 -pipe=out \
		   | sddsprocess -pipe \
		   "-define=col,Region0xDispersion,Region0x $alpha *  RFFreq0 * FreqStep /,units=mm" \
		   "-define=col,Region0yDispersion,Region0y $alpha *  RFFreq0 * FreqStep /,units=mm" \
		   "-define=col,Region1xDispersion,Region1x $alpha *  RFFreq0 * FreqStep /,units=mm" \
		   "-define=col,Region1yDispersion,Region1y $alpha *  RFFreq0 * FreqStep /,units=mm" \
		   "-define=col,Region2xDispersion,Region2x $alpha *  RFFreq0 * FreqStep /,units=mm" \
		   "-define=col,Region2yDispersion,Region2y $alpha *  RFFreq0 * FreqStep /,units=mm" \
		   "-define=col,Region3xDispersion,Region3x $alpha *  RFFreq0 * FreqStep /,units=mm" \
		   "-define=col,Region3yDispersion,Region3y $alpha *  RFFreq0 * FreqStep /,units=mm" \
		   "-define=col,Region4xDispersion,Region4x $alpha *  RFFreq0 * FreqStep /,units=mm" \
		   "-define=col,Region4yDispersion,Region4y $alpha *  RFFreq0 * FreqStep /,units=mm" \
		   "-define=col,Region5xDispersion,Region5x $alpha *  RFFreq0 * FreqStep /,units=mm" \
		   "-define=col,Region5yDispersion,Region5y $alpha *  RFFreq0 * FreqStep /,units=mm" \
		   "-define=col,Region6xDispersion,Region6x $alpha *  RFFreq0 * FreqStep /,units=mm" \
		   "-define=col,Region6yDispersion,Region6y $alpha *  RFFreq0 * FreqStep /,units=mm" \
		   "-define=col,Region7xDispersion,Region7x $alpha *  RFFreq0 * FreqStep /,units=mm" \
		   "-define=col,Region7yDispersion,Region7y $alpha *  RFFreq0 * FreqStep /,units=mm" \
		   "-define=col,Region8xDispersion,Region8x $alpha *  RFFreq0 * FreqStep /,units=mm" \
		   "-define=col,Region8yDispersion,Region8y $alpha *  RFFreq0 * FreqStep /,units=mm" \
		   "-define=col,Region9xDispersion,Region9x $alpha *  RFFreq0 * FreqStep /,units=mm" \
		   "-define=col,Region9yDispersion,Region9y $alpha *  RFFreq0 * FreqStep /,units=mm" \
		   | sddsconvert -pipe=in -rename=col,Rootname=BPMName $output.dispersion } result] {
	return -code error "Error process disp2: $result"
    }
    SetStatus "done."
    PlotDisp
}

proc PlotDisp {args} {
    global outputDir output
    cd $outputDir
    if ![file exist $output] {
	SetStatus "$output does not exit!"
	return
    }
    if ![file exist $output.dispersion] {
	if [catch {ProcessDisp} result] {
	    SetStatus "$result"
	    return
	}
    }
    exec sddsplot $output.dispersion  -grap=li,vary -sep=2 \
	-legend=yname,edit=%/Region//%/Dispersion//%/0//%/1//%/2//%/3//%/4//%/5//%/6//%/7//%/8//%/9// \
        -col=BPMName,Region0xDispersion -col=BPMName,Region0yDispersion -topline=Region0  \
	-col=BPMName,Region1xDispersion -col=BPMName,Region1yDispersion -topline=Region1   \
	-col=BPMName,Region2xDispersion -col=BPMName,Region2yDispersion -topline=Region2  \
	-col=BPMName,Region3xDispersion -col=BPMName,Region3yDispersion -topline=Region3 \
	-col=BPMName,Region4xDispersion -col=BPMName,Region4yDispersion -topline=Region4  \
	-col=BPMName,Region5xDispersion -col=BPMName,Region5yDispersion -topline=Region5 \
	-col=BPMName,Region6xDispersion -col=BPMName,Region6yDispersion -topline=Region6  \
	-col=BPMName,Region7xDispersion -col=BPMName,Region7yDispersion -topline=Region7  \
	-col=BPMName,Region8xDispersion -col=BPMName,Region8yDispersion -topline=Region8 \
	-col=BPMName,Region9xDispersion -col=BPMName,Region9yDispersion -topline=Region9   &
}


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."
}


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