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

set auto_path [linsert $auto_path 0  /usr/local/oag/apps/lib/$env(HOST_ARCH)]
set auto_path [linsert $auto_path 0 /usr/local/oag/lib_patch/$env(HOST_ARCH)]
APSDebugPath
APSStandardSetup

set usage "usage: SRRectoreCorrectorFromSCR -buttonOrientation <value>"
set buttonOrientation horizontal
set args $argv
APSParseArguments {buttonOrientation}

set CVSRevisionAuthor "\$Revision: 1.0 $ \$Author: shang $"

APSApplication . -name SRRestoreCorrectorFromSCR -version $CVSRevisionAuthor \
  -overview {This application restores selected SR correctors and BPM setpoints from selected SCR .}


set widget .config
set parent .userFrame
set rootname sconfig
set h_corrList ""
set v_corrList ""

APSFrameGrid $widget -parent $parent -yList {status top bot}

set sconfigConfigStatus ""
APSScrolledStatus .scrolled -parent $parent$widget.status -textVariable sconfigConfigStatus \
  -width 85 -height 6 -lineLimit 1000 -label "" -withButtons 1

APSFrame .but -parent $parent$widget.top

set sconfigConfigStatus "Ready..."

set hcorrList ""
set vcorrList ""
set hBPMList ""
set vBPMList ""
proc SetStatus {text} {
    global  sconfigConfigStatus
    set sconfigConfigStatus "[exec date] $text"
    update
}

