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

# This application is used with controllaw in the transport lines and
# linac.  It computes setpoints at two bpms that are used by controllaw
# to center the beam at two downstream quads.  To use this application,
# first run controllaw then adjust the bpm setpoints to find the center
# of the first quad.  Then, turn the first quad off and center in the
# second quad.  The bpm setpoints to center in both quads simultaneously
# are computed and a dialog box asks the user whether to install the new
# bpm setpoints.  The quad centers are also computed.
#

# Note: by convention, this procedure has only one argument. It provides the
# parent frame into which you should pack all widgets.

set CVSRevisionAuthor "\$Revision: 1.3 $ \$Author: soliday $"
APSApplication . -version $CVSRevisionAuthor \
  -name "ComputeBPMSetpointsForQuadCentering" -overview {This tool
      computes two upstream BPM setpoints used by controllaw to center the
      beam in two downstream quads.  The procedure to be followed is to
      first center the beam in the first downstream quad by adjusting the
      second downstream bpm setpoint with controllaw running.  When the
      beam is centered, the "Read BPM-2 Position 1" button is pressed.
      Next, the first downstream quad is turned off and the beam is
      centered in the second downstream quad by adjusting the second
      downstream bpm setpoint with controllaw running.  When the beam is
      centered, the "Read BPM-2 Position 2" button is pressed.  Finally,
      when satisfied with both BPM-2 positions, press the "Set BPM
Setpoints" button which applies the computed setpoints to center the
      beam in both quads.}

set status "Select bpms..."

set bpm1 L5:P3:x
set bpm2 L5:P4:x
set bpm2Position1 0.0
set bpm2Position2 0.0
set l1 3.000
set l2 2.105
set l3 2.660

APSLabeledEntry .bpm1 -parent .userFrame -label "BPM-1 (Upstream): " \
  -textVariable bpm1 -width 12 -contextHelp \
  "First bpm name assumed to be the upstream bpm."

APSLabeledEntry .bpm2 -parent .userFrame -label "BPM-2 (Downstream): " \
  -textVariable bpm2 -width 12 -contextHelp \
  "Second bpm name assumed to be the downstream bpm."

APSLabeledEntry .l1 -parent .userFrame -label "BPM separation (m): " \
  -textVariable l1 -width 12 -contextHelp \
  "Distance between bpms in meters."

APSLabeledEntry .l2 -parent .userFrame -label "BPM-2 and first downstream quad separation (m):" \
  -textVariable l2 -width 12 -contextHelp \
  "Distance between downstream bpm (BPM-2) and first downstream quad in meters."

APSLabeledEntry .l3 -parent .userFrame -label "Quad separation (m): " \
  -textVariable l3 -width 12 -contextHelp \
  "Distance between quadrupoles in meters."

APSLabeledOutput .bpm2Pos1 -parent .userFrame -label "BPM-2 Position 1: " \
  -textVariable bpm2Position1 -width 12 -contextHelp \
  "Second bpm position for centering in the first quad downstream of BPM-2."

APSLabeledOutput .bpm2Pos2 -parent .userFrame -label "BPM-2 Position 2: " \
  -textVariable bpm2Position2 -width 12 -contextHelp \
  "Second bpm position for centering in second quad downstream of BPM-2."

APSButton .bpm2Position1 -parent .userFrame -text "Read BPM-2 Position 1" \
  -command {set bpm2Position1 [setBPM2PositionVariable -bpm2 $bpm2]} \
  -contextHelp "Reads in BPM-2 Position 1 for centering in the first downstream quad."

APSButton .bpm2Position2 -parent .userFrame -text "Read BPM-2 Position 2" \
  -command {set bpm2Position2 [setBPM2PositionVariable -bpm2 $bpm2]} \
  -contextHelp "Reads in BPM-2 Position 2 for centering in the second downstream quad (with the first downstream quad unpowered)."

APSButton .computeAndSetBPMSetpoints -parent .userFrame \
  -text "Calculate BPM Setpoints" \
  -command {computeAndSetBPMSetpoints -bpm1Name $bpm1 -bpm2Name $bpm2 -bpm2Pos1 $bpm2Position1 -bpm2Pos2 $bpm2Position2} \
  -contextHelp "Computes and sets bpm setpoints required for controllaw to center the beam simulataneously in both downstream quads."

# Procedure used to set BPM-2 position variable after centering in a given quadrupole.

proc setBPM2PositionVariable {args} {

    set bpm2 ""
    if {[APSStrictParseArguments {bpm2}] || $bpm2==""} {
        return -code error "setBPM2PositionVariable: bad arguments"
    }

    set planeDesig [lindex [split [lindex [split $bpm2 ":"] 1] ""] 1]

    if {![string compare $planeDesig H]} {
        set pvPlaneDesig x
    } elseif {![string compare $planeDesig V]} {
        set pvPlaneDesig y
    }
#    return [exec cavget -list=${bpm2}:$pvPlaneDesig -repeat=number=5,pause=1,average -delimiter=]
    return [exec cavget -list=${bpm2} -repeat=number=5,pause=1,average -delimiter=]
}

proc computeAndSetBPMSetpoints {args} {

    global l1 l2 l3

    set bpm1Name ""
    set bpm2Name ""
    set bpm2Pos1 ""
    set bpm2Pos2 ""
    
    if {[APSStrictParseArguments {bpm1Name bpm2Name bpm2Pos1 bpm2Pos2}] || $bpm1Name=="" || $bpm2Name=="" || $bpm2Pos1=="" || $bpm2Pos2==""} {
        return -code error "computeAndSetBPMSetpoints: bad arguments"
    }

    set planeDesig [lindex [split [lindex [split $bpm2Name ":"] 1] ""] 1]

    if {![string compare $planeDesig H]} {
        set pvPlaneDesig x
    } elseif {![string compare $planeDesig V]} {
        set pvPlaneDesig y
    }

#    set bpm1Pos [exec cavget -list=${bpm1Name}:${pvPlaneDesig} -repeat=number=5,pause=1,average]
    set bpm1Pos [exec cavget -list=${bpm1Name} -repeat=number=5,pause=1,average]

    set qd1 [expr (($bpm2Pos1 - $bpm1Pos) * $l2) / $l1 + $bpm2Pos1]
    set qd2 [expr (($bpm2Pos2 - $bpm1Pos) * ($l2 + $l3)) / $l1 + $bpm2Pos2]
    set bpm2Setpoint [expr (($qd1 - $qd2) * $l2) / $l3 + $qd1]
    set bpm1Setpoint [expr (($qd1 - $qd2) * $l1) / $l3 + $bpm2Setpoint]

    APSInfoWindow .offsetSetpoints \
      -name "Quad Centers and BPM Setpoints" \
      -infoMessage "Quadrupole-1 Center - ${qd1} (mm)\nQuadrupole-2 Center - ${qd2} (mm)\nBPM-1 Setpoint - ${bpm1Setpoint} (mm)\nBPM-2 Setpoint - ${bpm2Setpoint} (mm)" \
      -width 120 \
      -contextHelp "Quadrupole offsets and bpm setpoints relative to bpm calibration and beamline steering."
    
    APSDialogBoxAddButton .installButton -parent .offsetSetpoints \
      -text "Install" \
      -command "exec cavput -list=${bpm1Name}:SetpointAO=${bpm1Setpoint},${bpm2Name}:SetpointAO=${bpm2Setpoint} -pendIoTime=20" \
      -contextHelp "Install the new bpm setpoints to center the beam in the quadrupoles."
    
    return 1
}
