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

#
#$Log: not supported by cvs2svn $
#Revision 2.1 2012/07/25 11:38:37 shang
#added windowing to both sides in post-process to avoid errors.
#
#Revision 2.0 2012/07/25  shang
#Added a window function to post-process when sddsprocess fails to detect the center where one side is flat, 
#so that it can always find a best amplitude position.
#
#Revision 1.9  2011/12/15 20:15:24  shang
#corrected the BTS efficiency plot command which used wrong file.
#
#Revision 1.8  2011/12/12 20:36:29  shang
#changed to plot BTSEfficiency instead of charge in the post-processing.
#
#Revision 1.7  2011/08/19 17:25:55  shang
#fixed a bug in post-processing.
#
#Revision 1.6  2011/08/19 14:56:08  shang
#changed made by CY.
#
#Revision 1.5  2011/06/28 19:41:41  shang
#made more changes and tested.
#
#Revision 1.4  2011/05/31 18:03:12  shang
#changed the default parameters and the best amplitude processing per CY's request, and added "loading reference" when "abort" button is clicked.
#
#Revision 1.3  2011/04/27 20:55:29  shang
#corrected the bump coefficient table since the H/V even/odd sectors behave differently, added B1C9H, B3C9H, B2C9V, and B4C9V sectors to missing list because they
#do not meet the requirement for 4-corrector bump (only have one bpm or bpm has been used by other sector)
#
#Revision 1.2  2011/04/25 21:45:22  shang
#remove shang's private version.
#
#Revision 1.1  2011/04/25 21:43:52  shang
#first version for scan booster 4-corrector bumps.
#


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

set version "Booster4CorrectorBumpScanNew\n\n\$Revision: 1.10 $\n\$Author: shang $"

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


proc GenerateBump {args} {
    set amplitude ""
    APSParseArguments {amplitude}
    global plane sector startBump endBump ampStart lattice dataDir outputDir sectorList ampStart ampEnd missingList
    if {![string length $startBump] || ![string length $endBump]} {
	return -code error "Bump range not selected."
    }
    if ![string length $amplitude] {
	set amplitude $ampStart
    }
    set fileList ""
    foreach quad {B1 B2 B3 B4} {
	foreach sector $sectorList {
	    set nm ${quad}$sector
	    global $nm
	    set nm1 ${nm}$plane
	    if [set $nm] {
		if [lsearch -exact $missingList $nm1]>=0 {
		    SetStatus "$nm1 not available, skip."
		    continue
		}
		SetStatus "generate bump for $nm..."
		if [catch {exec SetBoosterBumpAmplitude \
			       -outDir $outputDir \
			       -plane $plane -sector $nm -lattice default \
			       -startBump $startBump -endBump $endBump -amplitude $amplitude } result] {
		    return -code error "SetBoosterBumpAmplitude: $result"
		}
		SetStatus "$result"
		lappend fileList $outputDir/${nm}$plane.ramp
	    }
	}
    }
    if [llength $fileList] {
    	eval exec sddsplot -col=RampTime,OriginalRampSetpoint -col=RampTime,RampSetpoint -sep=2 -split=page  \
	    -leg -grap=line,vary -topline=@CorrName -title=@Sector $fileList &
    }
}

proc LoadBump {args} {
    global dataDir  lattice sectorList plane outputDir startBump
    
    foreach quad {B1 B2 B3 B4} {
	foreach sector $sectorList {
	    set nm ${quad}$sector
	    global $nm
	    set nm1 ${nm}$plane
	    if [set $nm] {
		if [lsearch -exact $missingList $nm1]>=0 {
		    SetStatus "$nm1 not available, skip."
		    continue
		}
		if [lsearch -exact $missingList1 $nm1]>=0 && \
		    $startBump >=160 {
		    SetStatus "$nm1 not available for extraction, skip."
		    continue
		}
		set rampFile $outputDir/${nm}${plane}.ramp
		if ![file exist $rampFile] {
		    SetStatus "$rampFile does not exist, generate the bump first."
		    continue
		}
		SetStatus "loading ramps for ${nm}$plane..."
		set command "ramploadnew $rampFile"
		if [catch {eval exec $command} result] {
		    return -code error "Error in loading ramp: $result"
		}
	    }
	}
    }
    SetStatus "done."
}

set processEfficiency 0.9
proc Postprocess {args} {
    global outputDir plane sectorList missingList fileSelection tolerance processEfficiency
    cd $outputDir
    set files [glob -nocomplain *.sdds]
    if ![llength $files] {
	return -code error "No scanned data found."
    }
    APSScrolledListWindow .display -name "scan file selection" \
        -label "Select a flile"  -acceptButton 0 \
        -itemList $files -selectionVar fileSelection \
        -directory $outputDir -appendDescription 0 \
        -rootnameOnly 1 -descriptionName Contents 
    tkwait variable fileSelection
    set sector [file root $fileSelection]
    if [regexp {H} $sector] {
	set plane H
    } else {
	set plane V
    }
    cd $outputDir
    set scanType ScanSet
    if [catch {PostprocessScan -filename $fileSelection -sector [string range $sector 0 end-1] -plane $plane -efficiency $processEfficiency -scanType ScanSet} result] {
	return -code error $result
    }
}

