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

#
#$Log: not supported by cvs2svn $
#Revision 1.5  2011/05/05 16:22:31  shang
#fixed a bug in computing coefficient where computing psi_c1p2.
#
#Revision 1.4  2011/05/03 15:11:22  shang
#corrected the coefficients calculation formula by CY.
#
#Revision 1.3  2011/05/02 16:29:13  shang
#fixed a bug in computing the coefficents where betaP2 should be used for computing K2, but betaP1 was used.
#
#Revision 1.2  2011/05/02 14:51:06  shang
#correctedt the coefficient computation and corrected the selection of bpm and corrector selection combination because the BPM and correctors have different order for different quadrant of H/V plane.
#
#Revision 1.1  2011/04/25 21:38:40  shang
#first version for computing corrector coefficients of 4-corrector bump.
#


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)]
APSDebugPath

set dataDir /home/helios/oagData/booster/ramps/correctors/lattices/
set outputDir $dataDir/default
set orbitfile $dataDir/default/booster.twi
set args $argv
set xorbit 0

# **************************** bbconfigure *****************************
set orbitFileOpened 0
set orbitElementNames ""
proc GetOrbitInfo {args} {
    global orbitData orbitFileOpened dataDir orbitElementNames hcorrnames vcorrnames bpmnames nux nuy
    global hLastCorr vLastCorr orbitfile
    
    
    if [catch {exec sddsprocess $orbitfile -pipe=out -match=col,ElementType=HKICK \
                   | sddssort -pipe -col=s \
                   | sddsprocess -pipe -clip=0,1,invert \
                   | sdds2stream -pipe -col=ElementName } hLastCorr] {
        return -code error $hLastCorr
    }
    set hLastCorr [string trim $hLastCorr]
    if [catch {exec sddsprocess $orbitfile -pipe=out -match=col,ElementType=VKICK \
                   | sddssort -pipe -col=s \
                   | sddsprocess -pipe -clip=0,1,invert \
                   | sdds2stream -pipe -col=ElementName } vLastCorr] {
        return -code error $vLastCorr
    }
    set vLastCorr [string trim $vLastCorr]
    if [catch {sdds load $orbitfile tmpData} result] {
        return -code error $result
    }
    set nux [exec sdds2stream -par=nux $orbitfile]
    set nuy [exec sdds2stream -par=nuy $orbitfile]
    set names [lindex $tmpData(Column.ElementName) 0]
    set types [lindex $tmpData(Column.ElementType) 0]
    set index 0
    set hcorrnames ""
    set vcorrnames ""
    set bpmnames ""
    foreach name $names type $types {
        set coord ""
        if {$type=="HKICK"} {
            if [string match "*H" $name] {
                set coord x
                lappend hcorrnames $name 
            }
        } elseif {$type=="VKICK"} {
            if [string match "*V" $name] {
                set coord y
                lappend vcorrnames $name
            }
        } elseif {$type=="MONI"} {
            set coord bmp
            lappend bpmnames $name
            set orbitData($name.betax) [lindex [lindex $tmpData(Column.betax) 0] $index]
            set orbitData($name.betay) [lindex [lindex $tmpData(Column.betay) 0] $index]
            set orbitData($name.psix) [lindex [lindex $tmpData(Column.psix) 0] $index]
            set orbitData($name.psiy) [lindex [lindex $tmpData(Column.psiy) 0] $index] 
        }
        if [string length $coord] { 
            set orbitData($name.s) [lindex [lindex $tmpData(Column.s) 0] $index] 
            switch $coord {
                x -
                y {
                    set orbitData($name.beta)  [lindex [lindex $tmpData(Column.beta$coord) 0] $index]
                    set orbitData($name.psi) [lindex [lindex $tmpData(Column.psi$coord) 0] $index]
                }
            }
        }
        incr index
    }
    set hcorrnames [lsort $hcorrnames]
    set vcorrnames [lsort $vcorrnames]
    set orbitFileOpened 1 
    unset tmpData
}

proc SetStatus {text} {
    global mainStatus
    set mainStatus "[exec date +%H:%M:%S] $text"
    update
}

proc makeCommonData {args} {
    global outputDir dataDir lattice
    set timeList [exec sdds2stream -page=1 -col=RampTime $dataDir/$lattice/HVCorr.ramp]
    set len [llength $timeList]
    set time0 [lindex $timeList 0]
    set delta [expr 0.9/([lindex $timeList end] - $time0)]
    
    for {set i 0} {$i<$len} {incr i} {
	set time [lindex $timeList $i]
	lappend valList [expr $delta*($time-$time0)]
    }
    
    if [catch {exec sddsmakedataset -col=RampTime,type=double -data=[join $timeList ,] \
		   -col=RampSetpoint,type=double -data=[join $valList ,] \
		   $outputDir/ramp.sdds } result] {
	return -code error $result
    }
}

