#!/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)]

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

APSStandardSetup

set env(EPICS_CA_ADDR_LIST) 164.54.85.79
proc SetStatus { text } {
    global statusText
    set statusText "$text ([exec date +%H:%M:%S])"
    update
}

proc TakeData {args} {
    set filename ""
    APSParseArguments {filename}
    
    global BM SF SD QD QF fftStart fftEnd
    global FitStart FitEnd startTime endTime preTrigger sparseInterval injTime  
    
    SetStatus "Only SF is available, now taking SF data..."
    
    if [catch {exec sddswmonitor -datatype=short \
                 -PVnames=PS:B:SF:CurrentWF,PS:B:SF:CurrentRefWF,PS:B:SF:VoltageWF,PS:B:SF:VoltageRefWF \
                 -steps=1 $filename.1 -erase  } result] {
        return -code error "Error in reading waveforms: $result"
    }
    
    set time_per_step [expr 500.0/5120]
    set currentSlope [expr ($SF(Current.high)-$SF(Current.low))/65535.0]
    set voltageSlope [expr ($SF(Voltage.high)-$SF(Voltage.low))/65535.0]
    
    set fitStart [expr int(0.5 + ($preTrigger + $injTime + $SF(FitStart)) / ($sparseInterval * $time_per_step))]
    set fitEnd [expr int(0.5 + ($preTrigger + $injTime + $SF(FitEnd)) / ($sparseInterval * $time_per_step))]
    set tmpRoot /tmp/[APSTmpString]
    set aveStart -$preTrigger
    set aveEnd [expr 20 - $preTrigger - 5.0]
    if [catch {exec sddsprocess $filename.1 -pipe=out \
                 "-define=col,time,i_row  $time_per_step * $preTrigger -,units=ms" \
                 "-redefine=col,%s,%s,type=ushort,select=*WF" \
                 | sddsprocess -pipe "-redefine=col,%s,%s,type=double,select=*WF" \
                 "-process=*WF,baselevel,%sBaseline,functionOf=time,lower=-20,upper=-5"  \
                 | sddsprocess -pipe  \
                 "-redefine=col,%s,%s %sBaseline -,select=*WF" \
                 "-filter=col,time,-$preTrigger,[expr 515 - $preTrigger]" \
                 | sddsprocess -pipe \
                 "-define=col,SFcurrent,PS:B:SF:CurrentWF $currentSlope * $SF(Current.low) +,units=A" \
                 "-define=col,SFcurrentRef,PS:B:SF:CurrentRefWF  $currentSlope * $SF(Current.low) +,units=A" \
                 "-define=col,SFvout,PS:B:SF:VoltageWF  $voltageSlope * $SF(Voltage.low) +,units=V" \
                 "-define=col,SFvoutRef,PS:B:SF:VoltageRefWF $voltageSlope * $SF(Voltage.low) +,units=V" \
                 | sddsprocess -pipe \
                 "-process=*current*,ave,%sOffset,functionOf=time,lowerlimit=$aveStart,upperLimit=$aveEnd" \
                 "-process=*vout*,ave,%sOffset,functionOf=time,lowerlimit=$aveStart,upperLimit=$aveEnd" \
                 | sddsprocess -pipe \
                 "-redefine=col,%s,%s %sOffset -,select=*current*" \
                 "-redefine=col,%s,%s %sOffset -,select=*vout*" \
                 | sddsprocess -pipe -sparse=$sparseInterval \
                 | sddsprocess -pipe \
                 "-redefine=col,index,i_row" \
                 | tee $filename.1 \
                 | sddsprocess -pipe \
                 -process=SFcurrent,slope,SFslope,functionof=index,lowerLimit=$fitStart,upperLimit=$fitEnd \
                 -process=SFcurrent,intercept,SFintercept,functionOf=index,lowerLimit=$fitStart,upperLimit=$fitEnd \
                 "-process=SFvout,slope,SFvSlope1,functionOf=time,lowerLimit=$SF(FitStart),upperLimit=$SF(FitEnd)" \
                 "-process=SFvout,intercept,SFvIntercept1,functionOf=time,lowerLimit=$SF(FitStart),upperLimit=$SF(FitEnd)" \
                 "-process=SFcurrent,slope,SFslope1,functionOf=time,lowerLimit=$SF(FitStart),upperLimit=$SF(FitEnd)" \
                 "-process=SFcurrent,intercept,SFintercept1,functionOf=time,lowerLimit=$SF(FitStart),upperLimit=$SF(FitEnd)" \
                 | sddsprocess -pipe \
                 "-define=col,SFcurrentFit,index SFintercept SFslope / -1.0 * < ? 0.0 : SFslope index * SFintercept + $ ,units=Amperes" \
                 "-redefine=param,SFzero,-1.0 SFintercept1 * SFslope1 / $preTrigger -,units=ms" \
                 "-redefine=param,SF_R,SFslope1 0.0 == ? 0.0 : SFvSlope1 SFslope1 / $ ,units=Ohms" \
                 "-redefine=param,SF_L,SFslope1 0.0 == ? 0.0 : SFvIntercept1 SF_R SFintercept1 * - SFslope1 / $ ,units=mH" \
                 | sddsprocess -pipe \
                 "-process=SFcurrentRef,max,RefMax" \
                 "-define=col,SFdV,SFvout SFvoutRef -" \
                 "-define=col,SFdI_fit,SFcurrent SFcurrentFit -" \
                 "-define=col,SFdI_ref,SFcurrent SFcurrentRef -" \
                 | sddsprocess -pipe=in $filename  -process=SFcurrent,max,MaxPos,functionOf=time,position \
                 "-define=col,SFdI/I_fit,SFcurrentFit 0.001 < ? 1.0 : SFdI_fit SFcurrentFit / $ " \
                 "-define=col,SFdI/I_ref,SFcurrentRef 0.001 < ? 1.0 : SFdI_ref SFcurrentRef / $ " }  result] {
        SetStatus "Process3: $result"
        SetStatus "There may be no signal, please check the device."
        exec rm $filename
    }
    if [file exist $filename] {
        set R [exec sdds2stream -par=SF_R $filename]
        set L [exec sdds2stream -par=SF_L $filename]
        SetStatus "R=$R oms, L = $L mH "
        if [catch {exec sddsprocess $filename -pipe=out -filter=col,time,$fftStart,$fftEnd \
                     | sddsfft -pipe=in  $filename.fft -col=time,*vout*,*current*,*dI/I* -suppress} result] {
            return -code error "sddsfft: $result"
        }
    } else {
        exec cp $filename.1 $filename
    }
    if [catch {exec gzip $filename} result] {
        return -code error $result
    }
    file delete -force $filename.1 $filename.2
    global outputFile
    set outputFile $filename
    
}

