#!/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.15 $ \$Author: emery $"

APSApplication . -name "SRCouplingAdjust" -version $CVSRevisionAuthor \
  -overview "SRCouplingAdjust minimized the coupling using sddsoptimize."

proc MakeActionWidget {widget args} {
    set parent ""
    APSParseArguments {parent}
    
    APSFrame $widget -parent $parent -label "" \
      -contextHelp "Action buttons"
    set w $parent$widget.frame

    APSFrame .options -parent $parent$widget.frame -label "" \
      -contextHelp "Action buttons for skews"
    set w $parent$widget.frame.options.frame

    APSLabeledEntry .logDir -parent $w -width 60 \
      -textVariable logDir \
      -label "Log directory:" \
      -contextHelp "Directory for log file of minimization."

    APSLabeledEntry .frames -parent $w -width 60 \
      -textVariable framesToAverage \
      -label "Video frames to average:" \
      -contextHelp "There are 30 frames per seconds, so selecting 300 frames will produce an average time constant of 10 seconds. A pause of twice this will be used for waiting for the beamsize reading to settle. If 50 frames is selected then a pause of about 3.3 seconds is used. Used only for beamsize method."

    APSLabeledEntry .lifetimePoints -parent $w -width 60 \
      -textVariable lifetimePoints \
      -label "Lifetime points:" \
      -contextHelp "Number of fit points for lifetime calculation. This is used to calculate the time required for a new lifetime calculation. Since the points to average cannot be changed to less than 10, then 10 seconds will be added to the number of fit points."

    APSRadioButtonFrame .method -parent $w \
      -variable method \
      -buttonList {beamsize "beamsize (VID 4)" lifetime} -valueList {beamsize beamsize4 lifetime} \
      -label "Method:" -orientation horizontal \
      -contextHelp "Select one or the other method. Each method will use a different PV to minimize."

    APSButton .daily -parent $w.logDir -packOption "-anchor e" \
      -text "daily" -size small \
      -command {set logDir [APSGoToDailyDirectory -subDirectory .]}

    APSFrame .skews -parent $parent$widget.frame -label "" \
      -contextHelp "Action buttons for skews"
    set w $parent$widget.frame.skews.frame

    APSButton .zeroAQS  -parent $w -text "AQS -> 0" \
      -command "ZeroSkews -AQSonly 1" \
      -contextHelp "Sets S<n>A:QS skew quadrupoles to zero."
    APSButton .zeroBQS  -parent $w -text "BQS -> 0" \
      -command "ZeroSkews -BQSonly 1" \
      -contextHelp "Sets S<n>B:QS skew quadrupoles to zero."
    APSButton .zeroAll  -parent $w -text "All QS -> 0" \
      -command "ZeroSkews" \
      -contextHelp "Sets S<n>\[AB\]:QS skew quadrupoles to zero."

    APSFrame .optimize -parent $parent$widget.frame -label "" \
      -contextHelp "Action buttons for skews"
    set w $parent$widget.frame.optimize.frame

    APSButton .minimize  -parent $w -text "Minimize coupling" \
      -command {runOptimize  -logDir $logDir \
                  -method $method \
                  -framesToAverage $framesToAverage \
                  -lifetimePoints $lifetimePoints} \
      -contextHelp "Starts sddsoptimize for minimizing the coupling."
    
    APSButton .plotProg  -parent $w -text "Plot Progress" \
      -command {plotProgress -logDir $logDir} \
      -contextHelp "Plots the knob values and emittance."

    $parent$widget.frame configure -relief flat -bd 0
    $parent$widget.frame.options.frame configure -relief flat -bd 0
    $parent$widget.frame.skews.frame configure -relief flat -bd 0
    $parent$widget.frame.optimize.frame configure -relief flat -bd 0
}

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