proc generateBump {args} {
    set plane ""
    APSParseArguments {plane}
    global bbvconfigured 

    global orbitfile xorbit orbitData orbitFileOpened hcorrnames vcorrnames bpmnames nux nuy PI totalCount outputDir
    global LastHCorr LastVCorr frameIndex hFrame vFrame lattice
   
    if ![file exist $outputDir/ramp.sdds] {
	makeCommonData
    }
    switch $plane {
	h {
	    set coord x
	}
	v {
	    set coord y
	}
    }
    # Setup
    if {!$orbitFileOpened} {
        if [catch {GetOrbitInfo} result] {
            return -code error $result
        }
    }
    global c1h c2h c3h c4h p1h p2h c1v c2v c3v c4v p1v p2v
    set fileList ""
    set tmpRoot /tmp/[APSTmpString]
    for {set i 0} {$i<$totalCount} {incr i} {
	set c1 [set c1${plane}($i.name)]
	set c2 [set c2${plane}($i.name)]
	set c3 [set c3${plane}($i.name)]
	set c4 [set c4${plane}($i.name)]
	set p1 [set p1${plane}($i.name)]
	set p2 [set p2${plane}($i.name)]
	
	set n [set ${plane}Frame($i.n)]
	set m [set ${plane}Frame($i.m)]
	if {$plane=="v" && $n==2 && $m==9} {
	    SetStatus "B${n}C${m}V does not exist, skip."
	    continue
	}
	SetStatus "compute coefficients for $plane plane B$n-C$m bump..."
	#puts "sector: B${n}C${m}[string toupper $plane]"
	ComputeCoefficients -plane $plane -c1 $c1 -c2 $c2 -c3 $c3 -c4 $c4 -p1 $p1 -p2 $p2 -index $i
	
	if [catch {exec sddsmakedataset $tmpRoot.$i -par=Lattice,type=string -data=$lattice \
		       -par=D1,type=double -data=$orbitData($i.D1) \
		       -par=D2,type=double -data=$orbitData($i.D2) \
		       -par=Z1,type=double -data=$orbitData($i.Z1) \
		       -par=Z2,type=double -data=$orbitData($i.Z2) \
		       -par=MonitorName1,type=string -data=$p1 \
		       -par=MonitorName2,type=string -data=$p2 \
		       -par=Sector,type=string -data=B${n}C${m}[string toupper $plane] \
		       -col=CorrectorName,type=string -data=$c1,$c2,$c3,$c4 \
		       -col=K,type=double -data=$orbitData($c1.$i.k),$orbitData($c2.$i.k),$orbitData($c3.$i.k),$orbitData($c4.$i.k) } result] {
	    return -code error "$result"
	    
	}
	lappend fileList $tmpRoot.$i
    }
    if [catch {eval exec sddscombine $fileList -over $outputDir/[string toupper $plane]coeff.sdds} result] {
	return -code error $result
    }
    eval file delete -force $fileList
    SetStatus "Done."
}