proc TakeDataAndFilterNoise {args} {
    set filename /tmp/[APSTmpString].filter
    
    global BM SF SD QD QF fftStart fftEnd
    global FitStart FitEnd startTime endTime preTrigger sparseInterval injTime   
    
    SetStatus "Only SF is available, now taking SF data..."
    
    if [catch {exec sddswmonitor -datatype=short \
                 -PVnames=PS:B:SF:CurrentWF,PS:B:SF:CurrentRefWF,PS:B:SF:VoltageWF,PS:B:SF:VoltageRefWF \
                 -steps=1 $filename.1 -erase  } result] {
        return -code error "Error in reading waveforms: $result"
    }
    
    set time_per_step [expr 500.0/5120]
    set currentSlope [expr ($SF(Current.high)-$SF(Current.low))/65535.0]
    set voltageSlope [expr ($SF(Voltage.high)-$SF(Voltage.low))/65535.0]
    
    set tmpRoot /tmp/[APSTmpString]
    set aveStart -$preTrigger
    set aveEnd [expr 20 - $preTrigger - 5.0]
    if [catch {exec sddsprocess $filename.1 -pipe=out \
                 "-define=col,time,i_row  $time_per_step * $preTrigger -,units=ms" \
                 "-redefine=col,%s,%s,type=ushort,select=*WF" \
                 | sddsprocess -pipe "-redefine=col,%s,%s,type=double,select=*WF" \
                 "-process=*WF,baselevel,%sBaseline,functionOf=time,lower=-20,upper=-5"  \
                 | sddsprocess -pipe  \
                 "-redefine=col,%s,%s %sBaseline -,select=*WF" \
                 "-filter=col,time,-$preTrigger,[expr 515 - $preTrigger]" \
                 | sddsprocess -pipe \
                 "-define=col,SFcurrent,PS:B:SF:CurrentWF $currentSlope * $SF(Current.low) +,units=A" \
                 "-define=col,SFcurrentRef,PS:B:SF:CurrentRefWF  $currentSlope * $SF(Current.low) +,units=A" \
                 "-define=col,SFvout,PS:B:SF:VoltageWF  $voltageSlope * $SF(Voltage.low) +,units=V" \
                 "-define=col,SFvoutRef,PS:B:SF:VoltageRefWF $voltageSlope * $SF(Voltage.low) +,units=V" \
                 | tee $filename.1 \
                 | sddsdigfilter -pipe=in -col=time,SFcurrent -low=1,[expr $SF(lowFreq)/1000.0] $filename.2 } result] {
        SetStatus "Process3a: $result"
        SetStatus "There may be no signal, please check the device."
        
    }
    
    if [catch {exec sddsdigfilter $filename.1 -col=time,SFcurrentRef \
                 -low=1,[expr $SF(lowFreq)/1000.0] $filename.3  
        exec sddsdigfilter $filename.1 -col=time,SFvout -low=1,[expr $SF(lowFreq)/1000.0] $filename.4
        exec sddsdigfilter $filename.1 -col=time,SFvoutRef -low=1,[expr $SF(lowFreq)/1000.0] $filename.5} result] {
        return -code error $result
    }
    if [catch {exec sddsxref $filename.2 $filename.3 $filename.4 $filename.5 -take=Dig* $filename
        exec gzip $filename } result] {
        return -code error $result
    }
    file delete -force "$filename.1 $filename.2 $filename.3 $filename.4 $filename.5"
    exec sddsplot -grap=line,vary -sep=2 -leg -col=time,SFcurrent -col=time,DigFilteredSFcurrent  \
      -col=time,SFcurrentRef -col=time,DigFilteredSFcurrentRef $filename.gz &
    exec sddsplot -grap=line,vary -sep=2 -leg -col=time,SFvout -col=time,DigFilteredSFvout \
      -col=time,SFvoutRef -col=time,DigFilteredSFvoutRef $filename.gz &
}


proc PlotIRatio {args} {
    global plotStart plotEnd collectData outputFile currentGain refGain
    if {$collectData || ![info exist outputFile]} {
        set filename /tmp/[APSTmpString]
    } else {
        set filename $outputFile
    }
    if ![file exist $filename.gz] {
        if [catch {TakeData -filename $filename} result] {
            SetStatus "Error in taking waveform data: $result"
            return
        }
    }
    set tmpfile /tmp/[APSTmpString]
    APSAddToTmpFileList -ID 1 -fileList $tmpfile
    if [catch {exec sddsprocess $filename.gz -pipe=out \
                 "-redefine=col,SFcurrentRef,SFcurrentRef 0.001 < ? 0.001 : SFcurrentRef $ " \
                 | sddsprocess -pipe=in $tmpfile \
                 "-define=col,I/Iref,SFcurrent $currentGain * SFcurrentRef / $refGain /"} result] {
        return -code error $result
    }
    exec sddsplot -legend -col=time,I/Iref -scale=$plotStart,$plotEnd,0,0 $tmpfile &
    exec sddsplot -legend -offset=xchange=-18 "-title=shifted 18ms" -col=time,I/Iref -scale=$plotStart,$plotEnd,0,0 $tmpfile &
    
}

proc PlotIRefTable {args} {
    global plotStart plotEnd collectData outputFile currentGain refGain
    if {$collectData || ![info exist outputFile]} {
        set filename /tmp/[APSTmpString]
    } else {
        set filename $outputFile
    }
    if ![file exist $filename.gz] {
        if [catch {TakeData -filename $filename} result] {
            SetStatus "Error in taking waveform data: $result"
            return
        }
    }
    set tmpfile /tmp/[APSTmpString]
    if [catch {exec sddswget -pv=PS:B:SF:CurrentRT $tmpfile.current
        exec sddswget -pv=PS:B:SF:CurrentRT.TIMA $tmpfile.time
        exec sddsxref $tmpfile.current $tmpfile.time -pipe=out -rename=col,Waveform=time \
                 | sddsprocess -pipe "-redefine=col,time,Index 0 == ? time : time 0 == ? 475.0 : time $ $ " \
                 | sddsprocess -proc=Waveform,max,Max1 -pipe \
                 | sddsprocess -pipe=in "-redefine=col,Waveform,Waveform Max1 /" \
                 $tmpfile.table} result] {
        return -code error "Error1: $result"
    }
    
    if [catch {exec sddsprocess $filename.gz $tmpfile.1 -filter=col,time,0,1000
        exec sddsinterp $tmpfile.table $tmpfile.2 \
                 -filevalues=$tmpfile.1,col=time -col=time,Waveform } result] {
        return -code error $result
    }
    if [catch {exec sddsxref $tmpfile.1 $tmpfile.2 -pipe=out -rename=col,Waveform=RefTable \
                 | sddsprocess -pipe "-redefine=col,RefTable,RefTable RefMax *" \
                 | sddsprocess -pipe=in $tmpfile.ref \
                 "-redefine=col,Iref/Itable,RefTable 0.01 < ? 1 : SFcurrentRef RefTable / $ " \
                 "-redefine=col,I/Itable,RefTable 0.01 < ? 1 : SFcurrent RefTable / $ " } result] {
        return -code error "Error2: $result"
    }
    set fileList [global $tmpfile.*]
    
    APSAddToTmpFileList -ID 1 -fileList $fileList
    exec sddsplot -legend -grap=line,vary -col=time,RefTable -col=time,SFcurrent -col=time,SFcurrentRef $tmpfile.ref &
    exec sddsplot -legend -grap=line,vary -col=time,Iref/Itable -col=time,I/Itable -scale=$plotStart,$plotEnd,0,0 $tmpfile.ref &
    exec sddsplot -legend -offset=xchange=-18 "-title=shifted 18ms" \
      -grap=line,vary -col=time,Iref/Itable -col=time,I/Itable -scale=$plotStart,$plotEnd,0,0 $tmpfile.ref &
    
}