proc PostprocessAll {args} {
    global outputDir plane sectorList missingList
    set fileList ""
    foreach quad {B1 B2 B3 B4} {
	foreach sector $sectorList {
	    set nm ${quad}$sector
	    global $nm 
	    set nm1 ${nm}$plane
	    if [set $nm] {
		if [lsearch -exact $missingList $nm1]>=0 {
		    SetStatus "$nm1 not available, skip."
		    continue
		}
		if [file exist $outputDir/${nm}${plane}.ramp] {
		    lappend fileList $outputDir/${nm}${plane}.ramp
		}
	    }
	}
    }
    if ![llength $fileList] {
	SetStatus "No ramp files found."
	return
    }
    set tmpRoot /tmp/[APSTmpString]
    if [catch {eval exec sddscombine $fileList $tmpRoot.all} result] {
	return -code error $result
    }
    set corrList [lsort -unique [exec sdds2stream -par=CorrName $tmpRoot.all]]
    
    set fileList ""
    foreach corr $corrList {
	if [catch {exec sddsprocess $tmpRoot.all $tmpRoot.$corr -match=par,CorrName=$corr} result] {
	    SetStatus "Error in processing $corr : $result"
	    continue
	}
	if [catch {exec sddsenvelope $tmpRoot.$corr -sum=1,RampSetpointDelta1 -copy=RampTime,OriginalRampSetpoint -pipe=out \
		       | sddsxref -pipe $tmpRoot.$corr -transfer=par,* -leave=* \
		       | sddsprocess -pipe=in $tmpRoot.$corr.ramp \
		   "-redefine=col,RampSetpoint,OriginalRampSetpoint RampSetpointDelta1Sum +" } result] {
	    return -code error "Error in computing average: $result"
	}
	lappend fileList $tmpRoot.$corr.ramp
    }
    if [llength $fileList] {
	if [catch {eval exec sddscombine $fileList $outputDir/${plane}bump.ramp -over} result] {
	    return -code error $result
	}
	if [APSYesNoPopUp "load the average bump $outputDir/${plane}bump.ramp now?"] {
	    SetStatus "loading averaged bump..."
	    set command "ramploadnew  $outputDir/${plane}bump.ramp"
	    if [catch {eval exec $command} result] {
		return -code error "Error in loading ramp: $result"
	    }
	}
    }
    SetStatus "done."
}

proc PostprocessScan {args} {
    set filename ""
    set sector ""
    set scanType ""
    set plane ""
    set efficiency ""
    APSParseArguments {filename sector scanType plane efficiency}
    global scanResult$sector startBump endBump outputDir btsCharge ptbCharge btsEfficiency abort bestAmp scanMode prevReference tolerance
    global efficiencyPV
    
    set dataDir /home/helios/oagData/booster/ramps/correctors/lattices/default
    set tmpRoot /tmp/[APSTmpString]
   # exec sddsplot -col=BpmAmplitude,BTS:CM:q.VAL $filename -topline=${sector}$plane &
    set cols [exec sddsquery -col $filename]
    if ![regexp $efficiencyPV $cols] {
        return -code error "$efficiencyPV does not exist in $filename, please select different efficiency PV."
    }
    if [catch {exec sddsprocess $filename $filename.1 "-redefine=par,StartBump,$startBump" \
		   "-test=col,PTB:CM:measCurrentCM 0 >" \
		   "-redefine=col,BTSEfficiency,$efficiencyPV PTB:CM:measCurrentCM /" \
		   "-redefine=par,EndBump,$endBump"} result] {
	return -code error $result
    }
    
    catch {file delete -force $outputDir/${sector}${plane}.ramp}
    if [catch {exec sddsconvert $filename.1 -pipe=out -del=par,*  \
                 | sddsprocess -pipe -process=BTSEfficiency,max,MaxEfficiency \
                 | sddsprocess -pipe "-define=col,RelativeEff,BTSEfficiency MaxEfficiency /" \
                 | sddsprocess -pipe -filter=col,RelativeEff,0.9,1.0 \
                 | sddsprocess -pipe=in -process=BpmAmplitude,ave,BestAmp \
                 -process=BTSEfficiency,ave,BestEff \
                 -process=BTSEfficiency,first,LeftEff \
                 -process=BTSEfficiency,last,RightEff \
                 -process=BpmAmplitude,first,LeftAmp \
                 -process=BpmAmplitude,last,RightAmp  $filename.2 } result] {
        return -code error "Error processing bestAmp (center of 90% efficiency): $result"
    }
    if [catch {exec sddsxref $filename $filename.2 $filename.proc \
                 -leave=* -transfer=par,* } result] {
        return -code error "Error processing $filename.proc : $result"
    }
    catch {file delete -force $filename.2}
    exec sddsplot $filename.proc -par=LeftAmp,LeftEff -grap=sym,conn,scal=2,subtype=1  -par=RightAmp,RightEff -grap=sym,conn,scal=2,subtype=1 \
      -par=BestAmp,BestEff  -grap=sym,conn,scal=2,subtype=1 \
      -col=BpmAmplitude,BTSEfficiency $filename.proc -topline=${sector}$plane  &
    set bestAmp [exec sdds2stream -par=BestAmp $filename.proc]
    
    if {$scanMode=="Manual"} {
        global popup bestAmpOrig
        set popup 0
        set bestAmpOrig $bestAmp
        APSDialogBox .popup \
          -name bestAmp \
          -okCommand "set popup 1" \
          -cancelCommand "set popup 2"
        APSLabel .title \
          -parent .popup.userFrame \
          -text "You may change the calculated value\nof bestAmp manually or click Cancel.\n"
        APSLabeledEntry .bestAmp \
          -parent .popup.userFrame \
          -label "bestAmp:" \
          -textVariable bestAmp \
          -packOption "-fill x -expand true"
        tkwait variable popup
        if {$popup ==2} {
            SetStatus "set best ramp was cancelled."
            return
        }
        if {$popup != 1 } {
            set bestAmp $bestAmpOrig
        }
    }
    #set prevReference [file readlink /home/helios/oagData/booster/ramps/correctors/lattices/default/HVCorr.ramp]
                       
    if [catch {exec SetBoosterBumpAmplitude \
                 -outDir $outputDir -load 0 \
                 -plane $plane -sector $sector  \
                 -startBump $startBump -endBump $endBump -amplitude $bestAmp } result] {
	return -code error "Error in SetBoosterBumpAmplitude: $result"
    }
    
    switch $scanType {
	ScanSetAve {
	    #wait after all the scan is done, but restore original ramp before next scan
	    set sector1 ${sector}$plane
	    if [catch {exec sddsprocess $dataDir/${plane}coeff.sdds -pipe=out -match=par,Sector=$sector1 \
			   | sdds2stream -pipe -col=CorrectorName} corrList] {
		return -code error "Error in getting scanned correctors: $corrList"
	    }
	    set option "-match=par,CorrName=[lindex $corrList 0]"
	    for {set i 1} {$i<[llength $corrList]} {incr i} {
		append option ",CorrName=[lindex $corrList $i],|"
	    }
	    if [catch {exec sddsprocess $dataDir/HVCorr.ramp $tmpRoot.set "$option"} result] {
		return -code eror "Error processing ramp table: result"
	    }
	    SetStatus "loading original ramp..."
	    set command "ramploadnew $tmpRoot.set"
	    if [catch {eval exec $command} result] {
		return -code error "Error in loading ramp: $result"
	    }
	}
	ScanSet {
	    #set the best ramp after each scan
	    set command "ramploadnew $outputDir/${sector}$plane.ramp"
	    
	    SetStatus "loading $sector $plane best ramp:"
	    if [catch {eval exec $command} result] {
		return -code error "Error in loading ramp: $result"
	    }
            APSWaitWithUpdate -waitSeconds 4 -updateInterval 1
	    if [catch {CheckBTSCharge} result] {
		SetStatus "BTS charge too low."
		set scanResult$sector aborted
		return
	    }
	    if {$btsEfficiency<[expr $efficiency - $tolerance]} {
                if {$scanMode=="Manual"} {
                    set answer [APSMultipleChoice [APSUniqueName .] -name Warning \
                                  -type warning  \
                                  -question "BTS efficiency dropped after loading ramps which means the bump may be bad, do you want to continue or abort scan?" \
                                  -returnList {Continue Abort} -labelList {Continue Abort} ]
                    if {$answer=="Abort"} {
                        SetStatus "aborted due to dropped BTS efficiency."
                        set scanResult$sector aborted
                        return
                    }
                } else {
                    SetStatus "$sector scan failed to improve the BTS efficiency, no action taken. continue to next scan in automatic mode."
                    SetStatus "restore reference..."
                    if [catch {LoadReference -plane $plane} result] {
                        return -code error "Error in loading reference: $result"
                    }
                    if [catch {CheckBTSCharge} result] {
                        return -code error $result
                    }
                    APSWaitWithUpdate -waitSeconds 20 -update 1
                }
	    } else {
                SetStatus "resuming controllaws...."
                if [catch {exec cavput -list=Booster:ControlLawLongRC,Booster:ControlLawXRC \
                             -list=.SUSP=0 -pend=10} result] {
                    return -code error $result
                }
                SetStatus "installing ${sector}$plane ramp to reference..."
                if [catch {MakeReference -newRampFile $outputDir/${sector}${plane}.ramp -yesno 0} result] {
                    SetStatus "Error in making new reference: $result"
                    set scanResult$sector aborted
                    return
                }
                SetStatus "Loading new installed reference."
                if [catch {LoadReference -plane $plane} result] {
                    return -code error "Error in loading reference: $result"
                }
                
                if [catch {CheckBTSCharge} result] {
                    return -code error $result
                }
                SetStatus "done."
            }
	}
    }
    set scanResult$sector done
}

