proc APSMpP0FeedbackLoadParametersInfo {} {
    return "load parameters for P0 feedback "

}

proc APSMpP0FeedbackLoadParametersInitDialog {frame args} {
    global APSMpP0FeedbackLoadParameters

    APSAddSCRDialog .scr -parent $frame -system P0Feedback \
        -arrayName  APSMpP0FeedbackLoadParameters\
        -defaultFile $APSMpP0FeedbackLoadParameters(ShortFilename)
    
    
}

#This procedure has been placed in the attic
proc APSMpP0FeedbackLoadParameters {args} {
    global APSMpP0FeedbackLoadParameters
    set ShortFilename ""
    APSStrictParseArguments {ShortFilename}

    APSMpStep init -promptDialog  APSMpP0FeedbackLoadParametersInitDialog \
              -desc "Choose SCR file"   \
              -vars "ShortFilename"
    APSMpStep "Restere selected SCR -- $ShortFilename"
    
    set snapDir /home/helios/oagData/SCR/snapshots/P0Feedback
    set tmpRoot /tmp/[APSTmpString]
    #restore scalars
    if [catch {exec sddsprocess $snapDir/$ShortFilename  $tmpRoot.scalar \
                 -match=col,ControlName=*WF,! } result] {
        APSMpReturn error "APSMpSRP0Feedback(1): error in processing $ShortFilename: $result"
    }
    if [catch {exec sddscasr -restore $tmpRoot.scalar  -pendIOTime=100} result] {
        APSMpReturn error "APSMpSRP0Feedback(1a): error in restore $ShortFilename: $result"
    }
    #restor other waveforms except gain
    if [catch {exec sddsprocess $snapDir/[file root $ShortFilename].waveform.gz $tmpRoot.other \
                 -match=par,WaveformPV=*Gain*,! } result] {
        APSMpReturn error "APSMpSRP0Feedback(2): error in processing $ShortFilename waveform: $result"
    }
    if [catch {exec sddswput $tmpRoot.other } result] {
         APSMpReturn error "APSMpSRP0Feedback(2): error in restoring other waveforms: $result"
    }
    
    #do not load waveform when loop is open
    foreach plane {X Y} {
        set value [lindex [exec caget S:P0FB:AcqGain${plane}_SetWF] 3]
        if {$value>1} {
            if [catch {exec sddsprocess $snapDir/[file root $ShortFilename].waveform.gz $tmpRoot.$plane \
                         -match=par,WaveformPV=S:P0FB:AcqGain${plane}_SetWF
                exec sddswput $tmpRoot.$plane } result] {
                APSMpReturn error "APSMpSRP0Feedback(3): error in restore $plane gain: $result"
            }
            file delete -force $tmpRoot.$plane
        }
    }
        
    APSMpReturn ok
}

proc APSMpTurnOnP0FeedbackInfo {} {
    return "turn on P0 feedback for selected plan."
}

proc APSMpTurnOnP0FeedbackInitDialog {frame args} {
    global APSMpTurnOnP0Feedback
    
    APSRadioButtonFrame .plane -parent $frame -label "Select plane:" -buttonList {x y both} \
      -valueList {x y both} -variable APSMpTurnOnP0Feedback(plane) -orientation horizontal
} 
#This procedure has been placed in the attic
proc APSMpTurnOnP0Feedback {args} {
    set plane ""
    APSParseArguments {plane}
    global APSMpTurnOnP0Feedback
    
    APSMpStep init -promptDialog  APSMpTurnOnP0FeedbackInitDialog \
              -desc "Select Plane"   \
              -vars "plane"
    
    if [catch {APSMpTurnOnOffP0Feedback -plane $plane -onoff on} result] {
        APSMpReturn error "Error in turn on P0 feedback: $result"
    }
    APSMpReturn ok
}

proc APSMpTurnOffP0FeedbackInfo {} {
    return "turn Off P0 feedback for selected plan."
}

proc APSMpTurnOffP0FeedbackInitDialog {frame args} {
    global APSMpTurnOffP0Feedback
    
    APSRadioButtonFrame .plane -parent $frame -label "Select plane:" -buttonList {x y both} \
      -valueList {x y both} -variable APSMpTurnOffP0Feedback(plane) -orientation horizontal
}

#This procedure has been placed in the attic
proc APSMpTurnOffP0Feedback {args} {
    set plane ""
    APSParseArguments {plane}
    global APSMpTurnOffP0Feedback
    
    APSMpStep init -promptDialog  APSMpTurnOffP0FeedbackInitDialog \
              -desc "Select Plane"   \
              -vars "plane"
    
    if [catch {APSMpTurnOnOffP0Feedback -plane $plane -onoff off} result] {
        APSMpReturn error "Error in turn off P0 feedback: $result"
    }
    APSMpReturn ok
}