proc ComputeCoefficients {args} {
    set plane h
    set c1 ""
    set c2 ""
    set c3 ""
    set c4 ""
    set p1 ""
    set p2 ""
    set index ""
    APSParseArguments {plane c1 c2 c3 c4 p1 p2 index}
    
    global  orbitData nux nuy
    
    switch $plane {
        h {
            set coord x
	    set nu $nux
        }
        v {
            set coord y
	    set nu $nuy
        }
    }
    
    foreach nm {c1 c2 c3 c4 p1 p2} {
	set name [set $nm]
	set ${nm}name $name
	set ${nm}s [set orbitData($name.s)]
	foreach var {psi beta} {
	    if [regexp {p} $nm] {
		set ${nm}$var [set orbitData($name.${var}$coord)]
	    } else {
		set ${nm}$var [set orbitData($name.$var)]
	    }
	}
	#puts "$name psi=[set ${nm}psi] beta=[set ${nm}beta]"
    }
    #compute determinant Det=Sqrt(beta_c1*beta_c2*beta_p1*beta_p2) * sin(psi_c1_c2) * sin(psi_p1p2)
    
   # set det [expr sqrt($c1beta * $c2beta * $p1beta * $p2beta) * sin($c2psi - $c1psi) * sin($p2psi - $p1psi)]
    set det 1.0
    set psi_c1c2 [expr $c2psi - $c1psi]
    set psi_p1p2 [expr $p2psi - $p1psi]
    set psi_c2p2 [expr $p2psi - $c2psi]
    set psi_c2p1 [expr $p1psi - $c2psi]
    set psi_c1p1 [expr $p1psi - $c1psi]
    set psi_c1p2 [expr $p2psi - $c1psi]
    set psi_c1c4 [expr $c4psi - $c1psi]
    set psi_c2c4 [expr $c4psi - $c2psi]
    set psi_c3c4 [expr $c4psi - $c3psi]
    set psi_c4c4 [expr $c4psi - $c4psi]
    set PI 3.141592653589793238462643
    #puts "before c1p1=${psi_c1p1} c2p1=$psi_c2p1 c1p2=$psi_c1p2 c2p2=$psi_c2p2"
    if {$psi_c1c2<0} {set psi_c1c2 [expr $psi_c1c2 + 2.0*$PI*$nu]}
    if {$psi_c1p1<0} {set psi_c1p1 [expr $psi_c1p1 + 2.0*$PI*$nu]}
    if {$psi_c1p2<0} {set psi_c1p2 [expr $psi_c1p2 + 2.0*$PI*$nu]}
    if {$psi_c2p1<0} {set psi_c2p1 [expr $psi_c2p1 + 2.0*$PI*$nu]}
    if {$psi_c2p2<0} {set psi_c2p2 [expr $psi_c2p2 + 2.0*$PI*$nu]}
    if {$psi_p1p2<0} {set psi_p1p2 [expr $psi_p1p2 + 2.0*$PI*$nu]}
    if {$psi_c1c4<0} {set psi_c1c4 [expr $psi_c1c4 + 2.0*$PI*$nu]}
    if {$psi_c2c4<0} {set psi_c2c4 [expr $psi_c2c4 + 2.0*$PI*$nu]}
    if {$psi_c3c4<0} {set psi_c3c4 [expr $psi_c3c4 + 2.0*$PI*$nu]}
    if {$psi_c4c4<0} {set psi_c4c4 [expr $psi_c4c4 + 2.0*$PI*$nu]}
   # puts "after c1p1=${psi_c1p1} c2p1=$psi_c2p1 c1p2=$psi_c1p2 c2p2=$psi_c2p2"
    set m11 [expr sqrt ($c1beta * $p1beta ) * sin ($psi_c1p1)]
    set m12 [expr sqrt ($c2beta * $p1beta ) * sin ($psi_c2p1)]
    set m21 [expr sqrt ($c1beta * $p2beta ) * sin ($psi_c1p2)]
    set m22 [expr sqrt ($c2beta * $p2beta ) * sin ($psi_c2p2)]
    set det [expr $m11 * $m22 - $m12 * $m21]
    set t11 [expr $m22 / $det ]
    set t12 [expr -$m12 / $det]
    set t21 [expr -$m21 / $det]
    set t22 [expr $m11 / $det]
    set k1  [expr $t11 + $t12]
    set k2  [expr $t21 + $t22]
    #set k1 [expr 1 / (sqrt ($c1beta * $p1beta * $p2beta) / \
			  sin ($psi_c1c2) * sin ($psi_p1p2)) * (sqrt($p2beta) * \
								      sin ($psi_c2p2) - sqrt ($p1beta) * sin ($psi_c2p1))]
   # set k2 [expr 1 / (sqrt ($c2beta * $p1beta * $p2beta) / \
			  sin ($psi_c1c2) * sin ($psi_p1p2)) * (-sqrt($p2beta) * \
								      sin ($psi_c1p2) + sqrt ($p1beta) * sin ($psi_c1p1))]

    set k3 [expr -1.0/(sqrt($c3beta)*sin($psi_c3c4)) * \
		($k1 * sqrt($c1beta) * sin($psi_c1c4) + $k2 * sqrt($c2beta) * sin($psi_c2c4))]
    set k4 [expr -1.0/sqrt($c4beta) * ($k1 * sqrt($c1beta) * cos($psi_c1c4) + \
					 $k2 * sqrt($c2beta) * cos($psi_c2c4) + \
					 $k3 * sqrt($c3beta) * cos($psi_c3c4))]

    set D1 [expr $k1 * sqrt ($c1beta * $p1beta) * sin($psi_c1p1) + \
		$k2 * sqrt ($c2beta * $p1beta) * sin ($psi_c2p1)]
    set D2 [expr $k1 * sqrt ($c1beta * $p2beta) * sin($psi_c1p2) + \
		$k2 * sqrt ($c2beta * $p2beta) * sin ($psi_c2p2)]
   # puts "k1=$k1 k2=$k2 k3=$k3 k4=$k4 D1=$D1 D2=$D2"
    set Z1 [expr $k1 *  sqrt ($c1beta) * cos ($psi_c1c4) + \
		$k2 *  sqrt ($c2beta)  * cos ($psi_c2c4) +  \
		$k3 *  sqrt ($c3beta) * cos ($psi_c3c4) +  \
		$k4 *  sqrt ($c4beta) * cos ($psi_c4c4) ] 
    set Z2 [expr $k1 *  sqrt ($c1beta) * sin ($psi_c1c4) + \
		$k2 *  sqrt ($c2beta)  * sin ($psi_c2c4) +  \
		$k3 *  sqrt ($c3beta) * sin ($psi_c3c4) +  \
		$k4 *  sqrt ($c4beta) * sin ($psi_c4c4) ] 
    set orbitData($c1name.$index.k) $k1
    set orbitData($c2name.$index.k) $k2
    set orbitData($c3name.$index.k) $k3
    set orbitData($c4name.$index.k) $k4
    set orbitData($index.D1) $D1
    set orbitData($index.D2) $D2
    set orbitData($index.Z1) $Z1
    set orbitData($index.Z2) $Z2
}


