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

APSApplication . -name "CPUcouplingAdjust" -version $CVSRevisionAuthor \
  -overview "CPUcouplingAdjust minimizes the observed beam size at the S35BM x-ray pinhole camera using the CPU skew magnets. The sequence is as follows.\n\n1.Select CPU mode\n2.Select CPU setpoint\n3.Press \"Minimize coupling\"\n4.Press \"Save CPU snapshot\"\n\nAfter a sufficient number of CPU setpoints press \"Process files\". A new file <mode>.<YYY-MMDD>.<nn> is created and chould be installed in /home/helios/oagData/sr/IDs/CPU/DCmodes for DC modes.\n\nFor AC modes, this GUI can be used as well. Select \"CW/CCW\" and the CPU set point. Use external medm screen to pulse the CPU a sufficient number of times. The CPU data should be manually copied into waveform files and installed as /home/helios/oagData/sr/IDs/CPU/ACmodes/skewOct.sdds and /home/helios/oagData/sr/IDs/CPU/ACmodes/skewOct.sdds"

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 require 10 seconds of pause before taking beamsize measurement."

    APSLabeledEntry .current -parent $w -width 60 \
      -textVariable current \
      -label "CPU setpoint (Vcoil):" \
      -contextHelp "Current for setting CPU. the CPU will ramp to this value when the optimize button is pressed. If the polarization mode is V, then the H coil is set with this value."

    APSLabeledEntry .rootname -parent $w -width 60 \
      -textVariable rootname \
      -label "Rootname for snp file:" \
      -contextHelp "Rootname for *.snp file saved. The actual file name is <rootname><nnn>.snp where <nnn> is a number that will make the file name unique. The request file is /home/helios/oagData/sr/IDs/CPU/DCmodes/CPU.mon"

    APSRadioButtonFrame .mode -parent $w -orientation horizontal \
      -label "CPU mode for processing: " -variable mode \
      -limitPerRow 5 \
      -buttonList {CW CCW H V CW/CCW} \
      -valueList {CW CCW H V CW/CCW} \
      -commandList {"set rootname CW" "set rootname CCW" "set rootname H" "set rootname V" "set rootname AC"} \
      -contextHelp \
      "Choose CPU mode for processing the files. This values is also used to determine whether the current value is sent to the V coil or the H coil. -- For CW CCW and H modes, the current values is sent to the V coil. For V modes, the current is sent to the H coil.\n\nChanging the selection will update the rootname for the snapshot file."

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

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

    APSButton .zeroSkewQuad  -parent $w -text "CPU Skew Quad -> 0" \
      -command "exec cavput -list=ID04b:US_SkewQuadSetpt=0" \
      -contextHelp "Sets the CPU skew quadrupole coil to zero."
    APSButton .zeroSkewOct  -parent $w -text "CPU Skew Oct -> 0" \
      -command "exec cavput -list=ID04b:DS_SkewQuadSetpt=0" \
      -contextHelp "Sets the CPU skew octupole coil to zero."
    APSButton .zeroAll  -parent $w -text "All CPU skew coils -> 0" \
      -command "exec cavput -list=ID04b:US_SkewQuadSetpt=0,ID04b:DS_SkewQuadSetpt=0" \
      -contextHelp "Sets the CPU skew quadrupole and octupole coil to zero."

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

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

    APSButton .saveSnap  -parent $w -text "Save CPU snapshot" \
      -command {saveSnap -logDir $logDir -rootname $rootname -current $current} \
      -contextHelp "Saves snapshot of the CPU data. Normally should be done after pressing \"Minimize coupling\". Should be done for DC and AC modes."

    APSButton .process1  -parent $w -text "Process files" \
      -command {processFiles -logDir $logDir -rootname $rootname -mode $mode} \
      -contextHelp "Combines files and does some processing. Done after all set points for a given mode are complete. Only applies to the DC modes."

    $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 processFiles {args} {
    set logDir .
    set rootname CPU
    set mode CW
    APSParseArguments {logDir rootname mode}

    set fileList  [glob ${rootname}???.snp]
    if {$fileList == ""} {
        return -code error "processFiles: No files matching ${rootname}???.snp found!"
    }
    switch $mode {
        H -
        CW {
            set factor -1
            set dependentVar Iv
        }
        CCW {
            set factor 1
            set dependentVar Iv
        }
        V {
            set factor 1
            set dependentVar Ih
        }
    }
    if [catch {eval exec sddscombine $fileList -pipe=out \
                 | sddsprocess -pipe \
                 -scan=col,Value,ValueString,%lf \
                 | sddsconvert -pipe \
                 -retain=col,ControlName,Value \
                 | sddstranspose -pipe \
                 | sddscombine -pipe -merge \
                 | sddssort -pipe=in ${rootname}settings \
                 -col=ID04b:set_V_coil  \
             } result ] {
        return -code error "processFiles: $result"
    }

    if [catch {exec sddsplot -col=ID04b:set_V_coil,ID04b:*\[67\]* ${rootname}settings \
                 -grap=sym,conn=sub,vary=sub,sca=3 -file & \
             } result ] {
        return -code error "processFiles: $result"
    }

    if [catch {exec sddsconvert ${rootname}settings -pipe=out \
                 -retain=col,ID04b:set_V_coil,ID04b:DS_SkewQuadSetpt,ID04b:US_SkewQuadSetpt \
                 -rename=col,ID04b:set_V_coil=${dependentVar} \
                 -rename=col,ID04b:DS_SkewQuadSetpt=RotatedOct \
                 -rename=col,ID04b:US_SkewQuadSetpt=RotatedQuad \
                 | sddsprocess -pipe=in ${rootname}settings.conv \
                 "-redef=col,${dependentVar},${dependentVar} $factor *,units=A"  \
             } result ] {
        return -code error "processFiles: $result"
    }
    set referenceFile /home/helios/oagData/sr/IDs/CPU/DCmodes/${mode}.default
    if [catch {exec sddsinterp ${rootname}settings.conv ${rootname}settings.interp \
                 -col=Iv,RotatedOct,RotatedQuad \
                 -fileValues=$referenceFile,col=${dependentVar} \
             } result ] {
        return -code error "processFiles: $result"
    }
    
    set ouputFile [APSNextGenerationedName -name ${mode}.[clock format [clock seconds] -format %Y-%m%d].00 -separator . -newFile 1]
    if [catch {exec sddsconvert $referenceFile  -pipe=out \
                 -dele=col,RotatedOct,RotatedQuad \
                 | sddsxref -pipe=in ${rootname}settings.interp $ouputFile \
                 -take=RotatedOct,RotatedQuad -equate=${dependentVar} \
             } result ] {
        return -code error "processFiles: $result"
    }
    APSSetVarAndUpdate status "File $logDir/$ouputFile was created."
    APSSetVarAndUpdate status "Copy this to /home/helios/oagData/sr/IDs/CPU/DCmodes for installation."
}