proc ScanStartEndAmplitude {args} {
    set sector ""
    set plane ""
    set start ""
    set end ""
    APSParseArguments {sector plane start end}
    global ampStart ampEnd ampStart1 ampEnd1 startBump endBump outputDir btsCharge lattice abort
    global btsEfficiency
    set ampStart1 $start
    set ampEnd1 $end
    SetStatus "Search new start amplitude where BTS charge is 0."
    set delta 0.2
    set count 0
    while {1} {
	if $abort {
	    Abort -plane $plane
	    return -code error "Manually aborted."
	}
	SetStatus "now start amp is $ampStart1"
	if [catch {exec SetBoosterBumpAmplitude \
		       -outDir $outputDir -load 1 \
		       -plane $plane -sector $sector -lattice default \
		       -startBump $startBump -endBump $endBump -amplitude $ampStart1 } result] {
	    return -code error "SetBoosterBumpAmplitude: $result"
	}
       
	ReadBTSCharge
	if {$btsEfficiency>0.6} {
	    set ampStart1 [expr $ampStart1 - $delta]
	} else {
	    break
	}
	incr count
	if {$count>3} {
	    set delta [expr 2.0*$delta]
	    set count 0
	}
	update
    }
    
    if [catch {LoadReference -plane $plane} result] {
	return -code error "Error in loading reference: $result"
    }
    
    if [catch {CheckBTSCharge} result] {
	return -code error $result
    }
    SetStatus "Search new end amplitude where BTS charge is 0."
    set ampEnd1 $ampEnd
    set delta 0.2
    set count 0
    while {1} {
	if $abort {
	    Abort -plane $plane
	    return -code error "Manually aborted."
	}
	SetStatus "Now the end amplitude is $ampEnd1"
	if [catch {exec SetBoosterBumpAmplitude \
		       -outDir $outputDir -load 1 \
		       -plane $plane -sector $sector -lattice default \
		       -startBump $startBump -endBump $endBump -amplitude $ampEnd1 } result] {
	    return -code error "SetBoosterBumpAmplitude: $result"
	}
	ReadBTSCharge
	if {$btsEfficiency>0.6} {
	    set ampEnd1 [expr $ampEnd1 + $delta]
	} else {
	    break
	}
	incr count
	if {$count>3} {
	    set delta [expr 2.0*$delta]
	    set count 0
	}
	update
    }
    SetStatus "Found new amplitude range $ampStart1 -- $ampEnd1 for $sector $plane."
    if [catch {LoadReference -plane $plane} result] {
	return -code error "Error in loading reference: $result"
    }
    after 1000
    
    if [catch {CheckBTSCharge} result] {
	return -code error $result
    }
}