# **************************** bbsetramp *******************************
proc bbsetramp {args} {
    global c1hname c2hname c3hname p1hname
    global c1hstrength c2hstrength c3hstrength p1hval 
    global bbhconfigured 

    global c1vname c2vname c3vname p1vname
    global c1vstrength c2vstrength c3vstrength p1vval 
    global bbvconfigured

    global loadRamp bumpStart hcorrnames vcorrnames outputDir

    set plane h  
    APSParseArguments {plane}
    set plane [string tolower $plane]
    if {![set bb${plane}configured]} {
        SetStatus "Horizontal not configured"
        return
    }
    if {$plane=="h"} {
        set orbitChange $p1hval
    } else {
        set orbitChange $p1vval
    }
    foreach nm {c1 c2 c3} {
        set ${nm}name [set ${nm}${plane}name]
        set ${nm}strength [set ${nm}${plane}strength]
    } 
    set origtable $outputDir/booster_orig_ramp.$plane
    if ![file exist $origtable] {
       # APSAddToTmpFileList -ID boosterbump -fileList $origtable
        SetStatus "Saving original $plane plane ramp table..."
        if [catch {SaveRampTable -corrList [set ${plane}corrnames] -ramptable $origtable \
                       -description "original ramp table" } result] {
            SetStatus $result
            return
        }
    }
    set index 1
    while {1} {
        set rampfile $outputDir/ramp_${c1name}_${c2name}_${c3name}_[format %03d ${index}].bump
        if ![file exist $rampfile] {
            break
        }
        incr index
    }
   
    regsub {bump} $rampfile before beforeBump
    #APSAddToTmpFileList -ID boosterbump -fileList $beforeBump
    SetStatus "Save current ramp table before bump:"
    if [catch {SaveRampTable -corrList [list $c1name $c2name $c3name] \
                   -ramptable $beforeBump -description "before bump" } result] {
        SetStatus $result
        return
    }
    SetStatus "Generating ramptable - $rampfile"
   # APSAddToTmpFileList -ID boosterbump -fileList "$rampfile"
    if [catch {exec  sddsboosterbump \
		   $rampfile -corrector=name=$c1name,bump=$c1strength -orbitChange=$orbitChange \
		   -corrector=name=$c2name,bump=$c2strength \
		   -corrector=name=$c3name,bump=$c3strength -bumptime=$bumpStart} result] {
        SetStatus $result
        return
    } 
    exec sddsplot -grap=sym,vary=sub,fill,conn=sub -split=page -group=page -sep=2 \
        -title=@ControlName -legend=par=Description \
        -col=RampTime,RampSetpoint $beforeBump  $rampfile &
    if $loadRamp {
        if ![APSYesNoPopUp "Load the ramp table with bump now?"] {
            return
        }
        SetStatus "Loading ramptable - $rampfile"
        if [catch {exec loadbramp -${plane} $rampfile} result] {
            SetStatus "Cannot load $rampfile\n$result"
            return
        }
    }
    SetStatus "done."
}