#set outputFile /tmp/071128-095220-4340psgroup1
proc ProcessFilter {args} {
    global filterStart filterEnd lowFreq outputFile
    if ![info exist outputFile] {
        set filename /tmp/[APSTmpString]
    } else {
        set filename $outputFile
    }
    if ![file exist $filename.gz] {
        if [catch {TakeData -filename $filename} result] {
            SetStatus "Error in taking waveform data: $result"
            return
        }
    }
    SetStatus "process $filename with low pass filter ..."
    set tmpfile /tmp/[APSTmpString]
    if [catch {exec sddsprocess $filename.gz $tmpfile.orig -filter=col,time,$filterStart,$filterEnd } result] {
        return -code error $result
    }
    if [catch {exec sddsfdfilter $tmpfile.orig $tmpfile.filter -col=time,SFdI/I_ref -clip=high=$lowFreq } result] {
        return -code error $result
    }
    exec sddsplot  -grap=line,vary -topline=$filename   \
      -col=time,SFdI/I_ref  $tmpfile.orig -leg=spec=original \
      -col=time,SFdI/I_ref  $tmpfile.filter -leg=spec=after_filter &
}
proc plotMagnetRamps {args} {
    set plotType ""
    APSParseArguments {plotType}
    global plotStart plotEnd collectData outputFile
    
    if {$collectData || ![info exist outputFile]} {
        set filename /tmp/[APSTmpString]
    } else {
        set filename $outputFile
    }
    
    if ![file exist $filename.gz] {
        if [catch {TakeData -filename $filename} result] {
            SetStatus "Error in taking waveform data: $result"
            return
        }
    }
    switch $plotType {
        fft {
            exec sddsplot -sep -grap=line,vary -legend -col=f,FFT*current* -col=f,FFT*vout* -group=namestring -sep=3 $filename.fft &
            exec sddsplot -sep -grap=line,vary -legend -col=f,FFT*dI* -group=namestring -sep=3 $filename.fft &
        }
        dI/I {
            exec sddsplot -sep -grap=line,vary -legend -sub=5,5 -col=time,SFdI/I_fit $filename.gz -scale=$plotStart,$plotEnd,-0.05,0.05 &
            exec sddsplot -sep -grap=line,vary -legend -sub=5,5 -offset=xchange=-18 -col=time,SFdI/I_fit \
              "-title=shifted 18ms" $filename.gz -scale=$plotStart,$plotEnd,-0.05,0.05 &
        }
        dI {
            exec sddsplot  -sep -grap=line,vary -legend -col=time,SFdI_fit -sub=5,5 $filename.gz -scale=$plotStart,$plotEnd,0,0 & 
            exec sddsplot  -sep -grap=line,vary -legend -offset=xchange=-18 "-title=shifted 18ms" -col=time,SFdI_fit -sub=5,5 $filename.gz -scale=$plotStart,$plotEnd,0,0 & 
        }
        dI/IRef {
            exec sddsplot -sep -grap=line,vary -legend -sub=5,5  -offset=xchange=-18 "-title=shifted 18ms" -col=time,SFdI/I_ref $filename.gz -scale=$plotStart,$plotEnd,-0.05,0.05 &
            exec sddsplot -sep -grap=line,vary -legend -sub=5,5 -col=time,SFdI/I_ref $filename.gz -scale=$plotStart,$plotEnd,-0.05,0.05 &
        }
        dIRef {
            exec sddsplot  -sep -grap=line,vary -legend -col=time,SFdI_ref -sub=5,5 $filename.gz -scale=$plotStart,$plotEnd,0,0 & 
        }
        dV {
            exec sddsplot  -sep -sub=5,5 -legend -col=time,*dV $filename.gz -scale=$plotStart,$plotEnd,0,0 &
        }
        voltage {
            exec sddsplot -grap=line,vary -sub=5,5 -scale=$plotStart,$plotEnd,0,0 \
              "-xlabel=time (ms)" "-ylabel=Voltage (V)" \
              -legend -col=time,*vout* $filename.gz &
        }
        current {
            exec sddsplot -grap=line,vary -sub=5,5  -scale=$plotStart,$plotEnd,0,0  \
              "-xlabel=time (ms)" "-ylabel=Current (A)" \
              -legend -col=time,*current* $filename.gz &
        }
    }
    return
}


proc computeBeamInjectionTime {pvname} {
    if [catch {exec cavget -list=It:Bs:StartRamp2BsIp.VAL -pend=30} rampstart] {
        return -code error $rampstart
    }
    if [catch {exec cavget -list=$pvname -pend=30} magnetDelay] {
        return -code error $magnetDelay
    }
    if {$rampstart=="?" || $magnetDelay=="?"} {
        return -code error "Can not read value of It:Bs:StartRamp2BsIp.VAL or $pvname."
    }
    set injTime [expr $rampstart - $magnetDelay]
    return [format "%.1f" $injTime]
}

proc computeBeamExtrationTime {injTime} {
    if [catch {exec cavget -list=A014-IETS:BTC:BInjectionCycleM,A014-IETS:BTC:BExtractionCycleM,A014-IETS:BTC:SRSetFreqM -pend=20 -printErrors -floatformat=%lf} results] {
        return -code error "Error reading A014-IETS:BTC:BInjectionCycleM,A014-IETS:BTC:BExtractionCycleM,A014-IETS:BTC:SRSetFreqM: $results"
    }
    set bInjectionCycle [lindex $results 0]
    set bExtractionCycle [lindex $results 1]
    set srFreq [lindex $results 2]
    set extTime [expr $injTime + (1000 * ($bExtractionCycle - $bInjectionCycle) / $srFreq)]
    return [format "%.1f" $extTime]
}
proc PlotArchiveRamp {args} {
    global plotcurrent plotdeltaI/I plotfitError plotvout dialogResponse
    global plotBM plotQD plotQF plotSF plotSD
    set archiveDir /home/helios/oagData/booster/ramps/autoRampCorrection
    
    set dialogResponse 0
    APSDialogBox .plot -name "Plot Autocorrection Archive Ramps" \
      -okCommand "set dialogResponse ok" \
      -cancelCommand "set dialogResponse cancel"
    APSCheckButtonFrame .supply -parent .plot.userFrame \
      -label "Check power supplies for plot:" \
      -buttonList {BM QF QD SF SD} \
      -variableList {plotBM plotQF plotQD plotSF plotSD} \
      -allNone 1
    APSCheckButtonFrame .type -parent .plot.userFrame \
      -label "Check quantity for plot:  " \
      -buttonList {current deltaI/I fitError vout} \
      -variableList {plotcurrent plotdeltaI/I plotfitError plotvout} \
      -allNone 1
    update
    tkwait variable dialogResponse
    set plotColumns ""
    foreach supply {BM QF QD SF SD} {
        if ![set plot$supply] {
            continue
        }
        foreach type {current deltaI/I fitError vout} {
            if ![set plot$type] {
                continue
            }
            lappend plotColumns ${supply}$type
        }
    }
    if ![llength $plotColumns] {
        return -code error "Nothing is selected for plot!"
    }
    set dataFile1 ""
    set dataFile1 [APSFileSelectDialog .dataFileSelectWidget \
                     -path ${archiveDir} \
                     -pattern *_Start.sdds.gz \
                     -title "Ramp data file selection"]
    if ![string length $dataFile1] {
        return -code error "None file is selected for plot."
    }
    regsub {Start} $dataFile1 Finish dataFile2
    #if ![file exist $dataFile2] {
    #   return -code error "$dataFile2 does not exist, i.e., the ramps were not archived after the correction."
    #}
    set corrSupply [string range [file tail $dataFile1] 0 1]
    if [file exist $dataFile2] {
        set plotCmd "sddsplot -grap=line,vary -sep=2 -scale=0,250,0,0"
    } else {
        set plotCmd "sddsplot -grap=line,vary -sep=1 -scale=0,250,0,0"
    }
    lappend plotCmd \"-title=booster ramps before and after $corrSupply correction.\"
    foreach col $plotColumns {
        lappend plotCmd "-col=time,$col -leg=spec=Start $dataFile1"
        if [string match "*deltaI/I" $col] {
            lappend plotCmd "-scal=0,250,-0.01,0.01"
        } else {
            lappend plotCmd "-scal=0,250,0,0"
        }
        if [file exist $dataFile2] {
            lappend plotCmd "-col=time,$col -leg=spec=Finish $dataFile2"
        }
    }
    catch {eval exec [join $plotCmd] &} result
}

