#!/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 apsttk 1

APSApplication . -name "SR BPM RMS Weekly History"

proc SetupWeeklyTimeFrames {args} {
    global StartTime EndTime
    set StartTime(1) [clock scan "Oct 4 08:00:00 2016"]
    set EndTime(1) [clock scan "Oct 10 08:00:00 2016"]
    set StartTime(2) [clock scan "Oct 11 08:00:00 2016"]
    set EndTime(2) [clock scan "Oct 17 08:00:00 2016"]
    set StartTime(3) [clock scan "Oct 18 08:00:00 2016"]
    set EndTime(3) [clock scan "Oct 24 08:00:00 2016"]
    set StartTime(4) [clock scan "Oct 25 08:00:00 2016"]
    set EndTime(4) [clock scan "Oct 31 08:00:00 2016"]
    set StartTime(5) [clock scan "Nov 2 08:00:00 2016"]
    set EndTime(5) [clock scan "Nov 7 08:00:00 2016"]
    set StartTime(6) [clock scan "Nov 8 08:00:00 2016"]
    set EndTime(6) [clock scan "Nov 14 08:00:00 2016"]
    set StartTime(7) [clock scan "Nov 15 08:00:00 2016"]
    set EndTime(7) [clock scan "Nov 23 08:00:00 2016"]
    set StartTime(8) [clock scan "Nov 25 08:00:00 2016"]
    set EndTime(8) [clock scan "Dec 5 08:00:00 2016"]
    set StartTime(9) [clock scan "Dec 6 08:00:00 2016"]
    set EndTime(9) [clock scan "Dec 12 08:00:00 2016"]
    set StartTime(10) [clock scan "Dec 13 08:00:00 2016"]
    set EndTime(10) [clock scan "Dec 19 08:00:00 2016"]
    
    set StartTime(11) [clock scan "Jan 31 08:00:00 2017"]
    set EndTime(11) [clock scan "Feb 6 08:00:00 2017"]
    set StartTime(12) [clock scan "Feb 7 08:00:00 2017"]
    set EndTime(12) [clock scan "Feb 13 08:00:00 2017"]
    set StartTime(13) [clock scan "Feb 14 08:00:00 2017"]
    set EndTime(13) [clock scan "Feb 20 08:00:00 2017"]
    set StartTime(14) [clock scan "Feb 21 08:00:00 2017"]
    set EndTime(14) [clock scan "Feb 27 08:00:00 2017"]
    set StartTime(15) [clock scan "Mar 1 08:00:00 2017"]
    set EndTime(15) [clock scan "Mar 6 08:00:00 2017"]
    set StartTime(16) [clock scan "Mar 7 08:00:00 2017"]
    set EndTime(16) [clock scan "Mar 13 08:00:00 2017"]
    set StartTime(17) [clock scan "Mar 14 08:00:00 2017"]
    set EndTime(17) [clock scan "Mar 20 08:00:00 2017"]
    set StartTime(18) [clock scan "Mar 21 08:00:00 2017"]
    set EndTime(18) [clock scan "Mar 27 08:00:00 2017"]
    set StartTime(19) [clock scan "Mar 28 08:00:00 2017"]
    set EndTime(19) [clock scan "Apr 3 08:00:00 2017"]
    set StartTime(20) [clock scan "Apr 4 08:00:00 2017"]
    set EndTime(20) [clock scan "Apr 10 08:00:00 2017"]
    set StartTime(21) [clock scan "Apr 11 08:00:00 2017"]
    set EndTime(21) [clock scan "Apr 17 08:00:00 2017"]
    set StartTime(22) [clock scan "Apr 18 08:00:00 2017"]
    set EndTime(22) [clock scan "Apr 25 00:00:00 2017"]
    
    set StartTime(23) [clock scan "May 31 08:00:00 2017"]
    set EndTime(23) [clock scan "Jun 5 08:00:00 2017"]
    set StartTime(24) [clock scan "Jun 6 08:00:00 2017"]
    set EndTime(24) [clock scan "Jun 12 08:00:00 2017"]
    set StartTime(25) [clock scan "Jun 13 08:00:00 2017"]
    set EndTime(25) [clock scan "Jun 19 08:00:00 2017"]
    set StartTime(26) [clock scan "Jun 20 08:00:00 2017"]
    set EndTime(26) [clock scan "Jun 26 08:00:00 2017"]
    set StartTime(27) [clock scan "Jun 28 08:00:00 2017"]
    set EndTime(27) [clock scan "Jul 4 08:00:00 2017"]
    set StartTime(28) [clock scan "Jul 5 08:00:00 2017"]
    set EndTime(28) [clock scan "Jul 10 08:00:00 2017"]
    set StartTime(29) [clock scan "Jul 11 08:00:00 2017"]
    set EndTime(29) [clock scan "Jul 17 08:00:00 2017"]
    set StartTime(30) [clock scan "Jul 18 08:00:00 2017"]
    set EndTime(30) [clock scan "Jul 24 08:00:00 2017"]
    set StartTime(31) [clock scan "Jul 25 08:00:00 2017"]
    set EndTime(31) [clock scan "Jul 31 08:00:00 2017"]
    set StartTime(32) [clock scan "Aug 1 08:00:00 2017"]
    set EndTime(32) [clock scan "Aug 7 08:00:00 2017"]
    set StartTime(33) [clock scan "Aug 8 08:00:00 2017"]
    set EndTime(33) [clock scan "Aug 14 08:00:00 2017"]
    set StartTime(34) [clock scan "Aug 15 08:00:00 2017"]
    set EndTime(34) [clock scan "Aug 23 00:00:00 2017"]
}

