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

set CVSRevisionAuthor "\$Revision: 1.4 $ \$Author: xiaoam $"

APSApplication . -name "CPUscanMultipoles" -version \
  $CVSRevisionAuthor -overview "Scans the multipole coils of the CPU, and measures orbit and emittance changes."

set status "Ready."
APSScrolledStatus .status -parent .userFrame -width 80 -height 10 \
        -textVariable status

proc StartScan {args} {
    set outputDir ""
    set root ""
    set index 0
    set abortVariable ""
    set steps 10
    set pause 5
    APSParseArguments {outputDir root index abortVariable steps pause}

    set output $outputDir/$root-[format %03ld $index]

    if [file exists $outputDir/$output] {
        return -code error "StartScan: file $output exists."
    }

    set CPUdataDir /home/helios/oagData/sr/IDs/CPU/DCmodes

    set tmpfile /tmp/[APSTmpString]
    set experimentFile $tmpfile.exp

    foreach mode {nq rq ro roPure} {
        global ${mode}Start ${mode}End ${mode}ScanType
    }

    exec replaceText $CPUdataDir/multipoleScanTemplate.exp $experimentFile \
      -original=<steps>,<pause>,<nqStart>,<nqEnd>,<nqScanType>,<rqStart>,<rqEnd>,<rqScanType>,<roStart>,<roEnd>,<roScanType> \
      -replace=$steps,$pause,$nqStart,$nqEnd,$nqScanType,$rqStart,$rqEnd,$rqScanType,$roStart,$roEnd,$roScanType

    set outputfile $outputDir/$root[format %02ld $index]
    APSExecLog .cpuExperiment \
      -lineLimit 2048  -width 90 \
      -name "Scan of CPU multipole coils." \
      -unixCommand "sddsexperiment $experimentFile $outputfile -summarize -verb"

    APSSetVarAndUpdate status "Done."
    return
}

proc MakeInputFrame {widget args} {
    set parent ""
    
    APSStrictParseArguments {parent}
    
    set outputDir .
    APSFrame $widget -parent $parent -label "Input parameters"
    set w $parent$widget.frame

    APSLabeledEntry .outputDir -parent $w \
      -label "Output directory:" -textVariable outputDir \
      -contextHelp "Enter a name for the output file directory." -width 60
    APSButton .daily -parent $w.outputDir -packOption "-anchor e" \
      -text "daily" -size small \
      -command {set outputDir [APSGoToDailyDirectory -subdirectory CPU]}
    APSLabeledEntry .root -parent $w -label "Root name of file: " \
      -textVariable root \
      -contextHelp "Enter the root name of the file for the processed output <root>-nnn."
    APSLabeledEntry .index -parent $w -label "Index: " -textVariable index \
      -contextHelp "Enter the index (minus 1) to be part of the name of the output file. The index is incremented by 1 before execution."
    APSRadioButtonFrame .scanMode -parent $w -orientation horizontal \
      -label "Scan mode: " -variable scanMode \
      -limitPerRow 3 \
      -buttonList {"Normal quad coil" "Rotated quad coil" "Rotated octupole coil" "\"Pure\" octupole field"} \
      -valueList {nq rq ro roPure} \
      -commandList {SetLimits SetLimits SetLimits SetLimits} \
      -contextHelp \
      "Choose scan mode. The pure rotated octupole field is a combination of the two rotated coils using the ratio given."

    set labelDescription(nq) "Normal Quadrupole coil (ID04b:DS_NormalQuadSetpt)"
    set labelDescription(rq) "Rotated Quadrupole coil (ID04b:US_SkewQuadSetpt)"
    set labelDescription(ro) "Rotated Octupole coil (ID04b:DS_SkewQuadSetpt)"
    foreach coil {nq rq ro} {
        # do manual frame and pack since the APSFrame puts in a
        # border, which gives the list of items a 
        # different spacing than the rest.
        frame $w.$coil -relief flat -bd 0
        pack $w.$coil -side top -fill both
        set widget $w.$coil
        label $widget.label -text [format %-50s $labelDescription($coil)]
        pack $widget.label -side left -ipady 0
        APSLabeledEntry .start -parent $widget -label "Initial:" -textVariable \
          ${coil}Start -width 10 \
          -contextHelp "Enter the initial value for the coil scan." \
        -packOption "-side left -ipady 0"
        APSLabeledEntry .end -parent $widget -label "Final:" -textVariable \
          ${coil}End -width 10 \
          -contextHelp "Enter the final value for the coil scan." \
        -packOption "-side left -ipady 0"
        APSCheckButtonFrame .rel -parent $widget -label {} -buttonList {Relative} \
          -variableList ${coil}ScanType -orientation horizontal \
          -contextHelp "If checked, then the variation range is defined relative to the PV's original value." \
          -packOption "-side left -ipady 0"
        $widget.rel.frame configure -relief flat
        
    }
    APSLabeledEntry .ratio -parent $w -label "Quad. strength ratio between rotated quad and octupole coils: " -textVariable ratio \
      -contextHelp "Enter the quadrupole strength ratio between rotated octupole coil and rotated quadrupole for pure octupole field scan. Ratio is normally positive and around 1.5 if there is no beam offset."

    APSLabeledEntry .steps -parent $w -label "Steps: " -textVariable steps \
      -contextHelp "Enter the number of steps for scan."
    APSLabeledEntry .waitAtLeast -parent $w -label "Time for orbit settling (s)" \
      -textVariable pause \
      -contextHelp "Enter the time for orbit correction at each steps."

}