proc SetDefaultParameters {} {
    global BM QF QD SF SD
    foreach type {BM QF QD SF SD} {
        set ${type}(Current.low) 0
        set ${type}(Current.high) 200
        set ${type}(Voltage.low) 0
        set ${type}(Voltage.high) 480
        
        foreach nm {Current Voltage} val {88.476 -30.27} {
            set ${type}($nm.offset) $val
        }
        set ${type}(FitStart) 50
        set ${type}(FitEnd) 150
        set ${type}(selected) 0
    }
    set SF(selected) 1
    
    foreach magnet {BM SF SD QF QD} {
        set ${magnet}(convFile) conv${magnet}.sdds
        set ${magnet}(filtFile) 40.180.3.coeffs
        set ${magnet}(filtDelay) 20
        set ${magnet}(fitStart) 50.0
        set ${magnet}(fitEnd) 150.0
        set ${magnet}(LLTime) 20.0
        set ${magnet}(LTime) 5.0
        set ${magnet}(crop) 245.0
        set ${magnet}(HTime) 30.0
        set ${magnet}(HHTime) 50.0
        set ${magnet}(LAvgTime) 0.0
        set ${magnet}(HAvgTime) 3.0
        set ${magnet}(sparse) 3
        set ${magnet}(smoothPt) 7
        set ${magnet}(smoothPass) 6
        set ${magnet}(shift) 11.5
        set ${magnet}(Vscale) 4000.0
        set ${magnet}(gainStart) [expr 0.2 / [set ${magnet}(Vscale)]]
        set ${magnet}(gainStop) [expr 0.2 / [set ${magnet}(Vscale)]]
        set ${magnet}(gainCurv) 1.0
        set ${magnet}(npoints) 1024
        set ${magnet}(normalize) 0.95
        set ${magnet}(ChangeRef) 0.15
    }
    set QF(crop) 253.0
    set QF(smoothPass) 4
    set QF(shift) 3.8
    set QF(Vscale) 750.0
    set QF(gainStart) [expr 0.7 / $QF(Vscale)]
    set QF(gainStop) [expr 0.4 / $QF(Vscale)]
    set QF(gainCurv) 2.0
    set QF(normalize) 1.0
    set QF(ChangeRef) 0.05

    set QD(crop) 253.0
    set QD(smoothPass) 4
    set QD(shift) 3.9
    set QD(Vscale) 750.0
    set QD(gainStart) [expr 0.7 / $QD(Vscale)]
    set QD(gainStop) [expr 0.4 / $QD(Vscale)]
    set QD(gainCurv) 2.0
    set QD(normalize) 1.0
    set QD(ChangeRef) 0.05

    set SF(LLTime) 18.0
    set SF(smoothPass) 4
    set SF(shift) 4.9
    set SF(Vscale) 150.0
    set SF(gainStart) [expr 0.6 / $SF(Vscale)]
    set SF(gainStop) [expr 0.3 / $SF(Vscale)]
    set SF(gainCurv) 2.0
    set SF(normalize) 1.0
    
    set SD(smoothPass) 4
    set SD(shift) 4.7
    set SD(Vscale) 150.0
    set SD(gainStart) [expr 0.6 / $SD(Vscale)]
    set SD(gainStop) [expr 0.3 / $SD(Vscale)]
    set SD(gainCurv) 2.0
    set SD(normalize) 1.0 
}

proc UpdateMagnetGains {args} {
    set magnet ""
    APSParseArguments {magnet}
    if ![string length $magnet] {
        return
    }
    global $magnet
    switch $magnet {
        BM {
            set start 0.2
            set end 0.2
        }
        QF -
        QD {
            set start 0.7
            set end 0.4
        }
        SF -
        SD {
            set start 0.6
            set end 0.3
        }
        default {
            return -code error "invalid magnet - $magnet provided."
        }
    }
    set ${magnet}(gainStart) [expr $start / [set ${magnet}(Vscale)]]
    set ${magnet}(gainStop) [expr $end / [set ${magnet}(Vscale)]]
}
proc CreateMagnetWidget {args} {
    set parent ""
    set magnet ""
    APSParseArguments {magnet parent}
    
    global BM QF SF QD SD
    APSFrame .par -parent $parent -label "$magnet Waveform Collecting Parameters"
    set w $parent.par.frame
    set width 15
    APSLabeledEntryFrame .vol -parent $w -label "Voltage high/low/offset value (V):" \
      -width $width -orientation horizontal \
      -variableList [list ${magnet}(Voltage.high) ${magnet}(Voltage.low) ${magnet}(Voltage.offset)] \
      -contextHelp "provided the high, low (the full range) and offset value for converting the voltage waveform raw data to voltage value."
    APSLabeledEntryFrame .current -parent $w -label "Current high/low/offset value (A):" \
      -width $width -orientation horizontal \
      -variableList [list ${magnet}(Current.high) ${magnet}(Current.low) ${magnet}(Current.offset)] \
      -contextHelp "provided the high, low (the full range) and offset value for converting the current waveform raw data to current value."
    APSLabeledEntryFrame .fit -parent $w -label "Fit time start/end (ms):          " \
      -width $width -orientation horizontal \
      -variableList [list ${magnet}(FitStart) ${magnet}(FitEnd)] \
      -contextHelp "provided the start and end time for the fitting the current waveform."
    

    APSFrame .ramp -parent $parent -label "$magnet Ramp Fix Parameters"
    set w $parent.ramp.frame
    APSFrameGrid .grid -parent $w -xList {x1 x2 x3}
    set w1 $w.grid.x1
    set w2 $w.grid.x2
    set w3 $w.grid.x3
    set width 15
    APSLabeledEntry .con -parent $w1 -label "Convert file:" -width $width \
      -textVariable ${magnet}(convFile) \
      -contextHelp "required coefficients of fixramp for the digital filter which converts the filtered current error to a voltage correction."
    APSLabeledEntry .filter -parent $w1 -label "Filter file:" -width $width \
      -textVariable ${magnet}(filtFile) -contextHelp \
      "optional coefficients of fixramp for a digital filter which is applied to the current error signal prior to applying the converter filter."

    APSLabeledEntry .delay -parent $w1 -label "Filter delay:" -width $width \
      -textVariable ${magnet}(filtDelay) -contextHelp \
      "defines the delay associated with the filter (in number of points)."
    APSLabeledEntry .lstart -parent $w1 -label "Low transition start:" -width $width \
      -textVariable ${magnet}(LLTime) -contextHelp \
      "start of low transition, where transition is the time taken to go from measured to fit w.r.t -range (default 5ms."
    APSLabeledEntry .lend -parent $w1 -label "Low transition end:" -width $width \
      -textVariable ${magnet}(LTime) -contextHelp \
      "end of low transition, where transition is the time taken to go from measured to fit w.r.t -range (default 5ms."
    
    
    APSLabeledEntry .hstart -parent $w1 -label "High transition start:" -width $width \
      -textVariable ${magnet}(HTime) -contextHelp \
      "start of high transition, where transition is the time taken to go from measured to fit w.r.t -range (default 5ms."
    APSLabeledEntry .hend -parent $w1 -label "High transition end:" -width $width \
      -textVariable ${magnet}(HHTime) -contextHelp \
      "end of high transition, where transition is the time taken to go from measured to fit w.r.t -range (default 5ms."
    
    APSLabeledEntry .crop -parent $w1 -label "Crop (ms):" -width $width \
      -textVariable ${magnet}(crop) -contextHelp \
      "Time at which the gain is set to zero. overrides -gain function."
    
    APSLabeledEntry .start -parent $w2 -label "Fit start:" -width $width \
      -textVariable ${magnet}(fitStart) -contextHelp \
      "range of correction, where start is relative to beam injection (+ve = earlier), and end is relative to extraction (+ve = later)."
    APSLabeledEntry .end -parent $w2 -label "Fit end:" -width $width \
      -textVariable ${magnet}(fitEnd) -contextHelp \
      "range of correction, where start is relative to beam injection (+ve = earlier), and end is relative to extraction (+ve = later)."
    
    
    APSLabeledEntry .have -parent $w2 -label "Ave. start time(ms):" -width $width \
      -textVariable ${magnet}(LAvgTime) -contextHelp \
      "average start time in ms."
    APSLabeledEntry .lave -parent $w2 -label "Ave. end time(ms):" -width $width \
      -textVariable ${magnet}(HAvgTime) -contextHelp \
      "average end time in ms."


    APSLabeledEntry .sparse -parent $w2 -label "Sparse:" -width $width \
      -textVariable ${magnet}(sparse) -contextHelp \
      "number of points for sparsing the raw data. A larger number speeds up the calculation time, but at the expense of time resolution. If sparse is 3 points, raw data is collected at 0.09765625 ms steps."
    APSLabeledEntry .smooth -parent $w2 -label "Smooth points:" -width $width \
      -textVariable ${magnet}(smoothPt) -contextHelp \
      "number of points to smooth the derived reference."
    APSLabeledEntry .pass -parent $w2 -label "Smooth passes:" -width $width \
      -textVariable ${magnet}(smoothPass)
    
    APSLabeledEntry .shift -parent $w2 -label "Shift (ms):" -width $width \
      -textVariable ${magnet}(shift) -contextHelp \
      "time shift of correction (ms) relative to the original reference. must be a positive number, which puts the waveform earlier."
    APSLabeledEntry .vscale -parent $w3 -label "Voltage scale (V):" -width $width \
      -textVariable ${magnet}(Vscale) -contextHelp \
      "the scale of magnet voltage."
    # bind $w3.vscale.entry <Leave> "UpdateMagnetGains -magnet $magnet"
    APSLabeledEntry .gainstart -parent $w3 -label "Gain start:" -width $width \
      -textVariable ${magnet}(gainStart) -contextHelp \
      "multiplier for the voltage correction."
    APSLabeledEntry .gainend -parent $w3 -label "Gain end:" -width $width \
      -textVariable ${magnet}(gainStop) -contextHelp \
      "multiplier for the voltage correction."
    APSLabeledEntry .gainc -parent $w3 -label "Gain curvature:" -width $width \
      -textVariable ${magnet}(gainCurv) -contextHelp \
      "multiplier for the voltage correction."
    APSLabeledEntry .npoints -parent $w3 -label "Number of points:" -width $width \
      -textVariable ${magnet}(npoints) -contextHelp \
      "specifies the number of points for the new ramptable."
    APSLabeledEntry .norm -parent $w3 -label "Normalize:" -width $width \
      -textVariable ${magnet}(normalize) -contextHelp \
      "value to which the waveform is normalized in the positive direction."
    APSLabeledEntry .change -parent $w3 -label "Change reference:" -width $width \
      -textVariable ${magnet}(ChangeRef) -contextHelp \
      "the maximum allowed change between new ramp table and reference ramp table."
    
    set SF(lowFreq) 1000
    APSLabeledEntry .freq -parent $w3 -label "Low pass frequency (Hz):" -width $width \
      -textVariable ${magnet}(lowFreq) -contextHelp \
      "the low pass frequency to filter out the frequency that is higher than this frequencey."
}