proc SaveBumpLimits {args} {
    global CorrectorList StartLimit StopLimit LatticeName
    set parDir /home/helios/oagData/booster/correctorBumpScan
    set filename ${LatticeName}-limit.sdds.[clock format [clock seconds] -format %Y-%m-%d:%H%M%S]
    foreach corr $CorrectorList {
        lappend startList $StartLimit($corr)
        lappend stopList $StopLimit($corr)
    }
    if [catch {exec sddsmakedataset $parDir/$filename \
                 -col=Sector,type=string -data=[join $CorrectorList ,] \
                 -col=bumpAmplitudeLow,type=double -data=[join $startList ,] \
                 -col=bumpAmplitudeHigh,type=double -data=[join $stopList ,] } result] {
        return -code error "Error in saving bump limits: $result"
    }
    cd $parDir
    exec rm ${LatticeName}-limit.sdds
    exec ln -s $filename ${LatticeName}-limit.sdds
    SetStatus "$filename was save for $LatticeName bump limits."
}

proc LoadBumpLimits {args} {
    global  StartLimit StopLimit HSectors VSectors CheckedScan CorrList SkipSector LatticeName CorrectorList
    set parDir /home/helios/oagData/booster/correctorBumpScan
    
    set boosterLink [file readlink /home/helios/oagData/booster/ramps/correctors/lattices/default]
    if [regexp "x13.75-y5.80" $boosterLink] {
        set lattice 92nm
    } elseif [regexp {x11.75-y9.80} $boosterLink] {
        set lattice 132nm
    } else {
        set lattice 92nm
    }
    set LatticeName $lattice
    
    set sectorList [exec sdds2stream -col=Sector $parDir/${lattice}-limit.sdds]
    set startList [exec sdds2stream -col=bumpAmplitudeLow $parDir/${lattice}-limit.sdds]
    set stopList [exec sdds2stream -col=bumpAmplitudeHigh $parDir/${lattice}-limit.sdds]
    foreach sector $sectorList start $startList stop $stopList {
        set StartLimit($sector) [format %.1f $start]
        set StopLimit($sector) [format %.1f $stop]
        set CheckedScan($sector) 0
        if [lsearch -exact $CorrList $sector]>=0 {
            set SkipSector($sector) 0
        } else {
            set SkipSector($sector) 1
        }
    }
    set CorrectorList $sectorList
}

proc ScanBumpLimit {args} {
    global CorrectorList CheckedScan StartLimit StopLimit CorrList
    
    foreach corr $CorrList {
        if [set CheckedScan($corr)] {
            SetStatus "Finding the scan limit of $corr..."
            if [catch {GetStartAndEndAmplitude -sector $corr } result] {
                return -code error "$result"
            }  
        }
    }
    SetStatus "done."
}

proc GetStartAndEndAmplitude {args} {
    set sector ""
    APSParseArguments {sector}
    
    global StartLimit StopLimit lattice outputDir startBump endBump efficiencyPV btsEfficiency 
    global AbortLimitScan
    
    set start $StartLimit($sector)
    set stop $StopLimit($sector)
    if [regexp {H} $sector] {
        set plane H
    } elseif [regexp {V} $sector] {
        set plane V
    } else {
        return -code error "invalid sector - $sector given."
    }
    set sector1 [string range $sector 0 end-1]

    if [catch {LoadReference -plane $plane} result] {
	return -code error "Error in loading reference: $result"
    }
    APSWaitWithUpdate -waitSeconds 3
    if [catch {ReadBTSCharge} result] {
        return -code error "Error reading BTS efficiency: $result"
    }
    if {$btsEfficiency<0.5} {
        return -code error "The reference efficiency ($btsEfficiency) is less than 50%"
    }
    set eff0 $btsEfficiency
    set relEff 1.0
    SetStatus "Getting the start amplitude ($start) of $sector ..."
    while {$relEff>0.7} {
        if $AbortLimitScan {
            set AbortLimitScan 0
            return -code error "Limit scan was aborted."
        }
        if [catch {exec SetBoosterBumpAmplitude -plane $plane -sector $sector1 \
                     -lattice $lattice -startBump $startBump -endBump $endBump \
                     -amplitude $start -load 1 } result] {
            if [regexp "Error in loading ramp" $result] {
                SetStatus "The start amplitude is too big (ramp greater than 1) ($result), decrease..."
                set start [expr $start + 0.2]
                continue
            } else {
                return -code error "Invalid start amplitude for $sector: $result"
            }
        }
        APSWaitWithUpdate -waitSeconds 3
        if [catch {ReadBTSCharge} result] {
            return -code error "Error reading BTS efficiency: $result"
        }
        SetStatus "amplitude = $start, BTS efficiency now = $btsEfficiency"
        set relEff [expr $btsEfficiency / $eff0]
        if {$relEff<0.7} {
            break
        }
        set start [expr $start - 0.2]
    }
    set StartLimit($sector) $start
    if [catch {LoadReference -plane $plane} result] {
	return -code error "Error in loading reference: $result"
    }
    after 3000
    if [catch {ReadBTSCharge} result] {
        return -code error "Error reading BTS efficiency: $result"
    }
    if {$btsEfficiency<0.5} {
        return -code error "The reference efficiency ($btsEfficiency) is less than 50%"
    }
    set eff0 $btsEfficiency
    set relEff 1.0
    SetStatus "Getting the end amplitude of $sector ..."
    while {$relEff>0.7} {
        if $AbortLimitScan {
            set AbortLimitScan 0
            return -code error "Limit scan was aborted."
        }
        if [catch {exec SetBoosterBumpAmplitude -plane $plane -sector $sector1 \
                     -lattice $lattice -startBump $startBump -endBump $endBump \
                     -amplitude $start -load 1 } result] {
            if [regexp "Error in loading ramp" $result] {
                SetStatus "The end amplitude is too big (ramp greater than 1) ($result), decrease..."
                set stop [expr $stop - 0.2]
                continue
            } else {
                return -code error "Invalid start amplitude for $sector: $result"
            }
        }
        if [catch {ReadBTSCharge} result] {
            return -code error "Error reading BTS efficiency: $result"
        }
        SetStatus "amplitude = $start, BTS efficiency now = $btsEfficiency"
        set relEff [expr $btsEfficiency / $eff0]
        if {$relEff<0.7} {
            break
        }
        set stop [expr $stop + 0.2]
    }
    set StopLimit($sector) $stop
    
    if [catch {LoadReference -plane $plane} result] {
	return -code error "Error in loading reference: $result"
    }
    APSWaitWithUpdate -waitSeconds 3
    if [catch {ReadBTSCharge} result] {
        return -code error "Error reading BTS efficiency: $result"
    }
    SetStatus "found $sector start/end amplitude: $start $stop"
}