# **************************** bbsetstrength ***************************
proc bbsetstrength {args} {
    global c1hname c2hname c3hname p1hname
    global c1hs c2hs c3hs p1hs
    global c1hbeta c2hbeta c3hbeta p1hbeta
    global c1hpsi c2hpsi c3hpsi p1hpsi
    global c1hk c2hk c3hk p1hk
    global c1hstrength c2hstrength c3hstrength p1hval 
    global bbhconfigured

    global c1vname c2vname c3vname p1vname
    global c1vs c2vs c3vs p1vs
    global c1vbeta c2vbeta c3vbeta p1vbeta
    global c1vpsi c2vpsi c3vpsi p1vpsi
    global c1vk c2vk c3vk p1vk
    global c1vstrength c2vstrength c3vstrength p1vval 
    global bbvconfigured

    global BMRAD2AMP

    set plane H
    APSParseArguments {plane}
    set plane [string toupper $plane]
    if {$plane=="H"} {
        if {$bbhconfigured} {
            set delta [expr $p1hval/$p1hk]
            set c1hstrength [format "%.6f" [expr $delta*$c1hk*$BMRAD2AMP]]
            set c2hstrength [format "%.6f" [expr $delta*$c2hk*$BMRAD2AMP]]
            set c3hstrength [format "%.6f" [expr $delta*$c3hk*$BMRAD2AMP]]
        } else {
            set delta "Not Configured"
            set c1hstrength "Not Configured"
            set c2hstrength "Not Configured"
            set c3hstrength "Not Configured"
        }
    } else { 
        if {$bbvconfigured} {
            set delta [expr $p1vval/$p1vk]
            set c1vstrength [format "%.6f" [expr $delta*$c1vk*$BMRAD2AMP]]
            set c2vstrength [format "%.6f" [expr $delta*$c2vk*$BMRAD2AMP]]
            set c3vstrength [format "%.6f" [expr $delta*$c3vk*$BMRAD2AMP]]
        } else {
            set delta "Not Configured"
            set c1vstrength "Not Configured"
            set c2vstrength "Not Configured"
            set c3vstrength "Not Configured"
        }
    }
}