proc SetupGUI {args} {
    global status StartTime EndTime start selectedSectors selectedBPMs
    set status "Ready..."
    APSScrolledStatus .status -parent .userFrame -textVariable status -packOption "-fill both -expand true"
    ttk::frame .userFrame.runs
    pack .userFrame.runs -fill x -anchor nw
    set sec [clock seconds]
    for {set i 1} {$i <= 34} {incr i} {
        if {$sec > $StartTime($i)} {
            set start($i) 1
        } else {
            set start($i) 0
        }
    }
    APSCheckButtonFrame .run2016-3 -parent .userFrame.runs -label "Run 2016-3" -allNone 1 -packOption "-side left" \
      -buttonList "\"[clock format $StartTime(1)]\" \"[clock format $StartTime(2)]\" \"[clock format $StartTime(3)]\" \"[clock format $StartTime(4)]\" \"[clock format $StartTime(5)]\" \"[clock format $StartTime(6)]\" \"[clock format $StartTime(7)]\" \"[clock format $StartTime(8)]\" \"[clock format $StartTime(9)]\" \"[clock format $StartTime(10)]\"" \
      -variableList "start(1) start(2) start(3) start(4) start(5) start(6) start(7) start(8) start(9) start(10)" 

    APSCheckButtonFrame .run2017-1 -parent .userFrame.runs -label "Run 2017-1" -allNone 1 -packOption "-side left" \
      -buttonList "\"[clock format $StartTime(11)]\" \"[clock format $StartTime(12)]\" \"[clock format $StartTime(13)]\" \"[clock format $StartTime(14)]\" \"[clock format $StartTime(15)]\" \"[clock format $StartTime(16)]\" \"[clock format $StartTime(17)]\" \"[clock format $StartTime(18)]\" \"[clock format $StartTime(19)]\" \"[clock format $StartTime(20)]\" \"[clock format $StartTime(21)]\" \"[clock format $StartTime(22)]\"" \
      -variableList "start(11) start(12) start(13) start(14) start(15) start(16) start(17) start(18) start(19) start(20) start(21) start(22)" 

    APSCheckButtonFrame .run2017-2 -parent .userFrame.runs -label "Run 2017-2" -allNone 1 -packOption "-side left" \
      -buttonList "\"[clock format $StartTime(23)]\" \"[clock format $StartTime(24)]\" \"[clock format $StartTime(25)]\" \"[clock format $StartTime(26)]\" \"[clock format $StartTime(27)]\" \"[clock format $StartTime(28)]\" \"[clock format $StartTime(29)]\" \"[clock format $StartTime(30)]\" \"[clock format $StartTime(31)]\" \"[clock format $StartTime(32)]\" \"[clock format $StartTime(33)]\" \"[clock format $StartTime(34)]\"" \
      -variableList "start(23) start(24) start(25) start(26) start(27) start(28) start(29) start(30) start(31) start(32) start(33) start(34)"

    ttk::frame .userFrame.options
    pack .userFrame.options -fill x -anchor nw

    for {set i 1} {$i <= 40} {incr i} {
        set selectedSectors($i) 1
    }
    APSCheckButtonFrame .sectors -parent .userFrame.options -label "Sectors" -allNone 1 -orientation horizontal -limitPerRow 10 \
      -buttonList "01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40" \
      -variableList "selectedSectors(1) selectedSectors(2) selectedSectors(3) selectedSectors(4) selectedSectors(5) selectedSectors(6) selectedSectors(7) selectedSectors(8) selectedSectors(9) selectedSectors(10) selectedSectors(11) selectedSectors(12) selectedSectors(13) selectedSectors(14) selectedSectors(15) selectedSectors(16) selectedSectors(17) selectedSectors(18) selectedSectors(19) selectedSectors(20) selectedSectors(21) selectedSectors(22) selectedSectors(23) selectedSectors(24) selectedSectors(25) selectedSectors(26) selectedSectors(27) selectedSectors(28) selectedSectors(29) selectedSectors(30) selectedSectors(31) selectedSectors(32) selectedSectors(33) selectedSectors(34) selectedSectors(35) selectedSectors(36) selectedSectors(37) selectedSectors(38) selectedSectors(39) selectedSectors(40)"

    set selectedBPMs(A) 1
    set selectedBPMs(B) 1
    set selectedBPMs(C) 0
    set selectedBPMs(BM) 0
    set selectedBPMs(ID) 0
    APSCheckButtonFrame .bpms -parent .userFrame.options -label "   BPMs" -allNone 1  -orientation horizontal -limitPerRow 1 \
      -buttonList {"S<sector>A:*:ErrorCC" "S<sector>B:*:ErrorCC" "S<sector>C:*:ErrorCC" "S<sector>BM:*:ErrorCC" "S<sector>ID:*:ErrorCC"} \
      -variableList "selectedBPMs(A) selectedBPMs(B) selectedBPMs(C) selectedBPMs(BM) selectedBPMs(ID)"

    APSButton .plot -parent .userFrame -text "Plot RMS" -command "PlotRMS"
}