proc CheckAmplitude {args} {
    set sector ""
    set amp ""
    APSParseArguments {sector amp}

    global StartLimit StopLimit lattice outputDir startBump endBump efficiencyPV btsEfficiency 
    
    if [regexp {H} $sector] {
        set plane H
    } elseif [regexp {V} $sector] {
        set plane V
    } else {
        return -code error "invalid sector - $sector given."
    }
    set sector1 [string range $sector 0 end-1]
    if [catch {exec SetBoosterBumpAmplitude -plane $plane -sector $sector1 \
                 -lattice $lattice -startBump $startBump -endBump $endBump \
                 -amplitude $amp -load 1 } result] {
        if [regexp "Error in loading ramp" $result] {
            return -code error "The amplitude is too big -- $result"
        } else {
            return -code error "Invalid start amplitude for $sector: $result"
        }
    }
    if [catch {ReadBTSCharge} result] {
        return -code error "Error reading BTS efficiency: $result"
    }
    if {$btsEfficiency>0.7} {
        return -code error "The amplitude is too small (efficiency is greater 70%)"
    }
    
}

proc MakeLimitWidget {args} {
    set parent ""
    APSParseArguments {parent}
    global StartLimit StopLimit HSectors VSectors CheckedScan CorrectorList AbortLimitScan

    set AbortLimitScan 0
    APSFrameGrid .limit -parent $parent -xList {x1 x2 x3 x4}
    
    set w1 $parent.limit.x1
    set w2 $parent.limit.x2
    set w3 $parent.limit.x3
    set w4 $parent.limit.x4

   
    set CorrectorList ""
    foreach plane {H V} {
        foreach B {B1 B2 B3 B4}  pw {w1 w2 w3 w4} {
            APSLabel .label$plane$B -parent [set $pw] -text "           StartBump    EndBump"
            set sectorList ""
            set variableList ""
            set entryVarList ""
            for {set c 0} {$c<10} {incr c} {
                set sector ${B}C${c}$plane
                lappend sectorList $sector
                lappend CorrectorList $sector
                lappend variableList CheckedScan($sector)
                lappend entryVarList StartLimit($sector)
            }
            set buttonList [APSCheckButtonEntryFrame .check$plane$B \
                -label "" -entryWidth 10  -parent [set $pw] -buttonList $sectorList \
                -variableList $variableList -entryVariableList $entryVarList]
            
            foreach button $buttonList sector $sectorList {
                set w [regsub ".button" $button ""]
                APSLabeledEntry .end -parent $w -textVariable StopLimit($sector) -width 10 -packOption "-side right" -label ""
            }
            
        }
    }
    
    APSButton .scan -parent $parent -text "Scan Bump Limit" -command "ScanBumpLimit" -contextHelp "scan bump limit for selected correctors."
    APSButton .save -parent $parent -text "Save Bump Limit" -command "SaveBumpLimits" -contextHelp "save current limit settings"
    APSButton .abort -parent $parent -text "Abort Limit Scan" -command "set AbortLimitScan 1"
    
    
}