proc APSMpTurnOnOffP0Feedback {args} {
    set plane ""
    set onoff ""
    APSParseArguments {plane onoff}
    
    if ![string length $plane] {
        return -code error "Error(APSMpTurnOnOffP0Feedback1): plane not provided."
    }
    if ![string length $onoff] {
        return -code error  "Error(APSMpTurnOnOffP0Feedback2): onoff not provided."
    }
    switch $plane {
        x {
            set planeList x
        }
        y {
            set planeList y
        }
        both {
            set planeList {x y}
        }
    }
    switch $onoff {
        on {
            set reference /home/helios/oagData/SCR/snapshots/P0Feedback/P0Feedback-loopClose.gz
        }
        off {
            set reference /home/helios/oagData/SCR/snapshots/P0Feedback/P0Feedback-loopOpen.gz
        }
        default {
            return -code error "Error(APSMpTurnOnOffP0Feedback3): Invalid onoff state - $onoff provided."
        }
    }
    
    set waveform [file root [file readlink $reference]].waveform.gz
    set tmpFile /tmp/[APSTmpString]
    foreach plane $planeList {
        switch $plane {
            x {
                set delayPV S:P0FB:P0_DelayRegX_AO
                set gainPV S:P0FB:AcqGainX_SetWF
            }
            y {
                set delayPV S:P0FB:P0_DelayRegY_AO
                set gainPV S:P0FB:AcqGainY_SetWF
            }
        }
        if ![file exist $reference] {
            return -code error "Error(APSMpTurnOnOffP0Feedback4): $reference does not exist. Please install SCR for it first."
        }
        if [catch {exec sddsprocess $reference -match=col,ControlName=$delayPV -pipe=out \
                     | sdds2stream -pipe=in -col=ValueString } delay] {
            return -code error "Error(APSMpTurnOnOffP0Feedback5): error in getting delay value from $reference: $delay"
        }
        if [catch {exec sddsprocess $waveform $tmpFile.$plane -match=par,WaveformPV=$gainPV } result] {
            return -code error "Error(APSMpTurnOnOffP0Feedback6): error in processing $waveform: $result"
        }
        
        if [catch {exec cavput -list=$delayPV=$delay -pend=30} result] {
            return -code error "Error(APSMpTurnOnOffP0Feedback6): Error in setting $delayPV to $delay: $result"
        }
        if [catch {exec sddswput $tmpFile.$plane -pend=100} result] {
            return -code error "Error(APSMpTurnOnOffP0Feedback7): Error in set gain waveform: $result"
        }
    }
}

proc APSMpGenerateP0FeedbackFIRInfo {} {
    return "regenerate FIR from SR tunes."
}

proc APSMpGenerateP0FeedbackFIRInitDialog {frame args} {
    global APSMpGenerateP0FeedbackFIR
    APSLabeledEntry .x -parent $frame -label "fractional x tune:" -width 20 -textVariable APSMpGenerateP0FeedbackFIR(xtune)
    APSLabeledEntry .y -parent $frame -label "fractional y tune:" -width 20 -textVariable APSMpGenerateP0FeedbackFIR(ytune)
    
}

proc APSLoadTwissParameters {args} {
    set twissFile /home/helios/PAR/feedback/generateFIR/aps_nux36nuy19_0601.twi
    APSParseArguments {twissFile plane sPickup sKickerx sKickery}
    
    global  prevTwissFile-x prevTwissFile-y targetNux targetNuy
   
    set tmpRoot /tmp/[APSTmpString]
    
    if [catch {exec  sddsprocess -filter=col,s,0,$sPickup $twissFile -pipe=out \
                 | sddsprocess -clip=0,1,invert -pipe \
                 | sdds2stream -col=s -pipe } lastElementPickup] {
        return -code error "APSLoadTwissParameters1: $lastElementPickup"
    }
    if [catch {exec sddsprocess -filter=col,s,$sPickup,1200 $twissFile -pipe=out \
                 | sddsprocess -clip=1,0,invert -pipe \
                 | sdds2stream -col=s -pipe } nextElementPickup] {
        return -code error "APSLoadTwissParameters2: $nextElementPickup"
    }
    if [catch {exec sddsprocess -filter=col,s,0,[set sKicker${plane}] $twissFile -pipe=out \
                 | sddsprocess -clip=0,1,invert -pipe \
                 | sdds2stream -col=s -pipe} lastElementKicker] {
        return -code error "APSLoadTwissParameters3: $lastElementKicker"
    }
    if [catch {exec sddsprocess -filter=col,s,[set sKicker${plane}],1200 $twissFile -pipe=out \
                              | sddsprocess -clip=1,0,invert -pipe \
                 | sdds2stream -col=s -pipe } nextElementKicker] {
        return -code error "APSLoadTwissParameters4: $nextElementKicker"
    }
   
    foreach element {Pickup Kicker} {
	set lastS [set lastElement${element}]
	set nextS [set nextElement${element}]
        
	set start [expr $lastS - 0.0001]
	set end [expr $lastS + 0.0001]
	set start1 [expr $nextS -0.0001]
	set end1 [expr $nextS +0.0001]
	if {[string match {Pickup} $element]} {
            set sValue [set s$element]
	} else {
            set sValue [set s${element}${plane}] 
	}
	foreach param [list beta${plane} alpha${plane} psi${plane}] {
            global ${param}$element
            set paramName "${param}${element}"
            set lastValue [lindex [exec sddsprocess -filter=col,s,$start,$end \
                                     $twissFile -pipe=out | sdds2stream -col=$param -pipe] 0]
            
            set nextValue [lindex [exec sddsprocess -filter=col,s,${start1},${end1} \
                                     $twissFile -pipe=out | sdds2stream -col=$param -pipe] 0] 
            set ${param}${element} [expr $lastValue + ( $nextValue -$lastValue) * ($sValue - $lastS  ) / ($nextS - $lastS ) ] 
	}
        
    }
    global nux nuy
    set nu${plane} [exec sdds2stream -para=nu${plane} $twissFile]
    set targetNu${plane} 0.0
    set prevTwissFile-${plane} $twissFile
}

