#!/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 CVSRevisionAuthor "\$Revision: 1.0 $ \$Author: shang $"


APSApplication . -name optimizeBTSEfficiency -version $CVSRevisionAuthor \
  -overview {Adjust steering setpoints in LTP and rf phase in linac to optimize PAR efficiency.}

set status "Don't use script during top-up!"
APSScrolledStatus .status -parent .userFrame \
  -textVariable status -width 50

set softPVexist 0
proc StartSoftPVs {args} {
    global mainDir softPVexist
    if $softPVexist {
	return
    }
    set softPVexist 1
    if [catch {exec caget SFoffset} result] {
	set softPVexist 0
    }
    if [regexp "Invalid channel name" $result] {
	set softPVexist 0
    }
    if !$softPVexist {
	SetStatus "start soft pvs..."
	exec sddspcas -standalone $mainDir/softPVs.sdds &
	set softPVexist 1
    }
}

proc APSRunBTSEfficiencyOptimizer {args} {
    set plot 0
    set save 0
    set restore 0
    set test 0
    set averages 30
    set postChangePause 6.0
    set statusCallback APSNoOp
    set stepSizeMultiplier 1.0
    APSStrictParseArguments {plot save restore statusCallback test stepSizeMultiplier averages postChangePause}
    
    global tolerance evaluations method simplex1d rcdsNoise rcdsStepSize rcdsDebugger rcdsUseMinimum cycles outDir inputConfig resumeList
    global rootname logFile mainDir useInjTune

    OptimizerParameter -edit 0
    
    if {$inputConfig=="SFSDoffset"} {
	StartSoftPVs
    }
    if $test {
        set tmpFile /tmp/[APSTmpString]
        if [catch {exec sddssnapshot $outDir/BTSOpt.tests -pipe=out \
		       | sddsprocess -pipe \
		       "-def=col,InBounds,MinimumValue Value < pop pop ? Value MaximumValue < pop pop ? 1 : 0 $ : 0 $,type=long" \
		       | sddsprocess -pipe=in -nowarnings -filter=col,InBounds,0,0 $tmpFile } result] {
	    return -code error "Error reading tests values: $result"
	}
	set rows [exec sdds2stream -rows=bar $tmpFile]
	if !$rows {
	    SetStatus "Tests passed."
	} else {
          exec  sddsprintout  $tmpFile $tmpFile.print  \
	      "-title=Following PVs failed testing.\n" \
	      -column=ControlName,format=%40s -column=MinimumValue,format=%10.3g \
	      -column=Value,format=%10.3g -column=MaximumValue,format=%10.3g 
	    APSFileDisplayWindow [APSUniqueName .] -height 20 \
	      -comment "Tests for BTS efficiency optimizer" \
	      -width 120 -fileName $tmpFile.print -deleteOnClose 1
	}
	APSAddToTmpFileList -ID parinjopt -fileList "$tmpFile $tmpFile.print"
	return
    }
    
    if [catch {CheckControllaw } result] {
	SetStatus "Error in checking controllaws: $result"
	return
    }
     
    SetStatus "Starting BTS injection efficiency optimization with $inputConfig ..."
    
    
    if $rcdsDebugger {
        set rcdsOpt -rcds=evaluations=$evaluations,cycles=$cycles,noise=$rcdsNoise,step=$rcdsStepSize,verbose
    } else {
        set rcdsOpt -rcds=evaluations=$evaluations,cycles=$cycles,noise=$rcdsNoise,step=$rcdsStepSize
    }
    if $rcdsUseMinimum {
        append rcdsopt ,useMin
    }
    switch $method {
	Simplex {
	    if !$simplex1d {
		set opt -simplex=restart=1,cycles=$cycles,eval=$evaluations,rand,no1dscan 
            } else {
                set opt -simplex=restart=1,cycles=$cycles,eval=$evaluations,rand 
            }
	}
	RCDS {
	    set opt $rcdsOpt
	}
    }
    if $useInjTune {
	set measScript "$mainDir/measureBTSeffic -checkTune 1"
	
    } else {
	set measScript $mainDir/measureBTSeffic
    }
    set oldDir [pwd]
    cd $outDir
    set optVarFile $outDir/${inputConfig}_input.sdds
    #et logFile ${method}-${rootname}.log
    if {$inputConfig=="SFSDoffset"} {
	append opt " -varScript=/home/oxygen/SHANG/oag/apps/src/tcltkapp/oagapp/UpDownSDSFRampRegion0 "
    }
    
  
    set optMeasFile $outDir/PAROpt.meas 
    global apsRunBTSEfficiencyOptimizer
    set apsRunBTSEfficiencyOptimizer -1
    
    APSExecLog [APSUniqueName .] -closeInput 0 \
      -unixCommand "sddsoptimize \"-measScript=$measScript\" \
        -tolerance=$tolerance \
        -varFile=$optVarFile  \
        $opt \
        -verbose -logFile=$outDir/$logFile -maximize " \
	-callback "set apsRunBTSEfficiencyOptimizer finished" \
	-abortCallback "set apsRunBTSEfficiencyOptimizer aborted" \
	-cancelCallback "set apsRunBTSEfficiencyOptimizer cancelled" \
      -width 120 -height 20 -lineLimit 1000 \
      -contextHelp "BTS efficiency optimizer"
    cd $oldDir
    eval $statusCallback {"BTS efficiency optimizer started."}
    if $plot {
        after 60000 "exec sddsplot -repeat \"-device=motif,-movie true -keep 1\" \
                       -column=EvalIndex,currentValue $logFile -graph=sym -factor=ymult=-1 \
                      -xlabel=IterationNumber -ylabel=ObjectiveValue &"
    }
    
    tkwait variable apsRunBTSEfficiencyOptimizer
   # PAROptCallback -status $apsRunParEfficiencyOptimizer
}