proc CreateParameterWidget {args} {
    set parent ""
    APSParseArguments {parent}
    global CurrentUpperLimit CurrentLowerLimit VoltageLowerLimit VoltageUpperLimit VoltageOffset CurrentOffset
    global FitStart FitEnd
    
    SetDefaultParameters
    set widgetList [APSTabFrame .tab -parent $parent -label "Parameters" \
                      -labelList {SF BM QF QD SD} -height 400 -width 1000]
    
    CreateMagnetWidget -parent [lindex $widgetList 0] -magnet SF
    CreateMagnetWidget -parent [lindex $widgetList 1] -magnet BM
    CreateMagnetWidget -parent [lindex $widgetList 2] -magnet QF
    CreateMagnetWidget -parent [lindex $widgetList 3] -magnet QD
    CreateMagnetWidget -parent [lindex $widgetList 4] -magnet SD
    
    return
    APSFrame .par -parent $parent -label "Parameters"
    set w $parent.par.frame
    set width 10
    APSFrame .vol -parent $w -label "Voltage" -packOption "-side left"
    APSFrame .upper -parent $w.vol.frame -label "Upper Limit" -packOption "-side left" -relief flat
    foreach type {BM QF SF QD SD} {
        set widget [string tolower $type]
        APSLabeledEntry .$widget -parent $w.vol.frame.upper.frame -label "$type" -textVariable VoltageUpperLimit($type) \
          -width $width
    }
    APSFrame .lower -parent $w.vol.frame -label "Lower Limit" -packOption "-side left" -relief flat
    foreach type {BM QF SF QD SD} {
        set widget [string tolower $type]
        APSLabeledEntry .$widget -parent $w.vol.frame.lower.frame -label "" -textVariable VoltageLowerLimit($type) \
          -width $width
    }
    APSFrame .offset -parent $w.vol.frame -label "Offset" -packOption "-side left" -relief flat
    foreach type {BM QF SF QD SD} {
        set widget [string tolower $type]
        APSLabeledEntry .$widget -parent $w.vol.frame.offset.frame -label "" -textVariable VoltageOffset($type) \
          -width $width
    }
    
    APSFrame .current -parent $w -label "Current" -packOption "-side left"
    APSFrame .upper -parent $w.current.frame -label "Upper Limit" -packOption "-side left" -relief flat
    foreach type {BM QF SF QD SD} {
        set widget [string tolower $type]
        APSLabeledEntry .$widget -parent $w.current.frame.upper.frame -label "$type" -textVariable CurrentUpperLimit($type) \
          -width $width
    }
    APSFrame .lower -parent $w.current.frame -label "Lower Limit" -packOption "-side left" -relief flat
    foreach type {BM QF SF QD SD} {
        set widget [string tolower $type]
        APSLabeledEntry .$widget -parent $w.current.frame.lower.frame -label "" -textVariable CurrentLowerLimit($type) \
          -width $width
    }
    APSFrame .offset -parent $w.current.frame -label "Offset" -packOption "-side left" -relief flat
    foreach type {BM QF SF QD SD} {
        set widget [string tolower $type]
        APSLabeledEntry .$widget -parent $w.current.frame.offset.frame -label "" -textVariable CurrentOffset($type) \
          -width $width
    }

    APSFrame .time -parent $w -label "Fit Time Range" -packOption "-side left"
    APSFrame .upper -parent $w.time.frame -label "Start (ms)" -packOption "-side left" -relief flat
    foreach type {BM QF SF QD SD} {
        set widget [string tolower $type]
        APSLabeledEntry .$widget -parent $w.time.frame.upper.frame -label "$type" -textVariable FitStart($type) \
          -width $width
    }
    APSFrame .lower -parent $w.time.frame -label "End (ms)" -packOption "-side left" -relief flat
    foreach type {BM QF SF QD SD} {
        set widget [string tolower $type]
        APSLabeledEntry .$widget -parent $w.time.frame.lower.frame -label "" -textVariable FitEnd($type) \
          -width $width
    }

    return
    set width 12
    foreach type {SF BM QF QD SD} {
        set widget [string tolower $type]
        if {$type=="SF"} {
            set cscaleLabel "Current Scale(A)"
            set coffsetLabel "Current Offset(A)"
            set vscaleLabel "Voltage Scale(V)"
            set voffsetLabel "Voltage Offset(V)"
            set startLabel "Fit Start Time(ms)"
            set endLabel "Fit End Time(ms)"
        } else {
            set cscaleLabel ""
            set coffsetLabel ""
            set vscaleLabel ""
            set voffsetLabel ""
            set startLabel ""
            set endLabel ""
        }
        APSFrame .$widget -parent $w -label "$type" -relief flat -packOption "-side left"
        APSLabeledEntry .cscale -parent $w.$widget.frame -label "$cscaleLabel" -width $width -textVariable CurrentScale($type)
        APSLabeledEntry .coffset -parent $w.$widget.frame -label "$coffsetLabel" -width $width -textVariable CurrentOffset($type)
        APSLabeledEntry .vscale -parent $w.$widget.frame -label "$vscaleLabel" -width $width -textVariable VoltageScale($type)
        APSLabeledEntry .voffset -parent $w.$widget.frame -label "$voffsetLabel" -width $width -textVariable VoltageScale($type)
        APSLabeledEntry .start -parent $w.$widget.frame -label "$startLabel" -width $width -textVariable StartTime($type)
        APSLabeledEntry .end -parent $w.$widget.frame -label "$endLabel" -width $width -textVariable EndTime($type)
    }
    
    

    return
    APSLabel .label -parent $w -text "                Current               Voltage                Fit Range(ms)"
    APSLabel .label1 -parent $w -text "       Scale       Offset       Scale        Offset     StartTime     EndTime"
    foreach type {BM QF QD SF SD} {
        set widget .[string tolower $type]
        set varList [list CurrentScale($type) CurrentOffset($type) VoltageScale($type) VoltageOffset($type) StartTime($type) EndTime($type)]
        
        APSLabeledEntryFrame $widget -parent $w -label "$type" -width 12 -orientation horizontal \
          -variableList $varList
    }

    return


    APSFrame .cscale -parent $w -relief flat -label "Current Scale" -width 25 -packOption "-side left"
    foreach type {BM QF QD SF SD} {
        set widget .[string tolower $type]
        APSLabeledEntry $widget -parent $w.cscale.frame -label "$type" \
          -textVariable CurrentScale($type) -width 10
    }
    set width1 15
    
    APSFrame .coffset -parent $w -relief flat -label "Current Offset" -width $width1 -packOption "-side left"
    foreach type {BM QF QD SF SD} {
        set widget .[string tolower $type]
        APSLabeledEntry $widget -parent $w.coffset.frame -label "" \
          -textVariable CurrentOffset($type) -width 10
    }

    APSFrame .vscale -parent $w -relief flat -label "Voltage Scale" -width $width1 -packOption "-side left"
    foreach type {BM QF QD SF SD} {
        set widget .[string tolower $type]
        APSLabeledEntry $widget -parent $w.vscale.frame -label "" \
          -textVariable VoltageScale($type) -width 10
    }
    
    APSFrame .voffset -parent $w -relief flat -label "Voltage Offset" -width $width1 -packOption "-side left"
    foreach type {BM QF QD SF SD} {
        set widget .[string tolower $type]
        APSLabeledEntry $widget -parent $w.voffset.frame -label "" \
          -textVariable VoltageOffset($type) -width 10
    }

    APSFrame .start -parent $w -relief flat -label "Fit Start Time(ms)" -width $width1 -packOption "-side left"
    foreach type {BM QF QD SF SD} {
        set widget .[string tolower $type]
        APSLabeledEntry $widget -parent $w.start.frame -label "" \
          -textVariable StartTime($type) -width 10
    }
    APSFrame .end -parent $w -relief flat -label "Fit End Time(ms)" -width $width1 -packOption "-side left"
    foreach type {BM QF QD SF SD} {
        set widget .[string tolower $type]
        APSLabeledEntry $widget -parent $w.end.frame -label "" \
          -textVariable EndTime($type) -width 10
    }
}

set abort 0
proc UpdateCurrentReferenceRamp {args} {
    global abort preTrigger
    set tmpRoot /tmp/[APSTmpString]
    
    set origTable /home/oxygen/SHANG/test/oag/fixramp/SF.ramp.test
    set count 1
    while {1} {
        if $abort {
            SetStatus "Updating current reference ramp was aborted."
            set abort 0
            return
        }
        if [catch {GenerateCurrentRefRamp -currentRamp $tmpRoot.$count.current} result] {
            SetStatus "$result"
            continue
        } 
        SetStatus "Loading $tmpRoot.$count.current to current reference ramp..."
        if [catch {LoadTable -rampTable $tmpRoot.$count.current -current 1} result] {
            return -code error $result
        }
        incr count
        after 1000
        
        APSWaitWithUpdate -waitSeconds 5 
        set fileList [glob $tmpRoot.*]
        # eval file delete -force $fileList
    }
    #    SetStatus "done."
}


proc CorrectMagnetRamps {args} {
    global BM SF SD QD QF rampTable

    set filename /tmp/[APSTmpString]
    if [catch {TakeData -filename $filename} result] {
        SetStatus "Error in taking waveform data: $result"
        return
    }
    set dir /home/oxygen/PSGROUP/ramps/testRamps
    set origTable $dir/SF.ramp
    
    set rampTable $dir/[APSNextGenerationedName -directory $dir -name SF.ramp.test-0000 -newFile 1 -separator -]
    
    set tmpRoot /tmp/[APSTmpString]
    if [catch {exec sddsprocess $filename.gz -pipe=out -process=SFcurrent,max,Itot \
                 "-redefine=col,SFdI/I_fit,SFcurrentFit 0 == ? 0 : SFdI_fit SFcurrentFit / $ " \
                 | sddsprocess -pipe \
                 "-redefine=col,deltaV,time 250 > ? 0 : SF_R SF_L SFslope * + SFdI/I_fit * Itot / $ " \
                 | sddsprocess -pipe "-redefine=col,time,time $SF(shift) -" \
                 | sddsconvert -pipe=in $tmpRoot.1 -retain=col,time,deltaV,SFcurrent,SFcurrentFit} result] {
        return -code error $result
    }
    SetStatus "$origTable"
    if [catch {exec sddsinterp $tmpRoot.1 -column=time,deltaV -fileValues=$origTable,column=RampTime $tmpRoot.2
        exec sddsxref $origTable $tmpRoot.2 -take=deltaV -pipe=out \
                 | sddsconvert -pipe -rename=col,RampSetpoint=RampSetpointOld \
                 | sddsprocess -pipe "-redefine=col,RampSetpoint,RampSetpointOld deltaV -" \
                 | sddsconvert -pipe=in $tmpRoot.new -retain=col,RampTime,RampSetpoint } result] {
        return -code error $result
    }
    
    exec sddsplot -leg -grap=line,vary -col=RampTime,RampSetpoint* $tmpRoot.new \
      -col=RampTime,RampSetpoint $origTable & 
    if [APSYesNoPopUp "Would you like to install the new rampTable now?"] {
        exec cp $tmpRoot.new $rampTable
        cd $dir
        if [catch {LoadTable -rampTable $rampTable} result] {
            return -code error $result
        }
        exec rm SF.ramp
        exec ln -s $rampTable SF.ramp
    }
}

proc GenerateCurrentRefRamp {args} {
    set currentRamp ""
    set plotData 0
    APSParseArguments {filename currentRamp plotData}
    set tmpRoot /tmp/[APSTmpString]
    set origTable /home/oxygen/PSGROUP/ramps/currentRef/SF.current.test-0000
    if ![string length $currentRamp] {
        set currentRamp /home/oxygen/PSGROUP/ramps/currentRef/SFcurrent[clock format [clock seconds] -format %Y-%m%d-%H%M%S]
    }
    
    set filename /tmp/[APSTmpString] 
    if [catch {TakeData -filename $filename} result] {
        return -code error $result
    }
    if [catch {exec sddsprocess $filename.gz $tmpRoot.1 \
                 -process=SFcurrent,max,MaxTime,functionOf=time,position \
                 -process=SFcurrent,max,MaxCurrent } result] {
        return -code error $result
    }
    set max [exec sdds2stream -par=MaxCurrent $tmpRoot.1]
    set maxPos [exec sdds2stream -par=MaxTime $tmpRoot.1]
    if [catch {exec  sddsinterp $filename.gz  -pipe=out \
                 -filevalues=$origTable,column=RampTime -col=time,SFcurrentFit \
                 | sddsprocess -pipe -filter=col,time,0,$maxPos \
                 "-redefine=col,SFcurrentFit,SFcurrentFit 200 / 5 *" \
                 | sddsconvert -pipe -retain=col,time,SFcurrentFit \
                 | sddsconvert -pipe=in $tmpRoot.cur1 -rename=col,time=RampTime,SFcurrentFit=RampSetpoint} result] {
        return -code error $result
    }
    set max [lindex [exec sdds2stream -col=RampSetpoint $tmpRoot.cur1] end]
    set slope [expr -$max/(470.0-$maxPos)]
    if [catch {exec sddsprocess $origTable $tmpRoot.cur2 -filter=col,RampTime,$maxPos,470.0 \
                 "-redefine=col,RampSetpoint,$slope RampTime $maxPos - * $max +"
        exec sddsprocess $origTable $tmpRoot.cur3 -filter=col,RampTime,470.0000001,500 \
                 "-redefine=col,RampSetpoint,0"
        exec sddscombine $tmpRoot.cur1 $tmpRoot.cur2 $tmpRoot.cur3 -merge -pipe=out \
                 | sddsprocess -pipe=in $currentRamp -reprint=par,ControlName,PS:B:SF:CurrentRT \
                 -process=RampSetpoint,max,MaxCurr \
                 -reprint=par,ControlType,pv -redefine=par,RampBias,0.0 } result] {
        return -code error $result
    }
    if $plotData {
        exec sddsplot -col=RampTime,RampSetpoint "-title=Current Reference Table" $currentRamp &
    }
    set maxcurr [exec sdds2stream -par=MaxCurr $currentRamp]
    if {$maxcurr<=0} {
        file delete -force $currentRamp
        return -code error "Corrupted current ramp table generated maybe due to no current signal."
    } else {
        SetStatus "New current reference $currentRamp were generated."
        return $currentRamp
    }
}