#This procedure has been placed in the attic
proc APSMpGenerateP0FeedbackFIR {args} {
    global APSMpGenerateP0FeedbackFIR
    set xtune 0
    set ytune 0
    APSParseArguments {xtune ytune}
    
    set sPickup 7.113932e+01
    set sKickerx 9.6535e+02
    set sKickery 4.353932e+01
   
    APSMpStep init -promptDialog  APSMpGenerateP0FeedbackFIRInitDialog \
      -desc "provide x and y fractional tune"   \
      -vars "xtune ytune"
    
    set outputDir /home/helios/oagData/par/P0feedback/FIRFiles
    set twissFile /home/helios/PAR/feedback/generateFIR/aps_nux36nuy19_0601.twi
    global betaxPickup betaxKicker betayPickup betayKicker alphaxPickup alphaxKicker alphayPickup alphayKicker 
    global psixPickup psixKicker psiyPickup psiyKicker nux nuy
    global prevTwissFile-x prevTwissFile-y DacDelay-x DacDelay-y 
    global order-x delay-x order-y delay-y
    global deltaNux deltaNuy 
    set order-x 6
    set delay-x 0
    set order-y 4
    set delay-y 0
    set deltaNu 0.02
    foreach plane {x y} {
        APSMpStep "loading parameters for $plane plane."
        APSLoadTwissParameters -plane $plane -sPickup $sPickup -sKickerx $sKickerx -sKickery $sKickery
    }
    if !$xtune {
        set nux [expr fmod ($nux, 1)]
    } else {
        set nux $xtune
    }
    if !$ytune {
        set nuy [expr fmod ($nuy, 1)]
    } else {
        set nuy $ytune
    }
    set fileroot [clock format [clock seconds] -format %Y-%m%d:%H%M%S]
    set targetNux 0
    set targetNuy 0
    global APSMpP0RampFIR 
    set APSMpP0RampFIR(steps) 10
    set APSMpP0RampFIR(interval) 1
    foreach plane {x y} {
        set outputFile $outputDir/${fileroot}.nu[set nu$plane].$plane
        APSMpStep "Generating filter file $outputFile for $plane ..."
        if [catch {APSMakeFIRFile -twissFile $twissFile -targetNu [set targetNu$plane] \
                     -outputFile $outputFile -plane $plane \
                     -order [set order-${plane}] -delay \
		     [set delay-${plane}] -nuxy [set nu$plane] \
                     -betaPickup [set beta${plane}Pickup] -betaKicker [set beta${plane}Kicker] \
                     -alphaPickup [set alpha${plane}Pickup] -alphaKicker [set alpha${plane}Kicker] \
                     -psiPickup [set psi${plane}Pickup] -psiKicker [set psi${plane}Kicker] \
                     -deltaNu $deltaNu } result ] {
            APSMpReturn error "Error in generating FIR file: $result"
        }
         APSAddToTmpFileList -ID p0feedback -fileList "$outputFile.1 $outputFile.2 $outputFile.3 $outputFile.4"
        if [catch {exec sddsprocess $outputFile $outputFile.1 "-define=col,PrevValue,Waveform" 
            exec  sddswget $outputFile.1 $outputFile.2 } result] {
            APSMpReturn error "Error in reading $plane FIR: $result"
        }
        if [catch {exec sddsprocess $outputFile.2 -pipe=out \
                     "-define=col,Diff,Waveform PrevValue - abs" \
                     "-define=col,Value,Waveform abs" \
                     -process=Value,sum,ValSum \
                     | tee $outputFile.3 \
                     | sddsprocess -pipe=in $outputFile.4 "-test=col,Diff 1.0e-5 >" -nowarnings } result] {
            APSMpReturn error "Error in processing$plane FIR: $result"
        }
        set rows [exec sdds2stream -rows=bare $outputFile.4]
        if !$rows {
            APSMpStep "No change in $plane FIR, no need loading new FIR."
            continue
        }
        set val [exec sdds2stream -par=ValSum $outputFile.3]
        if !$val {
            APSMpStep "Loading $plane plane filter.."
            if [catch {exec sddswput $outputFile } result] {
                APSMpReturn error "Error in loading FIR file ($outputFile): $result" 
            }
        } else {
            set answer [APSMultipleChoice .info -modal 1 -name "Load/Ramp new FIR for $plane plane" \
                          -question "Current coefficients for $plane plane are not zeros, do you want to load new FIR or ramp?" -labelList {Load Ramp} \
                          -returnList {Load Ramp} ]
            switch $answer {
                Load {
                    set load 1
                    APSMpStep "Loading $plane plane filter..."
                    if [catch {exec sddswput $outputFile } result] {
                        APSMpReturn error "Error in loading FIR file ($outputFile): $result" 
                    }
                }
                Ramp {
                    APSMpStep "Ramping $plane plane filter..."
                    if [catch {APSRampP0FeedbackFIR -filename $outputFile} result] {
                        APSMpReturn error "Error in ramping FIR file ($outputFile): $result" 
                    }
                }
            }
            
        }
    }
    APSMpReturn ok
}

proc APSRampP0FeedbackFIR {args} {
    set filename ""
    APSParseArguments {filename}
    global APSMpP0RampFIR APSMpP0RampFIRResponse
    set APSMpP0RampFIRResponse 0
    APSDialogBox .p0fir -name "Ramp P0Feedback FIR" \
      -okCommand "set  APSMpP0RampFIRResponse ok" \
      -cancelCommand "set APSMpP0RampFIRResponse cancel"
    APSLabeledEntry .steps -parent .p0fir.userFrame -label "Ramp Steps:" -width 20 -textVariable APSMpP0RampFIR(steps)
    APSLabeledEntry .interval -parent .p0fir.userFrame -label "Ramp Interval(seconds):" -width 20 -textVariable APSMpP0RampFIR(interval)

    tkwait variable APSMpP0RampFIRResponse
    if {$APSMpP0RampFIRResponse == "cancel"} {
        return -code error "Ramp P0feedback FIR was cancelled."
    }
    set tmpRoot /tmp/[APSTmpString]
    if [catch {exec sddsprocess $filename $tmpRoot.1 "-define=col,PrevValue,Waveform" 
        exec sddswget $tmpRoot.1 $tmpRoot.2 -pend=30 
        exec  sddsprocess $tmpRoot.2 $tmpRoot.3 "-define=col,Delta,Waveform PrevValue - $APSMpP0RampFIR(steps) /" } result] {
        return -code error "APSMpP0RampFIR(Error1): $result"
    }
    APSAddToTmpFileList -ID p0feedback -fileList "$tmpRoot $tmpRoot.1 $tmpRoot.2 $tmpRoot.3 $tmpRoot.4"
    APSMpStep "ramp filename..."
    for {set i 1} {$i<=$APSMpP0RampFIR(steps)} {incr i} {
        if [catch {exec sddsprocess $tmpRoot.3 $tmpRoot.4  \
                     "-redefine=col,Waveform,Waveform Delta $i * +" 
            exec sddswput $tmpRoot.4  -pend=30} result] {
            return -code error "APSMpP0RampFIR(Error2): step $i: $result"
        }
	after [expr 1000 * $APSMpP0RampFIR(interval)]
    }
    APSMpStep "ramp done."
}