proc UpdateLogFile {args} {
    global outDir logFile inputConfig method
    set logFile [APSNextGenerationedName -directory $outDir -name Log-${method}-${inputConfig}-000 -newFile 1 -separator -]
}

set outDir ""
proc OptimizerParameter {args} {
    set edit 1
    set update 0
    APSParseArguments {edit update}
    
    global mainDir inputConfig outDir gun useInjTune oldConfig
   
    if $useInjTune {
	set inputConfig QFQDDelay
    } else {
	#set inputConfig $oldConfig
    }
    if ![string length $outDir] {
	set outDir [APSGoToDailyDirectory -subdirectory btsInjEffOpt]
    }
    cd $outDir
    if {$update || ![file exist $outDir/${inputConfig}_input.sdds]} {
	exec cp $mainDir/${inputConfig}_input.sdds $outDir/${inputConfig}_input.sdds
    }
    if $edit {
	exec sddsedit $outDir/${inputConfig}_input.sdds &
    }
}

proc CheckControllaw {args} {
    global inputConfig
    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} {
	return -code error "Please check BM/QF/QD bcontrollaw and make sure they are running before start optimizer."
    }
    if {$inputConfig=="SFSDoffset"} {
	foreach mag {SF SD} {
	    if [set ${mag}bcontrol] {
		SetStatus "Suspend $mag bcontrol..."
		if [catch {exec cavput -list=B:${mag}bcontrollawRC.SUSP=1 -pend=10} result] {
		    return -code error "Error suspending $mag bcontrol: $result"
		}
	    }
	}
    } else {
	if {!$SFbcontrol || !$SDbcontrol} {
	    return -code error "Please check 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 !$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 BringUpChromGUI {args} {
    global outDir logFile
    set rootname [regsub "Log-" $logFile "Chrom-"]
    exec /home/oxygen/SHANG/oag/apps/src/tcltkapp/oagapp/BoosterChromMeasurement -outputDir $outDir -rootname $rootname &
}

proc BringupStripTool {args} {
    global mainDir 
    set file $mainDir/btsEffic.stp
    exec StripTool $file &
}

proc SetStatus {message} {
    APSSetVarAndUpdate status "$message"
}

proc UpdateSelection {args} {
    global useInjTune inputConfig oldConfig
    
    if $useInjTune {
	set oldConfig $inputConfig
	set inputConfig QFQDDelay
    } else {
	set inputConfig $oldConfig
    }
    OptimizerParameter -edit 0 -update 1
    UpdateLogFile
}

set stepSizeMultiplier 1.0
set readingsToAverage 5
set postChangePause 6.0
set tolerance 0.001
set evaluations 100
set method Simplex
set simplex1d 1
set rcdsNoise 0.003
set rcdsStepSize 0.01
set rcdsDebugger 1
set rcdsUseMinimum 0
set cycles 1
set mainDir /home/helios/oagData/booster/optimizationConfig/btsEffOptimizer
set inputConfig QFQDGainDelay
set logFile Log-${method}-${inputConfig}-000
set useInjTune 0
set oldConfig $inputConfig
APSLabeledEntry .dir -parent .userFrame -label "Output directory:" -textVariable outDir -width 60
APSLabeledEntry .root -parent .userFrame -label "Log file:" -textVariable logFile -width 60
APSLabeledEntry .tol -parent .userFrame -label "Tolerance:" -textVariable tolerance
APSLabeledEntry .eval -parent .userFrame -label "Max. number of evaluations:" -textVariable evaluations

APSRadioButtonFrame .method -parent .userFrame -label "Optimizer:" -buttonList {Simplex RCDS} \
    -variable method -valueList {Simplex RCDS} -orientation horizontal -commandList {UpdateLogFile UpdateLogFile}
APSRadioButtonFrame .1d -parent .userFrame -label "With 1d scan for simplex?" -variable simplex1d -buttonList {Yes No} \
    -valueList {1 0} -orientation horizontal
APSRadioButtonFrame .debug -parent .userFrame -label "RCDS debugger on/off?" -buttonList {On Off} \
    -valueList {1 0} -orientation horizontal -variable rcdsDebugger
APSRadioButtonFrame .min -parent .userFrame -label "RCDS use minimum for bracket scan?" -buttonList {Yes No} \
    -valueList {1 0} -orientation horizontal -variable rcdsUseMinimum
APSLabeledEntry .noise -parent .userFrame -label "RCDS signal noise:" -textVariable rcdsNoise
APSLabeledEntry .step -parent .userFrame -label "RCDS relative step size:" -textVariable rcdsStepSize
APSRadioButtonFrame .sub -parent .userFrame -label "Input and measurement configuration:" \
    -buttonList {QFQDGainDelay SFSDup_down QFQD_delay} -valueList {QFQDGainDelay SFSDoffset QFQDDelay} \
    -variable inputConfig -orientation horizontal -commandList {"OptimizerParameter -edit 0 -update 1;UpdateLogFile" "OptimizerParameter -edit 0 -update 1;UpdateLogFile" "OptimizerParameter -edit 0 -update 1;UpdateLogFile"}

APSRadioButtonFrame .tune -parent .userFrame -label "Check injection tune?" -buttonList {Yes No} -valueList {1 0} \
    -orientation horizontal -variable useInjTune -commandList {UpdateSelection UpdateSelection}

APSButton .run -parent .userFrame -text Run \
  -command \
    {APSRunBTSEfficiencyOptimizer -plot 1  -statusCallback SetStatus \
       -stepSizeMultiplier $stepSizeMultiplier -averages $readingsToAverage \
       -postChangePause $postChangePause } \
  -contextHelp "Run the optimizer."

APSButton .info -parent .userFrame -text Info -command \
  "exec medm -attach -x -macro \"RCPV=PAREfficOptimizerRC\" \
            ./sr/psApp/APSRunControlSingle.adl &" \
  -contextHelp "Bring up ADL screen showing the run control record for the optimizer."

#APSButton .test -parent .userFrame -text Test -command \
\#  "APSRunParEfficiencyOptimizer -test 1" \
 \# -contextHelp "Evaluate test values to see why the optimizer has halted or is complaining."

APSButton .par -parent .userFrame -text "Edit Var/Object/Test Params" -command OptimizerParameter \
  -contextHelp "bring up optimize variables and measurement info."

APSButton .strip -parent .userFrame -text "StripTool" -command "BringupStripTool"
OptimizerParameter -edit 0

APSButton .chrom -parent .userFrame -text "Measure Chrom" -command "BringUpChromGUI" 