proc LoadTable {args} {
    set rampTable ""
    set current 0
    APSParseArguments {current rampTable}

    exec rampload $rampTable
    if $current {
        if [catch {exec cavput -list=PS:B:SF:CurrentRT.SWAP=1 } result] {
            return -code error $result
        }
    } else {
        if [catch {exec cavput -list=PS:B:SF:VoltageRT.SWAP=1 } result] {
            return -code error $result
        }
    } 
    if [catch {exec cavput -list=PS:B:AFG100SyncBO=1 } result] {
        return -code error $result
    }
}

proc LoadVoltageRamp {args} {
    set dir /home/oxygen/PSGROUP/ramps/testRamps
    
    set rampTable [APSFileSelectDialog .chosefile -listDir $dir \
                     -title "Select a ramp table" -pattern "SF*" ]
    if ![string length $rampTable] {
        SetStatus "No ramp table was chosen."
        return
    }
    exec sddsplot -col=RampTime,RampSetpoint $rampTable &
    if [APSYesNoPopUp "load the voltage ramp table $rampTable now?"] {
        SetStatus "Loading $rampTable..."
        if [catch {LoadTable -rampTable $rampTable} result] {
            return -code error $result
        }
        SetStatus "done."
    }
}

proc LoadCurrentRefRamp {args} {
    set dir /home/oxygen/PSGROUP/ramps/currentRef
    
    set rampTable [APSFileSelectDialog .chosefile -listDir $dir \
                     -title "Select a ramp table" -pattern "SF*" ]
    if ![string length $rampTable] {
        SetStatus "No current ref. ramp table was chosen."
        return
    }
    exec sddsplot -col=RampTime,RampSetpoint $rampTable &
    if [APSYesNoPopUp "load the current reference table $rampTable now?"] {
        SetStatus "Loading $rampTable..."
        if [catch {LoadTable -rampTable $rampTable -current 1} result] {
            return -code error $result
        }
        SetStatus "done."
    }
}

proc LoadRampTable {args} {
    global rampTable  
    exec rampload $rampTable
    after 1000
    if [catch {exec cavput -list=PS:B:SF:VoltageRT.SWAP=1 } result] {
        return -code error $result
    }
    after 1000 
    if [catch {exec cavput -list=PS:B:AFG100SyncBO=1 } result] {
        return -code error $result
    }
    exec cp $rampTable  /home/oxygen/SHANG/oag/apps/src/booster/test_ramps/current/SFVref.afg100 
    after 1000
}

proc CorrectRamp {args} {
    #Never called
    global BM SF SD QD QF

    if [catch {VCorrectAndCheck -magnet SF} result] {
        SetStatus "Error in correct SF: $result"
    }
    
}
set tmpRoot /tmp/[APSTmpString]
proc VCorrectAndCheck {args} {
    #Never called
    set magnet ""
    APSParseArguments {magnet}
    global BM SF SD QD QF boosterDir injTime extTime rampTable sparseInterval tmpRoot
    
    set oldMagRampFile $tmpRoot.SF.old.afg100
    set newMagRampFile $tmpRoot.SF.new.afg100
    set logMagRampFile $tmpRoot.SF.log
    set boosterFileDir $boosterDir/current
    set boosterSafetyFileDir $boosterDir/safety
    set boosterErrorFileDir $boosterDir/rampCorrErrorFiles 
    
    file copy -force $boosterFileDir/${magnet}Vref.afg100 $oldMagRampFile
    
    foreach nm [array name $magnet] {
        set $nm [set ${magnet}($nm)]
    }
    if [catch {exec /home/helios/SHANG/oag/apps/src/booster/O.solaris-sparc/fixramp \
                 $oldMagRampFile $newMagRampFile -logFile=$logMagRampFile \
                 -converter=$boosterFileDir/$convFile,Acoeffs,Bcoeffs \
                 -filter=$boosterFileDir/$filtFile,Acoeffs,Bcoeffs \
                 -fitrange=start=$fitStart,end=$fitEnd \
                 -lowtransition=start=$LLTime,end=$LTime \
                 -crop=$crop \
                 -hightransition=start=$HTime,end=$HHTime \
                 -averageTime=start=$LAvgTime,end=$HAvgTime \
                 -sparse=$sparse \
                 -smooth=npoints=$smoothPt,npasses=$smoothPass \
                 -shift=$shift \
                 -gain=start=$gainStart,end=$gainStop,curvature=$gainCurv \
                 -delay=$filtDelay \
                 -npoints=$npoints \
                 -normalize=$normalize \
                 -testStand \
                 -injectionTime=$injTime -extractionTime=$extTime \
                 -currentScale=high=$SF(Current.high),low=$SF(Current.low),offset=$SF(Current.offset) } result] {
        SetStatus $result
        
        #return -code error "fixramp: $result"
    }
    set dataFileUniqueLabel [APSOffsetDateInfo -today 1 -dateFormat Y-M-D]_[lindex [exec date] 3]
    
    if [catch {exec sddschanges -pipe=out $newMagRampFile \
                 -changesIn=RampSetpoint \
                 -baseline=${boosterSafetyFileDir}/${magnet}Vref.afg100 \
                 | sddsxref -pipe $newMagRampFile \
                 -take=RampTime,RampSetpoint \
                 -rename=col,RampSetpoint=RampSetpointCorrection \
                 | sddsxref -pipe ${boosterSafetyFileDir}/${magnet}Vref.afg100 \
                 -take=RampTime,RampSetpoint \
                 -rename=col,RampSetpoint=RampSetpointSafety \
                 | sddsprocess -pipe=in /tmp/${magnet}Err${dataFileUniqueLabel}.sdds \
                 -process=ChangeInRampSetpoint,maximum,ChangeMax \
                 -process=ChangeInRampSetpoint,maximum,ChangeMaxPos,functionOf=RampTime,position \
                 -process=ChangeInRampSetpoint,minimum,ChangeMin \
                 -process=ChangeInRampSetpoint,minimum,ChangeMinPos,functionOf=RampTime,position \
                 -process=ChangeInRampSetpoint,sigma,ChangeSigma } result] {
        return -code error "sddschanges: $result"
    }

    # Verify that calculated ramp correction is within bounds as defined by the safety ramp.
    # If not, generate an error, plot and archive the bad data.
    
    set rampTable $newMagRampFile 
    set ChangeMax [expr abs([exec sdds2stream -param=ChangeMax /tmp/${magnet}Err${dataFileUniqueLabel}.sdds])]
    set ChangeMin [expr abs([exec sdds2stream -param=ChangeMin /tmp/${magnet}Err${dataFileUniqueLabel}.sdds])]
    exec sddsplot -graph=line,vary -subticksettings=xdivisions=5,ydivisions=5 \
      -yScalesGroup=namestring "-xLabel=Time (ms)" \
      "-topline=Correction Safety and Difference Voltage Ramps for ${magnet}" \
      -col=RampTime,RampSetpointCorrection /tmp/${magnet}Err${dataFileUniqueLabel}.sdds \
      "-legend=specified=Correction" \
      -col=RampTime,RampSetpointSafety /tmp/${magnet}Err${dataFileUniqueLabel}.sdds \
      "-legend=specified=Safety" \
      -col=RampTime,ChangeInRampSetpoint /tmp/${magnet}Err${dataFileUniqueLabel}.sdds \
      "-legend=specified=Difference" \
      -yLabel=Difference &
    
    if {$ChangeMax > $ChangeRef || $ChangeMin > $ChangeRef} {
        exec cp /tmp/${magnet}Err${dataFileUniqueLabel}.sdds ${boosterErrorFileDir}/${magnet}Err${dataFileUniqueLabel}.sdds
        SetStatus "$magnet ramp correction will not be done.  Ramp was corrupted.  Visually check the $magnet AFG, voltage and current ramp waveform shape before correcting again."
        APSAlertBox .alert -errorMessage "$magnet ramp correction will not be done.  Ramp was corrupted.  Visually check the $magnet AFG, voltage and current ramp waveform shape before correcting again."
        return 1
    } else {
        SetStatus "Applying corrected ${magnet} ramp."
        exec sddsplot -col=RampTime,RampSetpoint -sub=5,5 -grap=line,type=1 $newMagRampFile &
        #exec rampload $newMagRampFile
        #file copy -force $newMagRampFile $boosterFileDir/${magnet}Vref.afg100
        SetStatus "$magnet magnet ramp"
        SetStatus "The new table is:"
        SetStatus "$newMagRampFile"
        return 0
    }
}