proc MakeSectorBumpWidget {args} {
    set n ""
    set m ""
    set plane ""
    set parent ""
    set frameIndex ""
    APSParseArguments {n m plane parent frameIndex}
    global c1h c2h c3h c4h p1h p2h c1v c2v c3v c4v p1v p2v orbitData
    
    switch $plane {
	h {
	    set coord x
	}
	v {
	    set coord y
	}
    }
    if {$n<=0 || $n>4} {
	return -code error "Invalid n ($n) provided."
    }
    if {$m<0 || $m>9} {
	return -code error "Invalid m ($m) provided."
    }
   
    set pl [string toupper $plane]
    switch $plane {
	h {
	    set m1 [expr $m-1]
	    if {$m1<0} {
		set n1 [expr $n-1]
		if {$n1<=0} {
		    set n1 4
		}
		set m1 9
	    } else {
		set n1 $n
	    }
	    set n2 $n
	    set m2 $m
	    set m3 [expr $m+1]
	    if {$m3>9} {
		set n3 [expr $n+1]
		if {$n3>4} {
		    set n3 1
		}
		set m3 0
	    } else {
		set n3 $n
	    }
	    set m4 [expr $m3 +1]
	    if {$m4>9} {
		set n4 [expr $n3+1]
		if {$n4>4} {
		    set n4 1
		}
		set m4 0
	    } else {
		set n4 $n3
	    }
	    set c1h($frameIndex.name) B${n1}C${m1}H
	    set c2h($frameIndex.name) B${n2}C${m2}H
	    set c3h($frameIndex.name) B${n3}C${m3}H
	    set c4h($frameIndex.name) B${n4}C${m4}H
	    if {[expr $n%2]==1} {
		 #the position is C1(m-1) C2(n,m) P2(n,m) P1(m+1) C3(m+1) C4(m+1)
		set p1h($frameIndex.name) B${n}C${m}P2
		set p2h($frameIndex.name) B${n3}C${m3}P1
	    } else {
		#the position is C1(m-1) C2(n,m) P1(n,m) P2(n,m) C3(m+1) C4(m+1)
		set p1h($frameIndex.name) B${n}C${m}P1
		set p2h($frameIndex.name) B${n}C${m}P2
	    }
	}
	v {
	    if {$n==2 && $m==7} {
		#B2C7V
		set c1v($frameIndex.name) B2C6V
		set c2v($frameIndex.name) B2C7V
		set c3v($frameIndex.name) B2C8V
		set c4v($frameIndex.name) B3C1V
		set p1v($frameIndex.name) B2C7P1
		set p2v($frameIndex.name) B2C7P2
	    } elseif {$n==3 && $m==1} {
		#B3C1V
		set c1v($frameIndex.name) B2C7V
		set c2v($frameIndex.name) B3C0V
		set c3v($frameIndex.name) B3C1V
		set c4v($frameIndex.name) B3C2V
		set p1v($frameIndex.name) B3C1P1
		set p2v($frameIndex.name) B3C1P2
	    } else {
		if {[expr $n%2]==1} {
		    #the position is V1(m-2) V2(m-1) P1(n,m) P2(n,m) V3(n,m) V4(m+1)
		    set n3 $n
		    set m3 $m
		    set m2 [expr $m -1]
		    if {$m2<0} {
			set n2 [expr $n3 -1]
			if {$n2<=0} {
			    set n2 4
			}
			set m2 9
		    } else {
			set n2 $n3
		    }
		    if {$n2==2 && $m2==9} {
			#B2C9 does not exist, go to upper corrector B2C8V, moved to B2C7V per CY's request
			set m2 8
		    }
		    set m1 [expr $m2-1]
		    if {$m1<0} {
			set n1 [expr $n2 - 1]
			if {$n1<=0} {
			    set n1 4
			}
			set m1 9
		    } else {
			set n1 $n2
		    }
		    if {$n1==2 && $m1==9} {
			#B2C9 does not exist, go to upper corrector B2C8V
			set m1 8
		    }
		    set m4 [expr $m3+1]
		    if {$m4>9} {
			set n4 [expr $n3+1]
			if {$n4>4} {
			    set n4 1
			}
			set m4 0
		    } else {
			set n4 $n3
		    }
		    if {$n4==2 && $m4==9} {
			#B2C9V does not exist, go to next corrector B3C0V
			set n4 3
			set m4 0
		    }
		    set c1v($frameIndex.name) B${n1}C${m1}V
		    set c2v($frameIndex.name) B${n2}C${m2}V
		    set c3v($frameIndex.name) B${n3}C${m3}V
		    set c4v($frameIndex.name) B${n4}C${m4}V
		    set p1v($frameIndex.name) B${n}C${m}P1
		    set p2v($frameIndex.name) B${n}C${m}P2
		} else {
		    #the position is V1(m-1) V2(m) P2(n,m) P1(m+1) V3(m+1) V4(m+2)
		    set n2 $n
		    set m2 $m
		    set m1 [expr $m2 -1]
		    if {$m1<0} {
			set n1 [expr $n2 -1]
			if {$n1<=0} {
			    set n1 4
			}
			set m1 9
		    } else {
			set n1 $n2
		    }
		    if {$n1==2 && $m1==9} {
			#B2C9V does not exist, go to upper corrector B2C8V
			set m1 8
		    }
		    set m3 [expr $m2 + 1] 
		    if {$m3>9} {
			set n3 [expr $n2 +1]
			if {$n3>4} {
			    set n3 1
			}
			set m3 0
		    } else {
			set n3 $n2
		    }
		    if {$n3==2 && $m3==9} {
			#B2C9V does not exist, go to next corrector B3C0V
			set n3 3
			set m3 0
		    }
		    set m4 [expr $m3+1]
		    if {$m4>9} {
			set n4 [expr $n3+1]
			if {$n4>4} {
			    set n4 1
			}
			set m4 0
		    } else {
			set n4 $n3
		    }
		    if {$n4==2 && $m4==9} {
			#B2C9V does not exist, go to next corrector B3C0V
			set n4 3
			set m4 0
		    }
		    set c1v($frameIndex.name) B${n1}C${m1}V
		    set c2v($frameIndex.name) B${n2}C${m2}V
		    set c3v($frameIndex.name) B${n3}C${m3}V
		    set c4v($frameIndex.name) B${n4}C${m4}V
		    set p1v($frameIndex.name) B${n}C${m}P2
		    set p2v($frameIndex.name) B${n3}C${m3}P1
		}
		if {$n==1 && $m==0} {
		    #B1C0V
		    set p1v($frameIndex.name) B4C9P2
		    set p2v($frameIndex.name) B1C0P2
		}
		if {$n==3 && $m==0} {
		    set p1v($frameIndex.name) B2C9P2
		    set p2v($frameIndex.name) B3C0P2
		}
	    }
	}
    }
    APSFrameGrid .grid -parent $parent -xList {1 2 3 4 5 6 7} -yList {0 1 2 3 4 5 6 7} -packOption "-side left"
    set nameList {"Name" "s, m" "Beta" "Psi" "K" "Current Values, Amp, mm" "Bump Values, Amp, mm"}
    foreach corr {1 2 3 4} {
	set corrName [set c${corr}${plane}($frameIndex.name)]
	global $corrName
	set c${corr}varList [list c${corr}${plane}($frameIndex.name) orbitData(${corrName}.s) \
				 orbitData(${corrName}.beta) orbitData(${corrName}.psi) orbitData(${corrName}.$frameIndex.k) \
				 orbitData(${corrName}.cur) orbitData(${corrName}.$frameIndex.strength)]
	lappend varList orbitData(${corrName}.cur)
	lappend pvnameList ${corrName}:CurrentAO
    }
    set p1Name [set p1${plane}($frameIndex.name)]
    set p2Name [set p2${plane}($frameIndex.name)]
    set p1varList [list p1${plane}($frameIndex.name) orbitData(${p1Name}.s) \
		       orbitData(${p1Name}.beta$coord) orbitData(${p1Name}.psi$coord) orbitData(${p1Name}.k$coord) \
		       orbitData(${p1Name}.cur$coord) orbitData(${p1Name}.val$coord)]
    set p2varList [list p2${plane}($frameIndex.name) orbitData(${p2Name}.s) \
		       orbitData(${p2Name}.beta$coord) orbitData(${p2Name}.psi$coord) orbitData(${p2Name}.k$coord) \
		       orbitData(${p2Name}.cur$coord) orbitData(${p2Name}.val$coord)]
    lappend varList orbitData(${p1Name}.cur$coord)
    lappend pvnameList ${p1Name}:ms:$coord
    lappend varList orbitData(${p2Name}.cur$coord)
    lappend pvnameList ${p2Name}:ms:$coord
    if {0} {
    if [pv linkw $varList $pvnameList] {
	return -code error "Can not link to $pvnameList."
    }
    if [pv umon $varList] {
	return -code error "Can not monitor $pvnameList."
    }
	}
    set w $parent.grid
    set j 1
    for {set i 2} {$i<=7} {incr i} {
        if {$i==6} {
            set text P1
	} elseif {$i==7} {
	    set text P2
        } else {
            set text C$j
        }
        incr j
        APSLabel .c -parent $w.$i.0 -text $text
    }
    
    for {set j 1} {$j<=7} {incr j} {
        set i [expr $j -1]
	set contextHelp "Bump coefficients for correctors and a similar coefficient for the\
       monitor.  These are set during configuration.  The actual strengths\
       in mrad for correctors are these values times the bump amplitude.  The\
       monitor coefficient is defined so that the required bump amplitude\
       is the ratio of the monitor coefficient and the desired monitor value\
       in mm.  These coefficients do not depend on the corrector settings nor\
       the desired monitor value.  They are used to determine the corrector\
       settings given the desired bump value."

	APSLabel .label -parent $w.1.$j -text [lindex $nameList $i] -packOption "-side right" 
	APSLabeledOutput .c1 -parent $w.2.$j -label "" -textVariable [lindex $c1varList $i] -width 15 -contextHelp $contextHelp
	APSLabeledOutput .c2 -parent $w.3.$j -label "" -textVariable [lindex $c2varList $i] -width 15 -contextHelp $contextHelp
	APSLabeledOutput .c3 -parent $w.4.$j -label "" -textVariable [lindex $c3varList $i] -width 15 -contextHelp $contextHelp
	APSLabeledOutput .c4 -parent $w.5.$j -label "" -textVariable [lindex $c4varList $i] -width 15 -contextHelp $contextHelp
	APSLabeledOutput .p1 -parent $w.6.$j -label "" -textVariable [lindex $p1varList $i] -width 15 -contextHelp $contextHelp
	APSLabeledOutput .p2 -parent $w.7.$j -label "" -textVariable [lindex $p2varList $i] -width 15 -contextHelp $contextHelp
    }
    
}

proc MakeBumpWidget {args} {
    set parent ""
    set plane h
    APSParseArguments {parent plane}
    global hFrameIndex vFrameIndex hFrame vFrame totalCount
    set labelList ""
    set nList ""
    set mList ""
    
    set count 0
    for {set n 1} {$n<5} {incr n} {
	for {set m 0} {$m<10} {incr m} {
	    lappend labelList ${n}-${m}
	    set hFrame($count.n) $n
	    set hFrame($count.m) $m
	    set vFrame($count.n) $n
	    set vFrame($count.m) $m
	    incr count
	}
    }
    set totalCount $count
    set widgetList [APSTabFrame .sector -parent $parent -label "" -labelList $labelList \
			-width 1520 -height 320 -frameIndexVariable ${plane}FrameIndex]
    APSButton .gen -parent $parent -text "Generate Bump Table" -command "generateBump -plane $plane" -packOption "-side top" \
	-contextHelp "generate booster bump table for selected plan, 40 files will be generated for each plane."
    for {set i 0} {$i<$totalCount} {incr i} {
	set n [set ${plane}Frame($i.n)]
	set m [set ${plane}Frame($i.m)]
	set parent1 [lindex $widgetList $i]
	MakeSectorBumpWidget -n $n -m $m -plane $plane -parent $parent1 -frameIndex $i
    }
    return
}