proc SetLimits {} {
    global scanMode ratio
    foreach mode {nq rq ro roPure} {
        global ${mode}Start ${mode}End ${mode}ScanType
    }
    switch $scanMode {
        nq {
            # 0 means absolute scan; 1 means relative scan.
            set nqStart -4.7
            set nqEnd 4.7
            set nqScanType 0
            # need relative scan if the coil isn't to be changed.
            set rqStart 0
            set rqEnd 0
            set rqScanType 1
            set roStart 0
            set roEnd 0
            set roScanType 1
        }
        rq {
            # 0 means absolute scan; 1 means relative scan.
            set rqStart -6.0
            set rqEnd 6.0
            set rqScanType 0
            # need relative scan if the coil isn't to be changed.
            set nqStart 0
            set nqEnd 0
            set nqScanType 1
            set roStart 0
            set roEnd 0
            set roScanType 1
        }
        ro {
            # 0 means absolute scan; 1 means relative scan.
            set roStart -5.0
            set roEnd 5.0
            set roScanType 0
            # need relative scan if the coil isn't to be changed.
            set nqStart 0
            set nqEnd 0
            set nqScanType 1
            set rqStart 0
            set rqEnd 0
            set rqScanType 1
        }
        roPure {
            # 0 means absolute scan; 1 means relative scan.
            set roStart -5.0
            set roEnd 5.0
            set roScanType 0
            set rqStart [expr $roStart / $ratio]
            set rqEnd [expr $roEnd / $ratio]
            set rqScanType 0
            # need relative scan if the coil isn't to be changed.
            set nqStart 0
            set nqEnd 0
            set nqScanType 1
        }
    }
    return
}

set outputDir .
set index -1
set steps 10
set pause 5
set scanMode nq
SetLimits
set abortScan 0
set comment "Put comment here"
set root "normalQuad"
set root "rotatedQuad"
set ratio 1.27

MakeInputFrame .input -parent .userFrame

APSButton .run -parent .userFrame -text "SCAN COIL" -command \
  { \
      APSDisableButton .userFrame.run.button 
      APSEnableButton .userFrame.stop.button
      incr index
      catch {StartScan -outputDir $outputDir \
               -root $root -index $index \
               -abortVariable abortScan \
               -steps $steps -pause $pause \
           } status
      update idletasks
      APSEnableButton .userFrame.run.button }

APSButton .stop -parent .userFrame -text "ABORT" -command \
    { \
    APSEnableButton .userFrame.run.button
    APSDisableButton .userFrame.stop.button 
    set abortScan 1
}

APSDisableButton .userFrame.stop.button 

set scanMode rq
SetLimits