#application starts here


set magnetlist {BM QF QD SF SD} 
set bcontrollist {Slope Zero}
set bcontrolvarlist {slope zero}
set magnetDelayPVList {It:Ddg8chan6.DLY It:Ddg6chan3.DLY It:Ddg8chan7.DLY It:Ddg9chan2.DLY It:Ddg9chan3.DLY}

set statusText ""
SetDefaultParameters
set boosterDir /home/oxygen/SHANG/oag/apps/src/booster/test_ramps
APSApplication . -name BoosterTestStand -version "$CVSRevisionAuthor" \
  -overview {This utility allows automatic ramp correction for Booster test stand power supplies.}

APSScrolledStatus .status  -parent .userFrame  -textVariable statusText -width 60 \
  -height 8 -withButtons 1 -packOption "-fill x"


APSLabeledEntry .dir -parent .userFrame -label "Booster file directory:" \
  -width 70 -textVariable boosterDir -commandButton 1
set sparseInterval 5
set startTime 0
set endTime 500
set preTrigger 18
set plotStart -20
set plotEnd 270
set collectData 1
set injTime [expr 26.7323 - 1.46264]
set magnetDelay 1.46264
set extTime 254.0
set fftStart 35.0
set fftEnd 60.0
APSFrameGrid .grid -parent .userFrame -xList {x1 x2 }
set w1 .userFrame.grid.x1
set w2 .userFrame.grid.x2
set width 30
APSCheckButtonFrame .supplys -parent $w1 -label "Power Supplies:" \
  -buttonList {BM QF QD SF SD} -variableList {BM(selected) QF(selected) QD(selected) SF(selected) SD(selected)} -orientation horizontal \
  -allNone 1 -contextHelp "select the supply for starting/aborting auto-correction"
APSRadioButtonFrame .take -parent $w2 -label "Collect new data for each plot?" \
  -buttonList {Yes No} -valueList {1 0} -variable collectData -orientation horizontal
APSLabeledEntry .start -parent $w1 -width $width -textVariable startTime  -label "Start Time (ms):" \
  -contextHelp "the start time (ms) of the raw waveform, i.e., the time of value 0 corresponding to"

APSLabeledEntry .end -parent $w1 -width $width -textVariable endTime  -label "End Time (ms):" \
  -contextHelp "the end time (ms) of the raw waveform, i.e., the time of value 65535 corresponding to"
APSLabeledEntry .sparse -parent $w2 -width $width -textVariable sparseInterval -label "Sparse Interval:" \
  -contextHelp "Interval to sparse the raw waveform"
APSLabeledEntry .trigger -parent $w2 -width $width -textVariable preTrigger  -label "Pretrigger (ms):" \
  -contextHelp "the end time (ms) of the raw waveform, i.e., the time of value 65535 corresponding to"
CreateParameterWidget -parent .userFrame
APSLabeledEntry .pstart -parent $w1 -width $width -textVariable plotStart -label "Plot time start (ms):" 
APSLabeledEntry .pend -parent $w2 -width $width -textVariable plotEnd -label "Plot time end (ms):" 
APSLabeledEntry .inj -parent $w1 -width $width -textVariable injTime -label "Injection time (ms):" 
APSLabeledEntry .ext -parent $w2 -width $width -textVariable extTime -label "Extraction time (ms):" 
APSLabeledEntry .ffts -parent $w1 -width $width -textVariable fftStart -label "FFT start time (ms):"
APSLabeledEntry .ffte -parent $w2 -width $width -textVariable fftEnd -label "FFT end time (ms):"
set currentGain 10
set refGain 1
set lowFreq 20
set filterStart 30
set filterEnd 60
APSLabeledEntry .gain -parent $w1 -width $width -textVariable currentGain -label "Current gain:" 
APSLabeledEntry .gain1 -parent $w2 -width $width -textVariable refGain -label "Reference gain:"
APSLabeledEntry .freq -parent $w1 -width $width -textVariable lowFreq -label "Low pass frequency (Hz):" 
APSLabeledEntry .lowf -parent $w2 -width $width -textVariable filterStart -label "Filter start time(ms):"
APSLabeledEntry .highf -parent $w2 -width $width -textVariable filterEnd -label "Filter end time(ms):" 

APSFrame .but1 -parent .userFrame  
APSFrame .but2 -parent .userFrame
set w1 .userFrame.but1.frame
set w2 .userFrame.but2.frame
$w1 configure -bd 0
$w2 configure -bd 0
APSButton .plot1 -parent $w1 -text "dI" -command "plotMagnetRamps -plotType dI" 
APSButton .plot2 -parent $w1 -text "dI/I" -command "plotMagnetRamps -plotType dI/I" 
APSButton .plot3 -parent $w1 -text "dV" -command "plotMagnetRamps -plotType dV" 
APSButton .d1 -parent $w1 -text "dI ref." -command "plotMagnetRamps -plotType dIRef" 
APSButton .d2 -parent $w1 -text "dI/I ref." -command "plotMagnetRamps -plotType dI/IRef" 
APSButton .new -parent $w1 -text "I'/Iref'" -command "PlotIRatio"
APSButton .filter -parent $w1 -text "filtered dI/I_ref" -command "ProcessFilter"
APSButton .table -parent $w1 -text "I/Itable" -command "PlotIRefTable"

APSButton .plot4 -parent $w2 -text "FFT" -command "plotMagnetRamps -plotType fft"
APSButton .plot5 -parent $w2 -text "Current" -command "plotMagnetRamps -plotType current"
APSButton .plot6 -parent $w2 -text "Voltage" -command "plotMagnetRamps -plotType voltage" 
APSButton .plot7 -parent $w2 -text "Filtered Current/Voltage" -command "TakeDataAndFilterNoise"
APSButton .correct -parent $w2 -text "Correct" -command "CorrectMagnetRamps" 
APSButton .load1 -parent $w2 -text "Load Voltage" -command "LoadVoltageRamp"
APSButton .gen -parent $w2 -text "Generate Curr. Ref" -command "GenerateCurrentRefRamp"
APSButton .load2 -parent $w2 -text "Load CurRef" -command "LoadCurrentRefRamp"