proc PlotRMS {args} {

    APSSetVarAndUpdate status "Getting BPM PV list"
    if {[catch {GetPVList -all 1} pvListAll]} {
        APSSetVarAndUpdate status "Error: $pvListAll"
        return
    }
    if {[catch {GetPVList -all 0} pvList]} {
        APSSetVarAndUpdate status "Error: $pvList"
        return
    }
    APSSetVarAndUpdate status "[llength $pvList] BPM PVs found"

    APSSetVarAndUpdate status "Calculating RMS for all the BPM PVs"
    if {[catch {CompileRMSs -all 1 -pvList $pvListAll} results]} {
        APSSetVarAndUpdate status "Error: $results"
        return
    }
    if {[catch {CompileRMSs -all 0 -pvList $pvList} results]} {
        APSSetVarAndUpdate status "Error: $results"
        return
    }

    APSSetVarAndUpdate status "Identifying bad BPM PVs"
    if {[catch {GetBadBPMs -pvList $pvList} badPVs]} {
        APSSetVarAndUpdate status "Error: $badPVs"
        return
    }

    APSSetVarAndUpdate status "Calculating RMS for the selected sectors"
    if {[catch {SectorRMSs -pvList $pvList -badPVs $badPVs} results]} {
        APSSetVarAndUpdate status "Error: $results"
        return
    }

    APSSetVarAndUpdate status "BPM RMS file: /tmp/srBeamStabilityHistory.BPM.RMS.sdds"
    APSSetVarAndUpdate status "Sector RMS file: /tmp/srBeamStabilityHistory.Sector.RMS.sdds"
    
    APSSetVarAndUpdate status "Plotting Sector RMS values"
    catch {exec sddsplot -sep=namestring /tmp/srBeamStabilityHistory.Sector.RMS.sdds "-col=TimeStart,(Sector*)" -graph=symbol -tick=xtime -ylabel=RMS -legend &}
    
    PlotRMS2

}