proc MakeMainWidget {args} {
    set parent ""
    APSParseArguments {parent}
    
    global outputDir abort steps numToAve pauseAfterChange bumpIndex itemList startBump endBump efficiencyLimit
    global tolerance  processEfficiency  sectorList scanType scanMode efficiencyPV plane

    APSLabeledEntry .dir -parent $parent -label "Output directory:" -textVariable outputDir -width 70
    APSFrameGrid .grid1 -parent $parent -xList {x1 x2}
    set w1 $parent.grid1.x1
    set w2 $parent.grid1.x2
    
    APSLabeledEntry .steps -parent $w1 -label "Steps" -textVariable steps -width 15
    APSLabeledEntry .ave -parent $w1 -label "Number of readback average:" -textVariable numToAve -width 15
    APSLabeledEntry .pause -parent $w2 -label "Pause after change (s):" -textVariable pauseAfterChange -width 15
    APSComboboxFrame .sel -parent $w2 -label "Select Bump range" -textVariable bumpIndex \
      -itemList $itemList -editable 0 -width 15 -callback "SelectBumpRange -index" \
      -contextHelp "select the start end bump range of RampTime in ms."
    APSLabeledOutput .start -parent $w1 -label "Start Bump (ms)" -textVariable startBump -width 15
    APSLabeledOutput .end -parent $w2 -label "End Bump (ms)" -textVariable endBump -width 15
    
    APSLabeledEntry .eff -parent $w1 -label "BTS efficiency limit:" -textVariable efficiencyLimit -width 15 \
      -contextHelp "the lowest BTS efficiency that it should reach."
    APSLabeledEntry .tolerance -parent $w2 -label "BTS efficiency tolerance:" -textVariable tolerance -width 15 -contextHelp \
      "the tolerance of BTS efficiency for installing scanned bumps."
    APSLabeledEntry .effici -parent $w2 -label "Efficiency for post-processing:" -textVariable processEfficiency -width 15 -contextHelp \
      "desired efficiency for post-processing to be able to install scanned ramps."
    #APSRadioButtonFrame .sector -parent .userFrame -label "Sector" -buttonList $sectorList -valueList $sectorList \
      #    -variable sector -commandList $commList -limitPerRow 10 -orientation horizontal
    set scanType ScanSet
    APSRadioButtonFrame .scan -parent $parent -label "Scan and Set or Scan and Set Average?" \
      -buttonList {"Scan_Set" "ScanAll_SetAve"} -valueList {ScanSet ScanSetAve} \
      -variable scanType -orientation horizontal
    set scanMode Manual
    APSRadioButtonFrame .scanmode -parent $parent -label "Scan mode:   " -buttonList {Automatic Manual} \
      -valueList {Auto Manual} -variable scanMode -orientation horizontal 
    set efficiencyPV BTS:CM:q.VAL
    APSRadioButtonFrame .eff -parent $parent -label "Select current pv for efficiency computation:"  -buttonList {BTS Region1 Region2 Region3 Region4} \
      -valueList {BTS:CM:q.VAL B:diag1:rms:A:region1 B:diag1:rms:A:region2 B:diag1:rms:A:region3 B:diag1:rms:A:region4} \
      -variable efficiencyPV -orientation horizontal
    APSRadioButtonFrame .plane -parent $parent -buttonList {H V} -label "Select plane:" \
      -valueList {H V} -variable plane -orientation horizontal -commandList {"set coord X" "set coord Y"}
    
    APSFrame .f1 -parent $parent -label "Quadrant Selection"
    set w1 $parent.f1.frame
    set sectorList {C0 C1 C2 C3 C4 C5 C6 C7 C8 C9}
    foreach cat {B1 B2 B3 B4} {
        set varList ""
        foreach but $sectorList {
            global ${cat}$but
            set ${cat}$but 0
            lappend varList ${cat}$but
        }
        APSCheckButtonFrame .c$cat -parent $w1 -label "$cat" -buttonList $sectorList -variableList $varList \
          -orientation horizontal -allNone 1
        APSButton .c1 -parent $w1.c$cat -packOption "-side right" -text "Odd" -size small -command "SelectEvenOdd -category $cat -type odd"
        APSButton .c2 -parent $w1.c$cat -packOption "-side right" -text "Even" -size small -command "SelectEvenOdd -category $cat -type even"
    }
    
    set abort 0
    APSButton .all -parent $w1 -text "Select All" -command "SelectAll -all 1" -size small
    APSButton .clear -parent $w1 -text "Clear All" -command "SelectAll -all 0" -size small
    APSButton .gen -parent $parent -text GenerateBump -command "GenerateBump"
    APSButton .load -parent $parent -text LoadBump -command "LoadBump"
    APSButton .start -parent $parent -text StartScan -command "StartScan"
    APSButton .proc -parent $parent -text "PostProcess" -command "Postprocess"
    APSButton .ref -parent $parent -text "MakeReference" -command "MakeReference"
    APSButton .abort -parent $parent -text "Abort" -command "set abort 1"
    APSButton .strip -parent $parent -text "StripTool" -command "BringUpStripTool"
    APSButton .adt -parent $parent -text "BPM ADT" -command "BringUpADT"
    

}

proc TestStartAndEndAmplitude {args} {
    set sector ""
    APSParseArguments {sector}
    global ampStart1 ampEnd1 outputDir lattice startBump endBump
    
#    if [catch {LoadReference -plane $plane} result] {
#	return -code error "Error in loading reference: $result"
#    }
#    
#    SetStatus "Testing end amp $ampEnd1..."
#    if [catch {exec /home/helios/SHANG/oag/apps/src/tcltkapp/oagapp/SetBoosterBumpAmplitude \
#		   -outDir $outputDir \
#		   -plane $plane -sector $sector -lattice $lattice \
#		   -startBump $startBump -endBump $endBump -amplitude $ampEnd1 } result] {
#	return -code error "Invalid end amplitude ($ampEnd1) for $sector: $result"
#    }
#    ReadBTSCharge
#    if {$btsEfficiency>0.8} {
#	return -code error "Improper end amplitude ($endStart1) for $sector, the BTS efficiency at this point is too high (greater than 80%)."
#    }
    if [catch {LoadReference -plane $plane} result] {
	return -code error "Error in loading reference: $result"
    }
    SetStatus "found $sector start/end amp: $ampStart1 $ampEnd1"
}
proc Abort {args} {
    set plane ""
    APSParseArguments {plane}
    global abort
    if $abort {
	set abort 0
	LoadReference -plane $plane
	SetStatus "resuming controllaws...."
	if [catch {exec cavput -list=Booster:ControlLawLongRC,Booster:ControlLawXRC \
		       -list=.SUSP=0 -pend=10} result] {
	    return -code error $result
	}
	SetStatus "Aborted."
    }
}
set numToAve 10 
set pauseAfterChange 2 
set bestAmp 0.01

set bsp100IocList [exec sddsprocess  /home/helios/oagData/SCR/requestFiles/SBPMWaveform.config \
    -pipe=out -match=par,Location=Accel -match=par,BPMType=Booster | sdds2stream -pipe -par=IOCName]
foreach ioc $bsp100IocList {
    lappend bsp100sectorList $ioc
    set s [string index $ioc end]
    lappend bsp100sectorList [string range $ioc 0 end-1][expr $s + 1]
}