proc APSMakeFIRFile {args} {
    APSParseArguments {twissFile plane delay outputFile order deltaNu betaPickup betaKicker alphaPickup alphaKicker psiPickup psiKicker nuxy delay twissFile targetNu}
    
    set startFreq 0
    set endFreq 1
    set pi 3.14159265
    
    switch $plane {
        x {
	    set factor -1.0
	}
        y {
            set factor 1.0
        }
        default {
            return -code error "APSMakeFIRFile: invalid plane - $plane provided."
        }
    }
    set waveformPV S:P0FB:Coef_[string toupper $plane]_SetWF
    if { $targetNu } {
	set nu${plane}0 [set nu${plane}] 
	set nu${plane} [expr int ([ set nu${plane}0]) +  fmod ($targetNu,1)]
	set deltaNu${plane} [expr [set nu${plane}] - [set nu${plane}0] ]
	set nuRatio [expr [set nu${plane}]/ [set nu${plane}0] ]
	set psi${plane}Pickup [expr [set psi${plane}Pickup] * $nuRatio]
	set psi${plane}Kicker [expr [set psi${plane}Kicker] * $nuRatio]
    }
    
    set nuxy  [expr  fmod ($nuxy, 1)] 
    set deltaPsi [expr $psiKicker - $psiPickup]
    if { $deltaPsi < 0 } { set deltaPsi [expr $deltaPsi + 2 * $pi * $nuxy] }
    set deltaPsi [expr $deltaPsi + 2 * $pi * $delay * $nuxy ]
    set T11 [expr sqrt($betaKicker/$betaPickup)*(cos($deltaPsi)+$alphaPickup*sin($deltaPsi))]
    set T12 [expr sqrt($betaKicker*$betaPickup)*sin($deltaPsi)]
    set T21 [ expr ($alphaPickup - $alphaKicker)/sqrt($betaKicker*$betaPickup)*cos($deltaPsi)-(1+$alphaPickup*$alphaKicker)/sqrt($betaPickup*$betaKicker)*sin($deltaPsi)]
    set T22 [expr sqrt($betaPickup/$betaKicker)*(cos($deltaPsi)-$alphaKicker*sin($deltaPsi))]
    set m11 0
    set m12 0
    set m13 0 
    set m21 0
    set m22 0
    set m23 0
    set m31 0
    set m32 0
    set m33 0 
    set b1 ""
    set b2 ""
    set b3 ""
    
    for {set i 0} { $i<$order} {incr i} {
        set phi [expr 2*$pi*$nuxy*$i]
        set si [expr sin($phi)]
        set ci [expr cos($phi)]
        set m11 [expr $m11 + ($ci-$alphaPickup*$si)*($ci-$alphaPickup*$si)]
        set m12 [expr $m12 -($ci-$alphaPickup*$si)*($betaPickup*$si)]
        set m13 [expr $m13 + ($ci-$alphaPickup*$si)]
        set m22 [expr $m22 + ($betaPickup*$si)*($betaPickup*$si)]
        set m23 [expr $m23-($betaPickup*$si)]
        set m33 [expr $m33 + 1]
        # next to calculated each coeffients for PU samples.
        # the coeffients are stored in 2 arrays
        lappend b1 [expr $ci-$alphaPickup*$si]
        lappend b2 [expr -$betaPickup*$si];
        lappend b3 1
    }
    
    if [catch {exec sddsmakedataset $outputFile.mat \
                 -col=m1,type=double -data=$m11,$m12,$m13 \
                 -col=m2,type=double -data=$m12,$m22,$m23 \
                 -col=m3,type=double -data=$m13,$m23,$m33 } result] {
        return -code error "MakeFIRFile(error1): $result"
    }
    if [catch {exec sddsmatrixop $outputFile.mat $outputFile.Mi.mat -invert} result] {
        return -code error "MakeFIRFile(error2): $result"
    }
    set lists [exec sddsprintout -col=doubleColumn* -notitle -noLabels $outputFile.Mi.mat]
    
    set m11 [lindex $lists 0]
    set m12 [lindex $lists 1]
    set m13 [lindex $lists 2]
    set m21 [lindex $lists 3]
    set m22 [lindex $lists 4]
    set m23 [lindex $lists 5]
    #the waveform has 32
    for {set i 0} {$i < $delay } {incr i} {
	lappend c1 0 
	lappend c2 0 
    }
    for {set i 0} { $i < [expr 32 -$delay] } {incr i } {
        if {$i<$order} {
            set a1 [expr $m11 * [lindex $b1 $i] + $m12 * [lindex $b2 $i] + $m13 * [lindex $b3 $i]]
            set a2 [expr $m12 * [lindex $b1 $i] + $m22 * [lindex $b2 $i] + $m23 * [lindex $b3 $i]]
            lappend c1 [expr $T11 * $a1  + $T12 * $a2]
            lappend c2 [expr $T21 * $a1  + $T22 * $a2]
        } else {
            lappend c1 0
            lappend c2 0
        }
    }
    
    if [catch {exec sddsmakedataset -pipe=out -col=h,type=double -data=[join $c2 , ] \
                 | sddsprocess -pipe=in $outputFile  \
                 -print=par,plane,$plane \
                 -print=par,twissFile,$twissFile \
                 -print=par,WaveformPV,$waveformPV \
                 -define=col,Index,i_row,type=long \
                 -define=para,nu,$nuxy,type=double \
                 -define=para,order,$order,type=long \
                 -define=para,delay,$delay,type=long,units=turn \
                 -define=para,betaKicker,$betaKicker \
                 -define=para,betaPickup,$betaPickup \
                 -define=para,alphaKicker,$alphaKicker \
                 -define=para,alphaPickup,$alphaPickup \
                 -define=para,psiKicker,$psiKicker \
                 -define=para,psiPickup,$psiPickup \
                 -define=para,deltaNu,$deltaNu \
                 "-define=col,hAbs,h abs" \
                 "-process=hAbs,maximum,hMax"  \
                 "-redefine=col,Waveform,h hMax / $factor *" } result] {
        return -code error "MakeFIRFile(error3): $result"
    }
    ####### added position for test
    if [catch {exec sddsmakedataset -pipe=out -col=h,type=double -data=[join $c1 , ] \
                 | sddsprocess -pipe=in ${outputFile}-position  \
                 -print=par,plane,$plane \
                 -print=par,twissFile,$twissFile \
                 -print=par,WaveformPV,$waveformPV \
                 -define=col,Index,i_row,type=long \
                 -define=para,nu,$nuxy,type=double \
                 -define=para,order,$order,type=long \
                 -define=para,delay,$delay,type=long,units=turn \
                 -define=para,betaKicker,$betaKicker \
                 -define=para,betaPickup,$betaPickup \
                 -define=para,alphaKicker,$alphaKicker \
                 -define=para,alphaPickup,$alphaPickup \
                 -define=para,psiKicker,$psiKicker \
                 -define=para,psiPickup,$psiPickup \
                 -define=para,deltaNu,$deltaNu \
                 "-define=col,hAbs,h abs" \
                 "-process=hAbs,maximum,hMax"  \
                 "-redefine=col,Waveform,h hMax /" } result] {
        return -code error "MakeFIRFile(error30): $result"
    }
}