proc PlotRMS2 {args} {
    global selectedSectors
    sdds load /tmp/srBeamStabilityHistory.Sector.RMS.sdds data 
    set tstart [lindex [lindex $data(Column.TimeStart) 0] 0]
    set tend [lindex [lindex $data(Column.TimeEnd) 0] end]
    
    set timestart [lindex $data(Column.TimeStart) 0]
    set timeend [lindex $data(Column.TimeEnd) 0]
    set i 0
    set weeks [llength $timestart]
    set t $tstart
    set data(ColumnNames) "Time"
    set data(ColumnInfo.Time) "type SDDS_LONG"
    set timeList ""
    for {set j 1} {$j <= 40} {incr j} {
        if {$selectedSectors($j) == 0} {
            continue
        }
        lappend data(ColumnNames) "Sector$j"
        set data(ColumnInfo.Sector$j) "type SDDS_DOUBLE"
        set sectorList($j) ""
        set mMin($j) [eval tcl::mathfunc::min [lindex $data(Column.Sector$j) 0]]
        set mMax($j) [eval tcl::mathfunc::max [lindex $data(Column.Sector$j) 0]]
    }
    while {$t <= $tend} {
        if {($t >= [lindex $timestart $i]) && ($t <= [lindex $timeend $i])} {
            lappend timeList $t
            for {set j 1} {$j <= 40} {incr j} {
                if {$selectedSectors($j) == 0} {
                    continue
                }
                lappend sectorList($j) [expr ([lindex [lindex $data(Column.Sector$j) 0] $i] - $mMin($j)) / $mMax($j)]
            }
        } else {
            #inbetween runs
            lappend timeList $t
            for {set j 1} {$j <= 40} {incr j} {
                if {$selectedSectors($j) == 0} {
                    continue
                }
                lappend sectorList($j) 99e99
            }
        }
        if {($t > [lindex $timeend $i])} {
            incr i
        }
        incr t 3600
    }
    set data(Column.Time) [list $timeList]
    for {set j 1} {$j <= 40} {incr j} {
        if {$selectedSectors($j) == 0} {
            continue
        }
        set data(Column.Sector$j) [list $sectorList($j)]
    }
    sdds save /tmp/srBeamStabilityHistory.Sector.RMS.extended.sdds data
    APSSetVarAndUpdate status "Plotting Extended Sector RMS values"
    catch {exec sddscontour "-col=Time,Sector*" /tmp/srBeamStabilityHistory.Sector.RMS.extended.sdds -shade=100,0,1 -tick=xtime &}
}

proc GetPVList {args} {
    set all 0
    APSStrictParseArguments {all}
    global selectedBPMs selectedSectors
    set monFile /home/helios/oagData/logging/srBPMs/srBPMs.mon
    set matchList ""
    for {set sector 1} {$sector <= 40} {incr sector} {
        if {($selectedSectors($sector) == 1) || ($all == 1)} {
            if {($selectedBPMs(A) == 1) || ($all == 1)} {
                lappend matchList S${sector}A:P?:ms:?:ErrorCC
            }
            if {($selectedBPMs(B) == 1) || ($all == 1)} {
                lappend matchList S${sector}B:P?:ms:?:ErrorCC
            }
            if {($selectedBPMs(C) == 1) || ($all == 1)} {
                lappend matchList S${sector}C:P?:ms:?:ErrorCC
            }
            if {($selectedBPMs(BM) == 1) || ($all == 1)} {
                lappend matchList S${sector}BM:P?:ms:?:ErrorCC
            }
            if {($selectedBPMs(ID) == 1) || ($all == 1)} {
                lappend matchList S${sector}ID:P?:ms:?:ErrorCC
            }
        }
    }
    if {[llength $matchList] == 0} {
        return -code error "No BPM PVs found"
    }
    set matchOption ""
    set i 0
    foreach match $matchList {
        if {$i == 0} {
            set matchOption -match=column,ReadbackName=$match
            incr i
        } elseif {$i > 0} {
            append matchOption ",ReadbackName=$match,|"
        }
    }
    if {[catch {exec sddsprocess $monFile -pipe=out $matchOption | sdds2stream -pipe=in -col=ReadbackName} pvList]} {
        return -code error "$pvList"
    }
    return $pvList
}

