#!/bin/sh  
# \
exec oagtclsh "$0" "$@"

# $Log: not supported by cvs2svn $
# Revision 1.5  2008/04/15 21:07:24  shang
# test position scan with Karen and added radio button for selecting the energy gap scan.
#
# Revision 1.4  2006/05/31 20:06:06  shang
# added stream argument with default value of ds (downstream) since the ID names now
# have ds or us suffix, the ID gap (energy) name can not be obtained only from the sector.
#
# Revision 1.3  2006/01/31 19:31:08  shang
# changed the wait time for 4 seconds to 4.5 seconds
#
# Revision 1.2  2005/10/25 21:55:44  shang
# replaced ${id} (a bug) by the 2-digit sector value
#
# Revision 1.1  2005/10/25 14:45:29  shang
# developed by Michael Borland for changing the x' and y' steering setpoints for a specified sector.
#
# renamed from setIDAngles, devepoled by Michael Borland

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

# 
# This script changes the x' and y' steering setpoints for a specified sector
# A filename must be supplied so the script can keep track of the initial values
# of the BPM setpoints.  The caller-specified setpoints are all relative to these
# initial values.
#

set usage "usage: setIDSteeringAngles -sector <sector> -reference <filename> -stream <ds|us> -tagList \"xSlope ySlope \[energy\]\" -valueList \"<urad> <urad> \[<keV>\]\" \[-intensityPV <string>\]"
set sector 0
set reference ""
set tagList ""
set valueList ""
set intensityPV ""
set stream ds
set args $argv
if {[APSStrictParseArguments {sector reference tagList valueList intensityPV stream}] || \
      [llength $tagList]!=[llength $valueList] || ![string length $reference]} {
    puts stderr $usage
    exit 1
}

set knownTagList [list energy xSlope ySlope xPos yPos]
set energy 0
foreach tag $tagList value $valueList {
    if [lsearch -exact $knownTagList $tag]==-1 {
        puts stderr "Unknown tag $tag given.  Known tags are $knownTagList"
        exit 1
    }
    set $tag $value
}

set linkDir /home/helios/oagData/sr/localSteering/lattices/default/IDs
set id ${linkDir}/[format %02ld $sector]ID
set idLink [file readlink $id] 
switch -regexp $idLink  {
    P1 {
        # means that P1 bpms are used for steering
        set P0Sector 0
        set R11 1.09
        set R12 4.29
        set R33 0.91
        set R34 3.67
        set type P1
    }
    P0 {
        # means that P0 bpms are used for steering
        set P0Sector 1
        set R11 1.0
        set R12 2.48
        set R33 1.0
        set R34 2.48
        if {$sector == 34} {
            set R12 1.24
            set R34 1.24
        }
        set type P0
    }
}

if ![file exists $reference] {
    # If $reference doesn't exist, we assume that we are to establish a new
    # reference point.
    set id $sector
    set id1 [expr $sector+1]
    exec sddsmakedataset -pipe=out \
      -column=ControlName,type=string \
      -data=S${id}B:$type:ms:x:SetpointAO,S${id}B:$type:ms:y:SetpointAO,S${id1}A:$type:ms:x:SetpointAO,S${id1}A:$type:ms:y:SetpointAO \
      | sddscasr -pipe=in -save $reference
}
set dxPos 0
set dyPos 0
set dxAng 0
set dyAng 0
if [lsearch $tagList "xSlope"]>=0 {
    set dxAng [expr  $R12*$xSlope/1e3]
}
if [lsearch $tagList "xPos"]>=0 {
    set dxPos [expr $R11*$xPos/1e3]

}
if [lsearch $tagList "ySlope"]>=0 {
    set dyAng [expr $R34*$ySlope/1e3]
}
if [lsearch $tagList "yPos"]>=0 {
    set dyPos [expr $R33*$yPos/1e3]
}

# Add -dx to B:P x and +dx to A:P x
# Add -dy to B:P y and +dy to A:P y
if {$dxAng!=0 || $dyAng!=0} {
    exec sddsprocess $reference -pipe=out \
	-scan=column,Value,ValueString,%le,type=double \
	"-redefine=column,Value,ControlName \"*x*\" strmatch ? $dxAng : $dyAng $  ControlName \"*A:P*\" strmatch ? 1 : -1 $ * Value +" \
	-reprint=column,ValueString,%21.14e,Value \
	| tee $reference.1 \
	| sddscasr -pipe=in -restore
    set reference $reference.1
}
if {$dxPos!=0 || $dyPos!=0} {
    exec sddsconvert $reference -pipe=out -del=col,Value \
	| sddsprocess  -pipe \
	-scan=column,Value,ValueString,%le,type=double \
	"-redefine=column,Value,ControlName \"*x*\" strmatch ? $dxPos : $dyPos $  Value +" \
	-reprint=column,ValueString,%21.14e,Value \
	| sddscasr -pipe=in -restore
}

if $energy {
    set stream [string tolower $stream]
    set sectorf [format %02d $sector]
    switch $stream {
	ds -
	us {
	    set IDList ID${sectorf}$sream
	}
	both {
	    set streamList [list ID${sectorf}ds ID${sectorf}us]
	}
	default {
	    puts stderr "Invalid stream - $stream given, it has to be ds (downstream) or us (upstream) or both.\n"
	    exit 1
	}
    }
    set deviceList [APSIDGetDeviceList]
    foreach ID $IDList {
	if [lsearch $deviceList $ID]<0 {
	    puts stderr "Invalid stream - $stream given, $ID does not exist!"
	    exit 1
	}
    }
    exec cavput -list=[join $IDList ,] -list=:EnergySet=$energy
    APSIDsGoAndWait -IDList ${sector}$stream
}

# This is probably the right amount of time to wait. Allows for transfer of new setpoint
# to datapool and then convergence of correction.
#after 4500

#if [string length $intensityPV] {
#    # wait for the intensity PV to update twice
#    exec cawait -waitFor=$intensityPV,change -repeat=2
#}

#this wait time is moved to PauseAfterChange in sddsoptimize