proc StartScan {args} {
    global plane sectorList inputDir outputDir ampStart ampEnd steps numToAve pauseAfterChange scanType ampStart1 ampEnd1 coord region
    global lattice startBump endBump specialList missingList ptbCharge btsCharge btsEfficiency lastEfficiency abort bsp100sectorList
    global scanMode StartLimit StopLimit SkipSector
    
    if {![string length $startBump] || ![string length $endBump]} {
	return -code error "bump range not selected."
    }
    #check start and stop limit


    #
    if [catch {LoadReference -plane $plane} result] {
	return -code error "Error in loading reference: $result"
    }
    
    if [catch {CheckBTSCharge} result] {
	return -code error $result
    }
    
    set tmpRoot /tmp/[APSTmpString]
    set lastEfficiency 0
    foreach quad {B1 B2 B3 B4} {
	foreach sector $sectorList {
	    if $abort {
		Abort -plane $plane
		SetStatus "Manually aborted."
		return
	    }
	    set nm ${quad}$sector
	    global $nm scanResult$nm
	    set scanResult$nm 0
	    set nm1 ${nm}$plane
	    if [set $nm] {
		if [lsearch -exact $missingList $nm1]>=0 {
		    SetStatus "$nm1 not available, skip."
		    continue
		}
		if $abort {
		    Abort -plane $plane
		    SetStatus "Manually aborted."
		    return
		}
                if {0} {
                SetStatus "checking start/end amplitude..."
                set start $StartLimit($nm1)S
                set end $StopLimit($nm1)
                if [catch {CheckAmplitude -sector $nm1 -amp $start} result] {
                    return -code error "Problem with start amplitude ($start) -- $result"
                }
                if [catch {CheckAmplitude -sector $nm1 -amp $end} result] {
                    return -code error "Problem with end amplitude ($end) -- $result"
                }
                }
		SetStatus "suspending controllaws...."
		if [catch {exec cavput -list=Booster:ControlLawLongRC,Booster:ControlLawXRC \
			       -list=.SUSP=1 -pend=10} result] {
		    return -code error $result
		}
                after 2000
		if [catch {CheckBTSCharge} result] {
		    SetStatus $result
		    return
		}
		if $SkipSector($nm1) {
                    SetStatus "$nm1 does not exist, skip scan."
		    continue
		}
                
		set dateStr [clock format [clock seconds] -format %Y-%j-%m%d:%H%M%S]
		set outputFile $outputDir/${nm}${plane}.sdds
                
                if [lsearch $nm $bsp100sectorList]>=0 {
                    if [catch {exec replaceText /home/helios/oagData/booster/ramps/correctors/inputFiles/bsp100.mon.template $tmpRoot.mon \
                                 -orig=<sector>,<region>,<plane> -repl=$nm,$region,$coord } result] {
                        puts $result
                        return -codee rror "Error in generating monitor file1: $result"
                    }
                    if [catch {exec sddscombine /home/helios/oagData/booster/ramps/correctors/inputFiles/bcorrbump.mon $tmpRoot.mon \
                                 -merge $outputDir/${nm}${plane}.mon } result] {
                        return -codee rror "Error in generating monitor file2: $result"
                    }
                } else {
                    exec cp /home/helios/oagData/booster/ramps/correctors/inputFiles/bcorrbump.mon  $outputDir/${nm}${plane}.mon 
                }
		set expFile $outputDir/${nm}${plane}.exp
               
		if [catch {exec replaceText /home/helios/oagData/booster/ramps/correctors/inputFiles/bumpscanNew.exp $expFile \
                             -orig=<steps>,<start>,<end>,<numToAve>,<startBump>,<endBump>,<plane>,<sector>,<post_pause>,<monFile> \
			       -repl=$steps,$StartLimit($nm1),$StopLimit($nm1),$numToAve,$startBump,$endBump,$plane,$nm,$pauseAfterChange,$outputDir/${nm}${plane}.mon } result] {
		    return -code error "Error in generating exp file: $result"
		}
		catch {exec rm $outputFile}
	
	
		if $abort {
		    Abort -plane $plane
		    SetStatus "Manually aborted."
		    return
		}	
		if [catch {TogglePulsedMagnetEnables -location GunToBoosterExt} result] {
		    return -code error "error in enabling beam: $result"
		}
		after 3000
		if [catch {CheckBTSCharge} result] {
		    SetStatus $result
		    return
		}
                
		APSExecLog .bumpscan -name "$nm $plane  scan" -width 100 \
		    -unixCommand "sddsexperiment $expFile $outputFile -verbose" \
		    -callback "PostprocessScan -filename $outputFile -scanType $scanType -sector $nm -plane $plane -efficiency $btsEfficiency" \
		    -abortCallback "LoadReference -plane $plane;set scanResult$nm aborted" -cancelCallback "set scanResult$nm canceled"
		tkwait variable scanResult$nm
		
		if [string compare [set scanResult$nm] "done"]!=0 {
		    SetStatus "StartScan(2): $nm scan was [set scanResult$nm]"
		    return
		}
		set lastEfficiency $btsEfficiency
		#wait 1 minture
		SetStatus "waiting for 1 minute..."
		set timeout [expr [clock seconds]+20]
		while {[clock seconds]<$timeout} {
		    if $abort {
			Abort -plane $plane
			SetStatus "aborted."
			return
		    }
		    update
		    after 1000
		}
		SetStatus "$nm scan  done, deselect $nm."
                set $nm 0
	    }
	}
    }
    if {$scanType=="ScanSetAve"} {
	PostprocessAll
    }
    
}

proc ChangeLattice {args} {
    global dataDir lattice
    

}

set region 0
proc SelectBumpRange {args} {
    set index ""
    APSStrictParseArguments {index}
    
    global dataDir lattice startBump endBump itemList region
    set tmpList [split [lindex $itemList $index] "-"]
    set startBump [lindex $tmpList 0]
    set endBump [lindex $tmpList 1]
    set region $index
}