proc  APSMpRampToHigherChromaticityInfo {} {
    return "RampTo higher chromaticity without running P0 feedback."
}

#This procedure has been placed in the attic
proc APSMpRampToHigherChromaticity {args} {
    APSMpStep "Do SCR save before ramp-to-high-chromaticity..."
    if [catch {APSSaveMachine -machine SR \
		   -description "Prior to ramp-to-high-chromaticity(APSMpRampToHigherChromaticity pem)."} result] {
	APSMpReturn error "APSMpRampToHigherChromaticity(APSSaveMachine1): $result"
    }
    set scrFile /home/helios/oagData/SCR/snapshots/SR/SR-UserBeamPreferredNoP0Feedback.gz
    APSMpStep "Now it is going to restore higher chromaticity from $scrFile."
    set tmpRoot /tmp/[APSTmpString]
    #only ramp sextoples
    if [catch {exec sddsprocess $scrFile $tmpRoot -match=col,ControlName=S*:S*:CurrentAO \
		   -match=col,Category=MainPS } result] {
        APSMpReturn error "Error in processing $scrFile: $result"
    }
    #check if orbit correction is running
    while {1} {
        if [catch {exec cavget -list=DP:S:OrbitControlLaw -list=X,Y -list=SDDS.RUN -printErrors -pend=30} runList] {
            APSMpReturn error "APSMpRampToHigherChromaticity(check controllaw): problem in reading DP controllaw pvs."
        }
        set xrun [lindex $runList 0]
        set yrun [lindex $runList 0]
        if {!$xrun && !$yrun} {
            set message "both plane XRDP orbitcorrection is not running."
        } elseif {!$xrun} {
            set message "x plane data pool orbitcorrection is not running."
        } elseif {!$yrun} {
            set messsage "y plane data pool orbitcorrection is not running."
        } else {
            set message ""
        }
        if [string length $message] {
            set answer [APSMultipleChoice .warning -modal 1 -name "Orbit correction is not running" \
			    -question "$message, press \"re-check\" or \"Abort\" to abort" \
			    -returnList {Re-check Abort} -labelList {Re-check Abort}]
            if {$answer=="Abort"} {
                APSMpReturn error "APSMpRampToHigherChromaticity was aborted because of orbit correction not running!"
            }
        } else {
            break
        }
    }
    APSMpStep "Ramp the sextuple to higher chromaticity ..."
    if [catch {APSRampToSnapshot -initDialog 1 -fileName $tmpRoot  } result] {
        APSMpReturn error "APSMpRampToHigherChromaticity(APSRampToSnapshot): $result"
    }
    after 5000
    APSMpStep "Calculate model chromaticity..."
    if [catch {exec /home/helios/oagData/logging/SRLatticeParameters/computeLatticeParameters} result] {
	APSMpReturn error "APSMpRampToHigherChromaticity(computeLatticeParameters): $result"
    }
    if [catch {exec cavput -list=S:OPS:chromModeB0=High } result] {
	APSMpReturn error "Error in setting chromaticity toggle pv: $result"
    }
    
    APSMpStep "Do SR SCR save after ramp-to-high-chromaticity ..."
    if [catch {APSSaveMachine -machine SR \
		   -description "after ramp sextuples to higher chromaticity(APSMpRampToHigherChromaticity pem)."} result] {
	APSMpReturn error "APSMpRampToHigherChromaticity(APSSaveMachine): $result"
    }
    set snapshot [lindex $result 0]
    if [APSYesNoPopUp "Do you want to install just-saved SR SCR to UBOP without P0 Feedback? Yes(during operations) or No (during stuides only)"] {
	APSMpStep "Install UBOP..."
	if [catch {APSSCRInstallPreferredFile -system SR -choice "User beam operator preferred without P0 feedback" \
		       -filename $snapshot } result] {
	    APSMpReturn error "APSMpRampToHigherChromaticity(APSSCRInstallPreferredFile): $result"
	}
	if [catch {APSSRUpdateUBOPLink -suffix UserBeamPreferredNoP0Feedback} result] {
	    APSMpReturn error "APSMpRampToHigherChromaticity((update UBOP link): $result"
	}
    }
    
    APSMpReturn ok
}