proc RestoreSRCorrectorFromSCR {} {
    global stepNum pause  sconfigConfigStatus abortPressed w1 controlVar SR_Corrector_Recovery outputDir hIDsector vIDsector newConfig
    global hcorrList vcorrList hBPMList vBPMList description hNewConfig vNewConfig hOrigConfig vOrigConfig hOrigOption vOrigOption restartOC
    global deltaLimit maxDelta steeringOnly
    
    if ![string length $SR_Corrector_Recovery(ShortFilename)] {
	set sconfigConfigStatus "NO SCR file chosen!"
	return
    }
    GetSelectedCorrectors
    
    if {![llength $hcorrList] && ![llength $vcorrList]} {
	SetStatus "No correctors chosen!"
	return
    }
    if ![llength $hcorrList] {
	if ![APSYesNoPopUp "No horizontal plane correctors selected, are you sure to continue?"] {
	    return
	}
    }
    if ![llength $vcorrList] {
	if ![APSYesNoPopUp "No vertical plane correctors selected, are you sure to continue?"] {
	    return
	}
    }
    SetStatus "h $hcorrList"
    SetStatus "v $vcorrList"
    
   # APSAlertBox .warning -name "Check Controllaw Limits Setting" \
   \#   -errorMessage "Please check controllaw limits and make sure controllaw is running.\nThe controllaw limits for restoring corrector should be as following:\n\nCorrect range error limit: 300 A \n\n Corrector step limit: 2 A\n\nbpm limit: 15 mm\n\nxray bpm limit: 50mm\n\nPress the \"Full Start\" on the controllaw panel after these limits being changed\n\nPress following OK button to continue if the controllaw is running" -type warning

    SetStatus "Working..."
    APSDisableButton $w1.run.button
    set abortPressed 0
    update
    if {$stepNum < 1} {
        SetStatus "No steps selection"
        APSEnableButton $w1.run.button
        setOpenCloseAbortBut 1
        return
    }
    set rootname SRCorrRestore-[clock format [clock seconds] -format %H%M%S]
    set maxSteps 0
    set corrFiles ""
    set bpmFiles ""
    set corrWFFiles ""
    set bpmWFFiles ""
    set count 0
   
    foreach plane {h v} coord {x y} {
	set corrList [set ${plane}corrList]
	set bpmList [set ${plane}BPMList]
	if ![llength $corrList] {
	    continue
	}
	if [catch {RestoreCorrectorSetup -plane $plane -coord $coord -corrList $corrList -rootname $rootname -bpmList $bpmList} steps] {
	    return -code error "Error setup: $steps"
	}
	if {$steps>0} {
	    lappend corrFiles $outputDir/$rootname.${plane}corr
	    lappend bpmFiles $outputDir/$rootname.${plane}bpm
	    lappend corrWFFiles $outputDir/$rootname.${plane}corrWFRestore
	    lappend bpmWFFiles $outputDir/$rootname.${plane}bpmWFRestore
	    if {$steps>$maxSteps} {
		set maxSteps $steps
	    }
	    incr count
	}
    }
    SetStatus "max steps: $maxSteps"
    if !$count {
	SetStatus "There are no differences between current values and the selected SCR. No restoration is needed."
	APSEnableButton $w1.run.button
	return
    }
    if [llength $corrFiles]==1 {
	set corrFile $corrFiles
	set bpmFile $bpmFiles
	set corrWFFile $corrWFFiles
	set bpmWFFile $bpmWFFiles
    } else {
	if [catch {eval exec sddscombine $corrFiles $outputDir/${rootname}.corr -over -merge
	    eval exec sddscombine $bpmFiles -merge -pipe=out \
		       | sddsprocess -pipe=in \"-redefine=col,StepSize,Delta $maxSteps /\" $outputDir/$rootname.bpm
	    eval exec sddscombine $bpmWFFiles -pipe=out  \
		       | sddsprocess -pipe=in \"-redefine=col,StepSize,Delta $maxSteps /\" $outputDir/$rootname.bpmWF
	    eval exec sddscombine $corrWFFiles -pipe=out \
		       | sddsprocess -pipe=in \"-redefine=col,Waveform,Delta $maxSteps /\" $outputDir/$rootname.corrWF } result] {
	    return -code error "Error combining files: $result"
	}
	set corrFile  $outputDir/${rootname}.corr
	set bpmFile $outputDir/$rootname.bpm
	set corrWFFile $outputDir/$rootname.corrWF
	set bpmWFFile $outputDir/$rootname.bpmWF
    }
    for {set step 1} {$step<=$maxSteps} {incr step} {
	#SetStatus "Step $step..."
	if [catch {exec sddsprocess $bpmFile -pipe=out \
		       "-define=col,NewValue,RampFrom StepSize $step * +" \
		       | sddsprocess -pipe=in $bpmFile.step$step \
		       -reprint=col,ValueString,%lf,NewValue } result] {
	    return -code error "Error creating $type step file: $result"
	}
	if [catch {exec sddsprocess $bpmWFFile  \
		       $bpmWFFile.step$step\
		       "-redefine=col,Waveform,RampFrom StepSize $step * +" } result] {
	    return -code error "Error creating $type waveform step file: $result"
	}
    }
    
    SetStatus "Check current controllaw info..."
    global hOrigConfig vOrigConfig hOrigOption vOrigOption
    set corrList0 ""
    foreach plane {h v} coord {X Y} {
	set corrList [set ${plane}corrList]
	lappend corrList0 $corrList
	set bpmList [set ${plane}BPMList]
	if [catch {APSCheckControllawRunning -config ${plane}.defaultXRDP} running] {
	    return -code error "APSCheckControllawRunning $plane plane): $running"
	}
	if !$running {
	    if [catch {APSCheckControllawRunning -config ${plane}.defaultDP} running] {
		return -code error "APSCheckControllawRunning $plane plane): $running"
	    }
	    if !$running {
		if ![APSYesNoPopUp "DP controllaw is not running, do you still want to continue?"] {
		    SetStatus "DP controllaw is not running, abort."
		    return
		}
	    }
	}
    }
    SetStatus "update corrector range error..."
    set corrList0 [join $corrList0]
    #puts $corrList0
    if [catch {exec cavget -list=[join $corrList0 ,] -list=:RangeErrorCALC. -list=HIHI,LOLO -pend=30 -cavputForm } putList] {
	returnn -code "Error reading CALAC HIHI and LOLO: $putList"
    }
    #puts $putList
    if [catch {APSSaveMachine -machine SR -description "Save before restoring correctors from SCR - $description" -routine 0 } result] {
	return -code error "Error doing SCR save: $result"
    }
    set hihi [expr $maxDelta + 10]
    set lolo [expr -1*($maxDelta + 10)]
   # puts $corrList0
    if [catch {exec cavput -list=[join $corrList0 ,] -list=:RangeErrorCALC.HIHI=$hihi -pend=10
	exec cavput -list=[join $corrList0 ,] -list=:RangeErrorCALC.LOLO=$lolo -pend=10 } result] {
	return -code error "Error change corrector range error HIHI and LOLO: $result"
    }
    SetStatus "Ramp corrector and bpm setponts..."
    for {set step 1} {$step<=$maxSteps} {incr step} {
	SetStatus "Step $step, setting correctors and bpm setpoints..."
	
	if [catch {exec sddswput $corrWFFile
	    exec sddswput $bpmWFFile.step$step
	    exec sddscasr -restore $bpmFile.step$step  } result] {
	    return -code error "Error setting corrector and bpms: $result"
	}
	
	if {$pause<1} {
	    after [expr int($pause*1000)]
	} else {
	    APSWaitWithUpdate -waitSeconds $pause -updateInterval 1 -abortVariable abortPressed
	}
	if $abortPressed {
	    SetStatus "Procedure aborted in $step step"
	    APSEnableButton $w1.run.button
	    return
	}
	
    }
    
    APSEnableButton $w1.run.button
    SetStatus "Restore corrector range error CALC.B, HIH and LOLO..."
    if [catch {exec sddscasr -restore $corrFile } result] {
	return -code error "Error restore corrector setpoint: $result"
    }
    SetStatus "restor corrector range error..."
    if [catch {exec cavget -list=[join $corrList0 ,] -list=:DacAI -cavputForm -pend=10 } dacList] {
	return -code error "Error reading DacAI: $dacList"
    }
    set putList1 [regsub -all ":DacAI" $dacList ":RangeErrorCALC.B"]
   # puts $putList1
   # puts $putList
    if [catch {exec cavput -list=$putList1 -pend=10
	after 1000
	exec cavput -list=$putList -pend=10 } result] {
	return -code error "Error restore corrector range error: $result"
    }
    
    SetStatus "Reset steering accumulator..."
    set steeringPV ""
    set steerOpt ""
    global hIDsectorList vIDsectorList
   # puts $hIDsectorList
   # puts $vIDsectorList
    foreach plane {h v} coord {X Y} {
	foreach sector [set ${plane}IDsectorList] {
	    if [catch {exec cavput -list=ID$sector:${coord}pActualAccum=0 -pend=10} result] {
		return -code error "Error reseting steering accumulator: $result"
	    }
	    if [string length $steerOpt] {
		append steerOpt ,ControlName=ID[format %02d $sector]:${coord}pRunAccum,|
	    } else {
		set steerOpt -match=col,ControlName=ID[format %02d $sector]:${coord}pRunAccum
	    }
	}
    }
    if [string length $steerOpt] {
	if [catch {eval exec sddsprocess /home/helios/oagData/SCR/snapshots/SR/$SR_Corrector_Recovery(ShortFilename)  \
		       -nowarnings \"$steerOpt\" $rootname.steer } result] {
	    return -code error "Error getting steering run total: $result"
	}
	set rows [exec sdds2stream -rows=bar $rootname.steer]
	if {$rows} {
	    SetStatus "Restore the ID steering run total..."
	    if [catch {exec sddscasr -restore $rootname.steer } result] {
		return -code error "Error restore steering run total: $result"
	    }
	}
    }
    if [catch {APSSaveMachine -machine SR -description "Save after restoring correctors from SCR - $description" -routine 0 } result] {
	return -code error "Error doing SCR save: $result"
    }
    SetStatus "restore done. check corrector values with SCR"
    if [catch {exec sddsprocess $corrFile  -pipe=out  \
		   -reedit=col,ControlName,%/CurrentAO/DacAI/%/SFB:// \
		   | sddscasr -pipe -save -pend=10  \
		   | sddsprocess -pipe -scan=col,Current,ValueString,%lf \
		   | sddsprocess -pipe "-redefine=col,delta,Current RampTo - abs" \
		   | sddsprocess -pipe "-test=col,delta $deltaLimit 2 / >" -nowarnings \
		   | tee $rootname.corrcheck \
		   | sdds2stream -pipe=in -rows=bar } rows] {
	return -code error "Error in checking correctors: $rows"
    }
    if {!$rows} {
	SetStatus "All correctors reached SCR target values."
    } else {
	SetStatus "Some correctors did not reach SCR target, you may need restore the correctors again."
	exec sddsprintout $rootname.corrcheck -col=DeviceName -col=Current -col=RampTo -col=delta $rootname.corrprint 
	APSFileDisplayWindow [APSUniqueName .corr] -fileName $rootname.corrprint  -width 140  -height 30 -printCommand "enscript -r"
    }
    return
	    
}


proc RestoreCorrectorSetup {args} {
    set corrList ""
    set rootname ""
    set plane ""
    set coord ""
    set bpmList ""
    APSParseArguments {SCRFile corrList rootname plane coord bpmList}
    global outputDir SR_Corrector_Recovery deltaLimit stepNum pause abortPressed restartOC hNewConfig vNewConfig maxDelta steeringOnly
    set SCRFile /home/helios/oagData/SCR/snapshots/SR/$SR_Corrector_Recovery(ShortFilename)
    set opt ""
    foreach corr $corrList {
	if ![string length $opt] {
	    set opt -match=col,ControlName=SFB:${corr}:CurrentAO
	} else {
	    append opt ,ControlName=SFB:$corr:CurrentAO,|
	}
    }
    #puts $opt
    set opt1 ""
    #puts $bpmList
    #puts [llength $bpmList]
    if [llength $bpmList] {
	foreach bpm $bpmList {
	    if ![string length $opt1] {
		set opt1 -match=col,ControlName=$bpm:ms:${coord}:SetpointAO
	    } else {
		append opt1 ,ControlName=$bpm:ms:${coord}:SetpointAO,|
	    }
	}
    }
    #puts $opt1
    set wfDir /home/helios/oagData/sr/orbitControllaw/waveforms
    switch $plane {
	h {
	    set bpmWFFile $wfDir/adjustXBpmInfo.sdds
	    set corrWFFile $wfDir/hcorrInfo.sdds
	}
	v {
	    set bpmWFFile $wfDir/adjustYBpmInfo.sdds
	    set corrWFFile $wfDir/vcorrInfo.sdds
	}
    }
    #should read current value from correcgtor waveform
    
    if [catch {exec sddsprocess $SCRFile $opt $outputDir/$rootname.${plane}corr \
		   -scan=col,RampTo,ValueString,%lf \
		   -edit=col,DeviceName,ControlName,%/SFB://%/:CurrentAO// } result ] {
	return -code error "Error creating corrector file: $result"
    }
    # puts $opt1
    if [catch {exec sddsprocess $SCRFile $opt1 -pipe=out \
		   -scan=col,RampTo,ValueString,%lf \
		   | sddscasr -save -pipe \
		   | sddsprocess -pipe=in $outputDir/$rootname.${plane}bpm \
		   -edit=col,DeviceName,ControlName,%/:ms://%/x//%/y//%/:SetpointAO// \
		   -scan=col,RampFrom,ValueString,%lf \
		   "-define=col,Delta,RampTo RampFrom -" } result] {
	return -code error "Error create bpm file: $result"
    }
    
    if [catch {exec sddsconvert $corrWFFile $outputDir/${plane}CorrWFSetpoint -rename=par,WaveformPV=DeltaWaveformPV \
		   -rename=par,SetpointWaveformPV=WaveformPV 
	exec sddswget $outputDir/${plane}CorrWFSetpoint $outputDir/${plane}CorrWFSetpoint.init } result] {
	return -code error "Error reading corrector waveform setpoint: $result"
    }
    if [catch {exec sddsxref $outputDir/${plane}CorrWFSetpoint.init $outputDir/$rootname.${plane}corr -pipe=out \
		   -match=DeviceName -take=RampTo -nowarn -fillIn \
		   | sddsconvert -pipe -rename=col,Waveform=RampFrom \
		   | sddsprocess -pipe "-define=col,Delta,RampTo 0 == ? 0 : RampTo RampFrom - $ " \
		   | sddsprocess -pipe "-define=col,DeltaAbs,Delta abs" \
		   | sddsprocess -pipe=in $outputDir/$rootname.${plane}corrWF -proc=DeltaAbs,max,MaxCorrDelta } result] {
	return -code error "Error computing corrector delta: $result"
    }
    
    set maxDelta [exec sdds2stream -par=MaxCorrDelta $outputDir/$rootname.${plane}corrWF]
    
    if {$maxDelta<1.0e-3} {
	SetStatus "No corrector difference found."
	return 0
    }
    set stepSize [expr $maxDelta/($stepNum*1.0)]
    set steps $stepNum
    if {$stepSize>$deltaLimit} {
	set steps [expr int($maxDelta/$deltaLimit+0.5)]
	set stepSize [expr $maxDelta/($steps*1.0)]
    }
    
    if [catch {exec sddsprocess $outputDir/$rootname.${plane}bpm  "-define=col,StepSize,Delta $steps /" -nowarnings } result] {
	return -code error "Error creating corr and bpm restore file: $result"
    }
    
    if [catch {exec sddswget $bpmWFFile $outputDir/$rootname.${plane}bpmWF } result] {
	return -code error "Error reading corrector and bpm waveform: $result"
    }
    if [catch {exec sddsconvert $outputDir/$rootname.${plane}corrWF -rename=par,WaveformPV=SetpointWaveformPV \
		   -rename=par,DeltaWaveformPV=WaveformPV -pipe=out \
		   -rename=col,Waveform=RampFrom \
		   | sddsprocess -pipe=in $outputDir/$rootname.${plane}corrWFRestore \
		   "-redefine=col,Waveform,Delta $steps /" } result] {
	return -code error "Error creating corrector WF restore: $result"
    }
    
    if [catch {exec sddsxref $outputDir/$rootname.${plane}bpmWF $outputDir/$rootname.${plane}bpm -pipe=out -nowarn \
		   -match=DeviceName -reuse=page -fillIn -take=Delta \
		   | sddsprocess -pipe=in $outputDir/$rootname.${plane}bpmWFRestore \
		   "-define=col,RampFrom,Waveform" \
		   "-define=col,StepSize,Delta $steps /" } result] {
	return -code error "Error create bpm waveform file: $result"
    }
   # puts $steps
    return $steps
}

proc GetDefaultOCConfig {args} {
    global hOrigConfig vOrigConfig hOrigOption vOrigOption
    foreach plane {h v} coord {X Y} {
	set option [exec /usr/local/iocapps/R3.14.11/base/3-14-11-asd1/bin/linux-x86_64/caget \
                                -S DP:S:OrbitControlLaw${coord}SDDS.OPTN]
	#if [catch {APScagetTextFromWaveform -pvName DP:S:OrbitControlLaw${coord}SDDS.OPTN } option] {
	#    return -code error "Error getting DP OC option: $option"
	#}
	set options [split $option " "]
	set ${plane}OrigOption [lrange $options 1 end]
	#puts $options
	#puts [lindex $options 2]
	set ${plane}OrigConfig [file tail [file dir [lindex $options 2]]]
    }
}

GetDefaultOCConfig

proc GenerateNewOCConfig {args} {
    set plane ""
    set corrList ""
    set bpmList ""
    APSParseArguments {plane corrList bpmList}
    
    global hNewConfig vNewConfig
    set dir /home/helios/oagData/sr/orbitControllaw/lattices/default
    set name ${plane}.[clock format [clock seconds] -format %Y-%m%d].00
    
    set newConfig [APSNextGenerationedName -directory $dir -name ${plane}.[clock format [clock seconds] -format %Y-%m%d].00 -newFile 1 -separator .]
    SetStatus "Remove [join $corrList] and [join $bpmList] from $plane.defaultDP"
    exec mkdir $dir/$newConfig
    exec chmod 755 $dir/$newConfig
    set opt ""
    foreach corr $corrList {
	if ![string length $opt] {
	    set opt -match=col,Name=$corr,!
	} else {
	    append opt -match=col,Name=$corr,!,&
	}
    }
    foreach bpm $bpmList {
	if ![string length $opt] {
	    set opt -match=col,Name=$bpm,!
	} else {
	    append opt -match=col,Name=$bpm,!,&
	}
    }
    if [catch {exec sddsprocess $dir/$plane.defaultDP/config $dir/$newConfig/config $opt \
		   "-reprint=par,Description,removed [join $corrList] [join $bpmList]"} result] {
	return -code error "Error creating new config: $result"
    }
    if [catch {exec generateControllawFiles -configList $newConfig -pvSuffix msAve -bpmLimit 15 -xbpmLimit 50 \
                 -rangeError 300 -dccLimit 15 -debug 1} results] {
        return -code error "GenerateFilesWithPython: $results"
    }
    #compute irm
    set newCorrs [exec sddsprocess $dir/$newConfig/config -match=par,NameType=CorrectorNames -pipe=out | sdds2stream -pipe -rows=bar]
    if [file exist $dir/$plane.defaultDP/irm] {
	set singularValues [exec sdds2stream -par=NumberOfSingularValuesUsed -page=1 $dir/$plane.defaultDP/irm]
    } else {
	set singularValues $newCorrs
    }
    if [catch {APSSRGenerateOrbCorrFiles \
		   -rootname ${plane}config -generate 1 \
		   -configFile $dir/$newConfig/config \
		   -plane $plane \
		   -referenceMatrix $dir/refMatrices/${plane}.default \
		   -outputRoot $dir/$newConfig/ \
		   -singularValues $singularValues  \
	       } result] {
	return -code error "Error computing irm: $result"
    }
    # generate compensation matrices.
    set rtfbBaseDir /home/helios/oagData/sr/rtfeedback/lattices/default
    if [catch {APSSRGenerateOrbCorrFiles \
		   -rootname ${plane}config -generate 1 \
		   -configFile $dir/$newConfig/config \
		   -plane $plane \
		   -referenceMatrix $dir/refMatrices/${plane}.default \
		   -outputRoot $dir/$newConfig/ \
		   -compensationConfigFile ${rtfbBaseDir}/${plane}.default/config \
	       } result] {
	return -code error "Error generating rmFF matrix: $result"
    }
    return $newConfig
}

proc MakeSCRFrame {widget args} {
    set parent ""
    APSParseArguments {parent}

    global SR_Corrector_Recovery
    set SR_Corrector_Recovery(ShortFilename) ""
    APSAddSCRDialog $widget -parent $parent -system SR \
	-arrayName SR_Corrector_Recovery \
	-defaultFile $SR_Corrector_Recovery(ShortFilename) \
	-label "Choose SCR file:"
}

set delta_limit 0.1
set description "test"
set outputDir [APSGoToDailyDirectory -subdirectory SRCorrRestore]
proc MakeProceedConfigurationFrame {widget args} {
    set parent ""
    APSParseArguments {parent}
    
    global w1 stepNum pause h_delta v_delta outputDir
    APSFrame $widget -parent $parent -label "Proceed" \
      -contextHelp "Use this frame to proceed with correctors setup"
    
    set w1 $parent$widget.frame
    APSFrameGrid .procGrid -parent $w1 -xList {x1 x2} -yList {y1 y2 y3} 
    set stepNum 30
    APSLabeledEntry .step -parent $w1.procGrid.x1.y1 -label "Number of Steps: " \
      -width 10 -textVariable stepNum \
      -contextHelp "Input for a number of steps the reduction algorytm should be ruapsn"
    $w1.procGrid.x1.y1 configure -relief groove
    
    set pause 1
    APSLabeledEntry .pause -parent $w1.procGrid.x1.y2 -label "Time Interval: " \
      -width 10 -textVariable pause \
      -contextHelp "Time pause to wait for an user action to abort a procedure"
    $w1.procGrid.x1.y2 configure -relief groove
    global deltaLimit restartOC steeringOnly
    set restartOC 0
    set steeringOnly 0
    APSLabeledEntry .limit -parent $w1.procGrid.x1.y3 -label "Delta limit:" \
      -width 10 -textVariable deltaLimit \
      -contextHelp "The maximum delta in Amps allowed."
#    APSRadioButtonFrame .steer -parent $w1 -label "Restoring ID steering corrector only?" -buttonList {Yes No} \
#	-valueList {1 0} -variable steeringOnly -orientation horizontal
    
   # APSRadioButtonFrame .restart -parent $w1 -label "Restart orbit correction?" -buttonList {Yes No} \
\#	-valueList {1 0} -variable restartOC -orientation horizontal 
    
    set h_delta 1
    #APSLabeledEntry .hdelta -parent $w1.procGrid.x2.y1 -label "    Horizontal Corrector Delta: " \
    \#  -width 10 -textVariable h_delta \
     \# -contextHelp "Value of a delta to use for horizontal corrector current reduction"
    #$w1.procGrid.x2.y1 configure -relief groove
    
    set v_delta 1
    #APSLabeledEntry .vdelta -parent $w1.procGrid.x2.y2 -label "    Vertical Corrector Delta: " \
    \#  -width 10 -textVariable v_delta \
     \# -contextHelp "Value of a delta to use for vertical corrector current reduction"
    #$w1.procGrid.x2.y2 configure -relief groove

    APSLabeledEntry .description -parent $w1 -label "Description:" -textVariable description -width 80
    APSLabeledEntry .outputdir -parent $w1 -label "Output directory:" -textVariable outputDir -width 80
    APSButton .daily -parent $w1.outputdir -packOption "-side right" -text "daily" -size small \
	-command "set outputDir [APSGoToDailyDirectory -subdirectory SRCorrRestore]"
    
    APSButton .run -parent $w1 -text "Run" -command RestoreSRCorrectorFromSCR \
      -contextHelp "Button to invoke the reduction process" 
    APSButton .abort -parent $w1 -text "Abort" -command {set abortPressed 1} \
      -contextHelp "Button to stop the reduction process" 
    APSButton .enable -parent $w1 -text "Enable" -command "APSEnableButton $w1.run.button"
    if {0} {
	# APSButton .reset -parent $w1 -text "Restore" -command ResetChosenCorrectors \
		#   -contextHelp "Button to restore initial corrector setpoints"
	#APSButton .check -parent $w1 -text "Check" -command "MakeListOfCorrectors nonzero" \
		#  -contextHelp "Button to invoke procedure which makes a display of nonzero correctors."
	APSFrame .but -parent $w1 
	global w2
	set w2 $w1.but.frame
	APSButton .turnOff -parent $w2 -text "Turn Off" -command "MakeListOfCorrectors zero" \
	    -contextHelp "Button to invoke procedure which is turning all marked zero correctors off."
	APSButton .turnOn -parent $w2 -text "Turn On" -command "TurnOnAllOffListedCorrectors" \
	    -contextHelp "Button to invoke procedure which is turning all marked correctors on."
	APSButton .enable -parent $w2 -text "Enable" -command "setOpenCloseOnOffButs 1" \
	    -contextHelp "Enables \"Turn On\" and \"Turn Off\" buttons."
	APSButton .disable -parent $w2 -text "Disable" -command "setOpenCloseOnOffButs 0" \
	    -contextHelp "Disables \"Turn On\" and \"Turn Off\" buttons."
	update
	setOpenCloseResetBut 0
	setOpenCloseAbortBut 1
	setOpenCloseOnOffButs 0
    }
}

proc MakeWriteConfigurationFrame {widget args} {
    set parent ""
    APSParseArguments {parent}
    
    global outputFile writeDescription
    APSFrame $widget -parent $parent -label "Write Configuration" \
      -contextHelp "Use this frame to write corrector configurations."
    
    set w2 $parent$widget.frame
    set outputFile [pwd]
    APSLabeledEntry .file -parent $w2 -label "Output File: " -width 76 \
      -textVariable outputFile -contextHelp \
      "Output file used for the configuration to be written into."
    
    APSLabeledEntry .descrip -parent $w2 -label "Description: " -width 76 \
      -textVariable writeDescription -contextHelp \
      "Use to enter a description for the configuration to be written."
    set writeDescription ""
    APSButton .io -parent $w2 -text Write -size small -command WriteFile \
      -contextHelp "Press to write data, using the named configuration file."
}

proc RestartPVTest {args} {
    set plane h
    set dir ""
    APSParseArguments {plane dir}
    
    set steps 300000
    set testcontrolpv DP:[string toupper $plane]OCtestRC
    set interval 0.1
    set time [expr ($interval+3) * $steps ]
    set testInterval [expr $interval/2]
    set RCTimeout 30
    set pvOptions "-time=$time -interval=$testInterval -runControlPV=string=$testcontrolpv,pingTime=$RCTimeout -runControlDesc=string=runpvtest -pend=[expr $RCTimeout - 5]"
    SetStatus "abort PV test..."
    if [catch {exec logMessage  -sourceId=steeringAudit\
		   -tag=Instance $testcontrolpv -tag=Action Abort \
	       } result ] {
        return -code error "AbortPvtest: $result"
    }
    if [catch {exec cavput -list=$testcontrolpv.ABRT=1 -pend=30} result ] {
        return -code error "AbortPvtest: $result"
    }
    exec cawait -waitfor=$testcontrolpv.RUN,equal=0
    exec cavput -list=$testcontrolpv.CLR=1 -pend=30
    SetStatus  "starting sddspvtest .."
    if [file exist $dir/corrRangeError.tests] {
        if [catch {exec sddscasr $dir/corrRangeError.tests -restore -pend=60} result] {
            return -code error $result
        }
    }
    after 1000
    if [catch {exec logMessage  -sourceId=steeringAudit\
		   -tag=Instance $testcontrolpv -tag=Action Start \
	       } result ] {
        return -code error "AbortPvtest: $result"
    }
    set testpv DP:[string toupper $plane]OCtestStatus
   # puts $pvOptions
    eval exec sddspvtest $dir/tests -pvOutput=$testpv $pvOptions &
    puts "sddspvtest $dir/tests -pvOutput=$testpv $pvOptions"
    
    after 2000
    
    SetStatus "pv test restarted."
}

proc RestartControllaw {args} {
    set plane h
    set new 1
    APSParseArguments {config plane new}
    global hNewConfig vNewConfig hOrigConfig vOrigConfig hOrigOption vOrigOption
    set controllawDir  /home/helios/oagData/sr/orbitControllaw/lattices/default
    switch $plane {
	h  {
	    set coord X
	} 
	v {
	    set coord Y
	}
    }
    if $new {
	set dir $controllawDir/[set ${plane}NewConfig]
	set config [set ${plane}NewConfig]
    } else {
	set dir $controllawDir/[set ${plane}OrigConfig]
	set config [set ${plane}OrigConfig]
    }
    set Plane [string toupper $plane]
    SetStatus "abort current controllaw and pv test..."
    catch {exec logMessage -sourceId=steeringAudit \
	       -tag=Instance DP:S:OrbitControlLaw${coord}SDDS -tag=Action Abort}
    if [catch {exec cavput -list=DP:S:OrbitControlLaw${coord}SDDS.ABRT=1 -pend=30 } result] {
	return -code error "Error aborting $plane DP orbit correction: $result"
    }
    exec cawait -waitfor=DP:S:OrbitControlLaw${coord}SDDS.RUN,equal=0
    SetStatus "restore corrector range error..."
    if [catch {RestartPVTest -plane $plane -dir $dir } result] {
	return -code error "Error restart pv test: $result"
    }
   
    after 1000
    #restart controllaw
    if $new {
	set options [regsub -all [set ${plane}OrigConfig] [set ${plane}OrigOption] [set ${plane}NewConfig]]
    } else {
	set options  [set ${plane}OrigOption]
    }
   # puts $options
    exec /usr/local/iocapps/R3.14.11/base/3-14-11-asd1/bin/linux-x86_64/caput \
                                -S DP:S:OrbitControlLaw${coord}SDDS.OPTN $options
    #if [catch {APScaputTextToWaveform -pvName DP:S:OrbitControlLaw${coord}SDDS.OPTN -text "$options"} result] {
    #	return -code error "Error setting DC option: $result"
    #}
    SetStatus "start [set ${plane}OrigConfig]  OC ..."
    #restart controllaw
    catch {exec logMessage -sourceId=steeringAudit \
	       -tag=Instance DP:S:OrbitControlLaw${coord}SDDS -tag=Action Start}
    if [catch {exec cavput -list=DP:S:OrbitControlLaw${coord}SDDS.CMND=1 -pend=30} result] {
	return -code error $result
    }
    SetStatus "$config controllaw started."
}

proc GetCorrList {args} {
    set plane h
    APSParseArguments {plane}
    global hIDsector vIDsector hBPMList vBPMList hcorrList vcorrList rootname steeringOnly
    set sector [set ${plane}IDsector]
}

proc GetSelectedCorrectors {args} {
    global hBPMList vBPMList hcorrList vcorrList outputDir rootname SR_Corrector_Recovery IDsector
    
    set hItemList {A:H1 A:H2 A:H3 A:H4 B:H4 B:H3 B:H2 B:H1 C:H1}
    set vItemList {A:V1 A:V2 A:V3 A:V4 B:V4 B:V3 B:V2 B:V1 C:V1}
    
    set hcorrList ""
    set vcorrList ""
    set hBPMList ""
    set vBPMList ""
    set hsectorList ""
    set vsectorList ""
    foreach plane {h v} {
	set itemList [set ${plane}ItemList]
	foreach item $itemList {
	    for {set s 1} {$s<=40} {incr s} {
		set name S${s}$item
		set nameFlag sconfig$name
		global $nameFlag
		if [set $nameFlag] {
		    lappend ${plane}corrList $name
		    lappend ${plane}sectorList $s
		}
	    }
	}
    }
    
    set hsectorList [lsort -unique $hsectorList]
    set vsectorList [lsort -unique $vsectorList]
    
    set filename /home/helios/oagData/SCR/snapshots/SR/$SR_Corrector_Recovery(ShortFilename)
    
    set hBPMList ""
    set vBPMList ""
    #check if ID sector is selected
    global hID vID
    foreach plane {h v} {
	for {set i 1} {$i<=35} {incr i} {
	    if [set ${plane}ID($i)] {
		set ${plane}BPMList [concat [set ${plane}BPMList] $IDsector($plane.$i.bpmList)]
	    }
	}
    }
    
    set hBPMList [lsort -unique $hBPMList]
    set vBPMList [lsort -unique $vBPMList]
    
    foreach plane {h v} coord {x y} {
	set bpmList [set ${plane}BPMList]
	if [llength $bpmList] {
	    continue
	}
	set corrList [set ${plane}corrList]
	if [llength $corrList] {
	    set sectorList [set ${plane}sectorList]
	    set opt ""
	    
	    foreach sector $sectorList {
		if ![string length $opt] {
		    set opt -match=col,ControlName=S${sector}*P*:ms:${coord}:SetpointAO
		} else {
		    append opt ,ControlName=S${sector}*P*:ms:${coord}:SetpointAO,|
		}
	    }
	    #puts $opt
	    #puts $filename
	    if [catch {eval exec sddsprocess $filename $opt -pipe=out \
			   -edit=col,DeviceName,ControlName,%/:ms:${coord}:SetpointAO// \
			   | sdds2stream -pipe=in -col=DeviceName } bpmList] {
		return -code error "Error getting bpm names: $bpmList"
	    }
	    set ${plane}BPMList [join $bpmList]
	   # puts $corrList
	   # puts $bpmList
	}
    }
}

set hIDsectorList ""
set vIDsectorList ""
set hSingleID ""
set vSingleID ""
proc SelectSingleIDSector {args} {
    set plane h
    set sector ""
    APSParseArguments {plane sector}
    global sconfigCBWidget hID vID hIDsectorList vIDsectorList hBPMList vBPMList IDsector
    
    set dir /home/helios/oagData/sr/localSteering/lattices/default/IDs/[format %02d $sector]ID/
    set configFile $dir/${plane}.corrName
    set rmFile $dir/${plane}.steering.rm
    set corrList [join [exec sdds2stream -col=CorrName $configFile]]
    set BPMList [join [exec sdds2stream -col=BPMName $rmFile]]
    set IDsector($plane.$sector.bpmList) $BPMList
    foreach corr $corrList {
	set nameFlag sconfig$corr
	global $nameFlag
	set $nameFlag [set ${plane}ID($sector)]
	$sconfigCBWidget($corr) invoke
	$sconfigCBWidget($corr) invoke
    }
    if [set ${plane}ID($sector)] {
	if [lsearch -exact [set ${plane}IDsectorList] $sector]<0 {
	    lappend ${plane}IDsectorList $sector
	}
    } else {
	set index [lsearch -exact [set ${plane}IDsectorList] $sector]
	if {$index>=0} {
	    set ${plane}IDsectorList [lreplace [set ${plane}IDsectorList] $index $index]
	}
    }
    return
}
proc SelectNone {args} {
    set plane h
    APSParseArguments {plane}
    global rootname hIDsectorList vIDsectorList
    switch $plane {
	h {
	    APSSetSRSectorButtons -mode all-off -rootname $rootname -sectorCount 40 \
		-itemList {A:H1 A:H2 A:H3 A:H4 B:H4 B:H3 B:H2 B:H1 C:H1} 
	    set hIDsectorList ""
	}
	v {
	    APSSetSRSectorButtons -mode all-off -rootname $rootname -sectorCount 40 \
		-itemList {A:V1 A:V2 A:V3 A:V4 B:V4 B:V3 B:V2 B:V1 C:V1}
	    set vIDsectorList ""
	}
    }
    global hID vID
    for {set sector 1} {$sector<=35} {incr sector} {
	set ${plane}ID($sector) 0
    }
}

proc SelectIDSector {args} {
    set plane h
    APSParseArguments {plane}
    global hIDsector vIDsector hBPMList vBPMList hcorrList vcorrList rootname steeringOnly
    global hID vID hButtonNameList IDsectorList
    
    global sconfigCBWidget

    if [string compare $plane "both"]==0 {
	set planeList {h v}
    } else {
	set planeList $plane
    }
    foreach plane $planeList {
	foreach sector $IDsectorList {
	    if {$sector=="none"} {
		if {[set ${plane}ID($sector)]==1} {
		    switch $plane {
			h {
			    APSSetSRSectorButtons -mode all-off -rootname $rootname -sectorCount 40 \
				-itemList {A:H1 A:H2 A:H3 A:H4 B:H4 B:H3 B:H2 B:H1 C:H1} 
			} 
			v {
			    APSSetSRSectorButtons -mode all-off -rootname $rootname -sectorCount 40 \
				-itemList {A:V1 A:V2 A:V3 A:V4 B:V4 B:V3 B:V2 B:V1 C:V1}
			}
		    }
		    for {set i 1} {$i<40} {incr i} {
			set ${plane}ID($i) 0
		    }
		    set ${plane}ID($sector) 0
		    break
		}
		#else, do nothing
	    } else {
		SelectSingleIDSector -plane $plane -sector $sector
	    }
	}
    }
    return
}

set ${rootname}Lattice default
set ${rootname}MainDir /home/helios/oagData/sr/orbitControllaw
set ${rootname}LatSubDir lattices

set sconfigPlane h
set sconfigReadFile h.default
set sconfigReadDescription ""
set sconfigFilterEnd1 .*
set deltaLimit 0.5
APSMenubarAddMenu .program -parent .menu -text Programs -contextHelp "Run related programs"
if [string compare $buttonOrientation vertical]==0 {
    .menu.program.menu add command -label "Horizontal version" -command \
      "ConfirmRestart -mode horizontal"
} else {
    .menu.program.menu add command -label "Vertical version" -command \
      "ConfirmRestart -mode vertical"
}

if [string compare $buttonOrientation vertical]==0 {
    set cbOption "-side left"
} else {
    set cbOption "-side top"
}

set w $parent$widget.top.but.frame
set missingList ""
set missingListVar ""
set wList [APSTabFrame .corr -parent $w -label "" \
                  -labelList "H_Corrector V_Corrector" -width 1000 -height 300 ]
APSSRCorrectorCheckButtons .shbut -parent [lindex $wList 0] -rootname ${rootname} -plane H \
  -sectorControl 0 -globalButtons 0 \
  -orientation $buttonOrientation -packOption $cbOption

APSSetSRSectorButtons -mode all-off -rootname $rootname -sectorCount 40 \
    -itemList {A:H1 A:H2 A:H3 A:H4 B:H4 B:H3 B:H2 B:H1 C:H1} \

#lappend IDsectorList none
#lappend xIDComList "SelectIDSector -plane h"
#lappend yIDComList "SelectIDSector -plane v"
#set hID(non0) 0
#set vID(none) 0
#lappend xIDvarList hID(none)
#lappend yIDvarList vID(none)
#lappend variableList IDnone
for {set i 1} {$i<=35} {incr i} {
    lappend IDsectorList $i
    lappend xIDComList "SelectSingleIDSector -plane h -sector $i"
    lappend yIDComList "SelectSingleIDSector -plane v -sector $i"
    set hID($i) 0
    set vID($i) 0
    lappend xIDvarList hID($i)
    lappend yIDvarList vID($i)
    set IDsector(h.$i.bpmList) ""
    set IDsector(v.$i.bpmList) ""
}

#puts "[llength $IDsectorList] [llength $xIDComList] [llength $yIDComList]"
set hIDsector None
set vIDsector None
#APSRadioButtonFrame .id -parent [lindex $wList 0] -orientation horizontal -buttonList $IDsectorList -limitPerRow 18  \
 #   -valueList $IDsectorList -variable hIDsector -label "ID sector:" -commandList $xIDComList 
set hButtonNameList [APSCheckButtonFrame .id -parent [lindex $wList 0] -orientation horizontal \
    -buttonList $IDsectorList -limitPerRow 18  \
    -variableList $xIDvarList -orientation horizontal -commandList $xIDComList -label "ID sector:"]
APSButton .none -parent [lindex $wList 0].id -text "none" -size small -command "SelectNone -plane h"

set steeringOnly 0
#APSRadioButtonFrame .steer -parent [lindex $wList 0] -label "Restoring ID steering corrector only?" -buttonList {Yes No} \
#    -valueList {1 0} -variable steeringOnly -orientation horizontal -commandList {"SelectIDSector -plane both" "SelectIDSector -plane both"}


APSSRCorrectorCheckButtons .svbut -parent [lindex $wList 1] -rootname ${rootname} -plane V \
  -sectorControl 0 -globalButtons 0 \
  -orientation $buttonOrientation -packOption $cbOption

#APSRadioButtonFrame .id -parent [lindex $wList 1] -orientation horizontal -buttonList $IDsectorList  \
#    -valueList $IDsectorList -variable vIDsector -label "ID sector:"  -limitPerRow 18 -commandList $yIDComList


APSSetSRSectorButtons -mode all-off -rootname $rootname -sectorCount 40 \
    -itemList {A:V1 A:V2 A:V3 A:V4 B:V4 B:V3 B:V2 B:V1 C:V1} \
    
#APSRadioButtonFrame .steer -parent [lindex $wList 1] -label "Restoring ID steering corrector only?" -buttonList {Yes No} \
#	-valueList {1 0} -variable steeringOnly -orientation horizontal -commandList {"SelectIDSector -plane both" "SelectIDSector -plane both"}
set vButtonNameList [APSCheckButtonFrame .id -parent [lindex $wList 1] -orientation horizontal \
    -buttonList $IDsectorList -limitPerRow 18  \
    -variableList $yIDvarList -orientation horizontal -commandList $yIDComList -label "ID sector:"]
APSButton .none -parent [lindex $wList 1].id -text "none" -size small -command "SelectNone -plane v"

set widgetList [APSTabFrame .action -parent .userFrame -label "" \
                  -labelList "SCR Proceed" -width 800 -height 400 ]
MakeSCRFrame .scr -parent [lindex $widgetList 0]
MakeProceedConfigurationFrame .proceed -parent [lindex $widgetList 1]


set hNewConfig h.2021-1116.11
set vNewConfig v.2021-1116.11
set plane h

set options [regsub -all [set ${plane}OrigConfig] [set ${plane}OrigOption] [set ${plane}NewConfig]]