proc ZeroSkews {args} {
    set AQSonly 0
    set BQSonly 0
    APSParseArguments {AQSonly BQSonly}
    if {$AQSonly && $BQSonly} {
        return -code error "Zeroskews: Synatx error: Only one of AQSonly BQSonly can be 1"
    }
    if $AQSonly {
        if [catch {exec cavput -list=S -range=beg=3,end=40,interval=4 \
                     -list=A:QS:CurrentAO=0 -pend=15 \
                 } result ] {
            return -code error $result
        }
    } elseif $BQSonly {
        if [catch {exec cavput -list=S -range=beg=5,end=40,interval=4 \
                     -list=B:QS:CurrentAO=0 -pend=15 \
                 } result ] {
            return -code error $result
        }
    } else {
        if [catch {exec cavput -list=S -range=beg=3,end=40,interval=4 \
                     -list=A:QS:CurrentAO=0 -pend=15 
            exec cavput -list=S -range=beg=5,end=40,interval=4 \
                     -list=B:QS:CurrentAO=0 -pend=15 \
                 } result ] {
            return -code error $result
        }
    }
    SetStatus "Zeroing done."
    return
}

proc runOptimize {args} {
    set logDir .
    set framesToAverage 100
    APSParseArguments {logDir framesToAverage lifetimePoints method}
    set scriptDir /home/helios/oagData/sr/optimizeScripts/coupling
    
# this is relevant only when the vertical beam size is the readback
# A different pause time may be required for the lifetime readback.
    switch $method {
        beamsize {
            if [catch {exec cavput -list=S:VID1:numToAvgC=$framesToAverage \
                     } result ] {
                return -code error "runOptimize: $result"
            }
            set pauseTime [expr 2 * $framesToAverage / 30.0 + 1]
        }
        beamsize4 {
            if [catch {exec cavput -list=S:VID4:numToAvgC=$framesToAverage \
                     } result ] {
                return -code error "runOptimize: $result"
            }
            set pauseTime [expr 2 * $framesToAverage / 30.0 + 1]
        }
        lifetime {
             return -code error "S-DCCT:LifetimeStdesPoints2FitC no longer exists"
#            if [catch {exec cavput -list=S-DCCT:LifetimeStdesPoints2FitC=$lifetimePoints} result ] {
#                return -code error "runOptimize: $result"
#            }
            set pauseTime [expr $lifetimePoints + 10]
        }
    }
    set tmpfile /tmp/[APSTmpString]
    exec sddsprocess $scriptDir/var $tmpfile.var \
      -redef=para,pauseAfterChange,$pauseTime,units=s \
      -redef=para,PauseAfterChange,$pauseTime,units=s

    set measFile meas.$method
    if ![file exists $scriptDir/$measFile] {
        return -code error "File $scriptDir/$measFile doesn't exist"
    }

    APSExecLog .minimizeCoupling \
      -lineLimit 2048 -width 90 \
      -name "SR Coupling Correction" \
      -unixCommand "sddsoptimize -measFile=$scriptDir/$measFile \
            -pend=20 \
            -varFile=$tmpfile.var \
            -knobFiles=/home/helios/oagData/sr/knobs/skewQuad/skew.cokn  \
            -simplex=restarts=1,cycles=1,evaluations=50 \
            -testValues=file=$scriptDir/tests,limit=3 \
            -target=0.0 -verbose \
            -logFile=$logDir/coupling.optLog"
}

proc plotProgress {args} {
    set logDir .
    APSParseArguments {logDir}
    exec sddsplot $logDir/coupling.optLog \
      -col=EvalIndex,(SnA:QS:Cosine,SnA:QS:Sine,SnB:QS) \
      -grap=line,vary -alignzero=yfactor -leg \
      -col=EvalIndex,currentValue \
      -grap=line,vary -alignzero=yfactor -leg \
      -yscale=id=eval -uns=y \
      -end \
      -col=SnA:QS:Cosine,SnA:QS:Sine \
      -grap=sym,thick=10,vary=subtype  -split=column=currentValue,width=0.1 \
      -order=spectral \
      &

    exec sdds2dinterpolate $logDir/coupling.optLog $logDir/coupling.optLog.2d \
        -dep=currentValue -independentColumn=xcol=SnA:QS:Cosine,ycol=SnA:QS:Sine \
        -outDimen=xdim=10,ydim=10
    exec sddscontour -quant=currentValue $logDir/coupling.optLog.2d -shade=32 &

}

set logDir .
set framesToAverage 50
set lifetimePoints 10
set method beamsize
set status "Working."
APSScrolledStatus .status -parent .userFrame -textVariable status -width 90
MakeActionWidget .action -parent .userFrame
set status "Ready."