proc saveSnap {args} {
    set logDir .
    set rootname CPU
    set current 0
    APSParseArguments {logDir rootname current}

    # do not overwite
    set snapFile $logDir/$rootname[format %03ld ${current}].snp
    if [file exists $snapFile] {
        return -code error "saveSnap: File $snapFile already exists!"
    }
    if [catch {exec sddscasr -save /home/helios/oagData/sr/IDs/CPU/DCmodes/CPU.mon \
                 $snapFile \
             } result ] {
        return -code error "saveSnap: $result"
    }
    APSSetVarAndUpdate status "Saved $snapFile."
}

proc runOptimize {args} {
    set logDir .
    set framesToAverage 300
    set current 0
    set mode CW
    APSParseArguments {logDir framesToAverage current mode}
    set scriptDir /home/helios/oagData/sr/optimizeScripts/CPUcoupling
    
    if [catch {exec cavput -list=S:VID1:numToAvgC=$framesToAverage \
             } result ] {
        return -code error "runOptimize: $result"
    }
    # S:VID averaging is actually an exponential one
    # so we have to wait a longer time.
    set pauseTime [expr 2 * $framesToAverage / 30.0 + 1]
    set tmpfile /tmp/[APSTmpString]
    exec sddsprocess $scriptDir/var $tmpfile.var \
      -redef=para,pauseAfterChange,$pauseTime,units=s \
      -redef=para,PauseAfterChange,$pauseTime,units=s

    # setting current
    APSSetVarAndUpdate status "Setting main coil current ..."
    if {$mode=="V"} {
        set mainCoilPV ID04b:set_H_coil.VAL
    } else {
        set mainCoilPV ID04b:set_V_coil.VAL
    }
    if [catch {exec cavput -list=${mainCoilPV}=$current \
             } result ] {
        return -code error "runOptimize: $result"
    }
    after 1000
    set notReady 1
    set limit 10
    while {$notReady} {
        if [catch {exec cavget -list=ID04b:feedback } result ] {
            return -code error "runOptimize: $result"
        }
        if {$result=="Ready"} {
            set notReady 0
        }
        incr limit -1
        if {$limit==0} {
            return -code error "runOptimize: CPU didn't reach its setpoint. Optimization not started."
        }
        after 1000
    }

    # read current correcting coils and set them
    APSSetVarAndUpdate status "Setting skew quadrupole and octupole coils ..."
    if [catch {exec cavget -list=ID04b:DS_SkewQuadSetpt.VAL,ID04b:US_SkewQuadSetpt.VAL \
             } values] {
        return -code error "runOptimize: $avlues"
    }
    if [catch {exec cavput -list=ID04b:DS_SkewQuadSetpt=[expr 0.001 + [lindex $values 0]],ID04b:US_SkewQuadSetpt=[expr 0.001 + [lindex $values 1]] \
             } result] {
        return -code error "runOptimize: $result"
    }
    APSSetVarAndUpdate status "Starting optimizer ..."
    
    APSExecLog .minimizeCoupling \
      -lineLimit 2048 -width 90 \
      -name "SR Coupling Correction" \
      -unixCommand "sddsoptimize -measFile=$scriptDir/meas \
            -pend=20 \
            -varFile=$tmpfile.var \
            -simplex=restarts=2,cycles=1,evaluations=50 \
            -knobFiles=/home/helios/oagData/sr/optimizeScripts/CPUcoupling/skew.cokn \
            -testValues=file=$scriptDir/tests,limit=3 \
            -target=0.0 -verbose \
            -logFile=$logDir/CPUcoupling.optLog"
    
}

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

    exec sdds2dinterpolate $logDir/CPUcoupling.optLog $logDir/CPUcoupling.optLog.2d \
        -dep=currentValue -independentColumn=xcol=CPU:skew,ycol=ID04b:US_SkewQuadSetpt \
        -outDimen=xdim=10,ydim=10
    exec sddscontour -quant=currentValue $logDir/CPUcoupling.optLog.2d -shade=32 &
}

set logDir .
set framesToAverage 100
set status "Working."
APSScrolledStatus .status -parent .userFrame -textVariable status -width 90
MakeActionWidget .action -parent .userFrame
set status "Ready."

set current 0
set mode CCW
set rootname $mode


# Local Variables:
# mode: tcl
# indent-tabs-mode: nil
# End:
