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

# $Log: not supported by cvs2svn $
# Revision 1.4  2011/04/22 20:54:51  shang
# modified to use sddsexperiment to scan the booster ramp time for verify ramps, which is more efficient and tcl loop-scan.
#
# Revision 1.3  2011/03/08 16:11:24  shang
# changed to normalized the reference to 19 A, instead of normalize measurement to 1.
#
# Revision 1.2  2011/03/01 21:56:38  shang
# fixed a typo (aftr should be after).
#
# Revision 1.1  2011/02/28 22:45:09  shang
# new booster corrector ramp loading and verifying tool.
#

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.5 $ \$Author: shang $"
APSDebugPath

proc SetStatus {text} {
    global status
    set status "[exec date] $text"
    update
}

proc GetLatticeFile {args} {
    global latticeFile
    if [catch {exec cavget -list=BOO:LatticeCALC -pend=10 -printErrors} lattice] {
	return -code error $lattice
    }
    switch $lattice {
	 132 {
	     set Lattice x11.75-y9.80
	 }
	109 {
	    set Lattice x12.75-y9.80
	}
	 92 {
	     set Lattice x13.75-y5.80
	 }
	default {
            set Lattice "unknown"
	}
     }
   # set latticeFile /home/helios/oagData/booster/ramps/correctors/lattices/$Lattice/HVCorr.ramp
}

proc GetSelectedCorrectors {args} {
    global sectorList hCorr vCorr missingListH missingListV
    
    set corrList ""
    foreach quad {B1 B2 B3 B4} {
	foreach sector $sectorList {
	    set nm ${quad}$sector
	    global $nm
	    if [set $nm] {
		lappend corrList $nm
	    }
	}
    }
    if ![llength $corrList] {
	return -code error "No correctors selected."
    }
    set corrList1 ""
    if {!$hCorr && !$vCorr} {
	return -code error "corrector plane not selected."
    }
    foreach plane {h v} {
        switch $plane {
            h {
                set missingList $missingListH
            }
            v {
                set missingList $missingListV
            }
        }
	if [set ${plane}Corr] {
	    foreach corr $corrList {
                set corrpv ${corr}[string toupper $plane]
                if [lsearch -exact $missingList $corrpv]<0 {
                    lappend corrList1 $corrpv
                }
	    }
	}
    }
    return $corrList1
}

proc TurnOnOffPS {args} {
    set on 1
    APSParseArguments {on}
    if $on {
	set suffix :ResetSEQ
	set value 1
	set name resetON
    } else {
	set suffix :OnBO
	set value 0
	set name "turn Off"
    }
    if [catch {GetSelectedCorrectors} corrList] {
	SetStatus "$corrList"
	return
    }
    if [APSYesNoPopUp "Are you sure to $name [join $corrList ,]?"] {
	if [catch {exec cavput -list=[join $corrList] -list=$suffix=$value -pend=30} result] {
	    return -code error "Unable to $name correctors; $result"
	}
    }
}

proc LoadRamps {args} {
    global latticeFile corrList
    if [catch {GetSelectedCorrectors} corrList] {
	SetStatus "$corrList"
	return
    }
    set option -match=par,CorrName=[lindex $corrList 0]
    for {set i 1} {$i<[llength $corrList]} {incr i} {
	append option ,CorrName=[lindex $corrList $i],|
    }
    set tmpFile /tmp/[APSTmpString].bramp
    if [catch {exec sddsprocess $latticeFile $option $tmpFile} result] {
	return -code error $result
    }
    SetStatus "loading ramps..."
    if [catch {exec ramploadnew $tmpFile} result] {
	return -code error "Error in loading ramps $tmpFile: $result"
    }
    APSAddToTmpFileList -ID bcorr -fileList $tmpFile
    SetStatus "done."
}

proc VerifyRamps {args} {
    global corrList verifyFile latticeFile 
    if [catch {GetSelectedCorrectors} corrList] {
	SetStatus "$corrList"
	return
    }
  #  if [catch {LoadRamps} result] {
  #      return -code error "Error loading reference ramps: $result"
  #  }
    
    APSWaitWithUpdate -waitSeconds 2
    set pvList ""
    foreach corr $corrList {
        lappend pvList B:${corr}:CurrentWF
    }
    set tmpRoot /tmp/[APSTmpString]
    
    if [catch {exec sddswmonitor $tmpRoot.mon -pvnames=[join $pvList ,] -pend=20 -step=1 } result] {
        SetStatus "Error reading current waveform: $result"
        return
    }
    set interval [expr 476.264/4000]
    if [catch {exec sddsprocess $tmpRoot.mon $tmpRoot.verify "-define=col,Time,Index $interval *"  \
                 "-redefine=col,%s,%s 32767 - 32768 /,select=*WF" } result] {
        SetStatus "Error processing current waveform: $result"
        return
    }
    file delete $tmpRoot.mon
    set verifyFile $tmpRoot.verify
  
  #  exec sddsplot -sep -col=Index,*WF $tmpRoot.verify -leg &
    PlotCorrVerify 
    file delete $tmpRoot.verify
    return
}

proc PlotCorrVerify {args} {
    
    global latticeFile corrList verifyFile
    
    set tmpRoot /tmp/[APSTmpString]
    set option ""
    foreach corr $corrList {
        if [catch {exec sddsprocess $latticeFile $tmpRoot.$corr.ramp -match=par,CorrName=$corr
            exec sddsconvert $verifyFile -pipe=out \
		       -retain=col,Time,B:${corr}:CurrentWF \
                     | sddsinterp -pipe -col=Time,B:${corr}:CurrentWF -fileValues=$tmpRoot.$corr.ramp,col=RampTime \
                     | sddsconvert -pipe -rename=col,B:${corr}:CurrentWF=Measured \
                     | sddsprocess -pipe "-reprint=par,CorrName,$corr" \
                     | sddsxref -pipe=in $tmpRoot.$corr.ramp -take=RampSetpoint $tmpRoot.$corr } result] {
            return -code error "Error in process measurement for $corr: $result"
        }
        file delete $tmpRoot.$corr.ramp
	lappend fileList $tmpRoot.$corr
    }
    if [catch {eval exec sddscombine $fileList -pipe=out \
		   | sddssort -pipe=in -par=CorrName $tmpRoot.meas } result] {
	return -code error "Error in sddscombine: $result"
    }
    eval file delete $fileList
    APSAddToTmpFileList -ID bcorr -fileList $tmpRoot.meas
    exec  sddsplot -groupby=page -split=page -sep=page \
	-graph=sym,vary=type,connect=type,subtype=type \
	-col=Time,Measured \
	-samescale=y   \
	-leg=specified=Measured $tmpRoot.meas \
	-col=Time,RampSetpoint -topline=@CorrName -leg=specified=RampTable $tmpRoot.meas &
}

proc ReadCorrectorCurrent {args} {
    global corrList latticeFile 
    if [catch {GetSelectedCorrectors} corrList] {
        SetStatus "$corrList"
        return
    }
    set gainFile /home/helios/oagData/booster/ramps/correctors/lattices/corrector_gain.sdds
    
    set tmpRoot /tmp/[APSTmpString]
    puts $tmpRoot
    set pvList ""
    foreach corr $corrList {
        lappend pvList B:${corr}:CurrentWF
    }
    set interval [expr 476.264/4000]
    if [catch {exec sddswget -pvnames=[join $pvList ,] $tmpRoot.mon  -pend=50 } result] {
        SetStatus "Error reading current waveform: $result"
        return
    }
    set timeList [exec sdds2stream -col=RampTime $latticeFile -page=1]
    if [catch {exec sddsprocess $tmpRoot.mon  "-redefine=col,Time,Index $interval *" \
                 -edit=par,CorrName,WaveformPV,%/B://%/:CurrentWF// \
                 "-define=col,RampSetpoint,Waveform 32767 - 32768 /" -pipe=out \
                 | sddsinterp -pipe=in -col=Time,RampSetpoint -atValues=[join $timeList ,] \
                 $tmpRoot.current } result] {
        SetStatus "Error processing current waveform: $result"
        return
    }
    APSAddToTmpFileList -ID bcorr -fileList $tmpRoot.mon
    APSAddToTmpFileList -ID bcorr -fileList $tmpRoot.current
    set fileList ""
    foreach corr $corrList {
        if [catch {exec sddsprocess $gainFile -match=col,CorrName=$corr -pipe=out \
                     | sdds2stream -pipe -col=Gain } gain] {
            return -code error "Error geting $corr gain: $gain"
        }
        if [catch {exec sddsprocess $tmpRoot.current -match=par,CorrName=$corr \
                     -define=par,Gain,$gain $tmpRoot.$corr } result] {
            return -code error "Error process corrector gain: $result"
        }
        lappend fileList $tmpRoot.$corr
    }
    APSAddToTmpFileList -ID bcorr -fileList $fileList
    if [catch {eval exec sddscombine $fileList -pipe=out \
                 | sddsprocess -pipe=in $tmpRoot.ramp \"-define=col,Current,RampSetpoint Gain *,units=A\" } result] {
        SetStatus "Error computing current: $result"
        return
    }
    APSAddToTmpFileList -ID bcorr -fileList $tmpRoot.ramp
    exec  sddsplot -topline=@CorrName -split=page -sep=page \
      -graph=sym,vary=type,connect=type,subtype=type \
      -col=Time,Current \
      -samescale=y $tmpRoot.ramp &
}
   

proc SelectCorrectors {args} {
    set all 1
    APSParseArguments {all}
    global sectorList 
  
    foreach quad {B1 B2 B3 B4} {
	foreach sector $sectorList {
	    set nm ${quad}$sector
	    global $nm
	    set $nm $all
	}
    }
}

proc PickLatticeFile {args} {
    global latticeFile
    set dir [file dirname [file dirname $latticeFile]]
    
    set filename [APSFileSelectDialog .chooselatticeFile \
		      -listDir $dir]
    if {[string length $filename]!=0} {
        set latticeFile $filename
    }
}

proc SetBoosterPowerSupplies {args} {
    global PowerOn TurnOnPlane Fast RawOnly
    if $PowerOn {
        set text "turn on"
        set state1 on
    } else {
        set text "turn off"
        set state1 off
    }
    if ![APSYesNoPopUp "Are you sure to $text booster $TurnOnPlane plane power supplies"] {
        SetStatus "Turn $text  plane power supplies was cancelled."
        return
    }
    SetStatus "Set booster power supplies..."
    if [catch {APSMpBoosterSetCorrPowerSuppliesOnOff -state1 $state1 -selection $TurnOnPlane \
                 -Fast $Fast -RawOnly $RawOnly } result] {
        SetStatus "Error in setting booster power supplies: $result"
        return
    }
    SetStatus "done."
    return
}
set PowerOn on
set TurnOnPlane both
set Fast 0 
set RawOnly 0
proc TurnOnOffPowerSupplies {args} {
    global PowerOn TurnOnPlane Fast RawOnly
    
    APSDialogBox .onoff -name "Turn On/Off power supplies" -width 60 -cancelCommand "" -okCommand SetBoosterPowerSupplies \
      -contextHelp "press ok to turn on/off power supplies"
    APSFrame .power -parent .onoff.userFrame -label "Set Power Supplies"
    set w .onoff.userFrame.power.frame
    APSRadioButtonFrame .onoff -parent $w -label "Power: " -buttonList {on off} -valueList {on off} \
      -variable PowerOn -orientation horizontal \
      -contextHelp "Specifies whether to turn the correctors on or off."
    APSRadioButtonFrame .plane -parent $w -variable TurnOnPlane -label "Plane: " \
      -buttonList {H V Both} -valueList {h v both} -orientation horizontal -contextHelp \
      "Specifies the plane for which the correctors will be turned on/off."
    
    APSCheckButtonFrame .checkfast -parent $w -orientation horizontal \
      -label "" -buttonList {Fast "Raw Only"} \
      -variableList {Fast RawOnly } \
      -contextHelp \
      "Fast: Does not zero the ramps before turning off, and does not perform the\
       INIT/AUTO/ACTIVATE procedure before turning on.\n\
       Raw Only: Only does the raw supplies (and uses Fast mode)."
    
}

APSApplication . -name BoosterCorrectorControlNew -version $CVSRevisionAuthor \
  -overview "booster corrector controls." 

set missingListV {B2C9V}
set missingListH ""

set waitTime 1.0
set status ""
APSScrolledStatus .status -parent .userFrame -width 80 \
        -textVariable status 
set hCorr 1
set vCorr 1
APSCheckButtonFrame .plane -parent .userFrame -buttonList {HCorrs VCorrs} -label "Select plane:" \
    -variableList {hCorr vCorr} -orientation horizontal -allNone 0
APSButton .all -parent .userFrame.plane  -text "Both" -size small -packOption "-side left" \
    -command "set hCorr 1;set vCorr 1"
APSButton .none -parent .userFrame.plane  -text "None" -size small -packOption "-side left" \
    -command "set hCorr 0;set vCorr 0"
#only allow v plane for now

APSFrame .f1 -parent .userFrame -label "Quadrant Selection"
set w1 .userFrame.f1.frame
set sectorList {C0 C1 C2 C3 C4 C5 C6 C7 C8 C9}
foreach cat {B1 B2 B3 B4} {
    set varList ""
    set buttonList ""
    set buttonNumber 0
    foreach but $sectorList {
	set ${cat}$but 0
	lappend varList ${cat}$but
        incr buttonNumber
        lappend buttonList $buttonNumber
    }
    APSCheckButtonFrame .c$cat -parent $w1 -label "$cat" -buttonList $sectorList -variableList $varList \
      -orientation horizontal -allNone 1
}

proc GetLatticeDescription {lattice} {
    switch $lattice {
	"x11.75-y9.80" {
	    set BoosterLatticeState "High Emittance Lattice - 132 nm rad"
	}
	"x12.75-y9.80"  {
	    set BoosterLatticeState "Low Emittance Lattice - 109 nm rad"
	}
	"x13.75-y5.80" {
	    set BoosterLatticeState "Low Emittance Lattice - 92 nm rad"
	}
	default {
	    set BoosterLatticeState "unknown"
	}
    }
    return $BoosterLatticeState
}

proc GetBoosterLattice {args} {
    if [catch {exec cavget -list=BOO:LatticeCALC -pend=10} lattice] {
	return -code error "Unable to read lattice: $lattice"
    }
    global Lattice
    switch $lattice {
	132 {
	    set Lattice x11.75-y9.80
	}
	109 {
	    set Lattice x12.75-y9.80
	}
	92 {
	    set Lattice x13.75-y5.80
	}
	default {
            set Lattice "unknown"
	}
    }
    if [catch {exec cavget -list=It:L:1HzNot2Hz_bo.VAL -pend=20} mode] {
        retunr -code error "Error in reading mode: $mode"
    }
    if [string compare $Lattice "unknown"]==0 {
	SetStatus "Can not decide the lattice from chosen file, please choose one!"
	set Lattice ""
	APSDialog .lattice -name "Choose Lattice Dialog" \
	    -okCommand "update" -cancelCommand "destroy .lattice"
	APSRadioButtonFrame .radio -parent .lattice.userFrame -buttonList "92nm 109nm 132nm" \
	    -variable Lattice -valueList "x13.75-y5.80 x12.75-y9.80 x11.75-y9.80"
	tkwait window .lattice
	if ![string length $Lattice] {
	    return -code error "The lattice was not chosen!"
	}
    }
   # if [catch {file readlink /home/helios/oagData/booster/ramps/correctors/HVCorr.ramp} oldLink] {
   #     set oldLink ""
   # }
   # if {![string length $oldLink] || ![string match *$Lattice* $oldLink]} {
	#if [catch {file delete -force /home/helios/oagData/booster/ramps/correctors/HVCorr.ramp
	#    file link -symbolic /home/helios/oagData/booster/ramps/correctors/HVCorr.ramp /home/helios/oagData/booster/ramps/correctors/lattices/$Lattice/HVCorr.ramp } result] {
	 #   SetStatus "Unable to link the corrector ramp default dir to $Lattice, please link it manually: $result"
	#}
    #}
    #global BoosterLattice 
    #set BoosterLattice $Lattice
    SetStatus "The lattice now is $Lattice, [GetLatticeDescription $Lattice] $mode"
    return $Lattice
}

set RampSteps 5
set WaitTime 10
proc RampCorrector {args} {
    global latticeFile corrList abortRamp
    if [catch {GetSelectedCorrectors} corrList] {
	SetStatus "$corrList"
	return
    }
   
    global RampSteps WaitTime dialogResponse
    set dialogResponse 0
    APSDialogBox .ramp -name "Ramp Parameters" \
      -okCommand "set dialogResponse 1" \
      -cancelCommand "set dialogResponse 2"
    APSLabeledEntry .steps -parent .ramp.userFrame -label "Ramp Steps:" -textVariable RampSteps -width 40
    APSLabeledEntry .interval -parent .ramp.userFrame -label "Wait time between ramp steps:" -textVariable WaitTime -width 40
    tkwait variable dialogResponse
    if {$dialogResponse==2} {
        SetStatus "Ramp was canceled."
        return
    }
    set tmpRoot /tmp/[APSTmpString]
    set fileList ""
  
    foreach corr $corrList {
        APSAddToTempFileList -ID rampBcorr -fileList "$tmpRoot.$corr.1 $tmpRoot.$corr.2 $tmpRoot.$corr.3 $tmpRoot.$corr.4 $tmpRoot.$corr.ramp"
        if [catch {exec sddswmonitor -pv=B:${corr}:time,B:${corr}:source $tmpRoot.$corr.1 
            exec sddsconvert $tmpRoot.$corr.1 -pipe=out -rename=col,B:${corr}:time=RampTime,B:${corr}:source=RampSetpoint \
                     | sddsprocess -pipe -reprint=par,CorrName,$corr \
                    -process=RampTime,max,MaxIndex,position,functionOf=Index \
                     | sddsprocess -pipe=in $tmpRoot.$corr.2 -filter=col,Index,0,MaxIndex } result] {
            return -code error "Error reading $corr waveforms: $result"
        }
        if [catch {exec sddsprocess $latticeFile -match=par,CorrName=$corr $tmpRoot.$corr.3} result] {
            return -code error "Error in finding ramp waveform for $corr: $result"
        }
        set rampTo $tmpRoot.$corr.3
        if [catch {exec sddsdiff $tmpRoot.$corr.3 $tmpRoot.$corr.2 -col=RampTime} result] {
            #RampTime is different, need to do intepolate
            if [catch {exec sddsinterp $tmpRoot.$corr.3 -col=RampTime,RampSetpoint \
                         -fileValues=$tmpRoot.$corr.2,col=RampTime $tmpRoot.$corr.4} result] {
                return -code error "Error interploating ramp table: $result"
            }
            set rampTo $tmpRoot.$corr.4
        }
        if [catch {exec sddsxref $tmpRoot.$corr.2 $rampTo -equate=RampTime -rename=col,RampSetpoint=RampTo -pipe=out \
                     | sddsprocess -pipe=in $tmpRoot.$corr "-define=col,RampDelta,RampTo RampSetpoint - $RampSteps /" } result] {
            return -code error "Error generating ramp delta: $result"
        }
        lappend fileList $tmpRoot.$corr
    }
    if [catch {eval exec sddscombine $fileList $tmpRoot.ramp } result] {
        return -code error "Error combining files: $result"
    }
    APSAddToTempFileList -ID brampcorr -fileList $tmpRoot.ramp
    SetStatus "Ramping..."
    for {set i 1} {$i<=$RampSteps} {incr i} {
        if $abortRamp {
            set abortRamp 0
            if {$i>1} {
                SetStatus "The last ramp file loaded was $tmpRoot.ramp.[expr $i - 1]"
                set dailyDir [APSGoToDailyDirectory -subDir rampBCorr]
                set saveFile $dailyDir/bcorrRamp.[clock format [clock seconds] -format %H:%M:%S]
                exec cp $tmpRoot.ramp.[expr $i - 1] $saveFile
                SetStatus "The last ramp file loaded is saved at $saveFile"
            } else {
                SetStatus "Ramp was not started yet."
            }
            return
        }
        if [catch {exec sddsprocess $tmpRoot.ramp "-redefine=col,RampSetpoint,RampSetpoint RampDelta $i * +" $tmpRoot.ramp.$i } result] {
            return -code error "Error processing ramp step: $result"
        }
        if [catch {exec ramploadnew $tmpRoot.ramp.$i} result] {
            return -code error "Error in loading ramps $tmpFile: $result"
        }
        SetStatus "$tmpRoot.ramp.$i loaded."
        set timeout [expr [clock seconds] + $WaitTime]
        while {[clock seconds]<$timeout} {
            if $abortRamp {
                break
            }
            after 1000
            update
        }
    }
    SetStatus "done."
}

APSButton .all -parent $w1 -text "Select All" -command "SelectCorrectors -all 1" -size small
APSButton .clear -parent $w1 -text "Clear All" -command "SelectCorrectors -all 0" -size small
APSFrame .f2 -parent .userFrame -label "Commands"
set w .userFrame.f2.frame

GetLatticeFile
#APSLabeledEntry .wait -parent $w2 -label "Wait time after changing delay (seconds):" -textVariable waitTime -width 50
APSFrameGrid .grid -parent $w -yList {y1 y2}
set w1 $w.grid.y1
set w2 $w.grid.y2
APSLabeledEntry .file -parent $w1 -label "Lattice file" -width 80 -textVariable latticeFile
APSButton .pick -parent $w1 -text "PICK LATTICE" -command "PickLatticeFile"
APSButton .on -parent $w1 -text "RESET ON" -command "TurnOnOffPS -on 1"
APSButton .off -parent $w1 -text "OFF" -command "TurnOnOffPS -on 0"
APSButton .load -parent $w1 -text "LOAD RAMPS" -command "LoadRamps"
APSButton .verify -parent $w1 -text "VERIFY RAMPS" -command "VerifyRamps"
APSButton .current -parent $w2 -text "Plot Ramps Current" -command "ReadCorrectorCurrent"
APSButton .gain -parent $w2 -text "Scaling Factors" -command "exec sddsedit /home/helios/oagData/booster/ramps/correctors/lattices/corrector_gain.sdds &"
APSButton .onoff -parent $w1 -text "Turn On/Off Power Supplies" -command TurnOnOffPowerSupplies
APSButton .medm -parent $w2 -text "AFG WF Display" -command \
    "exec medm -x booster/psApp/afgMain.adl &" -packOption "-side left" -contextHelp \
    "bring up the medm screen of booster corrector current waveform display."
APSButton .lattice -parent $w2 -text "Get Lattice" \
  -command {GetBoosterLattice} \
  -contextHelp "Get the booster lattice and switch the default lattice to the obtained lattice"
APSButton .ramp -parent $w2 -text "Ramp" -command "RampCorrector" \
  -contextHelp "Ramp corrector ramp waveforms."
set abortRamp 0
APSButton .abort -parent $w2 -text "Abort Ramp" -command "set abortRamp 1" \
  -contextHelp "Abort ramp during ramping steps."

set latticeFile /home/helios/oagData/booster/ramps/correctors/lattices/default/HVCorr.ramp
