#!/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 system "par"
if {[llength $argv]} {
    set args $argv
    APSStrictParseArguments {system}
}
if {$system == "par"} {
    APSApplication . -name "PAR PS Rate Div Set And Log"
} elseif {$system == "linac"} {
    APSApplication . -name "Linac PS Rate Div Set And Log"
} else {
    puts stderr "Error: invalid -system option"
}

set glbRateDivSetBMQuad 100
set glbRateDivSetCorr 50

proc SetDefault {args} {
    global system
    if {$system == "par"} {    
        exec cavput -list=P:SD:RateDividerAO=300,P:SF:RateDividerAO=300,P:S1:RateDividerAO=300,P:BM:RateDividerAO=350,P:Q1:RateDividerAO=500,P:Q2:RateDividerAO=500,P:Q3BP:RateDividerAO=300,P:Q4:RateDividerAO=500,P2H1:RateDividerAO=300,P2V2:RateDividerAO=300,P2H3:RateDividerAO=300,P3H2:RateDividerAO=300,P3H1:RateDividerAO=300,P4H1:RateDividerAO=300,P4H2:RateDividerAO=300,P1H3:RateDividerAO=300,P1V2:RateDividerAO=300,P1H1:RateDividerAO=300,LTP:Q10:RateDividerAO=350,LTP:Q9:RateDividerAO=350,LTP:Q8:RateDividerAO=350,LTP:Q7:RateDividerAO=350,LTP:Q6:RateDividerAO=350,LTP:Q5:RateDividerAO=350,LTP:Q4:RateDividerAO=350,LTP:Q3:RateDividerAO=350,LTP:Q2:RateDividerAO=350,LTP:Q1:RateDividerAO=350,LTP:H4:RateDividerAO=350,LTP:V4:RateDividerAO=350,LTP:H3:RateDividerAO=350,LTP:V3:RateDividerAO=350,LTP:H2:RateDividerAO=350,LTP:V2:RateDividerAO=350,LTP:H1:RateDividerAO=350,LTP:V1:RateDividerAO=350,PTB:Q11:RateDividerAO=350,PTB:Q10:RateDividerAO=350,PTB:Q9:RateDividerAO=350,PTB:Q8:RateDividerAO=350,PTB:Q7:RateDividerAO=350,PTB:Q6:RateDividerAO=350,PTB:Q5:RateDividerAO=350,PTB:Q4:RateDividerAO=350,PTB:Q3:RateDividerAO=350,PTB:Q2:RateDividerAO=350,PTB:Q1:RateDividerAO=350,PTB:H4:RateDividerAO=350,PTB:V4:RateDividerAO=350,PTB:H3:RateDividerAO=350,PTB:V3:RateDividerAO=350,PTB:H2:RateDividerAO=350,PTB:V2:RateDividerAO=350,PTB:H1:RateDividerAO=350,PTB:V1:RateDividerAO=350 -pend=30
    } elseif {$system == "linac"} {
        exec cavput -list=L1:Q1:RateDividerC=500,L1:Q2:RateDividerC=500,L1:QM3:RateDivAO=500,L1:QM4:RateDivAO=500,L1:QM5:RateDivAO=500,L1:RG1:LFA:RateDivAO=300,L1:RG1:LFA:TRM:RateDivAO=300,L1:RG1:QM1:RateDivAO=500,L1:RG1:QM2:RateDivAO=500,L1:RG1:QM3:RateDivAO=500,L1:RG1:Q4:RateDividerC=500,L1:RG1:SC1:HZ:RateDivAO=300,L1:RG1:SC1:VL:RateDivAO=300,L1:RG1:SC2:HZ:RateDivAO=300,L1:RG1:SC2:VL:RateDivAO=300,L1:RG1:H3:RateDividerC=300,L1:RG1:V3:RateDividerC=300,L1:RG2:LFA:RateDivAO=100,L1:RG2:LFA:TRM:RateDivAO=300,L1:RG2:QM1:RateDivAO=500,L1:RG2:QM2:RateDivAO=500,L1:RG2:QM3:RateDivAO=500,L1:RG2:QM4:RateDivAO=500,L1:RG2:SC1:VL:RateDivAO=300,L1:RG2:SC2:HZ:RateDivAO=300,L1:RG2:SC2:VL:RateDivAO=300,L1:RG2:SC3:HZ:RateDivAO=300,L1:RG2:SC3:VL:RateDivAO=300,L1:H1:RateDividerC=300,L1:V1:RateDividerC=300,L1:H2:RateDividerC=300,L1:V2:RateDividerC=300,L1:SC3:HZ:RateDivAO=100,L1:SC3:VL:RateDivAO=100,L1:SC4:HZ:RateDivAO=100,L1:SC4:VL:RateDivAO=100
    }
}

proc SetGlbRates {args} {
    global glbRateDivSetBMQuad glbRateDivSetCorr

    global system
    if {$system == "par"} {    
        exec cavput -list=P:SD:RateDividerAO=${glbRateDivSetBMQuad},P:SF:RateDividerAO=${glbRateDivSetBMQuad},P:S1:RateDividerAO=${glbRateDivSetBMQuad},P:BM:RateDividerAO=${glbRateDivSetBMQuad},P:Q1:RateDividerAO=${glbRateDivSetBMQuad},P:Q2:RateDividerAO=${glbRateDivSetBMQuad},P:Q3BP:RateDividerAO=${glbRateDivSetBMQuad},P:Q4:RateDividerAO=${glbRateDivSetBMQuad},P2H1:RateDividerAO=${glbRateDivSetCorr},P2V2:RateDividerAO=${glbRateDivSetCorr},P2H3:RateDividerAO=${glbRateDivSetCorr},P3H2:RateDividerAO=${glbRateDivSetCorr},P3H1:RateDividerAO=${glbRateDivSetCorr},P4H1:RateDividerAO=${glbRateDivSetCorr},P4H2:RateDividerAO=${glbRateDivSetCorr},P1H3:RateDividerAO=${glbRateDivSetCorr},P1V2:RateDividerAO=${glbRateDivSetCorr},P1H1:RateDividerAO=${glbRateDivSetCorr},LTP:Q10:RateDividerAO=${glbRateDivSetBMQuad},LTP:Q9:RateDividerAO=${glbRateDivSetBMQuad},LTP:Q8:RateDividerAO=${glbRateDivSetBMQuad},LTP:Q7:RateDividerAO=${glbRateDivSetBMQuad},LTP:Q6:RateDividerAO=${glbRateDivSetBMQuad},LTP:Q5:RateDividerAO=${glbRateDivSetBMQuad},LTP:Q4:RateDividerAO=${glbRateDivSetBMQuad},LTP:Q3:RateDividerAO=${glbRateDivSetBMQuad},LTP:Q2:RateDividerAO=${glbRateDivSetBMQuad},LTP:Q1:RateDividerAO=${glbRateDivSetBMQuad},LTP:H4:RateDividerAO=${glbRateDivSetCorr},LTP:V4:RateDividerAO=${glbRateDivSetCorr},LTP:H3:RateDividerAO=${glbRateDivSetCorr},LTP:V3:RateDividerAO=${glbRateDivSetCorr},LTP:H2:RateDividerAO=${glbRateDivSetCorr},LTP:V2:RateDividerAO=${glbRateDivSetCorr},LTP:H1:RateDividerAO=${glbRateDivSetCorr},LTP:V1:RateDividerAO=${glbRateDivSetCorr},PTB:Q11:RateDividerAO=${glbRateDivSetBMQuad},PTB:Q10:RateDividerAO=${glbRateDivSetBMQuad},PTB:Q9:RateDividerAO=${glbRateDivSetBMQuad},PTB:Q8:RateDividerAO=${glbRateDivSetBMQuad},PTB:Q7:RateDividerAO=${glbRateDivSetBMQuad},PTB:Q6:RateDividerAO=${glbRateDivSetBMQuad},PTB:Q5:RateDividerAO=${glbRateDivSetBMQuad},PTB:Q4:RateDividerAO=${glbRateDivSetBMQuad},PTB:Q3:RateDividerAO=${glbRateDivSetBMQuad},PTB:Q2:RateDividerAO=${glbRateDivSetBMQuad},PTB:Q1:RateDividerAO=${glbRateDivSetBMQuad},PTB:H4:RateDividerAO=${glbRateDivSetCorr},PTB:V4:RateDividerAO=${glbRateDivSetCorr},PTB:H3:RateDividerAO=${glbRateDivSetCorr},PTB:V3:RateDividerAO=${glbRateDivSetCorr},PTB:H2:RateDividerAO=${glbRateDivSetCorr},PTB:V2:RateDividerAO=${glbRateDivSetCorr},PTB:H1:RateDividerAO=${glbRateDivSetCorr},PTB:V1:RateDividerAO=${glbRateDivSetCorr} -pend=30
    } elseif {$system == "linac"} {
        exec cavput -list=L1:Q1:RateDividerC=${glbRateDivSetBMQuad},L1:Q2:RateDividerC=${glbRateDivSetBMQuad},L1:QM3:RateDivAO=${glbRateDivSetBMQuad},L1:QM4:RateDivAO=${glbRateDivSetBMQuad},L1:QM5:RateDivAO=${glbRateDivSetBMQuad},L1:RG1:QM1:RateDivAO=${glbRateDivSetBMQuad},L1:RG1:QM2:RateDivAO=${glbRateDivSetBMQuad},L1:RG1:QM3:RateDivAO=${glbRateDivSetBMQuad},L1:RG1:Q4:RateDividerC=${glbRateDivSetBMQuad},L1:RG1:SC1:HZ:RateDivAO=${glbRateDivSetCorr},L1:RG1:SC1:VL:RateDivAO=${glbRateDivSetCorr},L1:RG1:SC2:HZ:RateDivAO=${glbRateDivSetCorr},L1:RG1:SC2:VL:RateDivAO=${glbRateDivSetCorr},L1:RG1:H3:RateDividerC=${glbRateDivSetCorr},L1:RG1:V3:RateDividerC=${glbRateDivSetCorr},L1:RG2:QM1:RateDivAO=${glbRateDivSetBMQuad},L1:RG2:QM2:RateDivAO=${glbRateDivSetBMQuad},L1:RG2:QM3:RateDivAO=${glbRateDivSetBMQuad},L1:RG2:QM4:RateDivAO=${glbRateDivSetBMQuad},L1:RG2:SC1:VL:RateDivAO=${glbRateDivSetCorr},L1:RG2:SC2:HZ:RateDivAO=${glbRateDivSetCorr},L1:RG2:SC2:VL:RateDivAO=${glbRateDivSetCorr},L1:RG2:SC3:HZ:RateDivAO=${glbRateDivSetCorr},L1:RG2:SC3:VL:RateDivAO=${glbRateDivSetCorr},L1:H1:RateDividerC=${glbRateDivSetCorr},L1:V1:RateDividerC=${glbRateDivSetCorr},L1:H2:RateDividerC=${glbRateDivSetCorr},L1:V2:RateDividerC=${glbRateDivSetCorr},L1:SC3:HZ:RateDivAO=${glbRateDivSetCorr},L1:SC3:VL:RateDivAO=${glbRateDivSetCorr},L1:SC4:HZ:RateDivAO=${glbRateDivSetCorr},L1:SC4:VL:RateDivAO=${glbRateDivSetCorr}
    }
}

proc GetRates {args} {
    global ratePVs
    
    set values [exec cavget -list=[join $ratePVs ,]]

    foreach value $values pv $ratePVs {
        global ${pv}
        set ${pv} ${value}
    }
}

proc SetRates {args} {
    global ratePVs
    foreach pv $ratePVs {
        global ${pv}
        lappend command "${pv}=[set ${pv}]"
    }
    exec cavput -list=[join $command ,] -pend=30
}

proc StartDataLogger {args} {
    global fileName currentaiPVs currentaoPVs conditioningPVs abortVariable
    if {![llength [info commands blt::bgexec]]} {
	package require BLT
	global blt_library
	lappend auto_path $blt_library
    }
    set fileName /tmp/[APSTmpString]
    APSAddToTempFileList fileName 
    set pvlist "$currentaiPVs $currentaoPVs $conditioningPVs"

    APSAddToTempFileList ${fileName}.in
    if {[catch {exec sddsmakedataset -pipe=out -column=ControlName,type=string \
                    -data=[join $pvlist ","] | \
                    sddsprocess -pipe=in ${fileName}.in -edit=column,ReadbackUnits,ControlName,D} results]} {
        puts stderr "error: $results"
        return
    }
    if {[catch {blt::bgexec abortVariable sddslogger ${fileName}.in $fileName -sampleInterval=0.5 -time=1800 &} results]} {
        puts stderr "error: $results"
        return
    }
}

proc ExamineData {args} {
    global fileName currentaiPVs currentaoPVs conditioningPVs abortVariable deviceList
    if {[info exists abortVariable] &&
        $abortVariable==0} {
        # wait for trailing data
        after 5000
    }
    set abortVariable 1
    set tmpRoot /tmp/[APSTmpString]
    set badSupplyList ""
    set plotOptionList ""
    set message ""

#######
#remove 
    file copy -force $fileName /tmp/cond.sdds
#
#######
    foreach device $deviceList setpoint $currentaoPVs readback $currentaiPVs queryCond $conditioningPVs {
        puts "Checking $device"
        if [catch {exec sddsconvert $fileName -pipe=out -retain=column,$setpoint,$readback,$queryCond,Time \
                       | sddsprocess -pipe -process=$setpoint,spread,%sSpread \
                       | sddsbreak -pipe -change=$setpoint \
                       | sddsprocess -pipe -process=$setpoint,first,%s -process=$readback,last,%s \
                       -process=Time,first,Time -process=$queryCond,sum,%sSum \
                       | sddscollapse -pipe=in $tmpRoot.$device} result] {
            puts stderr "error: $result"
            return 
        }
        if [catch {exec sdds2stream $tmpRoot.$device -rows=bare,total} result] {
            puts stderr "error: $result"
            return
        }
        if {$result < 2} {
            continue
        }
        if [catch {exec sddsprocess $tmpRoot.$device -nowarn \
                 -process=${queryCond}Sum,sum,%s \
                 "-define=column,${device}Deviation,$setpoint $readback - abs ${setpoint}Spread / 200 *,units=%" \
                 -process=${device}Deviation,max,%sMax} result] {
            puts stderr "error: $result"
            return 
        }
        APSAddToTempFileList $tmpRoot.$device
        if [catch {exec sdds2stream $tmpRoot.$device -parameter=${device}DeviationMax} deviationMax] {
            puts stderr "error: $deviationMax"
            return 
        }
        puts stderr "device=$device deviationMax=$deviationMax"
        if [expr $deviationMax>1.0] {
            lappend badSupplyList $device
            lappend plotOptionList -column=Time,($setpoint,$readback) -graph=sym,vary,subtype=type -end 
            exec sddsplot -legend -ticks=xtime -column=Time,($setpoint,$readback) -graph=sym,vary,subtype=type $tmpRoot.$device -end -column=Time,${device}Deviation $tmpRoot.$device &
            continue
        }
        continue
        if [catch {exec sdds2stream $tmpRoot.$device -parameter=${queryCond}Sum} queryCondSum] {
            puts stderr "error: $queryCondSum"
            return 
        }
        if [expr $queryCondSum<6] {
            lappend badSupplyList $device
            lappend plotOptionList -column=Time,($setpoint,$readback) -graph=sym,vary,subtype=type -end 
            continue
        }
    }

    if {[string length $badSupplyList]} {
        eval exec sddsplot -legend -ticks=xtime $fileName $plotOptionList  &
    }
    puts "Done"
}

if {$system == "par"} {
    lappend files /home/helios/oagData/controlFiles/PAR/P325MeV.Sstd
    lappend files /home/helios/oagData/controlFiles/PAR/P325MeV.std
    lappend files /home/helios/oagData/controlFiles/PAR/PAR_degauss.sdds
    lappend files /home/helios/oagData/controlFiles/LTP/LTPe325MeV.std
    lappend files /home/helios/oagData/controlFiles/LTP/LTP_degauss.sdds
    lappend files /home/helios/oagData/controlFiles/PTB/PTB325MeV.std
    lappend files /home/helios/oagData/controlFiles/PTB/PTB_degauss.sdds

    set i 1
    foreach f $files {
        set prefixes [exec sdds2stream $f -col=ControlName]
        foreach prefix $prefixes {
            lappend currentaiPVs "${prefix}:CurrentAI"
            lappend currentaoPVs "${prefix}:CurrentAO"
            lappend conditioningPVs "${prefix}:StandardizeSUB.PROC"
            lappend deviceList ${prefix}
            if {($prefix == "LTP:B1") || ($prefix == "PTB:B1") || ($prefix == "PTB:B2")} {
                continue
            }
            lappend ratePVs "${prefix}:RateDividerAO"
            if {$i <= 3} {
                lappend parPrefixes ${prefix}
                lappend parRatePVs ${prefix}:RateDividerAO
            } elseif {$i <= 5} {
                lappend ltpPrefixes ${prefix}
                lappend ltpRatePVs ${prefix}:RateDividerAO
            } else {
                lappend ptbPrefixes ${prefix}
                lappend ptbRatePVs ${prefix}:RateDividerAO
            }
        }
        incr i
    }
} elseif {$system == "linac"} {
    set f /home/helios/oagData/deviceConfig/linac/PSOps.pvTable
    set currentaiPVs [exec sddssort /home/helios/oagData/deviceConfig/linac/PSOps.pvTable -pipe=out -col=ControlName -numeric | sddsprocess -match=column,Operation=ReadCurrent -pipe | sdds2stream -pipe=in -col=ControlName]
    set currentaoPVs [exec sddssort /home/helios/oagData/deviceConfig/linac/PSOps.pvTable -pipe=out -col=ControlName -numeric | sddsprocess -match=column,Operation=SetCurrent -pipe | sdds2stream -pipe=in -col=ControlName]
    set conditioningPVs [exec sddssort /home/helios/oagData/deviceConfig/linac/PSOps.pvTable -pipe=out -col=ControlName -numeric | sddsprocess -match=column,Operation=QueryConditioning -pipe | sdds2stream -pipe=in -col=ControlName]
    foreach pv $currentaiPVs {
        set prefix [string range $pv 0 [expr {[string last ":" $pv] - 1}]]
        lappend deviceList ${prefix}
        if {([string range $prefix 0 5] == "L1:PG1") ||
            ([string range $prefix 0 4] == "L2:QM") ||
            ([string range $prefix 0 2] == "L3:") ||
            ([string range $prefix 0 2] == "L4:") ||
            ([string range $prefix 0 2] == "L5:") ||
            ([string range $prefix 0 4] == "L2:SC")} {
            continue
        }
        lappend ratePVs "${prefix}:RateDivAO"
        if {([string range $prefix 0 5] == "L1:RG1")} {
            lappend rg1Prefixes ${prefix}
            lappend rg1RatePVs ${prefix}:RateDivAO
        } elseif {([string range $prefix 0 5] == "L1:RG2")} {
            lappend rg2Prefixes ${prefix}
            lappend rg2RatePVs ${prefix}:RateDivAO
        } elseif {([string range $prefix 0 4] == "L1:SC")} {
            lappend l1scPrefixes ${prefix}
            lappend l1scRatePVs ${prefix}:RateDivAO
        } else {
            lappend l1qmPrefixes ${prefix}
            lappend l1qmRatePVs ${prefix}:RateDivAO
        }
                  
    }
}


GetRates

frame .userFrame.top
pack .userFrame.top
frame .userFrame.bottom
pack .userFrame.bottom
frame .userFrame.bottom2
pack .userFrame.bottom2

if {$system == "par"} {
    frame .userFrame.top.ltp
    frame .userFrame.top.par
    frame .userFrame.top.ptb
    
    pack .userFrame.top.ltp .userFrame.top.par .userFrame.top.ptb -side left -anchor n
    
    set i 1
    pack [label .userFrame.top.ltp.label -text "LTP Rate Dividers"]
    foreach ltpPrefix $ltpPrefixes ltpRatePV $ltpRatePVs {
        APSLabeledEntry .ltp$i -parent .userFrame.top.ltp -label "$ltpPrefix" -textVariable "$ltpRatePV"
        incr i
    }
    set i 1
    pack [label .userFrame.top.par.label -text "PAR Rate Dividers"]
    foreach parPrefix $parPrefixes parRatePV $parRatePVs {
        APSLabeledEntry .par$i -parent .userFrame.top.par -label "$parPrefix" -textVariable "$parRatePV"
        incr i
    }
    set i 1
    pack [label .userFrame.top.ptb.label -text "PTB Rate Dividers"]
    foreach ptbPrefix $ptbPrefixes ptbRatePV $ptbRatePVs {
        APSLabeledEntry .ptb$i -parent .userFrame.top.ptb -label "$ptbPrefix" -textVariable "$ptbRatePV"
        incr i
    }
} elseif {$system == "linac"} {
    frame .userFrame.top.rg1
    frame .userFrame.top.rg2
    frame .userFrame.top.l1sc
    frame .userFrame.top.l1qm
    
    pack .userFrame.top.rg1 .userFrame.top.rg2 .userFrame.top.l1sc .userFrame.top.l1qm -side left -anchor n
    
    set i 1
    pack [label .userFrame.top.rg1.label -text "RG1 Rate Dividers"]
    foreach rg1Prefix $rg1Prefixes rg1RatePV $rg1RatePVs {
        APSLabeledEntry .rg1$i -parent .userFrame.top.rg1 -label "$rg1Prefix" -textVariable "$rg1RatePV"
        incr i
    }
    set i 1
    pack [label .userFrame.top.rg2.label -text "RG2 Rate Dividers"]
    foreach rg2Prefix $rg2Prefixes rg2RatePV $rg2RatePVs {
        APSLabeledEntry .rg2$i -parent .userFrame.top.rg2 -label "$rg2Prefix" -textVariable "$rg2RatePV"
        incr i
    }
    set i 1
    pack [label .userFrame.top.l1sc.label -text "L1 SC Rate Dividers"]
    foreach l1scPrefix $l1scPrefixes l1scRatePV $l1scRatePVs {
        APSLabeledEntry .l1sc$i -parent .userFrame.top.l1sc -label "$l1scPrefix" -textVariable "$l1scRatePV"
        incr i
    }
    set i 1
    pack [label .userFrame.top.l1qm.label -text "L1 QM Rate Dividers"]
    foreach l1qmPrefix $l1qmPrefixes l1qmRatePV $l1qmRatePVs {
        APSLabeledEntry .l1qm$i -parent .userFrame.top.l1qm -label "$l1qmPrefix" -textVariable "$l1qmRatePV"
        incr i
    }
}

APSLabeledEntry .glbBMQuadEntry -parent .userFrame.bottom -label "Global Rate Divider Setpoint BM/Quads" -textVariable "glbRateDivSetBMQuad"
APSLabeledEntry .glbCorrEntry -parent .userFrame.bottom -label "Global Rate Divider Setpoint Correctors" -textVariable "glbRateDivSetCorr"

APSButton .getRates -parent .userFrame.bottom -text "Get Rate Dividers" -command GetRates
APSButton .setRates -parent .userFrame.bottom -text "Set Rate Dividers" -command SetRates
APSButton .setDefault -parent .userFrame.bottom -text "Set Default Rate Dividers" -command SetDefault

APSButton .startlogger -parent .userFrame.bottom2 -text "Start Data Logger" -command StartDataLogger
APSButton .examinelogger -parent .userFrame.bottom2 -text "Examine Logged Data" -command ExamineData
APSButton .setGlbRates -parent .userFrame.bottom2 -text "Set Global Rates" -command SetGlbRates