proc CompileRMSs {args} {
    global StartTime EndTime n data start
    set pvList ""
    set all 0
    APSStrictParseArguments {pvList all}
    if {$all == 1} {
        if {[file exists /home/oxygen/OAG/generalData/srBeamStabilityHistory.BPM.RMS.sdds]} {
            sdds load /home/oxygen/OAG/generalData/srBeamStabilityHistory.BPM.RMS.sdds dataold
            set timeStartList [lindex $dataold(Column.TimeStart) 0]
            set calcTime [lindex $dataold(Parameter.CalcTime) 0]
            set preexisting 1
        } else {
            set calcTime [clock seconds]
            set timeStartList ""
            set preexisting 0
        }
        
        set data(ColumnNames) "TimeStart TimeEnd TimeStartString TimeEndString"
        set data(ColumnInfo.TimeStart) "type SDDS_LONG"
        set data(ColumnInfo.TimeEnd) "type SDDS_LONG"
        set data(ColumnInfo.TimeStartString) "type SDDS_STRING"
        set data(ColumnInfo.TimeEndString) "type SDDS_STRING"
        set data(ParameterNames) "CalcTime"
        set data(ParameterInfo.CalcTime) "type SDDS_LONG"
        set data(Parameter.CalcTime) [clock seconds]
        
        foreach pv $pvList {
            lappend data(ColumnNames) $pv
            set data(ColumnInfo.$pv) "type SDDS_DOUBLE"
        }
        set pvcount [llength $pvList]
        set weeks 0
        for {set n 1} {$n <= 34} {incr n} {
            if {$start($n) == 1} {
                if {[clock seconds] > $EndTime($n)} {
                    if {([lsearch -exact $timeStartList $StartTime($n)] == -1) || ($calcTime < $EndTime($n))} {
                        incr weeks
                    }
                }
            }
        }
        if {$weeks == 0} {
            return
        }
        set week 0
        for {set n 1} {$n <= 34} {incr n} {
            if {$start($n) == 0} {
                continue
            }
            if {[clock seconds] < $EndTime($n)} {
                continue
            }
            if {([lsearch -exact $timeStartList $StartTime($n)] != -1) && ($calcTime >= $EndTime($n))} {
                continue
            }
            incr week
            if {[catch {GetTimeFilterFile} filterFile]} {
                return -code error $filterFile
            }
            lappend data(Column.TimeStart) $StartTime($n)
            lappend data(Column.TimeEnd) $EndTime($n)
            lappend data(Column.TimeStartString) [clock format $StartTime($n)]
            lappend data(Column.TimeEndString) [clock format $EndTime($n)]
            
            set tstring [clock format $StartTime($n)]
            set i 0
            foreach pv $pvList {
                incr i
                APSSetVarAndUpdate status "Working on $tstring $pv (week $week of $weeks, pv $i of $pvcount)"
                if {[catch {GetBPMrms $StartTime($n) $EndTime($n) $pv $filterFile 1} bpmRMS]} {
                    return -code error $bpmRMS
                }
                lappend data(Column.$pv) $bpmRMS
            }
            file delete $filterFile
        }
        
        set data(Column.TimeStart) [list $data(Column.TimeStart)]
        set data(Column.TimeEnd) [list $data(Column.TimeEnd)]
        set data(Column.TimeStartString) [list $data(Column.TimeStartString)]
        set data(Column.TimeEndString) [list $data(Column.TimeEndString)]
        foreach pv $pvList {
            set data(Column.$pv) [list $data(Column.$pv)]
        }
        
        if {$preexisting} {
            sdds save /home/oxygen/OAG/generalData/srBeamStabilityHistory.BPM.RMS.sdds.tmp data
            if {[catch {exec sddsprocess /home/oxygen/OAG/generalData/srBeamStabilityHistory.BPM.RMS.sdds /home/oxygen/OAG/generalData/srBeamStabilityHistory.BPM.RMS.sdds.tmp1 -filter=column,TimeEnd,0,$calcTime } results]} {
                catch {file delete /home/oxygen/OAG/generalData/srBeamStabilityHistory.BPM.RMS.sdds.tmp}
                catch {file delete /home/oxygen/OAG/generalData/srBeamStabilityHistory.BPM.RMS.sdds.tmp1}
                return -code error $results
            }
            if {[catch {exec sddscombine /home/oxygen/OAG/generalData/srBeamStabilityHistory.BPM.RMS.sdds.tmp /home/oxygen/OAG/generalData/srBeamStabilityHistory.BPM.RMS.sdds.tmp1 -merge -pipe=out | sddssort -pipe=in /home/oxygen/OAG/generalData/srBeamStabilityHistory.BPM.RMS.sdds -col=TimeStart} results]} {
                catch {file delete /home/oxygen/OAG/generalData/srBeamStabilityHistory.BPM.RMS.sdds.tmp}
                catch {file delete /home/oxygen/OAG/generalData/srBeamStabilityHistory.BPM.RMS.sdds.tmp1}
                return -code error $results
            }
            file delete /home/oxygen/OAG/generalData/srBeamStabilityHistory.BPM.RMS.sdds.tmp
            file delete /home/oxygen/OAG/generalData/srBeamStabilityHistory.BPM.RMS.sdds.tmp1
        } else {
            sdds save /home/oxygen/OAG/generalData/srBeamStabilityHistory.BPM.RMS.sdds data
        }
    } else {
        sdds load /home/oxygen/OAG/generalData/srBeamStabilityHistory.BPM.RMS.sdds data

        set data(ColumnNames) "TimeStart TimeEnd TimeStartString TimeEndString"
        set data(ColumnInfo.TimeStart) "type SDDS_LONG"
        set data(ColumnInfo.TimeEnd) "type SDDS_LONG"
        set data(ColumnInfo.TimeStartString) "type SDDS_STRING"
        set data(ColumnInfo.TimeEndString) "type SDDS_STRING"

        foreach pv $pvList {
            lappend data(ColumnNames) $pv
            set data(ColumnInfo.$pv) "type SDDS_DOUBLE"
        }
        sdds save /tmp/srBeamStabilityHistory.BPM.RMS.sdds data

        set filterOption ""
        set j 0
        for {set n 1} {$n <= 34} {incr n} {
            if {$start($n) == 1} {
                if {$j == 0} {
                    set filterOption "-filter=column,TimeStart,$StartTime($n),$StartTime($n)"
                    set j 1
                } else {
                    append filterOption ",TimeStart,$StartTime($n),$StartTime($n),|"
                }
            }
        }
        if {[catch {exec sddsprocess -nowarn /tmp/srBeamStabilityHistory.BPM.RMS.sdds $filterOption} results]} {
            return -code error $results
        }

        set weeks 0
        for {set n 1} {$n <= 34} {incr n} {
            if {$start($n) == 1} {
                if {([clock seconds] < $EndTime($n)) && ([clock seconds] > $StartTime($n))} {
                    incr weeks
                }
            }
        }
        if {$weeks == 0} {
            return
        }

        unset data
        set data(ColumnNames) "TimeStart TimeEnd TimeStartString TimeEndString"
        set data(ColumnInfo.TimeStart) "type SDDS_LONG"
        set data(ColumnInfo.TimeEnd) "type SDDS_LONG"
        set data(ColumnInfo.TimeStartString) "type SDDS_STRING"
        set data(ColumnInfo.TimeEndString) "type SDDS_STRING"

        foreach pv $pvList {
            lappend data(ColumnNames) $pv
            set data(ColumnInfo.$pv) "type SDDS_DOUBLE"
        }
        set pvcount [llength $pvList]
        set aa1 [clock seconds]
        set week 0        
        for {set n 1} {$n <= 34} {incr n} {
            if {$start($n) == 0} {
                continue
            }
            if {([clock seconds] > $EndTime($n)) || ([clock seconds] < $StartTime($n))} {
                continue
            }
            incr week
            if {[catch {GetTimeFilterFile} filterFile]} {
                return -code error $filterFile
            }
            lappend data(Column.TimeStart) $StartTime($n)
            lappend data(Column.TimeEnd) $EndTime($n)
            lappend data(Column.TimeStartString) [clock format $StartTime($n)]
            lappend data(Column.TimeEndString) [clock format $EndTime($n)]
            
            set tstring [clock format $StartTime($n)]
            set i 0
            foreach "pv" $pvList {
                incr i
                APSSetVarAndUpdate status "Working on $tstring $pv (week $week of $weeks, pv $i of $pvcount)"
                if {[catch {GetBPMrms $StartTime($n) $EndTime($n) $pv $filterFile 1} ret]} {
                    return -code error $ret
                }
                lappend data(Column.$pv) $ret
            }
            file delete $filterFile
        }
        APSSetVarAndUpdate status "time [expr [clock seconds] - $aa1]"
        set data(Column.TimeStart) [list $data(Column.TimeStart)]
        set data(Column.TimeEnd) [list $data(Column.TimeEnd)]
        set data(Column.TimeStartString) [list $data(Column.TimeStartString)]
        set data(Column.TimeEndString) [list $data(Column.TimeEndString)]
        foreach pv $pvList {
            set data(Column.$pv) [list $data(Column.$pv)]
        }
        
        sdds save /tmp/srBeamStabilityHistory.BPM.RMS.sdds.tmp data
        if {[catch {exec sddscombine /tmp/srBeamStabilityHistory.BPM.RMS.sdds /tmp/srBeamStabilityHistory.BPM.RMS.sdds.tmp -merge -pipe=out | sddssort -pipe=in /tmp/srBeamStabilityHistory.BPM.RMS.sdds -col=TimeStart} results]} {
            catch {file delete /tmp/srBeamStabilityHistory.BPM.RMS.sdds.tmp}
            catch {file delete /tmp/srBeamStabilityHistory.BPM.RMS.sdds}
            return -code error $results
        }
        file delete /tmp/srBeamStabilityHistory.BPM.RMS.sdds.tmp
        file delete /tmp/srBeamStabilityHistory.BPM.RMS.sdds~


    }
}