proc APSSRUpdateUBOPLink {args} {
    set suffix ""
    set choice ""
    APSParseArguments {suffix choice}
    
    if ![string length $suffix] {
	#check choice
	if ![string length $choice] {
	    return -code error "APSSRUpdateUBOPLink1: Either suffix or choice has to be provided.!"
	}
	set tmpFile /tmp/[APSTmpString]
	if [catch {exec sddsprocess /home/helios/oagData/SCR/preferredChoices/SR.sdds \
		       $tmpFile "-match=col,ChoiceName=$choice" } result] {
	    return -code error "APSSRUpdateUBOPLink1: $choice not found: $result"
	}
	set userList [exec sdds2stream $tmpFile -col=PrivilegedUsers]
	set suffix [exec sdds2stream $tmpFile -col=Suffix]
	set userList [regsub -all {\"} $userList ""]
	if [lsearch -exact $userList $env(USER)]<0 {
	    return -code error "APSSRUpdateUBOPLink2: $env(USER) is not authorized for installing UBOP."
	}
    }
    switch $suffix {
	UserBeamPreferredNoP0Feedback {
	    set toggleValue High
	}
	UserBeamPreferredWithP0Feedback {
	    set toggleValue Low
	}
	default {
	    return -code error "APSSRUpdateUBOPLink3: invalid $suffix provided."
	}
    }
    set oldDir [pwd]
    cd /home/helios/oagData/SCR/snapshots/SR
    if [catch {exec rm SR-UserBeamPreferred.gz
	exec ln -s SR-${suffix}.gz SR-UserBeamPreferred.gz } result] {
	return -code error "APSSRUpdateUBOPLink3: error in installing SR UBOP link: $result"
    }
    if [catch {exec cavput -list=S:OPS:chromModeB0=$toggleValue } result] {
	APSMpReturn error "Error in setting chromaticity toggle pv: $result"
    }
    set filename [file readlink SR-${suffix}.gz]
    cd $oldDir
    if [catch {APSSCRLogAction -file $filename -action "installed $suffix as SR UBOP"} result] {
        return -code error "APSSRUpdateUBOPLink4: $result"
    }
}

proc APSFindP0FBStartBucket {args} {
    set confirm 0
    set statusCallback ""
    set gainFile ""
    APSParseArguments {confirm statusCallback gainFile}
    if $confirm {
        APSInfoWindow [APSUniqueName .] -name "Inject single bunch or 24 singlet" -infoMessage "*Inject a single bunch or 24 singlet in the ring -- make sure single bunch current <= 2mA .\nPress ok when it is done." -modal 1 -width 80
    }
   
    set patternFile /home/helios/oagData/par/P0feedback/patternFiles/432-buckets
    set tmpRoot /tmp/[APSTmpString]
    if ![string length $gainFile] {
        set gainFile $tmpRoot.gain
        APSAddToTmpFileList -ID p0feedback -fileList $tmpRoot.gain
        if [catch {exec sddswget -pv=S:P0FB:AcqGainX_SetWF,S:P0FB:AcqGainY_SetWF $gainFile } result] {
            return -code error "APSFindP0FBStartBucket2a: Error reading gain pv: $result"
        }
    }
    if [string length $statusCallback] {
        eval $statusCallback {"set P0Feedback gain to zero."}
    }
    if [catch {exec sddsprocess $gainFile $tmpRoot.gain0 -redefine=col,Waveform,0 } result] {
        return -code error "APSFindP0FBStartBucket4a: error process gain file: $result"
    }
    if [catch {exec sddswput $tmpRoot.gain0 } result] {
        return -code error "APSFindP0FBStartBucket4b: error setting gain to zero: $result"
    }
    after 1000
    APSAddToTmpFileList -ID p0feedback -fileList $tmpRoot.gain0
    if [string length $statusCallback] {
        eval $statusCallback {"load a 432 sample pattern (sample all)."}
    }
    if [catch {exec sddswput $patternFile -pend=30} result] {
        return -code error "APSFindP0FBStartBucket1: Error loading 432 pattern: $result"
    }
    if [catch {exec cavget -list=C0:P0FB:SumAttSet.A,C1:P0FB:SumAttSet.A -printErrors -pend=30 } attenList] {
        return -code error "APSFindP0FBStartBucket2: Error reading attenuator values; $attenList"
    }
    set xatten [lindex $attenList 0]
    set yatten [lindex $attenList 1]
    if [string length $statusCallback] {
        eval $statusCallback {"set the attenuator to zero."}
    }
    if [catch {exec cavput -list=C0:P0FB:SumAttSet.A=0,C1:P0FB:SumAttSet.A=0 -pend=20} result] {
        return -code error "APSFindP0FBStartBucket4: Error setting attenuator to 0: $result"
    }
    if [string length $statusCallback] {
        eval $statusCallback {"Read the position of target bunch which defines startSample"}
    }
    
    if [catch {exec sddswget -pv=S:P0FB:scope:gtr:waveform0 -pipe=out \
                 | tee $tmpRoot.data \
                 | sddsprocess -pipe -clip=[expr 37 * 432],0,invert \
                 | sddsbreak -pipe -rowlimit=432 \
                 | sddsprocess -pipe -redefine=col,Index,i_row,type=long \
                 | tee $tmpRoot.break \
                 | sddsenvelope -pipe -mean=Waveform \
                 | tee $tmpRoot.1 \
                 | sddsprocess -pipe -redefine=col,Index,i_row,type=long \
                 -process=WaveformMean,ave,WaveformMeanAve \
                 | sddsprocess -pipe "-define=col,Change,WaveformMean WaveformMeanAve - abs" \
                 | sddsprocess -pipe -process=Change,max,MaxChange \
                 | sddsprocess -pipe "-define=col,RelativeChange,Change MaxChange /" \
                 | sddspeakfind -pipe -col=RelativeChange -threshold=0.5  \
                 | tee $tmpRoot.2 \
                 | sdds2stream -pipe -col=Index } peakIndexList] {
        return -code error "Error in getting peak index: $peakIndexList"
    }
    APSAddToTmpFileList -ID p0feedback -fileList "$tmpRoot.1 $tmpRoot.2"
    if [string length $statusCallback] {
        eval $statusCallback  {"Restore attenuator..."}
    }
    if [catch {exec cavput -list=C0:P0FB:SumAttSet.A=$xatten,C1:P0FB:SumAttSet.A=$yatten -pend=20} result] {
        return -code error "Error restoring attenuator: $result"
    }
    set found 0
    foreach i $peakIndexList {
        set start [expr 3*$i + 15]
        if {$start>=1020 && $start<=1073} {
            set multipletStart $start
            set found 1
            break
        }
    }
    if !$found {
        set i [lindex $peakIndexList 0]
        set multipletStart [expr 3*$i + 15]
    }
    if [string length $statusCallback] {
        eval $statusCallback {"The start bucket is $multipletStart"}
    }
    return $multipletStart
}

proc APSUpdateP0FBBunchPattern {args} {
    set statusCallback ""
    APSParseArguments {statusCallback}
   
    if [catch {exec cavget -list=SR:bunchPatternSO -pend=20 -printErrors} bunchPattern] {
        return -code error "APSUpdateP0FeedbackPattern2: error reading bunch pattern: $bunchPattern"
    }
    set patternDir /home/helios/oagData/par/P0feedback/patternFiles
    if [regexp {324} $bunchPattern] {
        #24 singlets
        #do nothing for 324
        return
    } elseif [regexp {24} $bunchPattern] {
        set patternFile $patternDir/24-singlet-pattern
    } else {
        set patternFile $patternDir/single-pattern
    }
    if [string length $statusCallback] {
        eval $statusCallback  {"Finding starting bucket..."}
    }
    set tmpRoot /tmp/[APSTmpString]
    if [catch {exec sddswget -pv=S:P0FB:AcqGainX_SetWF,S:P0FB:AcqGainY_SetWF $tmpRoot.gain } result] {
        return -code error "APSUpdateP0FeedbackPattern3a: Error reading gain pv: $result"
    }
    if [catch {APSFindP0FBStartBucket -statusCallback $statusCallback -gainFile $tmpRoot.gain } startBucket] {
        return -code "APSUpdateP0FeedbackPattern3: $startBucket"
    }
  
    set startSample [expr $startBucket / 3]
    if [catch {exec sddsprocess $patternFile -pipe=out -process=Waveform,Max,MaxPos,pos,func=Index \
                 | sddsprocess -pipe "-define=col,Index1,Index $startSample MaxPos - +,type=long" \
                 | sddsprocess -pipe "-define=col,Index2,Index1 0 < ? Index1 432 + : Index1 $ ,type=long" \
                 | sddsprocess -pipe "-redefine=col,Index2,Index2 432 mod,type=long" \
                 | sddsconvert -pipe -del=col,Index,Index1 \
                 | sddsconvert -pipe -rename=col,Index2=Index \
                 | sddssort -pipe=in -col=Index $tmpRoot.pattern } result] {
        return -code "APSUpdateP0FeedbackPattern4: error generating new pattern file: $result"
    }
    if [string length $statusCallback] {
        eval $statusCallback  {"loading new pattern ($tmpRoot.pattern)..."}
    }
   # APSAddToTmpFileList -ID p0feedback -fileList $tmpRoot.pattern
    if [catch {exec sddswput $tmpRoot.pattern} result] {
        return -code error "APSUpdateP0FeedbackPattern5: error loading new pattern: $result"
    }
    if [string length $statusCallback] {
        eval $statusCallback  {"new P0FB bunch pattern was loaded."}
    }
    if [catch {exec sddswput $tmpRoot.gain } result] {
        return -code error "APSUpdateP0FeedbackPattern6: error restore p0feedback gain: $result"
    }
}

proc APSMpSRSwitchFeedbackSystemInfo {args} {
    return "Switch SR feedback system between P0 and TFB (turn on one and turn off the other)"
}

proc APSMpSRSetFBSystem {args} {
    set parent ""
    set system ""
    APSParseArguments {parent system} 
    global APSMpSRSwitchFeedbackSystem
    
    switch $APSMpSRSwitchFeedbackSystem(system) {
        P0 {
            set system P0Feedback
        }
        TFB {
            set system TFeedback
        }
    }
    catch {destroy $parent.scr}
    APSAddSCRDialog .scr -parent $parent -system $system \
        -arrayName  APSMpSRSwitchFeedbackSystem  \
        -defaultFile $APSMpSRSwitchFeedbackSystem(ShortFilename)
}
proc APSMpSRSwitchFeedbackSystemInitDialog {frame} {
    global APSMpSRSwitchFeedbackSystem
    set APSMpSRSwitchFeedbackSystem(system) P0
    set APSMpSRSwitchFeedbackSystem(ShortFilename) ""
    APSFrame .f1 -parent $frame
    set f1 $frame.f1.frame
    APSRadioButtonFrame .system -parent $f1 -label "Select system to turn on:" -buttonList {P0 TFB} \
      -valueList {P0 TFB} -variable  APSMpSRSwitchFeedbackSystem(system) -orientation horizontal \
      -commandList [list "APSMpSRSetFBSystem -parent $f1" "APSMpSRSetFBSystem -parent $f1"]
    APSMpSRSetFBSystem -parent $f1
    
    
}

proc APSMpSRSetFBGain {args} {
    set system ""
    set xgain ""
    set ygain ""
    APSParseArguments {system xgain ygain}
    switch $system {
        P0 {
            set prefix S:P0FB
        }
        TFB {
            set prefix S:TFB:M
        }
    }
    set tmpRoot /tmp/[APSTmpString]
    foreach plane {x y} {
        set Plane [string toupper $plane]
        set gain [set ${plane}gain]
        if [catch {exec sddswget -pv=${prefix}:AcqGain${Plane}_GetWF $tmpRoot.$plane.1
            exec sddsprocess $tmpRoot.$plane.1 -redefine=col,Waveform,$gain -reedit=par,WaveformPV,%/GetWF/SetWF/ $tmpRoot.$plane} result] {
            return -code error "Erro reading $system gain: $result"
        }
    }
    APSAddToTmpFileList -ID fb -fileList $tmpRoot.x.1 $tmpRoot.x $tmpRoot.y.1 $tmpRoot.y
    if [catch {exec sddswput $tmpRoot.x 
        exec sddswput $tmpRoot.y } result] {
        return -code error "Error reseting $system gain: $result"
    }
}

#This procedure has been placed in the attic
proc APSMpSRSwitchFeedbackSystem {args} {
    global APSMpSRSwitchFeedbackSystem
    set system P0
    set ShortFilename ""
     APSMpStep init -promptDialog  APSMpSRSwitchFeedbackSystemInitDialog \
              -desc "Choose Feedback System and SCR file"   \
              -vars "system ShortFilename"
    APSMpStep "System $system selected, SCR: $ShortFilename"
    switch $system {
        P0 {
            set offSystem TFB
            set offPrefix S:TFB:M
            set SCRsystem P0Feedback
        }
        TFB {
            set offSystem P0
            set offPrefix S:P0FB
            set SCRsystem TFeedback
        }
    }
    APSMpStep "Read TFB and P0 gain..."
    if [catch {exec  sddswget -pv=S:P0FB:AcqGainX_GetWF -pend=30 -pipe=out \
		   | sddsprocess -pipe -process=Waveform,first,Gain \
		   | sdds2stream -pipe -par=Gain } xP0Gain] {
	APSMpReturn error "Error in reading P0 xGain: $xP0Gain"
    }
    if [catch {exec sddswget -pv=S:P0FB:AcqGainY_GetWF -pend=30 -pipe=out \
		   | sddsprocess -pipe -process=Waveform,first,Gain \
		   | sdds2stream -pipe -par=Gain } yP0Gain] {
	APSMpReturn error "Error in reading P0 yGain: $yP0Gain"
    }
    if [catch {exec  sddswget -pv=S:TFB:M:AcqGainX_GetWF -pend=30 -pipe=out \
		   | sddsprocess -pipe -process=Waveform,first,Gain \
		   | sdds2stream -pipe -par=Gain } xTFBGain] {
	APSMpReturn error "Error in reading TFB xGain: $xTFBGain"
    }
    if [catch {exec sddswget -pv=S:TFB:M:AcqGainY_GetWF -pend=30 -pipe=out \
		   | sddsprocess -pipe -process=Waveform,first,Gain \
		   | sdds2stream -pipe -par=Gain } yTFBGain] {
	APSMpReturn error "Error in reading TFB yGain: $yTFBGain"
    }
    if {$offSystem=="P0" && ($xP0Gain!=0 || $yP0Gain!=0)} {
        set answer [APSMultipleChoice .info -modal 1 -question "P0 Feedback is on, are you sure to turn it off and switch to TFB?" \
                      -labelList {"Continue" "Abort"} -returnList {"Continue" "Abort"} ]
        if {$answer=="Abort"} {
            APSMpReturn error "Aborted."
        }      
    } elseif {$offSystem=="TFB" && ($xTFBGain!=0 || $yTFBGain!=0)} {
        set answer [APSMultipleChoice .info -modal 1 -question "TBF Feedback is on, are you sure to turn it off and switch to P0?" \
                      -labelList {"Continue" "Abort"} -returnList {"Continue" "Abort"} ]
        if {$answer=="Abort"} {
            APSMpReturn error "Aborted."
        }         
    }
    #APSMpStep "Set P0 and TFB gains to zero."
    if {$offSystem=="P0"} {
        APSMpStep "Set P0 gains to zero."
        if [catch {APSMpSRSetFBGain -system P0 -xgain 0 -ygain  0} result] {
            APSMpReturn error "Error setting P0 gain to zero: $result"
        }
    }
    if {$offSystem=="TFB"} {
        APSMpStep "Set TFB gains to zero."
        if [catch {APSMpSRSetFBGain -system TFB -xgain 0 -ygain  0} result] {
            APSMpReturn error "Error setting TFB gain to zero: $result"
        }
    }
    #APSMpStep "Shift $offSystem Dacs up by 10 counts..."
    #if [catch {exec cavput -list=${offPrefix}:P0_DelayReg -list=X,Y -list=_AO=10 -deltaMode -pend=10} result] {
    #    APSMpReturn error "Error shift $offSystem Dacs up: $result"
    #}
    
    APSMpStep "Restore $system SCR."
   
    if [catch {exec sddsprocess /home/helios/oagData/SCR/snapshots/$SCRsystem/$ShortFilename -match=col,IsReadOnly=n  -pipe=out \
                 | sddscasr -pipe=in  -restore \
                 -waveform=directory=/home/helios/oagData/SCR/snapshots/$SCRsystem,onefile,rootname=[file root $ShortFilename],extension=.waveform.gz } result] {
        APSMpReturn error "Error restore $system SCR: $result."
    }
    APSMpStep "Switched to $system."
    APSMpReturn ok
}