proc SelectAll {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 LoadReference {args} {
    set plane ""
    APSParseArguments {plane}
    set refDir  /home/helios/oagData/booster/ramps/correctors/lattices/default
    set refFile $refDir/HVCorr.ramp
    
    SetStatus "loading reference ramp..."
    set tmpFile /tmp/[APSTmpString]
    if [catch {exec sddsprocess $refFile $tmpFile -match=par,CorrName=*[string toupper $plane]* } result] {
        return -code error "Error loading reference1: $result"
    }
    set command "ramploadnew $tmpFile "
    if [catch {eval exec $command} result] {
	return -code error "Error in loading reference ramp2: $result"
    }
    SetStatus "done."
}

proc MakeReference {args} {
    set newRampFile ""
    set yesno 1
    APSParseArguments {newRampFile yesno}
    global outputDir plane
    if ![string length $newRampFile] {
	set newRampFile  $outputDir/${plane}bump.ramp
    }
    if ![file exist $newRampFile] {
	SetStatus "$newRampFile does not exist."
	return
    }
    set refDir  /home/helios/oagData/booster/ramps/correctors/lattices/default
    set refFile $refDir/HVCorr.ramp
    set origFile [file readlink $refFile]
    set newFile [APSNextGenerationedName -name $origFile -separator - -newFile 1\
		     -directory $refDir ]
    set corrList [exec sdds2stream -par=CorrName $newRampFile]
    set option "-match=par,CorrName=[lindex $corrList 0],!"
    for {set i 1} {$i<[llength $corrList]} {incr i} {
	append option ",CorrName=[lindex $corrList $i],!,&"
    }
    if [catch {exec sddsprocess $refFile $outputDir/tmpFile $option} result] {
	return -code error "Error in filter new correctors from refFile: $result"
    }
    if [catch {exec sddscombine $outputDir/tmpFile $newRampFile -pipe=out \
		   | sddsprocess -pipe "-reprint=par,CorrectorBump,$corrList" \
		   | sddssort -pipe=in -par=CorrName $refDir/$newFile } result] {
	return -code error "Error in generating new file: $result"
    }
    if {$yesno} {
	if ![APSYesNoPopUp "Install new generated file $newFile as HVCorr.ramp?"] {
	    return
	}
    }
    set oldDir [pwd]
    cd $refDir
    exec rm HVCorr.ramp
    exec ln -s $newFile HVCorr.ramp
    cd $oldDir
}

proc CheckBTSCharge {args} {
    global ptbCharge btsCharge btsEfficiency abort efficiencyLimit plane
    
    ReadBTSCharge
    return
    while {1} {
	if $abort {
	    Abort -plane $plane
	    return -code error "Checking BTS charge was aborted."
	}
	if {$btsEfficiency>$efficiencyLimit} {
	    break
	} 
	bell
	set answer [APSMultipleChoice [APSUniqueName .] -name Warning \
			-type warning  \
			-question "BTS charge is too low, To continue, you should get BTS charge through first." \
				    -returnList {Fix-And-Continue Check-Again Abort} -labelList {Continue Check-Again Abort} ]
	if {$answer=="Abort"} {
	    return -code error "abort due to low bts charge."
	}
	if {$answer=="Continue"} {
	    break
	}
	ReadBTSCharge
    }
}
proc ReadBTSCharge {args} {
    global ptbCharge btsCharge btsEfficiency efficiencyPV
    if [catch {exec cavget -list=PTB:CM:measCurrentCM,$efficiencyPV -pend=10 -repeat=number=5,pause=0.5,average} valList] {
	return -code error "error in reading BTS charge: $valList"
    }
    set ptbCharge [lindex $valList 0]
    set btsCharge [lindex $valList 1]
    set btsEfficiency [expr $btsCharge/$ptbCharge]
    
}

proc SelectEvenOdd {args} {
    set category ""
    set type odd
    APSParseArguments {category type}
    
    switch $type {
	even {
	    set value 0
	}
	odd {
	    set value 1
	}
    }
    for {set i 0} {$i<10} {incr i} {
	set sector ${category}C${i}
	global $sector
	if {[expr $i%2]==$value} {
	    #odd
	    set $sector 1
	} else {
	    set $sector 0
	}
    }
}

proc BringUpStripTool {args} {
    exec StripTool /home/helios/oagData/booster/ramps/correctors/inputFiles/boosterCorrectorBumpScanConfig &
}

#if [regexp {.0} $env(DISPLAY)] {
#    set otherDisplay :0.1
#} else {
    set otherDisplay :0.0
#}

proc BringUpADT {args} {
    global region otherDisplay
    exec adt -f /home/helios/oagData/ADTFiles/booster/booster.bpm.pv-region${region}.pv &
}

set startBump ""
set endBump ""
set missingList {B1C9V B2C9V B3C9V B4C9V B2C8V}
set missingList1 {B2C6H B2C7H B2C8H B3C1H B3C2H}
set ampStart -1.5
set ampEnd 1.5
set steps 10
set dataDir /home/helios/oagData/booster/ramps/correctors/lattices/
set lattice [file tail [file readlink $dataDir/default]]
set outputDir [APSGoToDailyDirectory -subdirectory 4corrbump ]
set plane H
set coord X

APSApplication . -name Booster4CorrectorBumpScanNew -version $version -overview "Booster new AFG 4-corrector bump scan" \
  -contextHelp "Booster charge measurement with 4-corrector bump."
set mainStatus ""
APSScrolledStatus .status -parent .userFrame -textVariable mainStatus -width 70
#APSRadioButtonFrame .lattice -parent .userFrame -label "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


set refDir  /home/helios/oagData/booster/ramps/correctors/lattices/default
set refFile $refDir/HVCorr.ramp
set timeList [exec sdds2stream -page=1 -col=RampTime $refFile]
set len [llength $timeList]
for {set i 2} {$i<[expr $len -1]} {incr i} {
    set time0 [format %.1f [lindex $timeList [expr $i-1]]]
    set time1 [format %.1f [lindex $timeList $i]]
	lappend itemList ${time0}-${time1}
}
set StartBumpList {0    34.0 56.5 79.0 101.5 124.0 146.5 169.0 191  214.0}
set EndBumpList   {29.0 51.5 74   96.5 119   141.5 164.0 186   209  240.0}
set itemList ""
foreach start $StartBumpList end $EndBumpList {
    lappend itemList [format %0.1f $start]-[format %.1f $end]
}

set bumpIndex [lindex $itemList 0]
set tmpList [split $bumpIndex "-"]
set startBump [lindex $tmpList 0]
set endBump [lindex $tmpList 1]
#puts $itemList 
set efficiencyLimit 0.1
set tolerance 0.05

set wList [APSTabFrame .tab -parent .userFrame -labelList "Main LimitScan" -label "" -width 950  -height 600]
MakeMainWidget -parent [lindex $wList 0]
MakeLimitWidget -parent [lindex $wList 1]
set CorrList [join [exec sdds2stream -par=CorrName /home/helios/oagData/booster/ramps/correctors/lattices/default/HVCorr.ramp]]
LoadBumpLimits