proc GetTimeFilterFile {args} {
    global StartTime EndTime n

    set year [clock format $StartTime($n) -format %Y]
    set month [clock format $StartTime($n) -format %m]
    set endyear [clock format $EndTime($n) -format %Y]
    set endmonth [clock format $EndTime($n) -format %m]
    
    set tmpFile /tmp/[APSTmpString]

    set sampleIntervals "1 2 4 8 16 32 64 128 256"
    set fileList ""
    while {($year < $endyear) || (($year == $endyear) && ($month <= $endmonth))} {
        append fileList "[lsort [glob -nocomplain /home/helios/oagData/logging/\{[join $sampleIntervals ,]\}/SRDesiredMode/log-${year}-${month}.{gz,xz,????}]] "
        append fileList "[lsort [glob -nocomplain /home/helios/oagData/logging/Variable/[string toupper [string index SRDesiredMode 0]]/SRDesiredMode/log-${year}-${month}.{gz,xz,????}]] "
        if {$month == 12} {
            set month 01
            incr year
        } else {
            scan $month %d month
            incr month
            set month [format %02d $month]
        }
    }
    APSAddToTempFileList ${tmpFile}
    if {[llength $fileList] > 1} {
        if {[catch {eval exec sddscombine $fileList -pipe=out -merge | sddsprocess -pipe -filter=column,Time,$StartTime($n),$EndTime($n) -filter=column,SRDesiredMode,.9,1.1 | sddsprocess -pipe=in $tmpFile -retain=Column,Time} results]} {
            return -code error $results
        }
    } elseif {[llength $fileList] == 1} {
        if {[catch {eval exec sddsprocess $fileList -pipe=out -filter=column,Time,$StartTime($n),$EndTime($n) -filter=column,SRDesiredMode,.9,1.1 | sddsprocess -pipe=in $tmpFile -retain=Column,Time} results]} {
            return -code error $results
        }
    } else {
        return -code error "No data for SRDesiredMode in given time frame"
    }
    return $tmpFile
}