proc MakeBoosterConstantsFrame {args} {
    set parent ""
    APSParseArguments {parent}

    global loadRamp BMRAD2AMP BCORMAX nux nuy bumpStart outputDir

    APSFrame .const -parent $parent -label "Booster constants"
    set parent $parent.const.frame
    APSFrameGrid .grid -parent $parent -xList {x1 x2}
    set w1 $parent.grid.x1
    set w2 $parent.grid.x2 
    APSLabeledEntry .curr -parent $w1 -label "Maximum corr. current (Amp)" -textVariable BCORMAX -width 20
    APSLabeledEntry .curr1 -parent $w2 -label "Booster mini-rad to amp converter (Amp)" -textVariable BMRAD2AMP -width 20
    bind $w2.curr1.entry <Return> "UpdateCoefficients"
    APSLabeledEntry .nux -parent $w1 -label "X tune (rad):" -textVariable nux -width 20
    APSLabeledEntry .nuy -parent $w2 -label "Y tune (rad):" -textVariable nuy -width 20
    APSLabeledEntry .lattice -parent $w1 -label "Lattice:" -textVariable lattice
    APSButton .load -parent $w1.lattice -text "Load Orbit Data" -size small -packOption "-side right" \
        -command "GetLattice;bbconfigure -plane h;bbconfigure -plane v" \
        -contextHelp "press to load the orbit data if lattice changes."
    APSLabeledEntry .time -parent $w2 -label "Bump start time (ms):" -textVariable bumpStart -width 20
    APSRadioButtonFrame .load -parent $w1 -label "Load bump table?" -buttonList {Yes No} -valueList {1 0} -variable loadRamp \
        -orientation horizontal -contextHelp "If No is choosen, then the ramptable will be generated without loading. Otherwise, the generated ramptable will be loaded."
    APSButton .compare -parent $w2 -text "Plot" -command "PlotRampTables" \
        -contextHelp "plot the ramp table with bump and ramp table before the bump." 
    APSButton .loadorig -parent $w2 -text "Load Orig. Table" -command "LoadOrigRampTable"
    APSButton .savebump -parent $w2 -text "Save Bump" -command "SaveBumpTable"
    APSLabeledEntry .dir -parent $parent -label "Output directory:" -width 80 -textVariable outputDir \
	-fileSelectButton 1  -fileSelectDirectory 1
}

proc GetLattice {} {
    global lattice dataDir
    set lattice [file tail [file readlink $dataDir/default]]
    
}

# **************************** overviewtext ****************************
proc overviewtext {} {
    return "
                     Booster Bump Generator

     This interface can be used to set bumps in the Booster.  The
procedure is to specify the names of the correctors and the monitor,
\"Configure\" the bump by getting the Twiss parameters, specify the
bump amplitude at the monitor, and then \"Set\" the bump into the ramp
tables and load the AFG.  There are buttons for Configure and Set.

     By specifying -x on the command line, Xorbit will be used rather
than the real machine.

     The new ramps are loaded using the current values in the
:rampRAMPTABLE process variables.  These are not necessarily the
values that are loaded into the AFG foreground (and hence the ones
being used by the power supplies to actually ramp the correctors), but
they are the only values available.  It is necessary to insure that
the values in the :rampRAMPTABLE process variable are valid and have
been loaded into the AFG foreground.  This should be the case if a
rampload has been done recently."
}

proc UpdateDataDir {args} {
    global lattice dataDir outputDir orbitfile
    set outputDir $dataDir/$lattice
    set orbitfile $dataDir/$lattice/booster.twi
    GetOrbitInfo
}
# **********************************************************************
# **************************** main ************************************
# **********************************************************************

set name "Booster Bump Generator"
set overview [overviewtext]
set version "$name\n\n\$Revision: 1.6 $\n\$Author: soliday $"

APSApplication . -name $name -version $version -overview $overview \
  -contextHelp "Sorry, there is no context help available for this widget."

set mainStatus ""
APSScrolledStatus .status -parent .userFrame -textVariable mainStatus -width 70

GetLattice
APSRadioButtonFrame .lattice -parent .userFrame -label "Select lattice" -buttonList "x11.75-y9.80 x11.75-y9.80-A x12.75-y9.80 x13.75-y5.80" \
    -valueList "x11.75-y9.80 x11.75-y9.80-A x12.75-y9.80 x13.75-y5.80" -orientation horizontal -variable lattice \
    -commandList "UpdateDataDir UpdateDataDir UpdateDataDir UpdateDataDir"
APSLabeledEntry .dir -parent .userFrame -label "Bump output directory:" -textVariable outputDir -width 90
set widgetList [APSTabFrame .tab -parent .userFrame -label "Coefficients" -labelList "Horizontal Vertical" \
                    -width 1550 -height 400 -packOption "-expand true" -frameIndexVariable planeIndex]


MakeBumpWidget -parent [lindex $widgetList 0] -plane h
MakeBumpWidget -parent [lindex $widgetList 1] -plane v

GetOrbitInfo