proc GetBPMrms {StartTime EndTime pvs filterFile t} {
    
    set tmpFile /tmp/srBeamStabilityHistory.tempFile$t

    set sampleIntervals "1 2 4 8 16 32 64 128 256"
    set resultList ""
    foreach pv $pvs {
        set year [clock format $StartTime -format %Y]
        set month [clock format $StartTime -format %m]
        set endyear [clock format $EndTime -format %Y]
        set endmonth [clock format $EndTime -format %m]
        set fileList ""
        while {($year < $endyear) || (($year == $endyear) && ($month <= $endmonth))} {
            append fileList "[lsort [glob -nocomplain /home/helios/oagData/logging/\{[join $sampleIntervals ,]\}/${pv}/log-${year}-${month}.{gz,xz,????}]] "
            append fileList "[lsort [glob -nocomplain /home/helios/oagData/logging/Variable/[string toupper [string index ${pv} 0]]/${pv}/log-${year}-${month}.{gz,xz,????}]] "
            if {$month == 12} {
                set month 01
                incr year
            } else {
                scan $month %d month
                incr month
                set month [format %02d $month]
            }
        }

        if {[llength $fileList] > 1} {
            if {[catch {eval exec sddscombine $fileList -pipe=out -merge | sddsprocess -nowarn -pipe=in $tmpFile -filter=column,Time,$StartTime,$EndTime } results]} {
                catch {file delete $tmpFile}
                return -code error $results
            }
        } elseif {[llength $fileList] == 1} {
            if {[catch {eval exec sddsprocess -nowarn $fileList $tmpFile -filter=column,Time,$StartTime,$EndTime } results]} {
                catch {file delete $tmpFile}
                return -code error $results
            }
        } else {
            return -code error "Error: No data for ${pv} in given time frame"
        }
        if {[catch {exec sddsxref $tmpFile $filterFile -pipe=out -equate=Time "-leave=*" -nowarn | sddsprocess -pipe -process=${pv},rms,RMS | sdds2stream -pipe=in -para=RMS} results]} {
            catch {file delete $tmpFile}
            return -code error $results
        }
        file delete $tmpFile
        lappend resultList $results
    }

    return $resultList
}

proc GetBadBPMs {args} {
    set pvList ""
    APSStrictParseArguments {pvList}
    global data

    sdds load /tmp/srBeamStabilityHistory.BPM.RMS.sdds data
    
    set badPVs ""
    foreach pv $pvList {
        foreach v [lindex $data(Column.$pv) 0] {
            if {$v == 0} {
                lappend badPVs $pv
                break
            }
            set i 0
            foreach vv [lindex $data(Column.$pv) 0] {
                if {$v == $vv} {
                    incr i
                }
            }
            if {$i != 1} {
                lappend badPVs $pv
                break
            }
        }
    }
    return $badPVs
}

proc SectorRMSs {args} {
    set pvList ""
    set badPVs ""
    APSStrictParseArguments {pvList badPVs}
    global data selectedSectors
    
    sdds load /tmp/srBeamStabilityHistory.BPM.RMS.sdds data
    set rows [llength [lindex $data(Column.TimeStart) 0]]
    
    set data(ColumnNames) "TimeStart TimeEnd TimeStartString TimeEndString"
    for {set sector 1} {$sector <= 40} {incr sector} {
        if {$selectedSectors($sector) == 0} {
            continue
        }
        set sectorPVs ""
        foreach pv $pvList {
            if {[string match "S${sector}A:*" $pv] || \
                  [string match "S${sector}B:*" $pv] || \
                  [string match "S${sector}C:*" $pv] || \
                  [string match "S${sector}BM:*" $pv] || \
                  [string match "S${sector}ID:*" $pv]} {
                lappend sectorPVs $pv
            }
        }
        set pvs ""
        foreach pv $sectorPVs {
            if {[lsearch -exact $badPVs $pv] != -1} {
                continue
            }
            lappend pvs $pv
        }
        set sectorPVs $pvs
        set valueList ""
        for {set row 0} {$row < $rows} {incr row} {
            set value 0
            foreach pv $sectorPVs {
                set v [lindex [lindex $data(Column.$pv) 0] $row]
                set value [expr $value + ($v * $v)]
            }
            lappend valueList [expr sqrt($value / $rows)]
        }
        lappend data(ColumnNames) "Sector$sector"
        set data(ColumnInfo.Sector$sector) "type SDDS_DOUBLE"
        set data(Column.Sector$sector) [list $valueList]
    }

    sdds save /tmp/srBeamStabilityHistory.Sector.RMS.sdds data
}

SetupWeeklyTimeFrames
SetupGUI

